コード例 #1
0
static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
        union i2c_smbus_data *data,
        char read_write, int command,
        int hwpec)
{
    int i, len;
    int smbcmd;
    int status;
    int result;
    int timeout;

    result = i801_check_pre(priv);
    if (result < 0)
        return result;

    len = data->block[0];

    if (read_write == I2C_SMBUS_WRITE) {
        outb_p(len, SMBHSTDAT0(priv));
        outb_p(data->block[1], SMBBLKDAT(priv));
    }

    for (i = 1; i <= len; i++) {
        if (i == len && read_write == I2C_SMBUS_READ) {
            if (command == I2C_SMBUS_I2C_BLOCK_DATA)
                smbcmd = I801_I2C_BLOCK_LAST;
            else
                smbcmd = I801_BLOCK_LAST;
        } else {
            if (command == I2C_SMBUS_I2C_BLOCK_DATA
                    && read_write == I2C_SMBUS_READ)
                smbcmd = I801_I2C_BLOCK_DATA;
            else
                smbcmd = I801_BLOCK_DATA;
        }
        outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv));

        if (i == 1)
            outb_p(inb(SMBHSTCNT(priv)) | I801_START,
                   SMBHSTCNT(priv));

        /* We will always wait for a fraction of a second! */
        timeout = 0;
        do {
            msleep(1);
            status = inb_p(SMBHSTSTS(priv));
        } while ((!(status & SMBHSTSTS_BYTE_DONE))
                 && (timeout++ < MAX_TIMEOUT));

        result = i801_check_post(priv, status, timeout > MAX_TIMEOUT);
        if (result < 0)
            return result;

        if (i == 1 && read_write == I2C_SMBUS_READ
                && command != I2C_SMBUS_I2C_BLOCK_DATA) {
            len = inb_p(SMBHSTDAT0(priv));
            if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
                dev_err(&priv->pci_dev->dev,
                        "Illegal SMBus block read size %d\n",
                        len);
                /* Recover */
                while (inb_p(SMBHSTSTS(priv)) &
                        SMBHSTSTS_HOST_BUSY)
                    outb_p(SMBHSTSTS_BYTE_DONE,
                           SMBHSTSTS(priv));
                outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
                return -EPROTO;
            }
            data->block[0] = len;
        }

        /* Retrieve/store value in SMBBLKDAT */
        if (read_write == I2C_SMBUS_READ)
            data->block[i] = inb_p(SMBBLKDAT(priv));
        if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
            outb_p(data->block[i+1], SMBBLKDAT(priv));

        /* signals SMBBLKDAT ready */
        outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv));
    }

    return 0;
}
コード例 #2
0
ファイル: hd.c プロジェクト: s894330/linux-0.11-lab
void do_hd_request(void)
{
    int i, r = 0;
    unsigned int start_sector, dev, partition;
    unsigned int start_sec, head, cyl;
    unsigned int nsect;

    CHECK_REQUEST;
    partition = MINOR(CURRENT_REQ->dev);  /* get partition */
    start_sector = CURRENT_REQ->start_sector;
    nsect = CURRENT_REQ->nr_sectors;

    /* need to check if nsect is exceed the partition limit or not */
    if (partition >= 5 * NR_HD || nsect > hd[partition].nr_sects) {
        end_request(0);
        goto repeat;	/* repeat defined in blk.h */
    }

    start_sector += hd[partition].start_sect;
    dev = partition / 5;

    /* get cyl, head, start_sec number according start_sector */
    /* div result: EAX = Quotient, EDX = Remainder */
    /*
     * start_sector / sect nrs per track = total track number(start_sector)
     * ... remainder sector number(start_sec)
     */
    __asm__("divl %4"
            :"=a" (start_sector), "=d" (start_sec)
            :"0" (start_sector), "1" (0), "r" (hd_info[dev].sect));

    /* totoal track number / total head nrs = cylinder number(cyl)
     * ... head nr(head) */
    __asm__("divl %4"
            :"=a" (cyl), "=d" (head)
            :"0" (start_sector), "1" (0), "r" (hd_info[dev].head));

    start_sec++;

    if (reset) {
        reset = 0;
        recalibrate = 1;
        reset_hd(CURRENT_DEV);
        return;
    }

    if (recalibrate) {
        recalibrate = 0;
        hd_out(dev, hd_info[CURRENT_DEV].sect, 0, 0, 0, WIN_RESTORE,
               recal_intr);
        return;
    }

    if (CURRENT_REQ->cmd == WRITE) {
        hd_out(dev, nsect, start_sec, head, cyl, WIN_WRITE, write_intr);

        /* wait DRQ_STAT signal */
        for(i = 0; i < 3000 && !(r = inb_p(HD_STATUS) & DRQ_STAT); i++)
            /* nothing */ ;

        if (!r) {
            bad_rw_intr();
            goto repeat;
        }

        /* write 512 byte (1 sector) to HD */
        port_write(HD_DATA, CURRENT_REQ->buffer, 256);
    } else if (CURRENT_REQ->cmd == READ) {
        hd_out(dev, nsect, start_sec, head, cyl, WIN_READ, read_intr);
    } else {
        panic("unknown hd-command");
    }
}
コード例 #3
0
static u8 get_cmd640_reg_pci1(u16 reg)
{
	outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
	return inb_p((reg & 3) | 0xcfc);
}
コード例 #4
0
ファイル: ne2000.c プロジェクト: danilaslau/frotznet
/* This initializes the NE2000 card.  If it turns out the card is not
// really a NE2000 after all then it will return ERRNOTFOUND, else NOERR
// It also dumps the prom into buffer prom for the upper layers..
// Pass it a nic with a null iobase and it will initialize the structure for
// you, otherwise it will just reinitialize it. */
int nic_init(snic* nic, int addr, unsigned char *prom, unsigned char *manual) {
	uint f;
	kprintf("NE2000: reseting NIC card...");
	if(!nic->iobase) {
		nic->iobase=addr;
		nic_stat_clear(&nic->stat);
		nic->pstart=0; nic->pstop=0; nic->wordlength=0; 
		nic->current_page=0;
		nic->notify=NULL;
		for(f=0;f<MAX_TX;f++) {
			nic->tx_packet[f]= NULL;
/*			nic->tx_packet[f].count=0;
			nic->tx_packet[f].buf=NULL;
			nic->tx_packet[f].page=0; */
		}
		nic->last_tx=NULL;
		nic->busy=0;
		nic->sending=0;
	} else {
		if(!nic->iobase || nic->iobase!=addr) return ERR;
	}
	

	outb(inb(addr + NE_RESET), addr + NE_RESET);	/* reset the NE2000*/
	while(!(inb_p(addr+INTERRUPTSTATUS) & ISR_RST)) {
		/* TODO insert timeout code here.*/
	}
	kprintf("done.\n");
	outb_p(0xff,addr + INTERRUPTSTATUS);	/* clear all pending ints*/

	// Initialize registers
	outb_p(NIC_DMA_DISABLE | NIC_PAGE0 | NIC_STOP, addr);	/* enter page 0*/
	outb_p(DCR_DEFAULT, addr + DATACONFIGURATION);
	outb_p(0x00, addr + REMOTEBYTECOUNT0);
	outb_p(0x00, addr + REMOTEBYTECOUNT1);
	outb_p(0x00, addr + INTERRUPTMASK);	/* mask off all irq's*/
	outb_p(0xff, addr + INTERRUPTSTATUS);	/* clear pending ints*/
	outb_p(RCR_MON, RECEIVECONFIGURATION);	/* enter monitor mode*/
	outb_p(TCR_INTERNAL_LOOPBACK, TRANSMITCONFIGURATION); /* internal loopback*/
	
	nic->wordlength=nic_dump_prom(nic,prom);
	if(prom[14]!=0x57 || prom[15]!=0x57) {
		kprintf("NE2000: PROM signature does not match NE2000 0x57.\n");
		return ERRNOTFOUND;
	}
	kprintf("NE2000: PROM signature matches NE2000 0x57.\n");

	/* if the wordlength for the NE2000 card is 2 bytes, then
	// we have to setup the DP8390 chipset to be the same or 
	// else all hell will break loose.*/
	if(nic->wordlength==2) {
		outb_p(DCR_DEFAULT_WORD, addr + DATACONFIGURATION);
	}
	nic->pstart=(nic->wordlength==2) ? PSTARTW : PSTART;
	nic->pstop=(nic->wordlength==2) ? PSTOPW : PSTOP;

	outb_p(NIC_DMA_DISABLE | NIC_PAGE0 | NIC_STOP, addr);
	outb_p(nic->pstart, addr + TRANSMITPAGE);	/* setup local buffer*/
	outb_p(nic->pstart + TXPAGES, addr + PAGESTART);
	outb_p(nic->pstop - 1, addr + BOUNDARY);
	outb_p(nic->pstop, addr + PAGESTOP);
	outb_p(0x00, addr + INTERRUPTMASK);	/* mask off all irq's*/
	outb_p(0xff, addr + INTERRUPTSTATUS);	/* clear pending ints*/
	nic->current_page=nic->pstart + TXPAGES;
	
	/* put physical address in the registers */
	outb_p(NIC_DMA_DISABLE | NIC_PAGE1 | NIC_STOP, addr);  /* switch to page 1 */
	if(manual) for(f=0;f<6;f++) outb_p(manual[f], addr + PHYSICAL + f);
	else for(f=0;f<LEN_ADDR;f++) outb_p(prom[f], addr + PHYSICAL + f);
	kprintf("NE2000: Physical Address- ");
	kprintf("%X:%X:%X:%X:%X:%X\n",
		inb(addr+PAR0),inb(addr+PAR1),inb(addr+PAR2),
		inb(addr+PAR3),inb(addr+PAR4),inb(addr+PAR5));

	/* setup multicast filter to accept all packets*/
	for(f=0;f<8;f++) outb_p(0xFF, addr + MULTICAST + f);

	outb_p(nic->pstart+TXPAGES, addr + CURRENT);
	outb_p(NIC_DMA_DISABLE | NIC_PAGE0 | NIC_STOP, addr); /* switch to page 0 */

	return NOERR;
}
コード例 #5
0
ファイル: todc_time.c プロジェクト: 1x23/unifi-gpl
/* Access routines for accessing mc146818 type chips via addr/data regs */
u_char
todc_mc146818_read_val(int addr)
{
	outb_p(addr, todc_info->nvram_as0);
	return inb_p(todc_info->nvram_data);
}
コード例 #6
0
ファイル: i2c-i801.c プロジェクト: OPSF/uClinux
static int i801_transaction(void)
{
	int temp;
	int result = 0;
	int timeout = 0;

	dev_dbg(I801_dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
		inb_p(SMBHSTDAT1));

	/* Make sure the SMBus host is ready to start transmitting */
	/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
		dev_dbg(I801_dev, "SMBus busy (%02x). Resetting...\n",
			temp);
		outb_p(temp, SMBHSTSTS);
		if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
			dev_dbg(I801_dev, "Failed! (%02x)\n", temp);
			return -1;
		} else {
			dev_dbg(I801_dev, "Successfull!\n");
		}
	}

	outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);

	/* We will always wait for a fraction of a second! */
	do {
		i2c_delay(1);
		temp = inb_p(SMBHSTSTS);
	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));

	/* If the SMBus is still busy, we give up */
	if (timeout >= MAX_TIMEOUT) {
		dev_dbg(I801_dev, "SMBus Timeout!\n");
		result = -1;
	}

	if (temp & 0x10) {
		result = -1;
		dev_dbg(I801_dev, "Error: Failed bus transaction\n");
	}

	if (temp & 0x08) {
		result = -1;
		dev_err(I801_dev, "Bus collision! SMBus may be locked "
			"until next hard reset. (sorry!)\n");
		/* Clock stops and slave is stuck in mid-transmission */
	}

	if (temp & 0x04) {
		result = -1;
		dev_dbg(I801_dev, "Error: no response!\n");
	}

	if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
		outb_p(inb(SMBHSTSTS), SMBHSTSTS);

	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
		dev_dbg(I801_dev, "Failed reset at end of transaction "
			"(%02x)\n", temp);
	}
	dev_dbg(I801_dev, "Transaction (post): CNT=%02x, CMD=%02x, "
		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
		inb_p(SMBHSTDAT1));
	return result;
}
コード例 #7
0
static inline bool synth_writable(void)
{
	return inb_p(synth_port_control) & SYNTH_WRITABLE;
}
コード例 #8
0
ファイル: pcwd_pci.c プロジェクト: 12rafael/jellytimekernel
static inline void pcipcwd_check_temperature_support(void)
{
	if (inb_p(pcipcwd_private.io_addr) != 0xF0)
		pcipcwd_private.supports_temp = 1;
}
コード例 #9
0
ファイル: s3_pci.c プロジェクト: ele7enxxh/dtrace-pf
static int
s3lfb_set_mode(video_adapter_t *adp, int mode)
{
	device_t dev = s3pci_dev;			/* XXX */
	struct s3pci_softc *sc = (struct s3pci_softc *)device_get_softc(dev);
#if 0
	unsigned char tmp;
#endif
	int error;

	/* First, set the mode as if it was a classic VESA card
	 */
	if ((error = (*prevvidsw->set_mode)(adp, mode)))
		return error;

	/* If not in a linear mode (according to s3lfb_get_info() called
	 * by vesa_set_mode in the (*vidsw[adp->va_index]->get_info)...
	 * sequence, return with no error
	 */
#if 0
	if (!(adp->va_info.vi_flags & V_INFO_LINEAR))
		return 0;
#endif

	if ((mode <= M_VESA_BASE) ||
		!(adp->va_info.vi_flags & V_INFO_GRAPHICS) ||
		(adp->va_info.vi_flags & V_INFO_LINEAR))
		return 0;

	/* Ok, now apply the configuration to the card */

	outb_p(0x38, S3_CRTC_ADDR); outb_p(0x48, S3_CRTC_VALUE);
	outb_p(0x39, S3_CRTC_ADDR); outb_p(0xa5, S3_CRTC_VALUE);
       
       /* check that CR47 is read/write */
       
#if 0
	outb_p(0x47, S3_CRTC_ADDR); outb_p(0xff, S3_CRTC_VALUE);
	tmp = inb_p(S3_CRTC_VALUE);
	outb_p(0x00, S3_CRTC_VALUE);
	if ((tmp != 0xff) || (inb_p(S3_CRTC_VALUE)))
	{
		/* lock S3 registers */

		outb_p(0x39, S3_CRTC_ADDR); outb_p(0x5a, S3_CRTC_VALUE);
		outb_p(0x38, S3_CRTC_ADDR); outb_p(0x00, S3_CRTC_VALUE);

		return ENXIO;
	}
#endif

	/* enable enhanced register access */

	outb_p(0x40, S3_CRTC_ADDR);
	outb_p(inb_p(S3_CRTC_VALUE) | 1, S3_CRTC_VALUE);

	/* enable enhanced functions */

	outb_enh(inb_enh(0) | 1, 0x0);

	/* enable enhanced mode memory mapping */

	outb_p(0x31, S3_CRTC_ADDR);
	outb_p(inb_p(S3_CRTC_VALUE) | 8, S3_CRTC_VALUE);

	/* enable linear frame buffer and set address window to max */

	outb_p(0x58, S3_CRTC_ADDR);
	outb_p(inb_p(S3_CRTC_VALUE) | 0x13, S3_CRTC_VALUE);

	/* disabled enhanced register access */

	outb_p(0x40, S3_CRTC_ADDR);
	outb_p(inb_p(S3_CRTC_VALUE) & ~1, S3_CRTC_VALUE);

	/* lock S3 registers */

	outb_p(0x39, S3_CRTC_ADDR); outb_p(0x5a, S3_CRTC_VALUE);
	outb_p(0x38, S3_CRTC_ADDR); outb_p(0x00, S3_CRTC_VALUE);

	adp->va_info.vi_flags |= V_INFO_LINEAR;
	adp->va_info.vi_buffer = sc->mem_base;
	adp->va_buffer = s3lfb_map_buffer(adp->va_info.vi_buffer,
				adp->va_info.vi_buffer_size);
	adp->va_buffer_size = adp->va_info.vi_buffer_size;
	adp->va_window = adp->va_buffer;
	adp->va_window_size = adp->va_info.vi_buffer_size/adp->va_info.vi_planes;
	adp->va_window_gran = adp->va_info.vi_buffer_size/adp->va_info.vi_planes;

	return 0;
}
コード例 #10
0
static void acq_keepalive(void)
{
	/* Write a watchdog value */
	inb_p(wdt_start);
}
コード例 #11
0
static void acq_stop(void)
{
	/* Turn the card off */
	inb_p(wdt_stop);
}
コード例 #12
0
ファイル: i2c-piix4.c プロジェクト: garyvan/openwrt-1.6
static void piix4_poll(struct i2c_adapter *piix4_adapter,
		       struct i2c_op_q_entry *e,
		       unsigned int ns_since_last_poll)
{
	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter);
	unsigned short piix4_smba = adapdata->smba;
	int temp;
	int i;

	temp = inb_p(SMBHSTSTS);
	if (temp & 0x01) {
		e->time_left -= ns_since_last_poll;
		if (e->time_left <= 0) {
			dev_err(&piix4_adapter->dev, "SMBus Timeout!\n");
			e->result = -EBUSY;
			goto out_done;
		} else {
			/* Not done, return to restart the timer */
			e->call_again_ns = RETRY_TIME_NS;
		}
		return;
	}

	if (temp & 0x10) {
		e->result = -EIO;
		dev_err(&piix4_adapter->dev, "Error: Failed bus transaction\n");
		goto out_done;
	}

	if (temp & 0x08) {
		e->result = -EIO;
		dev_dbg(&piix4_adapter->dev, "Bus collision! SMBus may be "
			"locked until next hard reset. (sorry!)\n");
		/* Clock stops and slave is stuck in mid-transmission */
		goto out_done;
	}

	if (temp & 0x04) {
		e->result = -ENODEV;
		dev_dbg(&piix4_adapter->dev, "Error: no response!\n");
		goto out_done;
	}

	if (inb_p(SMBHSTSTS) != 0x00)
		outb_p(inb(SMBHSTSTS), SMBHSTSTS);

	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
		dev_err(&piix4_adapter->dev, "Failed reset at end of "
			"transaction (%02x)\n", temp);
	}
	dev_dbg(&piix4_adapter->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
		inb_p(SMBHSTDAT1));

	if ((e->smbus.read_write == I2C_SMBUS_WRITE)
	    || (e->smbus.size == PIIX4_QUICK))
		goto out_done;

	switch (e->smbus.size) {
	case PIIX4_BYTE:
	case PIIX4_BYTE_DATA:
		e->smbus.data->byte = inb_p(SMBHSTDAT0);
		break;
	case PIIX4_WORD_DATA:
		e->smbus.data->word = (inb_p(SMBHSTDAT0)
				       + (inb_p(SMBHSTDAT1) << 8));
		break;
	case PIIX4_BLOCK_DATA:
		e->smbus.data->block[0] = inb_p(SMBHSTDAT0);
		if (e->smbus.data->block[0] == 0 ||
			      e->smbus.data->block[0] > I2C_SMBUS_BLOCK_MAX) {
			e->result = -EPROTO;
			goto out_done;
		}
		i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
		for (i = 1; i <= e->smbus.data->block[0]; i++)
			e->smbus.data->block[i] = inb_p(SMBBLKDAT);
		break;
	}

 out_done:
	i2c_op_done(piix4_adapter, e);
}
コード例 #13
0
ファイル: i2c-piix4.c プロジェクト: garyvan/openwrt-1.6
static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
			     const struct pci_device_id *id)
{
	unsigned short piix4_smba;
	unsigned short smba_idx = 0xcd6;
	u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c;

	/* SB800 and later SMBus does not support forcing address */
	if (force || force_addr) {
		dev_err(&PIIX4_dev->dev, "SMBus does not support "
			"forcing address!\n");
		return -EINVAL;
	}

	/* Determine the address of the SMBus areas */
	if (!request_region(smba_idx, 2, "smba_idx")) {
		dev_err(&PIIX4_dev->dev, "SMBus base address index region "
			"0x%x already in use!\n", smba_idx);
		return -EBUSY;
	}
	outb_p(smb_en, smba_idx);
	smba_en_lo = inb_p(smba_idx + 1);
	outb_p(smb_en + 1, smba_idx);
	smba_en_hi = inb_p(smba_idx + 1);
	release_region(smba_idx, 2);

	if ((smba_en_lo & 1) == 0) {
		dev_err(&PIIX4_dev->dev,
			"Host SMBus controller not enabled!\n");
		return -ENODEV;
	}

	piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
	if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
		return -ENODEV;

	if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
		dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
			piix4_smba);
		return -EBUSY;
	}

	/* Request the SMBus I2C bus config region */
	if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) {
		dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region "
			"0x%x already in use!\n", piix4_smba + i2ccfg_offset);
		release_region(piix4_smba, SMBIOSIZE);
		return -EBUSY;
	}
	i2ccfg = inb_p(piix4_smba + i2ccfg_offset);
	release_region(piix4_smba + i2ccfg_offset, 1);

	if (i2ccfg & 1)
		dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n");
	else
		dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n");

	dev_info(&PIIX4_dev->dev,
		 "SMBus Host Controller at 0x%x, revision %d\n",
		 piix4_smba, i2ccfg >> 4);

	return piix4_smba;
}
コード例 #14
0
ファイル: i2c-piix4.c プロジェクト: garyvan/openwrt-1.6
			i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
			for (i = 1; i <= len; i++)
				outb_p(e->smbus.data->block[i], SMBBLKDAT);
		}
		e->smbus.size = PIIX4_BLOCK_DATA;
		break;
	default:
		dev_warn(&piix4_adapter->dev, "Unsupported transaction %d\n",
			 e->smbus.size);
		return -EOPNOTSUPP;
	}

	outb_p((e->smbus.size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);

	dev_dbg(&piix4_adapter->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
		inb_p(SMBHSTDAT1));

	/* Make sure the SMBus host is ready to start transmitting */
	temp = inb_p(SMBHSTSTS);
	if (temp != 0x00) {
		dev_dbg(&piix4_adapter->dev, "SMBus busy (%02x). "
			"Resetting...\n", temp);
		outb_p(temp, SMBHSTSTS);
		temp = inb_p(SMBHSTSTS);
		if (temp != 0x00) {
			dev_err(&piix4_adapter->dev, "Failed! (%02x)\n", temp);
			return -EBUSY;
		} else {
			dev_dbg(&piix4_adapter->dev, "Successfull!\n");
コード例 #15
0
ファイル: time.c プロジェクト: TitaniumBoy/lin
static unsigned char ddb_rtc_read_data(unsigned long addr)
{
	outb_p(addr, RTC_PORT(0));
	return inb_p(RTC_PORT(1));
}
コード例 #16
0
ファイル: speakup_decpc.c プロジェクト: AkyZero/wrapfs-latest
static int dt_getstatus(void)
{
	dt_stat = inb_p(speakup_info.port_tts) |
		 (inb_p(speakup_info.port_tts + 1) << 8);
	return dt_stat;
}
コード例 #17
0
ファイル: 3c501.c プロジェクト: dmgerman/original
static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int ioaddr = dev->base_addr;
	unsigned long flags;

	/*
	 *	Avoid incoming interrupts between us flipping txing and flipping
	 *	mode as the driver assumes txing is a faithful indicator of card
	 *	state
	 */

	spin_lock_irqsave(&lp->lock, flags);
	
	/*
	 *	Avoid timer-based retransmission conflicts.
	 */

	netif_stop_queue(dev);

	do
	{
		int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
		unsigned char *buf = skb->data;

		lp->tx_pkt_start = gp_start;
    		lp->collisions = 0;

    		lp->stats.tx_bytes += skb->len;

		/*
		 *	Command mode with status cleared should [in theory]
		 *	mean no more interrupts can be pending on the card.
		 */

		outb_p(AX_SYS, AX_CMD);
		inb_p(RX_STATUS);
		inb_p(TX_STATUS);

		lp->loading = 1;
		lp->txing = 1;

		/*
		 *	Turn interrupts back on while we spend a pleasant afternoon
		 *	loading bytes into the board
		 */

		spin_unlock_irqrestore(&lp->lock, flags);
		
		outw(0x00, RX_BUF_CLR);		/* Set rx packet area to 0. */
		outw(gp_start, GP_LOW);		/* aim - packet will be loaded into buffer start */
		outsb(DATAPORT,buf,skb->len);	/* load buffer (usual thing each byte increments the pointer) */
		outw(gp_start, GP_LOW);		/* the board reuses the same register */
	
		if(lp->loading != 2)
		{
			outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */
			lp->loading=0;
			dev->trans_start = jiffies;
			if (el_debug > 2)
				printk(" queued xmit.\n");
			dev_kfree_skb (skb);
			return 0;
		}
		/* A receive upset our load, despite our best efforts */
		if(el_debug>2)
			printk("%s: burped during tx load.\n", dev->name);
		spin_lock_irqsave(&lp->lock, flags);
	}
	while(1);

}
コード例 #18
0
ファイル: speakup_keypc.c プロジェクト: 020gzh/linux
static inline bool synth_writable(void)
{
	return (inb_p(synth_port + UART_RX) & 0x10) != 0;
}
コード例 #19
0
ファイル: i2c-i801.c プロジェクト: OPSF/uClinux
/* All-inclusive block transaction function */
static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
				  int command, int hwpec)
{
	int i, len;
	int smbcmd;
	int temp;
	int result = 0;
	int timeout;
	unsigned char hostc, errmask;

	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
		if (read_write == I2C_SMBUS_WRITE) {
			/* set I2C_EN bit in configuration register */
			pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
			pci_write_config_byte(I801_dev, SMBHSTCFG,
					      hostc | SMBHSTCFG_I2C_EN);
		} else if (!isich5) {
			dev_err(I801_dev,
				"I2C_SMBUS_I2C_BLOCK_READ unsupported!\n");
			return -1;
		}
	}

	if (read_write == I2C_SMBUS_WRITE) {
		len = data->block[0];
		if (len < 1)
			len = 1;
		if (len > 32)
			len = 32;
		outb_p(len, SMBHSTDAT0);
		outb_p(data->block[1], SMBBLKDAT);
	} else {
		len = 32;	/* max for reads */
	}

	if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
		/* set 32 byte buffer */
	}

	for (i = 1; i <= len; i++) {
		if (i == len && read_write == I2C_SMBUS_READ)
			smbcmd = I801_BLOCK_LAST;
		else if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
		         read_write == I2C_SMBUS_READ)
			smbcmd = I801_I2C_BLOCK_DATA;
		else
			smbcmd = I801_BLOCK_DATA;
		outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);

		dev_dbg(I801_dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
			"ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
			inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
			inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));

		/* Make sure the SMBus host is ready to start transmitting */
		temp = inb_p(SMBHSTSTS);
		if (i == 1) {
			/* Erronenous conditions before transaction: 
			 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
			errmask=0x9f; 
		} else {
			/* Erronenous conditions during transaction: 
			 * Failed, Bus_Err, Dev_Err, Intr */
			errmask=0x1e; 
		}
		if (temp & errmask) {
			dev_dbg(I801_dev, "SMBus busy (%02x). "
				"Resetting...\n", temp);
			outb_p(temp, SMBHSTSTS);
			if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
				dev_err(I801_dev,
					"Reset failed! (%02x)\n", temp);
				result = -1;
                                goto END;
			}
			if (i != 1) {
				/* if die in middle of block transaction, fail */
				result = -1;
				goto END;
			}
		}

		if (i == 1)
			outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);

		/* We will always wait for a fraction of a second! */
		timeout = 0;
		do {
			temp = inb_p(SMBHSTSTS);
			i2c_delay(1);
		}
		    while ((!(temp & 0x80))
			   && (timeout++ < MAX_TIMEOUT));

		/* If the SMBus is still busy, we give up */
		if (timeout >= MAX_TIMEOUT) {
			result = -1;
			dev_dbg(I801_dev, "SMBus Timeout!\n");
		}

		if (temp & 0x10) {
			result = -1;
			dev_dbg(I801_dev,
				"Error: Failed bus transaction\n");
		} else if (temp & 0x08) {
			result = -1;
			dev_err(I801_dev, "Bus collision!\n");
		} else if (temp & 0x04) {
			result = -1;
			dev_dbg(I801_dev, "Error: no response!\n");
		}

		if (i == 1 && read_write == I2C_SMBUS_READ) {
			if (command != I2C_SMBUS_I2C_BLOCK_DATA) {
				len = inb_p(SMBHSTDAT0);
				if (len < 1)
					len = 1;
				if (len > 32)
					len = 32;
				data->block[0] = len;
			} else {
				/* if slave returns < 32 bytes transaction will fail */
				data->block[0] = 32;
			}
		}

		/* Retrieve/store value in SMBBLKDAT */
		if (read_write == I2C_SMBUS_READ)
			data->block[i] = inb_p(SMBBLKDAT);
		if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
			outb_p(data->block[i+1], SMBBLKDAT);
		if ((temp & 0x9e) != 0x00)
			outb_p(temp, SMBHSTSTS);  /* signals SMBBLKDAT ready */

		if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
			dev_dbg(I801_dev,
				"Bad status (%02x) at end of transaction\n",
				temp);
		}
		dev_dbg(I801_dev, "Block (post %d): CNT=%02x, CMD=%02x, "
			"ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
			inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
			inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));

		if (result < 0)
			goto END;
	}

	if (hwpec) {
		/* wait for INTR bit as advised by Intel */
		timeout = 0;
		do {
			temp = inb_p(SMBHSTSTS);
			i2c_delay(1);
		} while ((!(temp & 0x02))
			   && (timeout++ < MAX_TIMEOUT));

		if (timeout >= MAX_TIMEOUT) {
			dev_dbg(I801_dev, "PEC Timeout!\n");
		}
		outb_p(temp, SMBHSTSTS); 
	}
	result = 0;
END:
	if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
	    read_write == I2C_SMBUS_WRITE) {
		/* restore saved configuration register value */
		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
	}
	return result;
}
コード例 #20
0
ファイル: speakup_keypc.c プロジェクト: 020gzh/linux
static inline bool synth_full(void)
{
	return (inb_p(synth_port + UART_RX) & 0x80) == 0;
}
コード例 #21
0
static inline bool synth_full(void)
{
	return inb_p(speakup_info.port_tts + UART_RX) == 'F';
}
コード例 #22
0
ファイル: apic.c プロジェクト: muromec/linux-ezxdev
void setup_APIC_timer(void * data)
{
	unsigned int clocks = (unsigned long) data, slice, t0, t1;
	int delta;

	/*
	 * ok, Intel has some smart code in their APIC that knows
	 * if a CPU was in 'hlt' lowpower mode, and this increases
	 * its APIC arbitration priority. To avoid the external timer
	 * IRQ APIC event being in synchron with the APIC clock we
	 * introduce an interrupt skew to spread out timer events.
	 *
	 * The number of slices within a 'big' timeslice is smp_num_cpus+1
	 */

	slice = clocks / (smp_num_cpus+1);
	printk(KERN_INFO "cpu: %d, clocks: %d, slice: %d\n",
		smp_processor_id(), clocks, slice);

	/*
	 * Wait for timer IRQ slice:
	 */

	if (hpet.address) {
		int trigger = hpet_readl(HPET_T0_CMP);
		while (hpet_readl(HPET_COUNTER) >= trigger);
		while (hpet_readl(HPET_COUNTER) <  trigger);
	} else {
		int c1, c2;
		outb_p(0x00, 0x43);
		c2 = inb_p(0x40);
		c2 |= inb_p(0x40) << 8;
		do {
			c1 = c2;
			outb_p(0x00, 0x43);
			c2 = inb_p(0x40);
			c2 |= inb_p(0x40) << 8;
		} while (c2 - c1 < 300);
	}

	__setup_APIC_LVTT(clocks);

	t0 = apic_read(APIC_TMICT)*APIC_DIVISOR;

	/* Wait till TMCCT gets reloaded from TMICT... */
	do {
		t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
		delta = (int)(t0 - t1 - slice*(smp_processor_id()+1));
	} while (delta >= 0);

	/* Now wait for our slice for real. */
	do {
		t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
		delta = (int)(t0 - t1 - slice*(smp_processor_id()+1));
	} while (delta < 0);

	__setup_APIC_LVTT(clocks);

	printk(KERN_INFO "CPU%d<T0:%u,T1:%u,D:%d,S:%u,C:%u>\n",
			smp_processor_id(), t0, t1, delta, slice, clocks);
}
コード例 #23
0
ファイル: ne2000.c プロジェクト: danilaslau/frotznet
/* You should call this before you just read the stats directlly from the
// snic struct.  This procedure updates the counters */
nic_stat nic_get_stats(snic *nic) { 
	nic->stat.errors.frame_alignment+=inb_p(nic->iobase + FAE_TALLY);
	nic->stat.errors.crc+=inb_p(nic->iobase + CRC_TALLY);
	nic->stat.errors.missed_packets+=inb_p(nic->iobase + MISS_PKT_TALLY);
	return nic->stat;
}
コード例 #24
0
/* Probe for the Etherlink II card at I/O port base IOADDR,
   returning non-zero on success.  If found, set the station
   address and memory parameters in DEVICE. */
