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

📄 pc87360.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
static ssize_t show_temp##offset##_status(struct device *dev, char *buf) \{ \	struct pc87360_data *data = pc87360_update_device(dev); \	return sprintf(buf, "%u\n", data->in_status[offset+7]); \} \static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \	size_t count) \{ \	struct i2c_client *client = to_i2c_client(dev); \	struct pc87360_data *data = i2c_get_clientdata(client); \	long val = simple_strtol(buf, NULL, 10); \	data->in_min[offset+7] = IN_TO_REG(val, data->in_vref); \	pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MIN, \			    data->in_min[offset+7]); \	return count; \} \static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \	size_t count) \{ \	struct i2c_client *client = to_i2c_client(dev); \	struct pc87360_data *data = i2c_get_clientdata(client); \	long val = simple_strtol(buf, NULL, 10); \	data->in_max[offset+7] = IN_TO_REG(val, data->in_vref); \	pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MAX, \			    data->in_max[offset+7]); \	return count; \} \static ssize_t set_temp##offset##_crit(struct device *dev, const char *buf, \	size_t count) \{ \	struct i2c_client *client = to_i2c_client(dev); \	struct pc87360_data *data = i2c_get_clientdata(client); \	long val = simple_strtol(buf, NULL, 10); \	data->in_crit[offset-4] = IN_TO_REG(val, data->in_vref); \	pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_CRIT, \			    data->in_crit[offset-4]); \	return count; \} \static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \	show_temp##offset##_input, NULL); \static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \	show_temp##offset##_min, set_temp##offset##_min); \static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \	show_temp##offset##_max, set_temp##offset##_max); \static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \	show_temp##offset##_crit, set_temp##offset##_crit); \static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \	show_temp##offset##_status, NULL);show_and_set_therm(4)show_and_set_therm(5)show_and_set_therm(6)static ssize_t show_vid(struct device *dev, char *buf){	struct pc87360_data *data = pc87360_update_device(dev);	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));}static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);static ssize_t show_vrm(struct device *dev, char *buf){	struct pc87360_data *data = pc87360_update_device(dev);	return sprintf(buf, "%u\n", data->vrm);}static ssize_t set_vrm(struct device *dev, const char *buf, size_t count){	struct i2c_client *client = to_i2c_client(dev);	struct pc87360_data *data = i2c_get_clientdata(client);	data->vrm = simple_strtoul(buf, NULL, 10);	return count;}static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);static ssize_t show_in_alarms(struct device *dev, char *buf){	struct pc87360_data *data = pc87360_update_device(dev);	return sprintf(buf, "%u\n", data->in_alarms);}static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);#define show_and_set_temp(offset) \static ssize_t show_temp##offset##_input(struct device *dev, char *buf) \{ \	struct pc87360_data *data = pc87360_update_device(dev); \	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \} \static ssize_t show_temp##offset##_min(struct device *dev, char *buf) \{ \	struct pc87360_data *data = pc87360_update_device(dev); \	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \} \static ssize_t show_temp##offset##_max(struct device *dev, char *buf) \{ \	struct pc87360_data *data = pc87360_update_device(dev); \	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \}\static ssize_t show_temp##offset##_crit(struct device *dev, char *buf) \{ \	struct pc87360_data *data = pc87360_update_device(dev); \	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[offset-1])); \}\static ssize_t show_temp##offset##_status(struct device *dev, char *buf) \{ \	struct pc87360_data *data = pc87360_update_device(dev); \	return sprintf(buf, "%d\n", data->temp_status[offset-1]); \}\static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \	size_t count) \{ \	struct i2c_client *client = to_i2c_client(dev); \	struct pc87360_data *data = i2c_get_clientdata(client); \	long val = simple_strtol(buf, NULL, 10); \	data->temp_min[offset-1] = TEMP_TO_REG(val); \	pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MIN, \			    data->temp_min[offset-1]); \	return count; \} \static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \	size_t count) \{ \	struct i2c_client *client = to_i2c_client(dev); \	struct pc87360_data *data = i2c_get_clientdata(client); \	long val = simple_strtol(buf, NULL, 10); \	data->temp_max[offset-1] = TEMP_TO_REG(val); \	pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MAX, \			    data->temp_max[offset-1]); \	return count; \} \static ssize_t set_temp##offset##_crit(struct device *dev, const char *buf, \	size_t count) \{ \	struct i2c_client *client = to_i2c_client(dev); \	struct pc87360_data *data = i2c_get_clientdata(client); \	long val = simple_strtol(buf, NULL, 10); \	data->temp_crit[offset-1] = TEMP_TO_REG(val); \	pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_CRIT, \			    data->temp_crit[offset-1]); \	return count; \} \static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \	show_temp##offset##_input, NULL); \static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \	show_temp##offset##_min, set_temp##offset##_min); \static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \	show_temp##offset##_max, set_temp##offset##_max); \static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \	show_temp##offset##_crit, set_temp##offset##_crit); \static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \	show_temp##offset##_status, NULL);show_and_set_temp(1)show_and_set_temp(2)show_and_set_temp(3)static ssize_t show_temp_alarms(struct device *dev, char *buf){	struct pc87360_data *data = pc87360_update_device(dev);	return sprintf(buf, "%u\n", data->temp_alarms);}static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);/* * Device detection, registration and update */static int pc87360_attach_adapter(struct i2c_adapter *adapter){	return i2c_detect(adapter, &addr_data, pc87360_detect);}static int pc87360_find(int sioaddr, u8 *devid, int *address){	u16 val;	int i;	int nrdev; /* logical device count */	/* No superio_enter */	/* Identify device */	val = superio_inb(sioaddr, DEVID);	switch (val) {	case 0xE1: /* PC87360 */	case 0xE8: /* PC87363 */	case 0xE4: /* PC87364 */		nrdev = 1;		break;	case 0xE5: /* PC87365 */	case 0xE9: /* PC87366 */		nrdev = 3;		break;	default:		superio_exit(sioaddr);		return -ENODEV;	}	/* Remember the device id */	*devid = val;	for (i = 0; i < nrdev; i++) {		/* select logical device */		superio_outb(sioaddr, DEV, logdev[i]);		val = superio_inb(sioaddr, ACT);		if (!(val & 0x01)) {			printk(KERN_INFO "pc87360: Device 0x%02x not "			       "activated\n", logdev[i]);			continue;		}		val = (superio_inb(sioaddr, BASE) << 8)		    | superio_inb(sioaddr, BASE + 1);		if (!val) {			printk(KERN_INFO "pc87360: Base address not set for "			       "device 0x%02x\n", logdev[i]);			continue;		}		address[i] = val;		if (i==0) { /* Fans */			confreg[0] = superio_inb(sioaddr, 0xF0);			confreg[1] = superio_inb(sioaddr, 0xF1);#ifdef DEBUG			printk(KERN_DEBUG "pc87360: Fan 1: mon=%d "			       "ctrl=%d inv=%d\n", (confreg[0]>>2)&1,			       (confreg[0]>>3)&1, (confreg[0]>>4)&1);			printk(KERN_DEBUG "pc87360: Fan 2: mon=%d "			       "ctrl=%d inv=%d\n", (confreg[0]>>5)&1,			       (confreg[0]>>6)&1, (confreg[0]>>7)&1);			printk(KERN_DEBUG "pc87360: Fan 3: mon=%d "			       "ctrl=%d inv=%d\n", confreg[1]&1,			       (confreg[1]>>1)&1, (confreg[1]>>2)&1);#endif		} else if (i==1) { /* Voltages */			/* Are we using thermistors? */			if (*devid == 0xE9) { /* PC87366 */				/* These registers are not logical-device				   specific, just that we won't need them if				   we don't use the VLM device */				confreg[2] = superio_inb(sioaddr, 0x2B);				confreg[3] = superio_inb(sioaddr, 0x25);				if (confreg[2] & 0x40) {					printk(KERN_INFO "pc87360: Using "					       "thermistors for temperature "					       "monitoring\n");				}				if (confreg[3] & 0xE0) {					printk(KERN_INFO "pc87360: VID "					       "inputs routed (mode %u)\n",					       confreg[3] >> 5);				}			}		}	}	superio_exit(sioaddr);	return 0;}/* We don't really care about the address.   Read from extra_isa instead. */int pc87360_detect(struct i2c_adapter *adapter, int address, int kind){	int i;	struct i2c_client *new_client;	struct pc87360_data *data;	int err = 0;	const char *name = "pc87360";	int use_thermistors = 0;	if (!i2c_is_isa_adapter(adapter))		return -ENODEV;	if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))		return -ENOMEM;	memset(data, 0x00, sizeof(struct pc87360_data));	new_client = &data->client;	i2c_set_clientdata(new_client, data);	new_client->addr = address;	init_MUTEX(&data->lock);	new_client->adapter = adapter;	new_client->driver = &pc87360_driver;	new_client->flags = 0;	data->fannr = 2;	data->innr = 0;	data->tempnr = 0;	switch (devid) {	case 0xe8:		name = "pc87363";		break;	case 0xe4:		name = "pc87364";		data->fannr = 3;		break;	case 0xe5:		name = "pc87365";		data->fannr = extra_isa[0] ? 3 : 0;		data->innr = extra_isa[1] ? 11 : 0;		data->tempnr = extra_isa[2] ? 2 : 0;		break;	case 0xe9:		name = "pc87366";		data->fannr = extra_isa[0] ? 3 : 0;		data->innr = extra_isa[1] ? 14 : 0;		data->tempnr = extra_isa[2] ? 3 : 0;		break;	}	strcpy(new_client->name, name);	data->valid = 0;	init_MUTEX(&data->update_lock);	for (i = 0; i < 3; i++) {		if (((data->address[i] = extra_isa[i]))		 && !request_region(extra_isa[i], PC87360_EXTENT,		 		    pc87360_driver.name)) {			dev_err(&new_client->dev, "Region 0x%x-0x%x already "				"in use!\n", extra_isa[i],				extra_isa[i]+PC87360_EXTENT-1);			for (i--; i >= 0; i--)				release_region(extra_isa[i], PC87360_EXTENT);			err = -EBUSY;			goto ERROR1;		}	}	/* Retrieve the fans configuration from Super-I/O space */	if (data->fannr)		data->fan_conf = confreg[0] | (confreg[1] << 8);	if ((err = i2c_attach_client(new_client)))		goto ERROR2;	/* Use the correct reference voltage	   Unless both the VLM and the TMS logical devices agree to	   use an external Vref, the internal one is used. */	if (data->innr) {		i = pc87360_read_value(data, LD_IN, NO_BANK,				       PC87365_REG_IN_CONFIG);		if (data->tempnr) {			i &= pc87360_read_value(data, LD_TEMP, NO_BANK,						PC87365_REG_TEMP_CONFIG);		}		data->in_vref = (i&0x02) ? 3025 : 2966;		dev_dbg(&new_client->dev, "Using %s reference voltage\n",			(i&0x02) ? "external" : "internal");		data->vid_conf = confreg[3];		data->vrm = 90;	}	/* Fan clock dividers may be needed before any data is read */	for (i = 0; i < data->fannr; i++) {		if (FAN_CONFIG_MONITOR(data->fan_conf, i))			data->fan_status[i] = pc87360_read_value(data,					      LD_FAN, NO_BANK,					      PC87360_REG_FAN_STATUS(i));	}	if (init > 0) {		if (devid == 0xe9 && data->address[1]) /* PC87366 */			use_thermistors = confreg[2] & 0x40;		pc87360_init_client(new_client, use_thermistors);	}	/* Register sysfs hooks */	if (data->innr) {		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_in5_input);		device_create_file(&new_client->dev, &dev_attr_in6_input);		device_create_file(&new_client->dev, &dev_attr_in7_input);		device_create_file(&new_client->dev, &dev_attr_in8_input);		device_create_file(&new_client->dev, &dev_attr_in9_input);		device_create_file(&new_client->dev, &dev_attr_in10_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_in5_min);		device_create_file(&new_client->dev, &dev_attr_in6_min);		device_create_file(&new_client->dev, &dev_attr_in7_min);		device_create_file(&new_client->dev, &dev_attr_in8_min);		device_create_file(&new_client->dev, &dev_attr_in9_min);		device_create_file(&new_client->dev, &dev_attr_in10_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_in5_max);		device_create_file(&new_client->dev, &dev_attr_in6_max);		device_create_file(&new_client->dev, &dev_attr_in7_max);		device_create_file(&new_client->dev, &dev_attr_in8_max);		device_create_file(&new_client->dev, &dev_attr_in9_max);		device_create_file(&new_client->dev, &dev_attr_in10_max);		device_create_file(&new_client->dev, &dev_attr_in0_status);		device_create_file(&new_client->dev, &dev_attr_in1_status);		device_create_file(&new_client->dev, &dev_attr_in2_status);		device_create_file(&new_client->dev, &dev_attr_in3_status);		device_create_file(&new_client->dev, &dev_attr_in4_status);		device_create_file(&new_client->dev, &dev_attr_in5_status);		device_create_file(&new_client->dev, &dev_attr_in6_status);		device_create_file(&new_client->dev, &dev_attr_in7_status);		device_create_file(&new_client->dev, &dev_attr_in8_status);		device_create_file(&new_client->dev, &dev_attr_in9_status);		device_create_file(&new_client->dev, &dev_attr_in10_status);		device_create_file(&new_client->dev, &dev_attr_cpu0_vid);		device_create_file(&new_client->dev, &dev_attr_vrm);		device_create_file(&new_client->dev, &dev_attr_alarms_in);	}	if (data->tempnr) {		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_temp1_min);		device_create_file(&new_client->dev, &dev_attr_temp2_min);		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_temp1_crit);		device_create_file(&new_client->dev, &dev_attr_temp2_crit);		device_create_file(&new_client->dev, &dev_attr_temp1_status);		device_create_file(&new_client->dev, &dev_attr_temp2_status);		device_create_file(&new_client->dev, &dev_attr_alarms_temp);	}	if (data->tempnr == 3) {		device_create_file(&new_client->dev, &dev_attr_temp3_input);		device_create_file(&new_client->dev, &dev_attr_temp3_min);		device_create_file(&new_client->dev, &dev_attr_temp3_max);		device_create_file(&new_client->dev, &dev_attr_temp3_crit);		device_create_file(&new_client->dev, &dev_attr_temp3_status);

⌨️ 快捷键说明

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