From 7e8c43e6b6d29d47aa0dbe82365c3faad6a149a2 Mon Sep 17 00:00:00 2001 From: Frodo Looijaard Date: Thu, 18 Mar 1999 15:32:20 +0000 Subject: [PATCH] Introducing module parameter scanning in sensors.c It is untested as of yet; but it compiled without problem. Next step: add support to the chip modules. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@324 7894878c-1315-0410-8ee3-d5d059ff63e0 --- TODO | 2 + kernel/include/sensors.h | 91 ++++++++++++++++++++++++++++ kernel/sensors.c | 125 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 216 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index 68ed386a..8136bcd5 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,7 @@ Many, many things. Most notably: +* Sensors program needs to print a + before lm75 temperatures +* Timer chips - block read problems? * LM78 detection: bit 5 reg 0x49 may be one?!? * bit-lp increases module count stupidly * Segfault if too high /dev/i2c-* file accessed diff --git a/kernel/include/sensors.h b/kernel/include/sensors.h index c61cf429..1c3baae9 100644 --- a/kernel/include/sensors.h +++ b/kernel/include/sensors.h @@ -80,6 +80,97 @@ extern int sensors_register_entry(struct i2c_client *client, const char *prefix, ctl_table *ctl_template); extern void sensors_deregister_entry(int id); + +/* A structure containing detect information. + Force variables overrule all other variables; they force a detection on + that place. If a specific chip is given, the module blindly assumes this + chip type is present; if a general force (kind == 0) is given, the module + will still try to figure out what type of chip is present. This is useful + if for some reasons the detect for SMBus or ISA address space filled + fails. + probe: insmod parameter. Initialize this list with SENSORS_I2C_END values. + A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for + the ISA bus, -1 for any I2C bus), the second is the address. + kind: The kind of chip. 0 equals any chip. +*/ +struct sensors_force_data { + unsigned short *force; + unsigned short kind; +}; + +/* A structure containing the detect information. + normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END. + A list of I2C addresses which should normally be examined. + normal_i2c_range: filled in by the module writer. Terminated by + SENSORS_I2C_END + A list of pairs of I2C addresses, each pair being an inclusive range of + addresses which should normally be examined. + normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END. + A list of ISA addresses which should normally be examined. + normal_isa_range: filled in by the module writer. Terminated by + SENSORS_ISA_END + A list of triples. The first two elements are ISA addresses, being an + range of addresses which should normally be examined. The third is the + modulo parameter: only addresses which are 0 module this value relative + to the first address of the range are actually considered. + probe: insmod parameter. Initialize this list with SENSORS_I2C_END values. + A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for + the ISA bus, -1 for any I2C bus), the second is the address. These + addresses are also probed, as if they were in the 'normal' list. + probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END + values. + A list of triples. The first value is a bus number (SENSORS_ISA_BUS for + the ISA bus, -1 for any I2C bus), the second and third are addresses. + These form an inclusive range of addresses that are also probed, as + if they were in the 'normal' list. + ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values. + A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for + the ISA bus, -1 for any I2C bus), the second is the I2C address. These + addresses are never probed. This parameter overrules 'normal' and + 'probe', but not the 'force' lists. + ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END + values. + A list of triples. The first value is a bus number (SENSORS_ISA_BUS for + the ISA bus, -1 for any I2C bus), the second and third are addresses. + These form an inclusive range of I2C addresses that are never probed. + This parameter overrules 'normal' and 'probe', but not the 'force' lists. + force_data: insmod parameters. A list, ending with an element of which + the force field is NULL. +*/ +struct sensors_address_data { + unsigned short *normal_i2c; + unsigned short *normal_i2c_range; + unsigned int *normal_isa; + unsigned int *normal_isa_range; + unsigned short *probe; + unsigned short *probe_range; + unsigned short *ignore; + unsigned short *ignore_range; + struct sensors_force_data *forces; +}; + +/* Internal numbers to terminate lists */ +#define SENSORS_I2C_END 0xfffe +#define SENSORS_ISA_END 0xfffefffe + +/* The numbers to use to set an ISA or I2C bus address */ +#define SENSORS_ISA_BUS 9191 +#define SENSORS_ANY_I2C_BUS 0xffff + +/* The length of the option lists */ +#define SENSORS_MAX_OPTS 48 + +typedef void sensors_found_addr_proc (struct i2c_adapter *adapter, + int addr, int kind); + +/* Detect function. It itterates over all possible addresses itself. For + SMBus addresses, it will only call found_proc if some client is connected + to the SMBus (unless a 'force' matched); for ISA detections, this is not + done. */ +extern void sensors_detect(struct i2c_adapter *adapter, + struct sensors_address_data *address_data, + sensors_found_addr_proc *found_proc); + #endif /* def __KERNEL__ */ diff --git a/kernel/sensors.c b/kernel/sensors.c index 3f30a531..aeebc8cc 100644 --- a/kernel/sensors.c +++ b/kernel/sensors.c @@ -29,6 +29,7 @@ #include "i2c-isa.h" #include "sensors.h" #include "compat.h" +#include "smbus.h" #ifdef MODULE @@ -113,8 +114,8 @@ int sensors_create_name(char **name, const char *prefix, } /* This rather complex function must be called when you want to add an entry - to /proc/sys/dev/sensors/chips (not yet implemented). It also creates - a new directory within /proc/sys/dev/sensors/. + to /proc/sys/dev/sensors/chips. It also creates a new directory within + /proc/sys/dev/sensors/. ctl_template should be a template of the newly created directory. It is copied in memory. The extra2 field of each file is set to point to client. If any driver wants subdirectories within the newly created directory, @@ -579,6 +580,126 @@ void sensors_write_reals(int nrels,void *buffer,int *bufsize,long *results, *bufsize=curbufsize; } + +/* Very inefficient for ISA detects! */ +void sensors_detect(struct i2c_adapter *adapter, + struct sensors_address_data *address_data, + sensors_found_addr_proc *found_proc) +{ + int addr,i,found,j; + struct sensors_force_data *this_force; + unsigned int end_marker = i2c_is_isa_adapter(adapter)?SENSORS_ISA_END: + SENSORS_I2C_END; + int adapter_id = i2c_is_isa_adapter(adapter)?SENSORS_ISA_BUS: + i2c_adapter_id(adapter); + + for (addr = 0x00; addr <= i2c_is_isa_adapter(adapter)?0xfff:0x7f; addr ++) { + /* If it is in one of the force entries, we don't do any detection + at all */ + found = 0; + for (i = 0; + !found && (this_force = address_data->forces+i, this_force->force); + i++) { + for (j = 0; !found && (this_force->force[j] != end_marker) ; i += 2) { + if (((adapter_id == this_force->force[j]) || + (this_force->force[j] == SENSORS_ANY_I2C_BUS)) && + (addr == this_force->force[j+1])) { + found_proc(adapter,addr,this_force->kind); + found = 1; + } + } + } + if (found) + continue; + + /* If this address is in one of the ignores, we can forget about it + right now */ + for (i = 0; + !found && (address_data->ignore[i] != end_marker); + i += 2) { + if (((adapter_id == address_data->ignore[i]) || + (address_data->ignore[i] == SENSORS_ANY_I2C_BUS)) && + (addr == address_data->ignore[i+1])) { + found = 1; + } + } + for (i = 0; + !found && (address_data->ignore_range[i] != end_marker); + i += 3) { + if (((adapter_id == address_data->ignore_range[i]) || + (address_data->ignore_range[i] == SENSORS_ANY_I2C_BUS)) && + (addr >= address_data->ignore_range[i+1]) && + (addr <= address_data->ignore_range[i+2])) + found = 1; + } + if (found) + continue; + + /* Now, we will do a detection, but only if it is in the normal or + probe entries */ + if (i2c_is_isa_adapter(adapter)) { + for (i = 0; + !found && (address_data->normal_isa[i] != SENSORS_ISA_END); + i += 1) { + if (addr == address_data->normal_isa[i]) { + found = 1; + } + for (i = 0; + !found && (address_data->normal_isa_range[i] != SENSORS_I2C_END); + i += 3) { + if ((addr >= address_data->normal_isa_range[i]) && + (addr <= address_data->normal_isa_range[i+1]) && + ((addr - address_data->normal_isa_range[i]) % + address_data->normal_isa_range[i+2] == 0)); + found = 1; + } + } + } else { + for (i = 0; + !found && (address_data->normal_i2c[i] != SENSORS_I2C_END); + i += 1) { + if (addr == address_data->normal_i2c[i]) { + found = 1; + } + for (i = 0; + !found && (address_data->normal_i2c_range[i] != SENSORS_I2C_END); + i += 2) { + if ((addr >= address_data->normal_i2c_range[i]) && + (addr <= address_data->normal_i2c_range[i+1])) + found = 1; + } + } + } + + for (i = 0; + !found && (address_data->probe[i] != SENSORS_I2C_END); + i += 2) { + if (((adapter_id == address_data->probe[i]) || + (address_data->probe[i] == SENSORS_ANY_I2C_BUS)) && + (addr == address_data->probe[i+1])) { + found = 1; + } + for (i = 0; + !found && (address_data->probe_range[i] != SENSORS_I2C_END); + i += 3) { + if (((adapter_id == address_data->probe_range[i]) || + (address_data->probe_range[i] == SENSORS_ANY_I2C_BUS)) && + (addr >= address_data->probe_range[i+1]) && + (addr <= address_data->probe_range[i+2])) + found = 1; + } + } + if (!found) + continue; + + /* OK, so we really should examine this address. First check + whether there is some client here at all! */ + if (!i2c_is_isa_adapter(adapter) || + (smbus_read_byte(adapter,addr) >= 0)) + found_proc(adapter,addr,0); + } +} + int sensors_init(void) { printk("sensors.o version %s (%s)\n",LM_VERSION,LM_DATE);