⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c-i801.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);		dev_dbg(&I801_dev->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->dev, "SMBus busy (%02x). "				"Resetting...\n", temp);			outb_p(temp, SMBHSTSTS);			if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {				dev_err(&I801_dev->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);			msleep(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->dev, "SMBus Timeout!\n");		}		if (temp & 0x10) {			result = -1;			dev_dbg(&I801_dev->dev,				"Error: Failed bus transaction\n");		} else if (temp & 0x08) {			result = -1;			dev_err(&I801_dev->dev, "Bus collision!\n");		} else if (temp & 0x04) {			result = -1;			dev_dbg(&I801_dev->dev, "Error: no response!\n");		}		if (i == 1 && read_write == I2C_SMBUS_READ) {			len = inb_p(SMBHSTDAT0);			if (len < 1)				len = 1;			if (len > 32)				len = 32;			data->block[0] = len;		}		/* 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->dev,				"Bad status (%02x) at end of transaction\n",				temp);		}		dev_dbg(&I801_dev->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);			msleep(1);		} while ((!(temp & 0x02))			   && (timeout++ < MAX_TIMEOUT));		if (timeout >= MAX_TIMEOUT) {			dev_dbg(&I801_dev->dev, "PEC Timeout!\n");		}		outb_p(temp, SMBHSTSTS); 	}	result = 0;END:	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {		/* restore saved configuration register value */		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);	}	return result;}/* Return -1 on error. */static s32 i801_access(struct i2c_adapter * adap, u16 addr,		       unsigned short flags, char read_write, u8 command,		       int size, union i2c_smbus_data * data){	int hwpec;	int block = 0;	int ret, xact = 0;	hwpec = isich4 && (flags & I2C_CLIENT_PEC)		&& size != I2C_SMBUS_QUICK		&& size != I2C_SMBUS_I2C_BLOCK_DATA;	switch (size) {	case I2C_SMBUS_QUICK:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		xact = I801_QUICK;		break;	case I2C_SMBUS_BYTE:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		if (read_write == I2C_SMBUS_WRITE)			outb_p(command, SMBHSTCMD);		xact = I801_BYTE;		break;	case I2C_SMBUS_BYTE_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		outb_p(command, SMBHSTCMD);		if (read_write == I2C_SMBUS_WRITE)			outb_p(data->byte, SMBHSTDAT0);		xact = I801_BYTE_DATA;		break;	case I2C_SMBUS_WORD_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		outb_p(command, SMBHSTCMD);		if (read_write == I2C_SMBUS_WRITE) {			outb_p(data->word & 0xff, SMBHSTDAT0);			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);		}		xact = I801_WORD_DATA;		break;	case I2C_SMBUS_BLOCK_DATA:	case I2C_SMBUS_I2C_BLOCK_DATA:		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),		       SMBHSTADD);		outb_p(command, SMBHSTCMD);		block = 1;		break;	case I2C_SMBUS_PROC_CALL:	default:		dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);		return -1;	}	if (hwpec)		outb_p(1, SMBAUXCTL);	/* enable hardware PEC */	if(block)		ret = i801_block_transaction(data, read_write, size, hwpec);	else {		outb_p(xact | ENABLE_INT9, SMBHSTCNT);		ret = i801_transaction();	}	if (hwpec)		outb_p(0, SMBAUXCTL);	/* disable hardware PEC */	if(block)		return ret;	if(ret)		return -1;	if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))		return 0;	switch (xact & 0x7f) {	case I801_BYTE:	/* Result put in SMBHSTDAT0 */	case I801_BYTE_DATA:		data->byte = inb_p(SMBHSTDAT0);		break;	case I801_WORD_DATA:		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);		break;	}	return 0;}static u32 i801_func(struct i2c_adapter *adapter){	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |	    I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK	     | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);}static struct i2c_algorithm smbus_algorithm = {	.smbus_xfer	= i801_access,	.functionality	= i801_func,};static struct i2c_adapter i801_adapter = {	.owner		= THIS_MODULE,	.class		= I2C_CLASS_HWMON,	.algo		= &smbus_algorithm,};static struct pci_device_id i801_ids[] = {	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },	{ 0, }};MODULE_DEVICE_TABLE (pci, i801_ids);static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id){	if (i801_setup(dev)) {		dev_warn(&dev->dev,			"I801 not detected, module not inserted.\n");		return -ENODEV;	}	/* set up the driverfs linkage to our parent device */	i801_adapter.dev.parent = &dev->dev;	snprintf(i801_adapter.name, I2C_NAME_SIZE,		"SMBus I801 adapter at %04x", i801_smba);	return i2c_add_adapter(&i801_adapter);}static void __devexit i801_remove(struct pci_dev *dev){	i2c_del_adapter(&i801_adapter);	release_region(i801_smba, (isich4 ? 16 : 8));}static struct pci_driver i801_driver = {	.name		= "i801_smbus",	.id_table	= i801_ids,	.probe		= i801_probe,	.remove		= __devexit_p(i801_remove),};static int __init i2c_i801_init(void){	return pci_register_driver(&i801_driver);}static void __exit i2c_i801_exit(void){	pci_unregister_driver(&i801_driver);}MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "		"Philip Edelbrock <phil@netroedge.com>, "		"and Mark D. Studebaker <mdsxyz123@yahoo.com>");MODULE_DESCRIPTION("I801 SMBus driver");MODULE_LICENSE("GPL");module_init(i2c_i801_init);module_exit(i2c_i801_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -