From 40ccaaa658e4868e58d9d9a09ce20f5878447808 Mon Sep 17 00:00:00 2001 From: "Mark D. Studebaker" Date: Sat, 4 Mar 2000 16:14:08 +0000 Subject: [PATCH] (mds) Add via686a integrated sensors support. Untested. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@742 7894878c-1315-0410-8ee3-d5d059ff63e0 --- kernel/chips/Module.mk | 1 + kernel/chips/via686a.c | 728 +++++++++++++++++++++++++++++++++++++++ kernel/include/sensors.h | 26 ++ lib/chips.c | 76 ++++ lib/chips.h | 37 ++ prog/sensors/chips.c | 141 +++++++- prog/sensors/chips.h | 1 + prog/sensors/main.c | 2 + 8 files changed, 1011 insertions(+), 1 deletion(-) create mode 100644 kernel/chips/via686a.c diff --git a/kernel/chips/Module.mk b/kernel/chips/Module.mk index f3d8dc58..832abdfb 100644 --- a/kernel/chips/Module.mk +++ b/kernel/chips/Module.mk @@ -26,6 +26,7 @@ KERNELCHIPSDIR := $(MODULE_DIR) KERNELCHIPSTARGETS := $(MODULE_DIR)/bt869.o $(MODULE_DIR)/gl520sm.o \ $(MODULE_DIR)/matorb.o $(MODULE_DIR)/maxilife.o \ $(MODULE_DIR)/thmc50.o \ + $(MODULE_DIR)/via686a.o \ $(MODULE_DIR)/ddcmon.o ifneq ($(shell if grep -q '^CONFIG_SENSORS_ADM1021=y' $(LINUX)/.config; then echo 1; fi),1) KERNELCHIPSTARGETS += $(MODULE_DIR)/adm1021.o diff --git a/kernel/chips/via686a.c b/kernel/chips/via686a.c new file mode 100644 index 00000000..ca196460 --- /dev/null +++ b/kernel/chips/via686a.c @@ -0,0 +1,728 @@ +/* + via686a.c - Part of lm_sensors, Linux kernel modules + for hardware monitoring + + Copyright (c) 1998, 1999,2000 Frodo Looijaard , + Kyösti Mälkki , + and Mark Studebaker + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "version.h" +#include "i2c-isa.h" +#include "sensors.h" +#include + +#ifndef PCI_DEVICE_ID_VIA_82C686_4 +#define PCI_DEVICE_ID_VIA_82C686_4 0x3057 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)) +#define init_MUTEX(s) do { *(s) = MUTEX; } while(0) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) +#define THIS_MODULE NULL +#endif + +/* Addresses to scan. + Note that we can't determine the ISA address until we have initialized + our module */ +static unsigned short normal_i2c[] = { SENSORS_I2C_END }; +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END }; +static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END }; +static unsigned int normal_isa_range[] = { SENSORS_ISA_END }; + +/* Insmod parameters */ +SENSORS_INSMOD_1(via686a); + +/* + The Via 686a southbridge has a LM78-like chip integrated on the same IC. + This driver is a customized copy of lm78.c +*/ + +/* Many VIA686A constants specified below */ + +/* Length of ISA address segment */ +#define VIA686A_EXTENT 0x80 +#define VIA686A_BASE_REG 0x70 +#define VIA686A_ENABLE_REG 0x74 + +/* The VIA686A registers */ +/* ins numbered 0-4 */ +#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2)) +#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2)) +#define VIA686A_REG_IN(nr) (0x22 + (nr)) + +/* fans numbered 1-2 */ +#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr)) +#define VIA686A_REG_FAN(nr) (0x28 + (nr)) + +static const u8 regtemp[] = {0x20, 0x21, 0x19}; +static const u8 regover[] = {0x39, 0x3d, 0x1d}; +static const u8 reghyst[] = {0x3a, 0x3e, 0x1e}; +/* temps numbered 1-3 */ +#define VIA686A_REG_TEMP(nr) (regtemp[(nr) - 1]) +#define VIA686A_REG_TEMP_OVER(nr) (regover[(nr) - 1]) +#define VIA686A_REG_TEMP_HYST(nr) (reghyst[(nr) - 1]) +#define VIA686A_REG_TEMP_LOW1 0x4b +#define VIA686A_REG_TEMP_LOW23 0x49 + +#define VIA686A_REG_ALARM1 0x41 +#define VIA686A_REG_ALARM2 0x42 +#define VIA686A_REG_FANDIV 0x47 +#define VIA686A_REG_CONFIG 0x40 + +/* Conversions. Rounding and limit checking is only done on the TO_REG + variants. */ + +/************** VOLTAGE CONVERSIONS FIXME *************/ +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255)) +#define IN_FROM_REG(val) (((val) * 16) / 10) + +extern inline u8 FAN_TO_REG(long rpm, int div) +{ + if (rpm == 0) + return 255; + rpm = SENSORS_LIMIT(rpm, 1, 1000000); + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, + 254); +} + +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) + +/********** TEMP CONVERSIONS FIXME ************/ +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\ + ((val)+5)/10),0,255)) +/* for 8-bit temperature hyst and over registers */ +#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10) +/* for 10-bit temperature readings */ +#define TEMP_FROM_REG10(val) (((val)>0x80?(val)-0x100:(val))*10) + +#define ALARMS_FROM_REG(val) (val) + +#define DIV_FROM_REG(val) (1 << (val)) +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) + +/* Initial limits */ +#define VIA686A_INIT_IN_0 200 +#define VIA686A_INIT_IN_1 250 +#define VIA686A_INIT_IN_2 330 +#define VIA686A_INIT_IN_3 (((500) * 100)/168) +#define VIA686A_INIT_IN_4 (((1200) * 10)/38) + +#define VIA686A_INIT_IN_PERCENTAGE 10 + +#define VIA686A_INIT_IN_MIN_0 \ + (VIA686A_INIT_IN_0 - VIA686A_INIT_IN_0 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MAX_0 \ + (VIA686A_INIT_IN_0 + VIA686A_INIT_IN_0 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MIN_1 \ + (VIA686A_INIT_IN_1 - VIA686A_INIT_IN_1 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MAX_1 \ + (VIA686A_INIT_IN_1 + VIA686A_INIT_IN_1 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MIN_2 \ + (VIA686A_INIT_IN_2 - VIA686A_INIT_IN_2 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MAX_2 \ + (VIA686A_INIT_IN_2 + VIA686A_INIT_IN_2 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MIN_3 \ + (VIA686A_INIT_IN_3 - VIA686A_INIT_IN_3 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MAX_3 \ + (VIA686A_INIT_IN_3 + VIA686A_INIT_IN_3 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MIN_4 \ + (VIA686A_INIT_IN_4 - VIA686A_INIT_IN_4 * VIA686A_INIT_IN_PERCENTAGE / 100) +#define VIA686A_INIT_IN_MAX_4 \ + (VIA686A_INIT_IN_4 + VIA686A_INIT_IN_4 * VIA686A_INIT_IN_PERCENTAGE / 100) + +#define VIA686A_INIT_FAN_MIN 3000 + +#define VIA686A_INIT_TEMP_OVER 600 +#define VIA686A_INIT_TEMP_HYST 500 + +#ifdef MODULE +extern int init_module(void); +extern int cleanup_module(void); +#endif /* MODULE */ + +/* This module may seem overly long and complicated. In fact, it is not so + bad. Quite a lot of bookkeeping is done. A real driver can often cut + some corners. */ + +/* For each registered VIA686A, we need to keep some data in memory. That + data is pointed to by via686a_list[NR]->data. The structure itself is + dynamically allocated, at the same time when a new via686a client is + allocated. */ +struct via686a_data { + struct semaphore lock; + int sysctl_id; + + struct semaphore update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + u8 in[5]; /* Register value */ + u8 in_max[5]; /* Register value */ + u8 in_min[5]; /* Register value */ + u8 fan[2]; /* Register value */ + u8 fan_min[2]; /* Register value */ + u16 temp[3]; /* Register value 10 bit */ + u8 temp_over[3]; /* Register value */ + u8 temp_hyst[3]; /* Register value */ + u8 fan_div[2]; /* Register encoding, shifted right */ + u16 alarms; /* Register encoding, combined */ +}; + + +#ifdef MODULE +static +#else +extern +#endif +int __init sensors_via686a_init(void); +static int __init via686a_cleanup(void); + +static int via686a_attach_adapter(struct i2c_adapter *adapter); +static int via686a_detect(struct i2c_adapter *adapter, int address, + unsigned short flags, int kind); +static int via686a_detach_client(struct i2c_client *client); +static int via686a_command(struct i2c_client *client, unsigned int cmd, + void *arg); +static void via686a_inc_use(struct i2c_client *client); +static void via686a_dec_use(struct i2c_client *client); + +static int via686a_read_value(struct i2c_client *client, u8 register); +static void via686a_write_value(struct i2c_client *client, u8 register, + u8 value); +static void via686a_update_client(struct i2c_client *client); +static void via686a_init_client(struct i2c_client *client); +static int via686a_find(int *address); + + +static void via686a_in(struct i2c_client *client, int operation, + int ctl_name, int *nrels_mag, long *results); +static void via686a_fan(struct i2c_client *client, int operation, + int ctl_name, int *nrels_mag, long *results); +static void via686a_temp(struct i2c_client *client, int operation, + int ctl_name, int *nrels_mag, long *results); +static void via686a_alarms(struct i2c_client *client, int operation, + int ctl_name, int *nrels_mag, long *results); +static void via686a_fan_div(struct i2c_client *client, int operation, + int ctl_name, int *nrels_mag, long *results); + +static int via686a_id = 0; + +/* The driver. I choose to use type i2c_driver, as at is identical to both + smbus_driver and isa_driver, and clients could be of either kind */ +static struct i2c_driver via686a_driver = { + /* name */ "VIA 686A", + /* id */ I2C_DRIVERID_VIA686A, + /* flags */ I2C_DF_NOTIFY, + /* attach_adapter */ &via686a_attach_adapter, + /* detach_client */ &via686a_detach_client, + /* command */ &via686a_command, + /* inc_use */ &via686a_inc_use, + /* dec_use */ &via686a_dec_use +}; + +/* Used by via686a_init/cleanup */ +static int __initdata via686a_initialized = 0; + +/* The /proc/sys entries */ +/* These files are created for each detected VIA686A. This is just a template; + though at first sight, you might think we could use a statically + allocated list, we need some way to get back to the parent - which + is done through one of the 'extra' fields which are initialized + when a new copy is allocated. */ +static ctl_table via686a_dir_table_template[] = { + {VIA686A_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_in}, + {VIA686A_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_in}, + {VIA686A_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_in}, + {VIA686A_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_in}, + {VIA686A_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_in}, + {VIA686A_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_fan}, + {VIA686A_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_fan}, + {VIA686A_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_temp}, + {VIA686A_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_temp}, + {VIA686A_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_temp}, + {VIA686A_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_fan_div}, + {VIA686A_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real, + &sensors_sysctl_real, NULL, &via686a_alarms}, + {0} +}; + +static inline int via686a_read_value(struct i2c_client *client, u8 reg) +{ + return(inb_p(client->addr + reg)); +} + +static inline void via686a_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + outb_p(value, client->addr + reg); +} + +/* This is called when the module is loaded */ +int via686a_attach_adapter(struct i2c_adapter *adapter) +{ + return sensors_detect(adapter, &addr_data, via686a_detect); +} + +/* Locate chip and get correct base address */ +int via686a_find(int *address) +{ + struct pci_dev *s_bridge; + u16 val; + + if (!pci_present()) + return -ENODEV; + + if (! (s_bridge = pci_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C686_4, NULL))) + return -ENODEV; + + if (PCIBIOS_SUCCESSFUL != + pci_read_config_word(s_bridge, VIA686A_BASE_REG, &val)) + return -ENODEV; + *address = (val & 0xff80); + + if (PCIBIOS_SUCCESSFUL != + pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val)) + return -ENODEV; + if((*address == 0) || !(val & 0x01)) { + printk("via686a.o: sensors not enabled - upgrade BIOS?\n"); + return -ENODEV; + } + return 0; +} + +int via686a_detect(struct i2c_adapter *adapter, int address, + unsigned short flags, int kind) +{ + int i; + struct i2c_client *new_client; + struct via686a_data *data; + int err = 0; + const char *type_name = "via686a sensors"; + + /* Make sure we are probing the ISA bus!! */ + if (!i2c_is_isa_adapter(adapter)) { + printk + ("via686a.o: via686a_detect called for an I2C bus adapter?!?\n"); + return 0; + } + + if (check_region(address, VIA686A_EXTENT)) { + printk("via686a.o: region 0x%x already in use!\n", address); + err = -ENODEV; + goto ERROR0; + } + + if (!(new_client = kmalloc(sizeof(struct i2c_client) + + sizeof(struct via686a_data), + GFP_KERNEL))) { + err = -ENOMEM; + goto ERROR0; + } + + data = (struct via686a_data *) (new_client + 1); + new_client->addr = address; + init_MUTEX(&data->lock); + new_client->data = data; + new_client->adapter = adapter; + new_client->driver = &via686a_driver; + new_client->flags = 0; + + /* Reserve the ISA region */ + request_region(address, VIA686A_EXTENT, type_name); + + /* Fill in the remaining client fields and put into the global list */ + strcpy(new_client->name, "Via 686A Integrated Sensors"); + + new_client->id = via686a_id++; + 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; + + /* Register a new directory entry with module sensors */ + if ((i = sensors_register_entry((struct i2c_client *) new_client, + type_name, + via686a_dir_table_template, + THIS_MODULE)) < 0) { + err = i; + goto ERROR4; + } + data->sysctl_id = i; + + /* Initialize the VIA686A chip */ + via686a_init_client(new_client); + return 0; + + ERROR4: + i2c_detach_client(new_client); + ERROR3: + release_region(address, VIA686A_EXTENT); + kfree(new_client); + ERROR0: + return err; +} + +int via686a_detach_client(struct i2c_client *client) +{ + int err; + + sensors_deregister_entry(((struct via686a_data *) (client->data))-> + sysctl_id); + + if ((err = i2c_detach_client(client))) { + printk + ("via686a.o: Client deregistration failed, client not detached.\n"); + return err; + } + + release_region(client->addr, VIA686A_EXTENT); + kfree(client); + + return 0; +} + +/* No commands defined yet */ +int via686a_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + return 0; +} + +void via686a_inc_use(struct i2c_client *client) +{ + MOD_INC_USE_COUNT; +} + +void via686a_dec_use(struct i2c_client *client) +{ + MOD_DEC_USE_COUNT; +} + +/* Called when we have found a new VIA686A. Set limits, etc. */ +void via686a_init_client(struct i2c_client *client) +{ + int i; + + /* Reset the device */ + via686a_write_value(client, VIA686A_REG_CONFIG, 0x80); + + via686a_write_value(client, VIA686A_REG_IN_MIN(0), + IN_TO_REG(VIA686A_INIT_IN_MIN_0)); + via686a_write_value(client, VIA686A_REG_IN_MAX(0), + IN_TO_REG(VIA686A_INIT_IN_MAX_0)); + via686a_write_value(client, VIA686A_REG_IN_MIN(1), + IN_TO_REG(VIA686A_INIT_IN_MIN_1)); + via686a_write_value(client, VIA686A_REG_IN_MAX(1), + IN_TO_REG(VIA686A_INIT_IN_MAX_1)); + via686a_write_value(client, VIA686A_REG_IN_MIN(2), + IN_TO_REG(VIA686A_INIT_IN_MIN_2)); + via686a_write_value(client, VIA686A_REG_IN_MAX(2), + IN_TO_REG(VIA686A_INIT_IN_MAX_2)); + via686a_write_value(client, VIA686A_REG_IN_MIN(3), + IN_TO_REG(VIA686A_INIT_IN_MIN_3)); + via686a_write_value(client, VIA686A_REG_IN_MAX(3), + IN_TO_REG(VIA686A_INIT_IN_MAX_3)); + via686a_write_value(client, VIA686A_REG_IN_MIN(4), + IN_TO_REG(VIA686A_INIT_IN_MIN_4)); + via686a_write_value(client, VIA686A_REG_IN_MAX(4), + IN_TO_REG(VIA686A_INIT_IN_MAX_4)); + via686a_write_value(client, VIA686A_REG_FAN_MIN(1), + FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2)); + via686a_write_value(client, VIA686A_REG_FAN_MIN(2), + FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2)); + for(i = 1; i < 3; i++) { + via686a_write_value(client, VIA686A_REG_TEMP_OVER(i), + TEMP_TO_REG(VIA686A_INIT_TEMP_OVER)); + via686a_write_value(client, VIA686A_REG_TEMP_HYST(i), + TEMP_TO_REG(VIA686A_INIT_TEMP_HYST)); + } + + /* Start monitoring */ + via686a_write_value(client, VIA686A_REG_CONFIG, 0x01); +} + +void via686a_update_client(struct i2c_client *client) +{ + struct via686a_data *data = client->data; + 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 = 1; i <= 3; i++) { + data->temp[i - 1] = via686a_read_value(client, + VIA686A_REG_TEMP(i)) << 2; + data->temp_over[i - 1] = via686a_read_value(client, + VIA686A_REG_TEMP_OVER(i)); + data->temp_hyst[i - 1] = via686a_read_value(client, + VIA686A_REG_TEMP_HYST(i)); + } + /* add in lower 2 bits */ + 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); +} + + +/* The next few functions are the call-back functions of the /proc/sys and + sysctl files. Which function is used is defined in the ctl_table in + the extra1 field. + Each function must return the magnitude (power of 10 to divide the date + with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must + put a maximum of *nrels elements in results reflecting the data of this + file, and set *nrels to the number it actually put in it, if operation== + SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from + results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE. + Note that on SENSORS_PROC_REAL_READ, I do not check whether results is + large enough (by checking the incoming value of *nrels). This is not very + good practice, but as long as you put less than about 5 values in results, + you can assume it is large enough. */ +void via686a_in(struct i2c_client *client, int operation, int ctl_name, + int *nrels_mag, long *results) +{ + struct via686a_data *data = client->data; + int nr = ctl_name - VIA686A_SYSCTL_IN0; + + if (operation == SENSORS_PROC_REAL_INFO) + *nrels_mag = 2; + else if (operation == SENSORS_PROC_REAL_READ) { + via686a_update_client(client); + results[0] = IN_FROM_REG(data->in_min[nr]); + results[1] = IN_FROM_REG(data->in_max[nr]); + results[2] = IN_FROM_REG(data->in[nr]); + *nrels_mag = 3; + } else if (operation == SENSORS_PROC_REAL_WRITE) { + if (*nrels_mag >= 1) { + data->in_min[nr] = IN_TO_REG(results[0]); + via686a_write_value(client, VIA686A_REG_IN_MIN(nr), + data->in_min[nr]); + } + if (*nrels_mag >= 2) { + data->in_max[nr] = IN_TO_REG(results[1]); + via686a_write_value(client, VIA686A_REG_IN_MAX(nr), + data->in_max[nr]); + } + } +} + +void via686a_fan(struct i2c_client *client, int operation, int ctl_name, + int *nrels_mag, long *results) +{ + struct via686a_data *data = client->data; + int nr = ctl_name - VIA686A_SYSCTL_FAN1 + 1; + + if (operation == SENSORS_PROC_REAL_INFO) + *nrels_mag = 0; + else if (operation == SENSORS_PROC_REAL_READ) { + via686a_update_client(client); + results[0] = FAN_FROM_REG(data->fan_min[nr - 1], + DIV_FROM_REG(data-> + fan_div[nr - 1])); + results[1] = + FAN_FROM_REG(data->fan[nr - 1], + DIV_FROM_REG(data->fan_div[nr - 1])); + *nrels_mag = 2; + } else if (operation == SENSORS_PROC_REAL_WRITE) { + if (*nrels_mag >= 1) { + data->fan_min[nr - 1] = FAN_TO_REG(results[0], + DIV_FROM_REG(data->fan_div[nr - 1])); + via686a_write_value(client, + VIA686A_REG_FAN_MIN(nr), + data->fan_min[nr - 1]); + } + } +} + +void via686a_temp(struct i2c_client *client, int operation, int ctl_name, + int *nrels_mag, long *results) +{ + struct via686a_data *data = client->data; + int nr = ctl_name - VIA686A_SYSCTL_TEMP; + + if (operation == SENSORS_PROC_REAL_INFO) + *nrels_mag = 1; + else if (operation == SENSORS_PROC_REAL_READ) { + via686a_update_client(client); + results[0] = TEMP_FROM_REG(data->temp_over[nr]); + results[1] = TEMP_FROM_REG(data->temp_hyst[nr]); + results[2] = TEMP_FROM_REG10(data->temp[nr]); + *nrels_mag = 3; + } else if (operation == SENSORS_PROC_REAL_WRITE) { + if (*nrels_mag >= 1) { + data->temp_over[nr] = TEMP_TO_REG(results[0]); + via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), + data->temp_over[nr]); + } + if (*nrels_mag >= 2) { + data->temp_hyst[nr] = TEMP_TO_REG(results[1]); + via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), + data->temp_hyst[nr]); + } + } +} + +void via686a_alarms(struct i2c_client *client, int operation, int ctl_name, + int *nrels_mag, long *results) +{ + struct via686a_data *data = client->data; + if (operation == SENSORS_PROC_REAL_INFO) + *nrels_mag = 0; + else if (operation == SENSORS_PROC_REAL_READ) { + via686a_update_client(client); + results[0] = ALARMS_FROM_REG(data->alarms); + *nrels_mag = 1; + } +} + +void via686a_fan_div(struct i2c_client *client, int operation, + int ctl_name, int *nrels_mag, long *results) +{ + struct via686a_data *data = client->data; + int old; + + if (operation == SENSORS_PROC_REAL_INFO) + *nrels_mag = 0; + else if (operation == SENSORS_PROC_REAL_READ) { + via686a_update_client(client); + results[0] = DIV_FROM_REG(data->fan_div[0]); + results[1] = DIV_FROM_REG(data->fan_div[1]); + *nrels_mag = 2; + } else if (operation == SENSORS_PROC_REAL_WRITE) { + old = via686a_read_value(client, VIA686A_REG_FANDIV); + if (*nrels_mag >= 2) { + data->fan_div[1] = DIV_TO_REG(results[1]); + old = (old & 0x3f) | (data->fan_div[1] << 6); + } + if (*nrels_mag >= 1) { + data->fan_div[0] = DIV_TO_REG(results[0]); + old = (old & 0xcf) | (data->fan_div[0] << 4); + via686a_write_value(client, VIA686A_REG_FANDIV, + old); + } + } +} + +int __init sensors_via686a_init(void) +{ + int res, addr; + + printk("via686a.o version %s (%s)\n", LM_VERSION, LM_DATE); + via686a_initialized = 0; + + if (via686a_find(&addr)) { + printk("via686a.o: No Via 686A sensors found.\n"); + return -ENODEV; + } + normal_isa[0] = addr; + + if ((res = i2c_add_driver(&via686a_driver))) { + printk + ("via686a.o: Driver registration failed.\n"); + via686a_cleanup(); + return res; + } + via686a_initialized++; + return 0; +} + +int __init via686a_cleanup(void) +{ + int res; + + if (via686a_initialized >= 1) { + if ((res = i2c_del_driver(&via686a_driver))) { + printk("via686a.o: Driver deregistration failed.\n"); + return res; + } + via686a_initialized--; + } + return 0; +} + +EXPORT_NO_SYMBOLS; + +#ifdef MODULE + +MODULE_AUTHOR("Kyösti Mälkki , Mark Studebaker "); +MODULE_DESCRIPTION("VIA 686A Sensor device"); + +int init_module(void) +{ + return sensors_via686a_init(); +} + +int cleanup_module(void) +{ + return via686a_cleanup(); +} + +#endif /* MODULE */ diff --git a/kernel/include/sensors.h b/kernel/include/sensors.h index e6a054a1..5e54d8ed 100644 --- a/kernel/include/sensors.h +++ b/kernel/include/sensors.h @@ -374,6 +374,7 @@ extern inline int SENSORS_LIMIT(long value, long low, long high) #define I2C_DRIVERID_GL520 1016 #define I2C_DRIVERID_THMC50 1017 #define I2C_DRIVERID_DDCMON 1018 +#define I2C_DRIVERID_VIA686A 1019 /* Sysctl IDs */ #ifdef DEV_HWMON @@ -639,6 +640,31 @@ struct sensors_chips_data { #define SIS5595_ALARM_FAN1 0x40 #define SIS5595_ALARM_FAN2 0x80 +#define VIA686A_SYSCTL_IN0 1000 +#define VIA686A_SYSCTL_IN1 1001 +#define VIA686A_SYSCTL_IN2 1002 +#define VIA686A_SYSCTL_IN3 1003 +#define VIA686A_SYSCTL_IN4 1004 +#define VIA686A_SYSCTL_FAN1 1101 +#define VIA686A_SYSCTL_FAN2 1102 +#define VIA686A_SYSCTL_TEMP 1200 +#define VIA686A_SYSCTL_TEMP2 1201 +#define VIA686A_SYSCTL_TEMP3 1202 +#define VIA686A_SYSCTL_FAN_DIV 2000 +#define VIA686A_SYSCTL_ALARMS 2001 + +#define VIA686A_ALARM_IN0 0x01 +#define VIA686A_ALARM_IN1 0x02 +#define VIA686A_ALARM_IN2 0x04 +#define VIA686A_ALARM_IN3 0x08 +#define VIA686A_ALARM_TEMP 0x10 +#define VIA686A_ALARM_FAN1 0x40 +#define VIA686A_ALARM_FAN2 0x80 +#define VIA686A_ALARM_IN4 0x100 +#define VIA686A_ALARM_TEMP2 0x400 +#define VIA686A_ALARM_CHAS 0x1000 +#define VIA686A_ALARM_TEMP3 0x8000 + #define ICSPLL_SYSCTL1 1000 #define BT869_SYSCTL_STATUS 1000 diff --git a/lib/chips.c b/lib/chips.c index 5fd0821a..742ce5de 100644 --- a/lib/chips.c +++ b/lib/chips.c @@ -1559,6 +1559,81 @@ static sensors_chip_feature thmc50_features[] = { 0 } }; +static sensors_chip_feature via686a_features[] = + { + { SENSORS_VIA686A_IN0, "2.0V", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_IN0, VALUE(3), 2 }, + { SENSORS_VIA686A_IN1, "2.5V", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_IN1, VALUE(3), 2 }, + { SENSORS_VIA686A_IN2, "3.3V", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_IN2, VALUE(3), 2 }, + { SENSORS_VIA686A_IN3, "5.0V", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_IN3, VALUE(3), 2 }, + { SENSORS_VIA686A_IN4, "12V", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_IN4, VALUE(3), 2 }, + { SENSORS_VIA686A_IN0_MIN, "in0_min", SENSORS_VIA686A_IN0, SENSORS_VIA686A_IN0, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN0, VALUE(1), 2 }, + { SENSORS_VIA686A_IN1_MIN, "in1_min", SENSORS_VIA686A_IN1, SENSORS_VIA686A_IN1, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN1, VALUE(1), 2 }, + { SENSORS_VIA686A_IN2_MIN, "in2_min", SENSORS_VIA686A_IN2, SENSORS_VIA686A_IN2, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN2, VALUE(1), 2 }, + { SENSORS_VIA686A_IN3_MIN, "in3_min", SENSORS_VIA686A_IN3, SENSORS_VIA686A_IN3, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN3, VALUE(1), 2 }, + { SENSORS_VIA686A_IN3_MIN, "in4_min", SENSORS_VIA686A_IN4, SENSORS_VIA686A_IN4, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN4, VALUE(1), 2 }, + { SENSORS_VIA686A_IN0_MAX, "in0_max", SENSORS_VIA686A_IN0, SENSORS_VIA686A_IN0, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN0, VALUE(2), 2 }, + { SENSORS_VIA686A_IN1_MAX, "in1_max", SENSORS_VIA686A_IN1, SENSORS_VIA686A_IN1, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN1, VALUE(2), 2 }, + { SENSORS_VIA686A_IN2_MAX, "in2_max", SENSORS_VIA686A_IN2, SENSORS_VIA686A_IN2, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN2, VALUE(2), 2 }, + { SENSORS_VIA686A_IN3_MAX, "in3_max", SENSORS_VIA686A_IN3, SENSORS_VIA686A_IN3, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN3, VALUE(2), 2 }, + { SENSORS_VIA686A_IN3_MAX, "in4_max", SENSORS_VIA686A_IN4, SENSORS_VIA686A_IN4, + SENSORS_MODE_RW, VIA686A_SYSCTL_IN4, VALUE(2), 2 }, + { SENSORS_VIA686A_FAN1, "fan1", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_FAN1, VALUE(2), 0 }, + { SENSORS_VIA686A_FAN2, "fan2", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_FAN2, VALUE(2), 0 }, + { SENSORS_VIA686A_FAN1_MIN, "fan1_min", SENSORS_VIA686A_FAN1, SENSORS_VIA686A_FAN1, + SENSORS_MODE_RW, VIA686A_SYSCTL_FAN1, VALUE(1), 0 }, + { SENSORS_VIA686A_FAN2_MIN, "fan2_min", SENSORS_VIA686A_FAN2, SENSORS_VIA686A_FAN2, + SENSORS_MODE_RW, VIA686A_SYSCTL_FAN2, VALUE(1), 0 }, + { SENSORS_VIA686A_TEMP, "temp1", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_TEMP, VALUE(3), 1 }, + { SENSORS_VIA686A_TEMP_HYST, "temp1_hyst", SENSORS_VIA686A_TEMP, + SENSORS_VIA686A_TEMP, SENSORS_MODE_RW, + VIA686A_SYSCTL_TEMP, VALUE(2), 1 }, + { SENSORS_VIA686A_TEMP_OVER, "temp1_over", SENSORS_VIA686A_TEMP, + SENSORS_VIA686A_TEMP, SENSORS_MODE_RW, + VIA686A_SYSCTL_TEMP, VALUE(1), 1 }, + { SENSORS_VIA686A_TEMP, "temp2", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_TEMP, VALUE(3), 1 }, + { SENSORS_VIA686A_TEMP_HYST, "temp2_hyst", SENSORS_VIA686A_TEMP2, + SENSORS_VIA686A_TEMP2, SENSORS_MODE_RW, + VIA686A_SYSCTL_TEMP, VALUE(2), 1 }, + { SENSORS_VIA686A_TEMP_OVER, "temp2_over", SENSORS_VIA686A_TEMP2, + SENSORS_VIA686A_TEMP2, SENSORS_MODE_RW, + VIA686A_SYSCTL_TEMP, VALUE(1), 1 }, + { SENSORS_VIA686A_TEMP, "temp3", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_TEMP, VALUE(3), 1 }, + { SENSORS_VIA686A_TEMP_HYST, "temp3_hyst", SENSORS_VIA686A_TEMP3, + SENSORS_VIA686A_TEMP3, SENSORS_MODE_RW, + VIA686A_SYSCTL_TEMP, VALUE(2), 1 }, + { SENSORS_VIA686A_TEMP_OVER, "temp3_over", SENSORS_VIA686A_TEMP3, + SENSORS_VIA686A_TEMP3, SENSORS_MODE_RW, + VIA686A_SYSCTL_TEMP, VALUE(1), 1 }, + { SENSORS_VIA686A_FAN1_DIV, "fan1_div", SENSORS_VIA686A_FAN1, SENSORS_NO_MAPPING, + SENSORS_MODE_RW, VIA686A_SYSCTL_FAN_DIV, VALUE(1), + 0 }, + { SENSORS_VIA686A_FAN2_DIV, "fan2_div", SENSORS_VIA686A_FAN2, SENSORS_NO_MAPPING, + SENSORS_MODE_RW, VIA686A_SYSCTL_FAN_DIV, VALUE(2), + 0 }, + { SENSORS_VIA686A_ALARMS, "alarms", SENSORS_NO_MAPPING, SENSORS_NO_MAPPING, + SENSORS_MODE_R, VIA686A_SYSCTL_ALARMS, VALUE(1), 0 }, + { 0 } + }; + static sensors_chip_feature ddcmon_features[] = { { SENSORS_DDCMON_ID, "Monitor ID", @@ -1644,6 +1719,7 @@ sensors_chip_features sensors_chip_features_list[] = { SENSORS_THMC50_PREFIX, thmc50_features }, /* Cheat on ADM1022 for now - no separate #defines */ { SENSORS_ADM1022_PREFIX, thmc50_features }, + { SENSORS_VIA686A_PREFIX, via686a_features }, { SENSORS_DDCMON_PREFIX, ddcmon_features }, { SENSORS_EEPROM_PREFIX, eeprom_features }, { 0 } diff --git a/lib/chips.h b/lib/chips.h index c5f488a9..30669ac0 100644 --- a/lib/chips.h +++ b/lib/chips.h @@ -724,6 +724,43 @@ #define SENSORS_THMC50_INTER_MASK 82 /* RW */ #define SENSORS_THMC50_DIE_CODE 90 /* R */ +/* SiS southbridge with integrated lm78 */ + +#define SENSORS_VIA686A_PREFIX "via686a" + +#define SENSORS_VIA686A_IN0 1 /* R */ +#define SENSORS_VIA686A_IN1 2 /* R */ +#define SENSORS_VIA686A_IN2 3 /* R */ +#define SENSORS_VIA686A_IN3 4 /* R */ +#define SENSORS_VIA686A_IN4 5 /* R */ +#define SENSORS_VIA686A_IN0_MIN 11 /* RW */ +#define SENSORS_VIA686A_IN1_MIN 12 /* RW */ +#define SENSORS_VIA686A_IN2_MIN 13 /* RW */ +#define SENSORS_VIA686A_IN3_MIN 14 /* RW */ +#define SENSORS_VIA686A_IN4_MIN 15 /* RW */ +#define SENSORS_VIA686A_IN0_MAX 21 /* RW */ +#define SENSORS_VIA686A_IN1_MAX 22 /* RW */ +#define SENSORS_VIA686A_IN2_MAX 23 /* RW */ +#define SENSORS_VIA686A_IN3_MAX 24 /* RW */ +#define SENSORS_VIA686A_IN4_MAX 25 /* RW */ +#define SENSORS_VIA686A_FAN1 31 /* R */ +#define SENSORS_VIA686A_FAN2 32 /* R */ +#define SENSORS_VIA686A_FAN1_MIN 41 /* RW */ +#define SENSORS_VIA686A_FAN2_MIN 42 /* RW */ +#define SENSORS_VIA686A_TEMP 51 /* R */ +#define SENSORS_VIA686A_TEMP_HYST 52 /* RW */ +#define SENSORS_VIA686A_TEMP_OVER 53 /* RW */ +#define SENSORS_VIA686A_TEMP2 54 /* R */ +#define SENSORS_VIA686A_TEMP2_HYST 55 /* RW */ +#define SENSORS_VIA686A_TEMP2_OVER 56 /* RW */ +#define SENSORS_VIA686A_TEMP3 57 /* R */ +#define SENSORS_VIA686A_TEMP3_HYST 58 /* RW */ +#define SENSORS_VIA686A_TEMP3_OVER 59 /* RW */ +#define SENSORS_VIA686A_FAN1_DIV 71 /* RW */ +#define SENSORS_VIA686A_FAN2_DIV 72 /* RW */ +#define SENSORS_VIA686A_ALARMS 81 /* R */ + + /* DDC Monitor */ #define SENSORS_DDCMON_PREFIX "ddcmon" diff --git a/prog/sensors/chips.c b/prog/sensors/chips.c index 661fa389..feb00172 100644 --- a/prog/sensors/chips.c +++ b/prog/sensors/chips.c @@ -418,9 +418,148 @@ void print_sis5595(const sensors_chip_name *name) if (!sensors_get_label(*name,SENSORS_SIS5595_ALARMS,&label)) { print_label(label,10); printf("Board temperature input (usually LM75 chips) %s\n", - alarms & SIS5595_ALARM_BTI?"ALARM":" "); + alarms & SIS5595_ALARM_BTI ?"ALARM":" "); } free_the_label(&label); + +} + +void print_via686a(const sensors_chip_name *name) +{ + char *label = NULL; + double cur,min,max,fdiv; + int alarms,valid; + + if (!sensors_get_feature(*name,SENSORS_VIA686A_ALARMS,&cur)) + alarms = cur + 0.5; + else { + printf("ERROR: Can't get alarm data!\n"); + alarms = 0; + } + + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_IN0,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN0,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN0_MIN,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN0_MAX,&max)) { + if (valid) { + print_label(label,10); + printf("%+6.2f V (min = %+6.2f V, max = %+6.2f V) %s\n", + cur,min,max,alarms&VIA686A_ALARM_IN0?"ALARM":""); + } + } else + printf("ERROR: Can't get IN0 data!\n"); + free_the_label(&label); + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_IN1,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN1,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN1_MIN,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN1_MAX,&max)) { + if (valid) { + print_label(label,10); + printf("%+6.2f V (min = %+6.2f V, max = %+6.2f V) %s\n", + cur,min,max,alarms&VIA686A_ALARM_IN1?"ALARM":""); + } + } else + printf("ERROR: Can't get IN1 data!\n"); + free_the_label(&label); + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_IN2,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN2,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN2_MIN,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN2_MAX,&max)) { + if (valid) { + print_label(label,10); + printf("%+6.2f V (min = %+6.2f V, max = %+6.2f V) %s\n", + cur,min,max,alarms&VIA686A_ALARM_IN2?"ALARM":""); + } + } else + printf("ERROR: Can't get IN2 data!\n"); + free_the_label(&label); + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_IN3,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN3,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN3_MIN,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN3_MAX,&max)) { + if (valid) { + print_label(label,10); + printf("%+6.2f V (min = %+6.2f V, max = %+6.2f V) %s\n", + cur,min,max,alarms&VIA686A_ALARM_IN3?"ALARM":""); + } + } else + printf("ERROR: Can't get IN3 data!\n"); + free_the_label(&label); + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_IN4,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN4,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN4_MIN,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_IN4_MAX,&max)) { + if (valid) { + print_label(label,10); + printf("%+6.2f V (min = %+6.2f V, max = %+6.2f V) %s\n", + cur,min,max,alarms&VIA686A_ALARM_IN4?"ALARM":""); + } + } else + printf("ERROR: Can't get IN4 data!\n"); + free_the_label(&label); + + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_FAN1,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_FAN1,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_FAN1_DIV,&fdiv) && + !sensors_get_feature(*name,SENSORS_VIA686A_FAN1_MIN,&min)) { + if (valid) { + print_label(label,10); + printf("%4.0f RPM (min = %4.0f RPM, div = %1.0f) %s\n", + cur,min,fdiv, alarms&VIA686A_ALARM_FAN1?"ALARM":""); + } + } else + printf("ERROR: Can't get FAN1 data!\n"); + free_the_label(&label); + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_FAN2,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_FAN2,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_FAN2_DIV,&fdiv) && + !sensors_get_feature(*name,SENSORS_VIA686A_FAN2_MIN,&min)) { + if (valid) { + print_label(label,10); + printf("%4.0f RPM (min = %4.0f RPM, div = %1.0f) %s\n", + cur,min,fdiv, alarms&VIA686A_ALARM_FAN2?"ALARM":""); + } + } else + printf("ERROR: Can't get FAN2 data!\n"); + free_the_label(&label); + + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_TEMP,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP_HYST,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP_OVER,&max)) { + if (valid) { + print_label(label,10); + printf("%+3.0f C (limit = %+3.0f C, hysteresis = %+3.0f C) %s\n", + cur,max,min, alarms&VIA686A_ALARM_TEMP?"ALARM":""); + } + } else + printf("ERROR: Can't get TEMP data!\n"); + free_the_label(&label); + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_TEMP2,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP2,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP2_HYST,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP2_OVER,&max)) { + if (valid) { + print_label(label,10); + printf("%+3.0f C (limit = %+3.0f C, hysteresis = %+3.0f C) %s\n", + cur,max,min, alarms&VIA686A_ALARM_TEMP2?"ALARM":""); + } + } else + printf("ERROR: Can't get TEMP2 data!\n"); + free_the_label(&label); + if (!sensors_get_label_and_valid(*name,SENSORS_VIA686A_TEMP3,&label,&valid) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP3,&cur) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP3_HYST,&min) && + !sensors_get_feature(*name,SENSORS_VIA686A_TEMP3_OVER,&max)) { + if (valid) { + print_label(label,10); + printf("%+3.0f C (limit = %+3.0f C, hysteresis = %+3.0f C) %s\n", + cur,max,min, alarms&VIA686A_ALARM_TEMP3?"ALARM":""); + } + } else + printf("ERROR: Can't get TEMP3 data!\n"); + free_the_label(&label); + } void print_lm78(const sensors_chip_name *name) diff --git a/prog/sensors/chips.h b/prog/sensors/chips.h index 5b32604b..6c203266 100644 --- a/prog/sensors/chips.h +++ b/prog/sensors/chips.h @@ -29,6 +29,7 @@ extern void print_adm1021(const sensors_chip_name *name); extern void print_adm9240(const sensors_chip_name *name); extern void print_lm78(const sensors_chip_name *name); extern void print_sis5595(const sensors_chip_name *name); +extern void print_via686a(const sensors_chip_name *name); extern void print_gl518(const sensors_chip_name *name); extern void print_lm80(const sensors_chip_name *name); extern void print_w83781d(const sensors_chip_name *name); diff --git a/prog/sensors/main.c b/prog/sensors/main.c index a7b74218..58f9ebf3 100644 --- a/prog/sensors/main.c +++ b/prog/sensors/main.c @@ -262,6 +262,8 @@ void do_a_print(sensors_chip_name name) print_lm78(&name); else if (!strcmp(name.prefix,"sis5595")) print_sis5595(&name); + else if (!strcmp(name.prefix,"via686a")) + print_via686a(&name); else if (!strcmp(name.prefix,"lm80")) print_lm80(&name); else if (!strcmp(name.prefix,"gl518sm"))