static int __init
el2_probe1(struct net_device *dev, int ioaddr)
{
    int i, iobase_reg, membase_reg, saved_406, wordlength, retval;
    static unsigned version_printed;
    unsigned long vendor_id;

    if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
	return -EBUSY;

    if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) {
	retval = -EBUSY;
	goto out;
    }

    /* Reset and/or avoid any lurking NE2000 */
    if (inb(ioaddr + 0x408) == 0xff) {
    	mdelay(1);
	retval = -ENODEV;
	goto out1;
    }

    /* We verify that it's a 3C503 board by checking the first three octets
       of its ethernet address. */
    iobase_reg = inb(ioaddr+0x403);
    membase_reg = inb(ioaddr+0x404);
    /* ASIC location registers should be 0 or have only a single bit set. */
    if (   (iobase_reg  & (iobase_reg - 1))
	|| (membase_reg & (membase_reg - 1))) {
	retval = -ENODEV;
	goto out1;
    }
    saved_406 = inb_p(ioaddr + 0x406);
    outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
    outb_p(ECNTRL_THIN, ioaddr + 0x406);
    /* Map the station addr PROM into the lower I/O ports. We now check
       for both the old and new 3Com prefix */
    outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
    vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
    if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
	/* Restore the register we frobbed. */
	outb(saved_406, ioaddr + 0x406);
	retval = -ENODEV;
	goto out1;
    }

    if (ei_debug  &&  version_printed++ == 0)
	printk(version);

    dev->base_addr = ioaddr;

    printk("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);

    /* Retrieve and print the ethernet address. */
    for (i = 0; i < 6; i++)
	dev->dev_addr[i] = inb(ioaddr + i);
    printk("%pM", dev->dev_addr);

    /* Map the 8390 back into the window. */
    outb(ECNTRL_THIN, ioaddr + 0x406);

    /* Check for EL2/16 as described in tech. man. */
    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
    outb_p(0, ioaddr + EN0_DCFG);
    outb_p(E8390_PAGE2, ioaddr + E8390_CMD);
    wordlength = inb_p(ioaddr + EN0_DCFG) & ENDCFG_WTS;
    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);

    /* Probe for, turn on and clear the board's shared memory. */
    if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg);
    outb(EGACFR_NORM, ioaddr + 0x405);	/* Enable RAM */

    /* This should be probed for (or set via an ioctl()) at run-time.
       Right now we use a sleazy hack to pass in the interface number
       at boot-time via the low bits of the mem_end field.  That value is
       unused, and the low bits would be discarded even if it was used. */
