📄 pc87360.c
字号:
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 + -