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

📄 via686a.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* This is called when the module is loaded */static int via686a_attach_adapter(struct i2c_adapter *adapter){	if (!(adapter->class & I2C_CLASS_HWMON))		return 0;	return i2c_detect(adapter, &addr_data, via686a_detect);}static int via686a_detect(struct i2c_adapter *adapter, int address, int kind){	struct i2c_client *new_client;	struct via686a_data *data;	int err = 0;	const char client_name[] = "via686a";	u16 val;	/* Make sure we are probing the ISA bus!!  */	if (!i2c_is_isa_adapter(adapter)) {		dev_err(&adapter->dev,		"via686a_detect called for an I2C bus adapter?!?\n");		return 0;	}	/* 8231 requires multiple of 256, we enforce that on 686 as well */	if(force_addr)		address = force_addr & 0xFF00;	if(force_addr) {		dev_warn(&adapter->dev,"forcing ISA address 0x%04X\n", address);		if (PCIBIOS_SUCCESSFUL !=		    pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))			return -ENODEV;	}	if (PCIBIOS_SUCCESSFUL !=	    pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))		return -ENODEV;	if (!(val & 0x0001)) {		dev_warn(&adapter->dev,"enabling sensors\n");		if (PCIBIOS_SUCCESSFUL !=		    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,		                      val | 0x0001))			return -ENODEV;	}	/* Reserve the ISA region */	if (!request_region(address, VIA686A_EXTENT, "via686a-sensor")) {		dev_err(&adapter->dev,"region 0x%x already in use!\n",		       address);		return -ENODEV;	}	if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {		err = -ENOMEM;		goto ERROR0;	}	memset(data, 0, sizeof(struct via686a_data));	new_client = &data->client;	i2c_set_clientdata(new_client, data);	new_client->addr = address;	new_client->adapter = adapter;	new_client->driver = &via686a_driver;	new_client->flags = 0;	new_client->dev.parent = &adapter->dev;	/* Fill in the remaining client fields and put into the global list */	snprintf(new_client->name, I2C_NAME_SIZE, client_name);	data->valid = 0;	init_MUTEX(&data->update_lock);	/* Tell the I2C layer a new client has arrived */	if ((err = i2c_attach_client(new_client)))		goto ERROR3;		/* Initialize the VIA686A chip */	via686a_init_client(new_client);	/* Register sysfs hooks */	device_create_file(&new_client->dev, &dev_attr_in0_input);	device_create_file(&new_client->dev, &dev_attr_in1_input);	device_create_file(&new_client->dev, &dev_attr_in2_input);	device_create_file(&new_client->dev, &dev_attr_in3_input);	device_create_file(&new_client->dev, &dev_attr_in4_input);	device_create_file(&new_client->dev, &dev_attr_in0_min);	device_create_file(&new_client->dev, &dev_attr_in1_min);	device_create_file(&new_client->dev, &dev_attr_in2_min);	device_create_file(&new_client->dev, &dev_attr_in3_min);	device_create_file(&new_client->dev, &dev_attr_in4_min);	device_create_file(&new_client->dev, &dev_attr_in0_max);	device_create_file(&new_client->dev, &dev_attr_in1_max);	device_create_file(&new_client->dev, &dev_attr_in2_max);	device_create_file(&new_client->dev, &dev_attr_in3_max);	device_create_file(&new_client->dev, &dev_attr_in4_max);	device_create_file(&new_client->dev, &dev_attr_temp1_input);	device_create_file(&new_client->dev, &dev_attr_temp2_input);	device_create_file(&new_client->dev, &dev_attr_temp3_input);	device_create_file(&new_client->dev, &dev_attr_temp1_max);	device_create_file(&new_client->dev, &dev_attr_temp2_max);	device_create_file(&new_client->dev, &dev_attr_temp3_max);	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);	device_create_file(&new_client->dev, &dev_attr_temp2_max_hyst);	device_create_file(&new_client->dev, &dev_attr_temp3_max_hyst);	device_create_file(&new_client->dev, &dev_attr_fan1_input);	device_create_file(&new_client->dev, &dev_attr_fan2_input);	device_create_file(&new_client->dev, &dev_attr_fan1_min);	device_create_file(&new_client->dev, &dev_attr_fan2_min);	device_create_file(&new_client->dev, &dev_attr_fan1_div);	device_create_file(&new_client->dev, &dev_attr_fan2_div);	device_create_file(&new_client->dev, &dev_attr_alarms);	return 0;      ERROR3:	kfree(data);      ERROR0:	release_region(address, VIA686A_EXTENT);	return err;}static int via686a_detach_client(struct i2c_client *client){	int err;	if ((err = i2c_detach_client(client))) {		dev_err(&client->dev,		"Client deregistration failed, client not detached.\n");		return err;	}	release_region(client->addr, VIA686A_EXTENT);	kfree(i2c_get_clientdata(client));	return 0;}/* Called when we have found a new VIA686A. Set limits, etc. */static void via686a_init_client(struct i2c_client *client){	u8 reg;	/* Start monitoring */	reg = via686a_read_value(client, VIA686A_REG_CONFIG);	via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);	/* Configure temp interrupt mode for continuous-interrupt operation */	via686a_write_value(client, VIA686A_REG_TEMP_MODE, 			    via686a_read_value(client, VIA686A_REG_TEMP_MODE) &			    !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));}static struct via686a_data *via686a_update_device(struct device *dev){	struct i2c_client *client = to_i2c_client(dev);	struct via686a_data *data = i2c_get_clientdata(client);	int i;	down(&data->update_lock);       if ((jiffies - data->last_updated > HZ + HZ / 2) ||           (jiffies < data->last_updated) || !data->valid) {		for (i = 0; i <= 4; i++) {			data->in[i] =			    via686a_read_value(client, VIA686A_REG_IN(i));			data->in_min[i] = via686a_read_value(client,							     VIA686A_REG_IN_MIN							     (i));			data->in_max[i] =			    via686a_read_value(client, VIA686A_REG_IN_MAX(i));		}		for (i = 1; i <= 2; i++) {			data->fan[i - 1] =			    via686a_read_value(client, VIA686A_REG_FAN(i));			data->fan_min[i - 1] = via686a_read_value(client,						     VIA686A_REG_FAN_MIN(i));		}		for (i = 0; i <= 2; i++) {			data->temp[i] = via686a_read_value(client,						 VIA686A_REG_TEMP(i)) << 2;			data->temp_over[i] =			    via686a_read_value(client,					       VIA686A_REG_TEMP_OVER(i));			data->temp_hyst[i] =			    via686a_read_value(client,					       VIA686A_REG_TEMP_HYST(i));		}		/* add in lower 2 bits 		   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1		   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23		   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23		 */		data->temp[0] |= (via686a_read_value(client,						     VIA686A_REG_TEMP_LOW1)				  & 0xc0) >> 6;		data->temp[1] |=		    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &		     0x30) >> 4;		data->temp[2] |=		    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &		     0xc0) >> 6;		i = via686a_read_value(client, VIA686A_REG_FANDIV);		data->fan_div[0] = (i >> 4) & 0x03;		data->fan_div[1] = i >> 6;		data->alarms =		    via686a_read_value(client,				       VIA686A_REG_ALARM1) |		    (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);		data->last_updated = jiffies;		data->valid = 1;	}	up(&data->update_lock);	return data;}static struct pci_device_id via686a_pci_ids[] = {       {	       .vendor 		= PCI_VENDOR_ID_VIA, 	       .device 		= PCI_DEVICE_ID_VIA_82C686_4, 	       .subvendor	= PCI_ANY_ID, 	       .subdevice	= PCI_ANY_ID,        },       { 0, }};static int __devinit via686a_pci_probe(struct pci_dev *dev,                                      const struct pci_device_id *id){       u16 val;       int addr = 0;       if (PCIBIOS_SUCCESSFUL !=           pci_read_config_word(dev, VIA686A_BASE_REG, &val))               return -ENODEV;       addr = val & ~(VIA686A_EXTENT - 1);       if (addr == 0 && force_addr == 0) {               dev_err(&dev->dev,"base address not set - upgrade BIOS or use force_addr=0xaddr\n");               return -ENODEV;       }       if (force_addr)               addr = force_addr;      /* so detect will get called */       if (!addr) {               dev_err(&dev->dev,"No Via 686A sensors found.\n");               return -ENODEV;       }       normal_isa[0] = addr;       s_bridge = dev;       return i2c_add_driver(&via686a_driver);}static void __devexit via686a_pci_remove(struct pci_dev *dev){       i2c_del_driver(&via686a_driver);}static struct pci_driver via686a_pci_driver = {       .name		= "via686a",       .id_table	= via686a_pci_ids,       .probe		= via686a_pci_probe,       .remove		= __devexit_p(via686a_pci_remove),};static int __init sm_via686a_init(void){       return pci_module_init(&via686a_pci_driver);}static void __exit sm_via686a_exit(void){       pci_unregister_driver(&via686a_pci_driver);}MODULE_AUTHOR("Ky鰏ti M鋖kki <kmalkki@cc.hut.fi>, "              "Mark Studebaker <mdsxyz123@yahoo.com> "             "and Bob Dougherty <bobd@stanford.edu>");MODULE_DESCRIPTION("VIA 686A Sensor device");MODULE_LICENSE("GPL");module_init(sm_via686a_init);module_exit(sm_via686a_exit);

⌨️ 快捷键说明

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