#if defined(EI8390_THICK) || defined(EL2_AUI)
    ei_status.interface_num = 1;
#else
    ei_status.interface_num = dev->mem_end & 0xf;
#endif
    printk(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");

    if ((membase_reg & 0xf0) == 0) {
	dev->mem_start = 0;
	ei_status.name = "3c503-PIO";
	ei_status.mem = NULL;
    } else {
	dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
	    ((membase_reg & 0xA0) ? 0x4000 : 0);
#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
	ei_status.mem = ioremap(dev->mem_start, EL2_MEMSIZE);

#ifdef EL2MEMTEST
	/* This has never found an error, but someone might care.
	   Note that it only tests the 2nd 8kB on 16kB 3c503/16
	   cards between card addr. 0x2000 and 0x3fff. */
	{			/* Check the card's memory. */
	    void __iomem *mem_base = ei_status.mem;
	    unsigned int test_val = 0xbbadf00d;
	    writel(0xba5eba5e, mem_base);
	    for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
		writel(test_val, mem_base + i);
		if (readl(mem_base) != 0xba5eba5e
		    || readl(mem_base + i) != test_val) {
		    printk("3c503: memory failure or memory address conflict.\n");
		    dev->mem_start = 0;
		    ei_status.name = "3c503-PIO";
		    iounmap(mem_base);
		    ei_status.mem = NULL;
		    break;
		}
		test_val += 0x55555555;
		writel(0, mem_base + i);
	    }
	}
#endif  /* EL2MEMTEST */

	if (dev->mem_start)
		dev->mem_end = dev->mem_start + EL2_MEMSIZE;

	if (wordlength) {	/* No Tx pages to skip over to get to Rx */
		ei_status.priv = 0;
		ei_status.name = "3c503/16";
	} else {
		ei_status.priv = TX_PAGES * 256;
		ei_status.name = "3c503";
	}
    }

    /*
	Divide up the memory on the card. This is the same regardless of
	whether shared-mem or PIO is used. For 16 bit cards (16kB RAM),
	we use the entire 8k of bank1 for an Rx ring. We only use 3k
	of the bank0 for 2 full size Tx packet slots. For 8 bit cards,
	(8kB RAM) we use 3kB of bank1 for two Tx slots, and the remaining
	5kB for an Rx ring.  */

    if (wordlength) {
	ei_status.tx_start_page = EL2_MB0_START_PG;
	ei_status.rx_start_page = EL2_MB1_START_PG;
    } else {
	ei_status.tx_start_page = EL2_MB1_START_PG;
	ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
    }

    /* Finish setting the board's parameters. */
    ei_status.stop_page = EL2_MB1_STOP_PG;
    ei_status.word16 = wordlength;
    ei_status.reset_8390 = &el2_reset_8390;
    ei_status.get_8390_hdr = &el2_get_8390_hdr;
    ei_status.block_input = &el2_block_input;
    ei_status.block_output = &el2_block_output;

    if (dev->irq == 2)
	dev->irq = 9;
    else if (dev->irq > 5 && dev->irq != 9) {
	printk("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
	       dev->irq);
	dev->irq = 0;
    }

    ei_status.saved_irq = dev->irq;

    dev->netdev_ops = &el2_netdev_ops;
    dev->ethtool_ops = &netdev_ethtool_ops;
#ifdef CONFIG_NET_POLL_CONTROLLER
    dev->poll_controller = eip_poll;
#endif

    retval = register_netdev(dev);
    if (retval)
	goto out1;

    if (dev->mem_start)
	printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
		dev->name, ei_status.name, (wordlength+1)<<3,
		dev->mem_start, dev->mem_end-1);

    else
    {
	ei_status.tx_start_page = EL2_MB1_START_PG;
	ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
	printk("\n%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
	       dev->name, ei_status.name, (wordlength+1)<<3);
    }
    release_region(ioaddr + 0x400, 8);
    return 0;
out1:
    release_region(ioaddr + 0x400, 8);
out:
    release_region(ioaddr, EL2_IO_EXTENT);
    return retval;
}
コード例 #25
0
ファイル: au1x00_uart.c プロジェクト: gnensis/linux-2.6.15
static int serial8250_startup(struct uart_port *port)
{
	struct uart_8250_port *up = (struct uart_8250_port *)port;
	unsigned long flags;
	int retval;

	/*
	 * Clear the FIFO buffers and disable them.
	 * (they will be reeanbled in set_termios())
	 */
	if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
		serial_outp(up, UART_FCR, 0);
	}

	/*
	 * Clear the interrupt registers.
	 */
	(void) serial_inp(up, UART_LSR);
	(void) serial_inp(up, UART_RX);
	(void) serial_inp(up, UART_IIR);
	(void) serial_inp(up, UART_MSR);

	/*
	 * At this point, there's no way the LSR could still be 0xff;
	 * if it is, then bail out, because there's likely no UART
	 * here.
	 */
	if (!(up->port.flags & UPF_BUGGY_UART) &&
	    (serial_inp(up, UART_LSR) == 0xff)) {
		printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
		return -ENODEV;
	}

	retval = serial_link_irq_chain(up);
		if (retval)
			return retval;

	/*
	 * Now, initialize the UART
	 */
	serial_outp(up, UART_LCR, UART_LCR_WLEN8);

	spin_lock_irqsave(&up->port.lock, flags);
	if (up->port.flags & UPF_FOURPORT) {
		if (!is_real_interrupt(up->port.irq))
			up->port.mctrl |= TIOCM_OUT1;
	} else
		/*
		 * Most PC uarts need OUT2 raised to enable interrupts.
		 */
		if (is_real_interrupt(up->port.irq))
			up->port.mctrl |= TIOCM_OUT2;

	serial8250_set_mctrl(&up->port, up->port.mctrl);
	spin_unlock_irqrestore(&up->port.lock, flags);

	/*
	 * Finally, enable interrupts.  Note: Modem status interrupts
	 * are set via set_termios(), which will be occurring imminently
	 * anyway, so we don't enable them here.
	 */
	up->ier = UART_IER_RLSI | UART_IER_RDI;
	serial_outp(up, UART_IER, up->ier);

	if (up->port.flags & UPF_FOURPORT) {
		unsigned int icp;
		/*
		 * Enable interrupts on the AST Fourport board
		 */
		icp = (up->port.iobase & 0xfe0) | 0x01f;
		outb_p(0x80, icp);
		(void) inb_p(icp);
	}

	/*
	 * And clear the interrupt registers again for luck.
	 */
	(void) serial_inp(up, UART_LSR);
	(void) serial_inp(up, UART_RX);
	(void) serial_inp(up, UART_IIR);
	(void) serial_inp(up, UART_MSR);

	return 0;
}
コード例 #26
0
static int amd756_transaction(struct i2c_adapter *adap)
{
	int temp;
	int result = 0;
	int timeout = 0;

	dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, "
		"DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS),
		inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS),
		inb_p(SMB_HOST_DATA));

	/* Make sure the SMBus host is ready to start transmitting */
	if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) {
		dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp);
		do {
			msleep(1);
			temp = inw_p(SMB_GLOBAL_STATUS);
		} while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
		         (timeout++ < MAX_TIMEOUT));
		/* If the SMBus is still busy, we give up */
		if (timeout >= MAX_TIMEOUT) {
			dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp);
			goto abort;
		}
		timeout = 0;
	}

	/* start the transaction by setting the start bit */
	outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);

	/* We will always wait for a fraction of a second! */
	do {
		msleep(1);
		temp = inw_p(SMB_GLOBAL_STATUS);
	} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));

	/* If the SMBus is still busy, we give up */
	if (timeout >= MAX_TIMEOUT) {
		dev_dbg(&adap->dev, "Completion timeout!\n");
		goto abort;
	}

	if (temp & GS_PRERR_STS) {
		result = -1;
		dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n");
	}

	if (temp & GS_COL_STS) {
		result = -1;
		dev_warn(&adap->dev, "SMBus collision!\n");
	}

	if (temp & GS_TO_STS) {
		result = -1;
		dev_dbg(&adap->dev, "SMBus protocol timeout!\n");
	}

	if (temp & GS_HCYC_STS)
		dev_dbg(&adap->dev, "SMBus protocol success!\n");

	outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);

#ifdef DEBUG
	if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
		dev_dbg(&adap->dev,
			"Failed reset at end of transaction (%04x)\n", temp);
	}
#endif

	dev_dbg(&adap->dev,
		"Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
		inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
		inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));

	return result;

 abort:
	dev_warn(&adap->dev, "Sending abort\n");
	outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
	msleep(100);
	outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
	return -1;
}
コード例 #27
0
ファイル: w83977f_wdt.c プロジェクト: CSCLOG/beaglebone
static int wdt_start(void)
{
	unsigned long flags;

	spin_lock_irqsave(&spinlock, flags);

	/* Unlock the SuperIO chip */
	outb_p(UNLOCK_DATA, IO_INDEX_PORT);
	outb_p(UNLOCK_DATA, IO_INDEX_PORT);

	/*
	 * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
	 * F2 has the timeout in watchdog counter units.
	 * F3 is set to enable watchdog LED blink at timeout.
	 * F4 is used to just clear the TIMEOUT'ed state (bit 0).
	 */
	outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
	outb_p(0x08, IO_DATA_PORT);
	outb_p(0xF2, IO_INDEX_PORT);
	outb_p(timeoutW, IO_DATA_PORT);
	outb_p(0xF3, IO_INDEX_PORT);
	outb_p(0x08, IO_DATA_PORT);
	outb_p(0xF4, IO_INDEX_PORT);
	outb_p(0x00, IO_DATA_PORT);

	/* Set device Aux2 active */
	outb_p(0x30, IO_INDEX_PORT);
	outb_p(0x01, IO_DATA_PORT);

	/*
	 * Select device Aux1 (dev=7) to set GP16 as the watchdog output
	 * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
	 * Map GP16 at pin 119.
	 * In test mode watch the bit 0 on F4 to indicate "triggered" or
	 * check watchdog LED on SBC.
	 */
	outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
	outb_p(0x07, IO_DATA_PORT);
	if (!testmode) {
		unsigned pin_map;

		outb_p(0xE6, IO_INDEX_PORT);
		outb_p(0x0A, IO_DATA_PORT);
		outb_p(0x2C, IO_INDEX_PORT);
		pin_map = inb_p(IO_DATA_PORT);
		pin_map |= 0x10;
		pin_map &= ~(0x20);
		outb_p(0x2C, IO_INDEX_PORT);
		outb_p(pin_map, IO_DATA_PORT);
	}
	outb_p(0xE3, IO_INDEX_PORT);
	outb_p(0x08, IO_DATA_PORT);

	/* Set device Aux1 active */
	outb_p(0x30, IO_INDEX_PORT);
	outb_p(0x01, IO_DATA_PORT);

	/* Lock the SuperIO chip */
	outb_p(LOCK_DATA, IO_INDEX_PORT);

	spin_unlock_irqrestore(&spinlock, flags);

	printk(KERN_INFO PFX "activated.\n");

	return 0;
}
コード例 #28
0
/* Return -1 on error. */
static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
		  unsigned short flags, char read_write,
		  u8 command, int size, union i2c_smbus_data * data)
{
	int i, len;

	/** TODO: Should I supporte the 10-bit transfers? */
	switch (size) {
	case I2C_SMBUS_PROC_CALL:
		dev_dbg(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
		/* TODO: Well... It is supported, I'm just not sure what to do here... */
		return -1;
	case I2C_SMBUS_QUICK:
		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMB_HOST_ADDRESS);
		size = AMD756_QUICK;
		break;
	case I2C_SMBUS_BYTE:
		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMB_HOST_ADDRESS);
		if (read_write == I2C_SMBUS_WRITE)
			outb_p(command, SMB_HOST_DATA);
		size = AMD756_BYTE;
		break;
	case I2C_SMBUS_BYTE_DATA:
		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMB_HOST_ADDRESS);
		outb_p(command, SMB_HOST_COMMAND);
		if (read_write == I2C_SMBUS_WRITE)
			outw_p(data->byte, SMB_HOST_DATA);
		size = AMD756_BYTE_DATA;
		break;
	case I2C_SMBUS_WORD_DATA:
		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMB_HOST_ADDRESS);
		outb_p(command, SMB_HOST_COMMAND);
		if (read_write == I2C_SMBUS_WRITE)
			outw_p(data->word, SMB_HOST_DATA);	/* TODO: endian???? */
		size = AMD756_WORD_DATA;
		break;
	case I2C_SMBUS_BLOCK_DATA:
		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMB_HOST_ADDRESS);
		outb_p(command, SMB_HOST_COMMAND);
		if (read_write == I2C_SMBUS_WRITE) {
			len = data->block[0];
			if (len < 0)
				len = 0;
			if (len > 32)
				len = 32;
			outw_p(len, SMB_HOST_DATA);
			/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
			for (i = 1; i <= len; i++)
				outb_p(data->block[i],
				       SMB_HOST_BLOCK_DATA);
		}
		size = AMD756_BLOCK_DATA;
		break;
	}

	/* How about enabling interrupts... */
	outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);

	if (amd756_transaction(adap))	/* Error in transaction */
		return -1;

	if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
		return 0;


	switch (size) {
	case AMD756_BYTE:
		data->byte = inw_p(SMB_HOST_DATA);
		break;
	case AMD756_BYTE_DATA:
		data->byte = inw_p(SMB_HOST_DATA);
		break;
	case AMD756_WORD_DATA:
		data->word = inw_p(SMB_HOST_DATA);	/* TODO: endian???? */
		break;
	case AMD756_BLOCK_DATA:
		data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f;
		if(data->block[0] > 32)
			data->block[0] = 32;
		/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
		for (i = 1; i <= data->block[0]; i++)
			data->block[i] = inb_p(SMB_HOST_BLOCK_DATA);
		break;
	}

	return 0;
}
コード例 #29
0
static u8 get_cmd640_reg_vlb(u16 reg)
{
	outb_p(reg, cmd640_key);
	return inb_p(cmd640_key + 4);
}
コード例 #30
0
/* Return negative errno on error. */
static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
			  unsigned short flags, char read_write, u8 command,
			  int size, union i2c_smbus_data *data)
{
	int i, len;
	int temp;
	int timeout;
	s32 result = 0;

	/* make sure SMBus is idle */
	temp = inb_p(SMBHSTSTS);
	for (timeout = 0;
	     (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE);
	     timeout++) {
		usleep_range(1000, 2000);
		temp = inb_p(SMBHSTSTS);
	}
	if (timeout >= MAX_TIMEOUT)
		dev_warn(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp);

	/* clear status register (clear-on-write) */
	outb_p(0xFF, SMBHSTSTS);

	switch (size) {
	case I2C_SMBUS_QUICK:
		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMBHSTADD);
		size = ALI1535_QUICK;
		outb_p(size, SMBHSTTYP);	/* output command */
		break;
	case I2C_SMBUS_BYTE:
		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMBHSTADD);
		size = ALI1535_BYTE;
		outb_p(size, SMBHSTTYP);	/* output command */
		if (read_write == I2C_SMBUS_WRITE)
			outb_p(command, SMBHSTCMD);
		break;
	case I2C_SMBUS_BYTE_DATA:
		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMBHSTADD);
		size = ALI1535_BYTE_DATA;
		outb_p(size, SMBHSTTYP);	/* output command */
		outb_p(command, SMBHSTCMD);
		if (read_write == I2C_SMBUS_WRITE)
			outb_p(data->byte, SMBHSTDAT0);
		break;
	case I2C_SMBUS_WORD_DATA:
		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMBHSTADD);
		size = ALI1535_WORD_DATA;
		outb_p(size, SMBHSTTYP);	/* output command */
		outb_p(command, SMBHSTCMD);
		if (read_write == I2C_SMBUS_WRITE) {
			outb_p(data->word & 0xff, SMBHSTDAT0);
			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
		}
		break;
	case I2C_SMBUS_BLOCK_DATA:
		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
		       SMBHSTADD);
		size = ALI1535_BLOCK_DATA;
		outb_p(size, SMBHSTTYP);	/* output command */
		outb_p(command, SMBHSTCMD);
		if (read_write == I2C_SMBUS_WRITE) {
			len = data->block[0];
			if (len < 0) {
				len = 0;
				data->block[0] = len;
			}
			if (len > 32) {
				len = 32;
				data->block[0] = len;
			}
			outb_p(len, SMBHSTDAT0);
			/* Reset SMBBLKDAT */
			outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP);
			for (i = 1; i <= len; i++)
				outb_p(data->block[i], SMBBLKDAT);
		}
		break;
	default:
		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
		result = -EOPNOTSUPP;
		goto EXIT;
	}