Show
Ignore:
Timestamp:
12/01/98 22:11:32 (15 years ago)
Author:
frodo
Message:

Many things, most notable the lm78 module

* Some Makefile changes. doc/makefiles documents most of them.
* The lm78 module now compiles, but it will still crash.
* New module sensors, with general code usable by chip driver modules
* i2c-core: added function i2c_adapter_id(), which returns a (low)

unique i2c-bus ID.

* lm78.h stuff moved into lm78.c or sensors.h

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lm-sensors/trunk/kernel/chips/lm78.c

    r16 r19  
     1 
    12/* 
    23    lm78.c - A Linux module for reading sensor data. 
     
    2223#include <linux/proc_fs.h> 
    2324#include <linux/ioport.h> 
     25#include <linux/sysctl.h> 
    2426#include <asm/errno.h> 
    2527#include <asm/io.h> 
    2628#include <linux/types.h> 
    27 #include "lm78.h" 
    2829#include "smbus.h" 
    2930#include "version.h" 
    3031#include "isa.h" 
    3132#include "sensors.h" 
    32  
     33#include "i2c.h" 
     34#include "compat.h" 
     35 
     36/* Many LM78 constants needed below */ 
     37 
     38/* Length of ISA address segment */ 
     39#define LM78_EXTENT 8 
     40 
     41/* Where are the ISA address/data registers relative to the base address */ 
     42#define LM78_ADDR_REG_OFFSET 5 
     43#define LM78_DATA_REG_OFFSET 6 
     44 
     45/* The LM78 registers */ 
     46#define LM78_REG_IN_MAX(nr) (0x2b + (nr) * 2) 
     47#define LM78_REG_IN_MIN(nr) (0x2c + (nr) * 2) 
     48#define LM78_REG_IN(nr) (0x20 + (nr)) 
     49 
     50#define LM78_REG_FAN_MIN(nr) (0x3a + (nr)) 
     51#define LM78_REG_FAN(nr) (0x27 + (nr)) 
     52 
     53#define LM78_REG_TEMP 0x27 
     54#define LM78_REG_TEMP_OVER 0x39 
     55#define LM78_REG_TEMP_HYST 0x3a 
     56 
     57#define LM78_REG_ALARM1 0x41 
     58#define LM78_REG_ALARM2 0x42 
     59 
     60#define LM78_REG_VID_FANDIV 0x47 
     61 
     62#define LM78_REG_CONFIG 0x40 
     63 
     64 
     65/* Conversions */ 
     66static int lm78_in_conv[7] = {10000, 10000, 10000, 16892, 38000,  
     67                              -34768, -15050 }; 
     68#define IN_TO_REG(val,nr) ((((val) * 100000 / lm78_in_conv[nr]) + 8) / 16) 
     69#define IN_FROM_REG(val,nr) (((val) *  16 * lm78_in_conv[nr]) / 100000) 
     70 
     71#define FAN_TO_REG(val) (((val)==0)?255:((1350000+(val))/((val)*2))) 
     72#define FAN_FROM_REG(val) (((val)==0)?-1:\ 
     73                           ((val)==255)?0:(1350000 + (val))/((val)*2)) 
     74 
     75#define TEMP_TO_REG(val) ((val)<0?(val)&0xff:(val)) 
     76#define TEMP_FROM_REG(val) ((val)>0x80?(val)-0x100:(val)); 
     77 
     78#define VID_FROM_REG(val) ((val) == 0x0f?0:350-(val)*10) 
     79 
     80#define ALARMS_FROM_REG(val) (val) 
     81 
     82#define DIV_FROM_REG(val) (1 >> (val)) 
     83#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?1:2) 
     84 
     85/* Initial limits */ 
     86#define LM78_INIT_IN_0 280 
     87#define LM78_INIT_IN_1 280 
     88#define LM78_INIT_IN_2 330 
     89#define LM78_INIT_IN_3 500 
     90#define LM78_INIT_IN_4 1200 
     91#define LM78_INIT_IN_5 -1200 
     92#define LM78_INIT_IN_6 -500 
     93 
     94#define LM78_INIT_IN_PERCENTAGE 100 
     95 
     96#define LM78_INIT_IN_MIN_0 \ 
     97        (LM78_INIT_IN_0 - LM78_INIT_IN_0 * LM78_INIT_IN_PERCENTAGE / 100)  
     98#define LM78_INIT_IN_MAX_0 \ 
     99        (LM78_INIT_IN_0 + LM78_INIT_IN_0 * LM78_INIT_IN_PERCENTAGE / 100)  
     100#define LM78_INIT_IN_MIN_1 \ 
     101        (LM78_INIT_IN_1 - LM78_INIT_IN_1 * LM78_INIT_IN_PERCENTAGE / 100)  
     102#define LM78_INIT_IN_MAX_1 \ 
     103        (LM78_INIT_IN_1 + LM78_INIT_IN_1 * LM78_INIT_IN_PERCENTAGE / 100)  
     104#define LM78_INIT_IN_MIN_2 \ 
     105        (LM78_INIT_IN_2 - LM78_INIT_IN_2 * LM78_INIT_IN_PERCENTAGE / 100)  
     106#define LM78_INIT_IN_MAX_2 \ 
     107        (LM78_INIT_IN_2 + LM78_INIT_IN_2 * LM78_INIT_IN_PERCENTAGE / 100)  
     108#define LM78_INIT_IN_MIN_3 \ 
     109        (LM78_INIT_IN_3 - LM78_INIT_IN_3 * LM78_INIT_IN_PERCENTAGE / 100)  
     110#define LM78_INIT_IN_MAX_3 \ 
     111        (LM78_INIT_IN_3 + LM78_INIT_IN_3 * LM78_INIT_IN_PERCENTAGE / 100)  
     112#define LM78_INIT_IN_MIN_4 \ 
     113        (LM78_INIT_IN_4 - LM78_INIT_IN_4 * LM78_INIT_IN_PERCENTAGE / 100)  
     114#define LM78_INIT_IN_MAX_4 \ 
     115        (LM78_INIT_IN_4 + LM78_INIT_IN_4 * LM78_INIT_IN_PERCENTAGE / 100)  
     116#define LM78_INIT_IN_MIN_5 \ 
     117        (LM78_INIT_IN_5 - LM78_INIT_IN_5 * LM78_INIT_IN_PERCENTAGE / 100)  
     118#define LM78_INIT_IN_MAX_5 \ 
     119        (LM78_INIT_IN_5 + LM78_INIT_IN_5 * LM78_INIT_IN_PERCENTAGE / 100)  
     120#define LM78_INIT_IN_MIN_6 \ 
     121        (LM78_INIT_IN_6 - LM78_INIT_IN_6 * LM78_INIT_IN_PERCENTAGE / 100)  
     122#define LM78_INIT_IN_MAX_6 \ 
     123        (LM78_INIT_IN_6 + LM78_INIT_IN_6 * LM78_INIT_IN_PERCENTAGE / 100)  
     124 
     125#define LM78_INIT_FAN_MIN_1 3000 
     126#define LM78_INIT_FAN_MIN_2 3000 
     127#define LM78_INIT_FAN_MIN_3 3000 
     128 
     129#define LM78_INIT_TEMP_OVER 60 
     130#define LM78_INIT_TEMP_HYST 50 
    33131 
    34132#ifdef MODULE 
     
    52150   some corners. */ 
    53151 
     152/* For each registered LM78, we need to keep some data in memory. That 
     153   data is pointed to by lm78_list[NR]->data. The structure itself is 
     154   dynamically allocated, at the same time when a new lm78 client is 
     155   allocated. */ 
     156struct lm78_data { 
     157         struct semaphore lock; 
     158         int sysctl_id; 
     159 
     160         struct semaphore update_lock; 
     161         char valid;                 /* !=0 if following fields are valid */ 
     162         unsigned long last_updated; /* In jiffies */ 
     163 
     164         u8 in[7];                   /* Register value */ 
     165         u8 in_max[7];               /* Register value */ 
     166         u8 in_min[7];               /* Register value */ 
     167         u8 fan[3];                  /* Register value */ 
     168         u8 fan_min[3];              /* Register value */ 
     169         u8 temp;                    /* Register value */ 
     170         u8 temp_over;               /* Register value */ 
     171         u8 temp_hyst;               /* Register value */ 
     172         u8 fan_div[2];              /* Register encoding, shifted right */ 
     173         u8 vid;                     /* Register encoding, combined */ 
     174         u16 alarms;                 /* Register encoding, combined */ 
     175}; 
     176 
     177 
    54178static int lm78_init(void); 
    55179static int lm78_cleanup(void); 
     
    63187static int lm78_new_client(struct i2c_adapter *adapter, 
    64188                           struct i2c_client *new_client); 
    65 static void lm78_init_client(struct i2c_client *client); 
    66189static void lm78_remove_client(struct i2c_client *client); 
    67190static int lm78_command(struct i2c_client *client, unsigned int cmd,  
     
    69192static void lm78_inc_use (struct i2c_client *client); 
    70193static void lm78_dec_use (struct i2c_client *client); 
     194 
    71195static int lm78_read_value(struct i2c_client *client, u8 register); 
    72196static int lm78_write_value(struct i2c_client *client, u8 register, u8 value); 
     197static void lm78_update_client(struct i2c_client *client); 
     198static void lm78_init_client(struct i2c_client *client); 
     199 
     200static int lm78_sysctl (ctl_table *table, int *name, int nlen, void *oldval,  
     201                        size_t *oldlenp, void *newval, size_t newlen, 
     202                        void **context); 
     203static int lm78_proc (ctl_table *ctl, int write, struct file * filp, 
     204                      void *buffer, size_t *lenp); 
     205 
     206 
     207static void write_in(struct i2c_client *client, int nr, int nrels,  
     208                     long *results); 
     209static void read_in(struct i2c_client *client, int nr, long *results); 
     210static void write_fan(struct i2c_client *client, int nr, int nrels,  
     211                      long *results); 
     212static void read_fan(struct i2c_client *client, int nr, long *results); 
     213static void write_temp(struct i2c_client *client, int nrels, long *results); 
     214static void read_temp(struct i2c_client *client, long *results); 
     215static void read_vid(struct i2c_client *client, long *results); 
     216static void read_alarms(struct i2c_client *client, long *results); 
     217static void write_fan_div(struct i2c_client *client, int nrels, long *results); 
     218static void read_fan_div(struct i2c_client *client, long *results); 
     219 
     220 
    73221 
    74222/* I choose here for semi-static LM78 allocation. Complete dynamic 
    75223   allocation could also be used; the code needed for this would probably 
    76    take more memory than the datastructures take now */ 
     224   take more memory than the datastructure takes now. */ 
    77225#define MAX_LM78_NR 4 
    78226static struct i2c_client *lm78_list[MAX_LM78_NR]; 
    79 static struct semaphore lm78_semaphores[MAX_LM78_NR]; 
    80227 
    81228/* The driver. I choose to use type i2c_driver, as at is identical to both 
     
    95242static int lm78_initialized = 0; 
    96243 
     244/* The /proc/sys entries */ 
     245/* These files are created for each detected LM78. This is just a template; 
     246   though at first sight, you might think we could use a statically 
     247   allocated list, we need some way to get back to the parent - which 
     248   is done through one of the 'extra' fields which are initialized  
     249   when a new copy is allocated. */ 
     250static ctl_table lm78_dir_table_template[] = { 
     251  { LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     252  { LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     253  { LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     254  { LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     255  { LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     256  { LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     257  { LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     258  { LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     259  { LM78_SYSCTL_FAN2, "fan1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     260  { LM78_SYSCTL_FAN3, "fan1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     261  { LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     262  { LM78_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     263  { LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     264 
     265  { LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl } 
     266}; 
     267 
     268 
    97269/* This function is called when: 
    98      * lm78_driver is inserted, for each available adapter 
     270     * lm78_driver is inserted (when this module is loaded), for each 
     271       available adapter 
    99272     * when a new adapter is inserted (and lm78_driver is still present) */ 
    100273int lm78_attach_adapter(struct i2c_adapter *adapter) 
     
    106279} 
    107280 
    108 /* This function is called whenever a client should be removed */ 
     281/* This function is called whenever a client should be removed: 
     282    * lm78_driver is removed (when this module is unloaded) 
     283    * when an adapter is removed which has a lm78 client (and lm78_driver 
     284      is still present). */ 
    109285int lm78_detach_client(struct i2c_client *client) 
    110286{ 
     
    139315    request_region(address, LM78_EXTENT, "lm78"); 
    140316 
    141     if (! (new_client = kmalloc(sizeof(struct isa_client), GFP_KERNEL))) 
     317    /* Allocate space for a new client structure */ 
     318    if (! (new_client = kmalloc(sizeof(struct isa_client) +  
     319                                sizeof(struct lm78_data), 
     320                               GFP_KERNEL))) 
    142321    { 
    143       release_region(address,LM78_EXTENT); 
    144322      err=-ENOMEM; 
    145       continue; 
    146     } 
     323      goto ERROR1; 
     324    }  
     325 
     326    /* Fill the new client structure with data */ 
     327    new_client->data = (struct lm78_data *) (new_client + 1); 
    147328    new_client->addr = 0; 
    148329    new_client->isa_addr = address; 
    149330    if ((err = lm78_new_client((struct i2c_adapter *) adapter, 
    150                                (struct i2c_client *) new_client))) { 
    151       release_region(address, LM78_EXTENT); 
    152       kfree(new_client); 
    153       continue; 
    154     }  
    155     if ((err = isa_attach_client(new_client))) { 
    156       release_region(address, LM78_EXTENT); 
    157       lm78_remove_client((struct i2c_client *) new_client); 
    158       kfree(new_client); 
    159       continue; 
    160     } 
     331                               (struct i2c_client *) new_client))) 
     332      goto ERROR2; 
     333 
     334    /* Tell i2c-core a new client has arrived */ 
     335    if ((err = isa_attach_client(new_client))) 
     336      goto ERROR3; 
     337     
     338    /* Register a new directory entry with module sensors */ 
     339    if ((err = sensors_register_entry((struct i2c_client *) new_client,"lm78", 
     340                                      lm78_dir_table_template) < 0)) 
     341      goto ERROR4; 
     342    ((struct lm78_data *) (new_client->data)) -> sysctl_id = err; 
     343 
     344    /* Initialize the LM78 chip */ 
    161345    lm78_init_client((struct i2c_client *) new_client); 
     346    continue; 
     347 
     348/* OK, this is not exactly good programming practice, usually. But it is 
     349   very code-efficient in this case. */ 
     350 
     351ERROR4: 
     352    isa_detach_client(new_client); 
     353ERROR3: 
     354    lm78_remove_client((struct i2c_client *) new_client); 
     355ERROR2: 
     356    kfree(new_client); 
     357ERROR1: 
     358    release_region(address, LM78_EXTENT); 
    162359  } 
    163360  return err; 
     361 
    164362} 
    165363 
     
    167365int lm78_detach_isa(struct isa_client *client) 
    168366{ 
    169   int err; 
     367  int err,i; 
     368  for (i = 0; i < MAX_LM78_NR; i++) 
     369    if ((client == (struct isa_client *) (lm78_list[i]))) 
     370      break; 
     371  if (i == MAX_LM78_NR) { 
     372    printk("lm78.o: Client to detach not found.\n"); 
     373    return -ENOENT; 
     374  } 
     375 
     376  sensors_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id); 
     377 
    170378  if ((err = isa_detach_client(client))) { 
    171379    printk("lm78.o: Client deregistration failed, client not detached.\n"); 
    172380    return err; 
    173381  } 
    174   release_region(client->isa_addr,LM78_EXTENT); 
    175382  lm78_remove_client((struct i2c_client *) client); 
    176383  kfree(client); 
     384  release_region(client->isa_addr,LM78_EXTENT); 
    177385  return 0; 
    178386} 
     
    195403    /* Real detection code goes here */ 
    196404 
    197     new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); 
    198     new_client->addr = address; 
    199     if ((err = lm78_new_client(adapter,new_client))) { 
    200       kfree(new_client); 
     405    /* Allocate space for a new client structure */ 
     406    if (! (new_client = kmalloc(sizeof(struct i2c_client) +  
     407                                sizeof(struct lm78_data), 
     408                               GFP_KERNEL))) { 
     409      err = -ENOMEM; 
    201410      continue; 
    202411    } 
    203     if ((err = i2c_attach_client(new_client))) { 
    204       lm78_remove_client(new_client); 
    205       kfree(new_client); 
    206       continue; 
    207     } 
     412 
     413    /* Fill the new client structure with data */ 
     414    new_client->data = (struct lm78_data *) (new_client + 1); 
     415    new_client->addr = address; 
     416    if ((err = lm78_new_client(adapter,new_client))) 
     417      goto ERROR2; 
     418 
     419    /* Tell i2c-core a new client has arrived */ 
     420    if ((err = i2c_attach_client(new_client)))  
     421      goto ERROR3; 
     422 
     423    /* Register a new directory entry with module sensors */ 
     424    if ((err = sensors_register_entry(new_client,"lm78", 
     425                                      lm78_dir_table_template) < 0)) 
     426      goto ERROR4; 
     427    ((struct lm78_data *) (new_client->data))->sysctl_id = err; 
     428 
     429    /* Initialize the LM78 chip */ 
    208430    lm78_init_client(new_client); 
     431    continue; 
     432 
     433/* OK, this is not exactly good programming practice, usually. But it is 
     434   very code-efficient in this case. */ 
     435ERROR4: 
     436    i2c_detach_client(new_client); 
     437ERROR3: 
     438    lm78_remove_client((struct i2c_client *) new_client); 
     439ERROR2: 
     440    kfree(new_client); 
    209441  } 
    210442  return err; 
     
    213445int lm78_detach_smbus(struct i2c_client *client) 
    214446{ 
    215   int err; 
     447  int err,i; 
     448  for (i = 0; i < MAX_LM78_NR; i++) 
     449    if (client == lm78_list[i]) 
     450      break; 
     451  if ((i == MAX_LM78_NR)) { 
     452    printk("lm78.o: Client to detach not found.\n"); 
     453    return -ENOENT; 
     454  } 
     455 
     456  sensors_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id); 
     457 
    216458  if ((err = i2c_detach_client(client))) { 
    217459    printk("lm78.o: Client deregistration failed, client not detached.\n"); 
     
    229471{ 
    230472  int i; 
     473  struct lm78_data *data; 
    231474 
    232475  /* First, seek out an empty slot */ 
     
    241484   
    242485  lm78_list[i] = new_client; 
    243   lm78_semaphores[i] = MUTEX; 
    244   new_client->data = &lm78_semaphores[i]; 
    245486  strcpy(new_client->name,"LM78 chip"); 
    246487  new_client->id = i; 
    247488  new_client->adapter = adapter; 
    248489  new_client->driver = &lm78_driver; 
     490  data = new_client->data; 
     491  data->valid = 0; 
     492  data->lock = MUTEX; 
     493  data->update_lock = MUTEX; 
    249494  return 0; 
    250495} 
    251496 
     497/* Inverse of lm78_new_client */ 
    252498void lm78_remove_client(struct i2c_client *client) 
    253499{ 
    254500  int i; 
    255501  for (i = 0; i < MAX_LM78_NR; i++) 
    256     if (client == lm78_list[i]) 
     502    if (client == lm78_list[i])  
    257503      lm78_list[i] = NULL; 
    258 } 
    259  
    260 /* Called when we have found a new LM78. It should set limits, etc. */ 
    261 void lm78_init_client(struct i2c_client *client) 
    262 { 
    263504} 
    264505 
     
    317558} 
    318559 
    319 /* ANYTHING BELOW IS JUST AN EXAMPLE. IGNORE IF YOU WANT TO BASE A DRIVER 
    320    ON THE CODE IN THIS FILE */ 
    321  
    322 /* Stupid entry in /proc */ 
    323 static int proc_function(char *buf, char **start, off_t offset, int len, 
    324                          int unused) 
    325 { 
     560/* Called when we have found a new LM78. It should set limits, etc. */ 
     561void lm78_init_client(struct i2c_client *client) 
     562{ 
     563  /* Reset all except Watchdog values and last conversion values 
     564     This sets fan-divs to 2, among others */ 
     565  lm78_write_value(client,LM78_REG_CONFIG,0x80); 
     566 
     567  lm78_write_value(client,LM78_REG_IN_MIN(0),IN_TO_REG(LM78_INIT_IN_MIN_0,0)); 
     568  lm78_write_value(client,LM78_REG_IN_MAX(0),IN_TO_REG(LM78_INIT_IN_MAX_0,0)); 
     569  lm78_write_value(client,LM78_REG_IN_MIN(1),IN_TO_REG(LM78_INIT_IN_MIN_1,1)); 
     570  lm78_write_value(client,LM78_REG_IN_MAX(1),IN_TO_REG(LM78_INIT_IN_MAX_1,1)); 
     571  lm78_write_value(client,LM78_REG_IN_MIN(2),IN_TO_REG(LM78_INIT_IN_MIN_2,2)); 
     572  lm78_write_value(client,LM78_REG_IN_MAX(2),IN_TO_REG(LM78_INIT_IN_MAX_2,2)); 
     573  lm78_write_value(client,LM78_REG_IN_MIN(3),IN_TO_REG(LM78_INIT_IN_MIN_3,3)); 
     574  lm78_write_value(client,LM78_REG_IN_MAX(3),IN_TO_REG(LM78_INIT_IN_MAX_3,3)); 
     575  lm78_write_value(client,LM78_REG_IN_MIN(4),IN_TO_REG(LM78_INIT_IN_MIN_4,4)); 
     576  lm78_write_value(client,LM78_REG_IN_MAX(4),IN_TO_REG(LM78_INIT_IN_MAX_4,4)); 
     577  lm78_write_value(client,LM78_REG_IN_MIN(5),IN_TO_REG(LM78_INIT_IN_MIN_5,5)); 
     578  lm78_write_value(client,LM78_REG_IN_MAX(5),IN_TO_REG(LM78_INIT_IN_MAX_5,5)); 
     579  lm78_write_value(client,LM78_REG_IN_MIN(6),IN_TO_REG(LM78_INIT_IN_MIN_6,6)); 
     580  lm78_write_value(client,LM78_REG_IN_MAX(6),IN_TO_REG(LM78_INIT_IN_MAX_6,6)); 
     581  lm78_write_value(client,LM78_REG_FAN_MIN(1),FAN_TO_REG(LM78_INIT_FAN_MIN_1)); 
     582  lm78_write_value(client,LM78_REG_FAN_MIN(2),FAN_TO_REG(LM78_INIT_FAN_MIN_2)); 
     583  lm78_write_value(client,LM78_REG_FAN_MIN(3),FAN_TO_REG(LM78_INIT_FAN_MIN_3)); 
     584  lm78_write_value(client,LM78_REG_TEMP_OVER,TEMP_TO_REG(LM78_INIT_TEMP_OVER)); 
     585  lm78_write_value(client,LM78_REG_TEMP_HYST,TEMP_TO_REG(LM78_INIT_TEMP_HYST)); 
     586 
     587  /* Start monitoring */ 
     588  lm78_write_value(client,LM78_REG_CONFIG, 
     589                   (lm78_read_value(client,LM78_REG_CONFIG) & 0xf7) | 0x01); 
     590   
     591} 
     592 
     593void lm78_update_client(struct i2c_client *client) 
     594{ 
     595  struct lm78_data *data =  client->data; 
    326596  int i; 
    327   len = 0; 
    328   for (i = 0; i < MAX_LM78_NR; i++) 
    329     if(lm78_list[i]) { 
    330       if(i2c_is_isa_client(lm78_list[i]))  
    331         len += sprintf(buf+len,"(isa) %d: address=%x\n",i, 
    332                        ((struct isa_client *) (lm78_list[i]))->isa_addr); 
    333       else 
    334         len += sprintf(buf+len,"(i2c) %d: address=%x\n",i, 
    335                        lm78_list[i]->addr); 
     597 
     598  down(&data->update_lock); 
     599 
     600  if ((jiffies - data->last_updated > HZ+HZ/2 ) || 
     601      (jiffies < data->last_updated) || ! data->valid) { 
     602 
     603    for (i = 0; i <= 6; i++) { 
     604      data->in[i]     = lm78_read_value(client,LM78_REG_IN(i)); 
     605      data->in_min[i] = lm78_read_value(client,LM78_REG_IN_MIN(i)); 
     606      data->in_max[i] = lm78_read_value(client,LM78_REG_IN_MAX(i)); 
    336607    } 
    337   return len; 
    338 } 
    339  
    340 /* OK, this is a test entry. Just ignore, it is not important. */ 
    341 static struct proc_dir_entry proc_entry = 
    342         { 
    343           0,12,"sensors-test", 
    344           S_IFREG | S_IRUGO, 1, 0, 0, 
    345           0, NULL, 
    346           &proc_function 
    347         }; 
    348  
     608    for (i = 1; i <= 3; i++) { 
     609      data->fan[i-1] = lm78_read_value(client,LM78_REG_FAN(i)); 
     610      data->fan_min[i-1] = lm78_read_value(client,LM78_REG_FAN_MIN(i)); 
     611    } 
     612    data->temp = lm78_read_value(client,LM78_REG_TEMP); 
     613    data->temp_over = lm78_read_value(client,LM78_REG_TEMP_OVER); 
     614    data->temp_hyst = lm78_read_value(client,LM78_REG_TEMP_HYST); 
     615    i = lm78_read_value(client,LM78_REG_VID_FANDIV); 
     616    data->vid = i & 0x0f; 
     617    data->fan_div[0] = (i >> 4) & 0x03; 
     618    data->fan_div[1] = i >> 6; 
     619    data->alarms = lm78_read_value(client,LM78_REG_ALARM1) + 
     620                   (lm78_read_value(client,LM78_REG_ALARM2) >> 8); 
     621    data->last_updated = jiffies; 
     622    data->valid = 1; 
     623  } 
     624 
     625  up(&data->update_lock); 
     626} 
     627 
     628/* This function is called when /proc/sys/dev/lm78-???/... is accessed */ 
     629int lm78_proc (ctl_table *ctl, int write, struct file * filp, 
     630               void *buffer, size_t *lenp) 
     631{ 
     632  int nrels,mag; 
     633  long results[7]; 
     634  struct i2c_client *client = ctl -> extra1; 
     635 
     636  /* If buffer is size 0, or we try to read when not at the start, we  
     637     return nothing. Note that I think writing when not at the start 
     638     does not work either, but anyway, this is straight from the kernel 
     639     sources. */ 
     640  if (!*lenp || (filp->f_pos && !write)) { 
     641    *lenp = 0; 
     642    return 0; 
     643  } 
     644 
     645  /* How many numbers are found within these files, and how to scale them? */ 
     646  switch (ctl->ctl_name) { 
     647    case LM78_SYSCTL_IN0: case LM78_SYSCTL_IN1: case LM78_SYSCTL_IN2:  
     648    case LM78_SYSCTL_IN3: case LM78_SYSCTL_IN4: case LM78_SYSCTL_IN5: 
     649    case LM78_SYSCTL_IN6: 
     650      nrels=3; 
     651      mag=2; 
     652      break; 
     653    case LM78_SYSCTL_FAN_DIV: case LM78_SYSCTL_TEMP: 
     654      nrels=3; 
     655      mag=0; 
     656      break; 
     657    case LM78_SYSCTL_FAN1: case LM78_SYSCTL_FAN2: case LM78_SYSCTL_FAN3: 
     658      nrels=2; 
     659      mag=0; 
     660      break; 
     661    case LM78_SYSCTL_VID: 
     662      nrels=1; 
     663      mag=2; 
     664      break; 
     665    case LM78_SYSCTL_ALARMS: 
     666      nrels=1; 
     667      mag=0; 
     668      break; 
     669    default: /* Should never be called */ 
     670      return -EINVAL; 
     671  } 
     672  
     673  /* OK, try writing stuff. */ 
     674  if (write) { 
     675    sensors_parse_reals(&nrels,buffer,*lenp,results,mag); 
     676    if (nrels == 0) 
     677      return 0; 
     678    switch (ctl->ctl_name) { 
     679      case LM78_SYSCTL_IN0: write_in(client,0,nrels,results); break; 
     680      case LM78_SYSCTL_IN1: write_in(client,1,nrels,results); break; 
     681      case LM78_SYSCTL_IN2: write_in(client,2,nrels,results); break; 
     682      case LM78_SYSCTL_IN3: write_in(client,3,nrels,results); break; 
     683      case LM78_SYSCTL_IN4: write_in(client,4,nrels,results); break; 
     684      case LM78_SYSCTL_IN5: write_in(client,5,nrels,results); break; 
     685      case LM78_SYSCTL_IN6: write_in(client,6,nrels,results); break; 
     686      case LM78_SYSCTL_FAN1: write_fan(client,1,nrels,results); break; 
     687      case LM78_SYSCTL_FAN2: write_fan(client,2,nrels,results); break; 
     688      case LM78_SYSCTL_FAN3: write_fan(client,3,nrels,results); break; 
     689      case LM78_SYSCTL_FAN_DIV: write_fan_div(client,nrels,results);break; 
     690      case LM78_SYSCTL_TEMP: write_temp(client,nrels,results);break; 
     691      case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: break; 
     692      default: /* Should never be called */ *lenp=0; return -EINVAL; break; 
     693    } 
     694    filp->f_pos += *lenp; 
     695    return 0; 
     696  } else { /* read */ 
     697    /* Update all values in LM_Sensor_Data */ 
     698 
     699    lm78_update_client((struct i2c_client *) (ctl->extra1)); 
     700 
     701    /* Read the values to print into results */ 
     702    switch (ctl->ctl_name) { 
     703      case LM78_SYSCTL_IN0: read_in(client,0,results);break; 
     704      case LM78_SYSCTL_IN1: read_in(client,1,results);break; 
     705      case LM78_SYSCTL_IN2: read_in(client,2,results);break; 
     706      case LM78_SYSCTL_IN3: read_in(client,3,results);break; 
     707      case LM78_SYSCTL_IN4: read_in(client,4,results);break; 
     708      case LM78_SYSCTL_IN5: read_in(client,5,results);break; 
     709      case LM78_SYSCTL_IN6: read_in(client,6,results);break; 
     710      case LM78_SYSCTL_FAN1: read_fan(client,1,results);break; 
     711      case LM78_SYSCTL_FAN2: read_fan(client,2,results);break; 
     712      case LM78_SYSCTL_FAN3: read_fan(client,3,results);break; 
     713      case LM78_SYSCTL_TEMP: read_temp(client,results);break; 
     714      case LM78_SYSCTL_FAN_DIV: read_fan_div(client,results);break; 
     715      case LM78_SYSCTL_VID: read_vid(client,results);break; 
     716      case LM78_SYSCTL_ALARMS: read_alarms(client,results);break; 
     717      default: /* Should never be called */ return -EINVAL; 
     718    } 
     719    /* OK, print it now */ 
     720    sensors_write_reals(nrels,buffer,lenp,results,mag); 
     721    filp->f_pos += *lenp; 
     722    return 0; 
     723  } 
     724} 
     725 
     726/* This function is called when a sysctl on a lm78 file is done */ 
     727int lm78_sysctl (ctl_table *table, int *name, int nlen, void *oldval,  
     728               size_t *oldlenp, void *newval, size_t newlen, 
     729               void **context) 
     730{ 
     731  long results[7]; 
     732  int nrels,oldlen; 
     733  struct i2c_client *client = table -> extra1; 
     734  
     735  /* How many numbers are found within these files, and how to scale them? */ 
     736  switch (table->ctl_name) { 
     737    case LM78_SYSCTL_IN0: case LM78_SYSCTL_IN1: case LM78_SYSCTL_IN2:  
     738    case LM78_SYSCTL_IN3: case LM78_SYSCTL_IN4: case LM78_SYSCTL_IN5:  
     739    case LM78_SYSCTL_IN6: case LM78_SYSCTL_TEMP: case LM78_SYSCTL_FAN_DIV: 
     740      nrels=3; 
     741      break; 
     742    case LM78_SYSCTL_FAN1: case LM78_SYSCTL_FAN2: case LM78_SYSCTL_FAN3: 
     743      nrels=2; 
     744      break; 
     745    case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: 
     746      nrels=1; 
     747      break; 
     748    default: /* Should never be called */ 
     749      return -EINVAL; 
     750  } 
     751 
     752  /* Check if we need to output the old values */ 
     753  if (oldval && oldlenp && ! get_user_data(oldlen,oldlenp) && oldlen) { 
     754 
     755    /* Update all values in LM_Sensor_Data */ 
     756    lm78_update_client((struct i2c_client *) (table->extra1)); 
     757    switch (table->ctl_name) { 
     758      case LM78_SYSCTL_IN0: read_in(client,0,results);break; 
     759      case LM78_SYSCTL_IN1: read_in(client,1,results);break; 
     760      case LM78_SYSCTL_IN2: read_in(client,2,results);break; 
     761      case LM78_SYSCTL_IN3: read_in(client,3,results);break; 
     762      case LM78_SYSCTL_IN4: read_in(client,4,results);break; 
     763      case LM78_SYSCTL_IN5: read_in(client,5,results);break; 
     764      case LM78_SYSCTL_IN6: read_in(client,6,results);break; 
     765      case LM78_SYSCTL_FAN1: read_fan(client,1,results);break; 
     766      case LM78_SYSCTL_FAN2: read_fan(client,2,results);break; 
     767      case LM78_SYSCTL_FAN3: read_fan(client,3,results);break; 
     768      case LM78_SYSCTL_TEMP: read_temp(client,results);break; 
     769      case LM78_SYSCTL_FAN_DIV: read_fan_div(client,results);break; 
     770      case LM78_SYSCTL_VID: read_vid(client,results);break; 
     771      case LM78_SYSCTL_ALARMS: read_alarms(client,results);break; 
     772      default: /* Should never be called */ return -EINVAL; 
     773    } 
    349774     
     775    /* Note the rounding factor! */ 
     776    if (nrels * sizeof(long) < oldlen) 
     777      oldlen = nrels * sizeof(long); 
     778    oldlen = (oldlen / sizeof(long)) * sizeof(long); 
     779    copy_to_user(oldval,results,oldlen); 
     780    put_user(oldlen,oldlenp); 
     781  } 
     782 
     783  /* Check to see whether we need to read the new values */ 
     784  if (newval && newlen) { 
     785    if (nrels * sizeof(long) < newlen) 
     786      newlen = nrels * sizeof(long); 
     787    nrels = newlen / sizeof(long); 
     788    newlen = (newlen / sizeof(long)) * sizeof(long); 
     789    copy_from_user(results,newval,newlen); 
     790     
     791    switch (table->ctl_name) { 
     792      case LM78_SYSCTL_IN0: write_in(client,0,nrels,results); break; 
     793      case LM78_SYSCTL_IN1: write_in(client,1,nrels,results); break; 
     794      case LM78_SYSCTL_IN2: write_in(client,2,nrels,results); break; 
     795      case LM78_SYSCTL_IN3: write_in(client,3,nrels,results); break; 
     796      case LM78_SYSCTL_IN4: write_in(client,4,nrels,results); break; 
     797      case LM78_SYSCTL_IN5: write_in(client,5,nrels,results); break; 
     798      case LM78_SYSCTL_IN6: write_in(client,6,nrels,results); break; 
     799      case LM78_SYSCTL_FAN1: write_fan(client,1,nrels,results); break; 
     800      case LM78_SYSCTL_FAN2: write_fan(client,2,nrels,results); break; 
     801      case LM78_SYSCTL_FAN3: write_fan(client,3,nrels,results); break; 
     802      case LM78_SYSCTL_TEMP: write_temp(client,nrels,results); break; 
     803      case LM78_SYSCTL_FAN_DIV: write_fan_div(client,nrels,results);break; 
     804      case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: break; 
     805      default: /* Should never be called */ return -EINVAL; break; 
     806    } 
     807  } 
     808  return 1; /* We have done all the work */ 
     809} 
     810 
     811void write_in(struct i2c_client *client, int nr, int nrels, long *results) 
     812{ 
     813  struct lm78_data *data = client->data; 
     814  if (nrels >= 1) { 
     815    data->in_min[nr] = IN_TO_REG(results[0],nr); 
     816    lm78_write_value(client,LM78_REG_IN_MIN(nr),data->in_min[nr]); 
     817  } 
     818  if (nrels >= 2) { 
     819    data->in_max[nr] = IN_TO_REG(results[1],nr); 
     820    lm78_write_value(client,LM78_REG_IN_MAX(nr),data->in_max[nr]); 
     821  } 
     822} 
     823 
     824void read_in(struct i2c_client *client, int nr, long *results) 
     825{ 
     826  struct lm78_data *data = client->data; 
     827  results[0] = IN_FROM_REG(data->in_min[nr],nr); 
     828  results[1] = IN_FROM_REG(data->in_min[nr],nr); 
     829  results[2] = IN_FROM_REG(data->in_min[nr],nr); 
     830} 
     831 
     832void write_fan(struct i2c_client *client, int nr, int nrels, long *results) 
     833{ 
     834  struct lm78_data *data = client->data; 
     835  if (nrels >= 1) { 
     836    data->fan_min[nr-1] = FAN_TO_REG(results[0]); 
     837    lm78_write_value(client,LM78_REG_FAN_MIN(nr),data->fan_min[nr-1]); 
     838  } 
     839} 
     840 
     841void read_fan(struct i2c_client *client, int nr, long *results) 
     842{ 
     843  struct lm78_data *data = client->data; 
     844  results[0] = FAN_FROM_REG(data->fan_min[nr-1]); 
     845  results[1] = FAN_FROM_REG(data->fan[nr-1]); 
     846} 
     847 
     848void write_temp(struct i2c_client *client, int nrels, long *results) 
     849{ 
     850  struct lm78_data *data = client->data; 
     851  if (nrels >= 1) { 
     852    data->temp_over = TEMP_TO_REG(results[0]); 
     853    lm78_write_value(client,LM78_REG_TEMP_OVER,data->temp_over); 
     854  } 
     855  if (nrels >= 2) { 
     856    data->temp_hyst = TEMP_TO_REG(results[0]); 
     857    lm78_write_value(client,LM78_REG_TEMP_HYST,data->temp_hyst); 
     858  } 
     859} 
     860 
     861void read_temp(struct i2c_client *client, long *results) 
     862{ 
     863  struct lm78_data *data = client->data; 
     864  results[0] = TEMP_FROM_REG(data->temp_over); 
     865  results[1] = TEMP_FROM_REG(data->temp_hyst); 
     866  results[2] = TEMP_FROM_REG(data->temp); 
     867} 
     868 
     869void read_vid(struct i2c_client *client, long *results) 
     870{ 
     871  struct lm78_data *data = client->data; 
     872  results[0] = VID_FROM_REG(data->vid); 
     873} 
     874 
     875void read_alarms(struct i2c_client *client, long *results) 
     876{ 
     877  struct lm78_data *data = client->data; 
     878  results[0] = ALARMS_FROM_REG(data->alarms); 
     879} 
     880 
     881void read_fan_div(struct i2c_client *client, long *results) 
     882{ 
     883  struct lm78_data *data = client->data; 
     884  results[0] = DIV_FROM_REG(data->fan_div[0]); 
     885  results[1] = DIV_FROM_REG(data->fan_div[1]); 
     886} 
     887  
     888void write_fan_div(struct i2c_client *client, int nrels, long *results) 
     889{ 
     890  struct lm78_data *data = client->data; 
     891  if (nrels >= 2) 
     892    data->fan_div[1] = DIV_TO_REG(results[1]); 
     893  if (nrels >= 1) { 
     894    data->fan_div[0] = DIV_TO_REG(results[0]); 
     895    lm78_write_value(client,LM78_REG_VID_FANDIV, 
     896                     (data->fan_div[0] >> 4) | (data->fan_div[1] >> 6)); 
     897  } 
     898} 
     899 
    350900int lm78_init(void) 
    351901{ 
     
    354904  printk("lm78.o version %s (%s)\n",LM_VERSION,LM_DATE); 
    355905  lm78_initialized = 0; 
    356  
    357   /* OK, we register some stupid proc file here. This is *just* *temporary*, 
    358     for test purposes. Ignore if you want. Only works for kernels 2.0.x. */ 
    359   if ((res = proc_register_dynamic(&proc_root,&proc_entry))) { 
    360     printk("lm78.o: Couldn't create /proc/sensors-test, " 
    361            "module not inserted.\n"); 
    362     lm78_cleanup(); 
    363     return res; 
    364   } 
    365   lm78_initialized ++; 
    366906 
    367907  if ((res =i2c_add_driver(&lm78_driver))) { 
     
    378918  int res; 
    379919 
    380   if (lm78_initialized >= 2) { 
     920  if (lm78_initialized >= 1) { 
    381921    if ((res = i2c_del_driver(&lm78_driver))) { 
    382922      printk("lm78.o: Driver deregistration failed, module not removed.\n"); 
     
    386926    lm78_initialized --; 
    387927 
    388   if (lm78_initialized >= 1) { 
    389     if((res = proc_unregister(&proc_root,proc_entry.low_ino))) { 
    390       printk("lm78.o: Deregistration of /proc/sensors_test failed, " 
    391               "module not removed.\n"); 
    392       return res; 
    393     } 
    394   } else 
    395     lm78_initialized --; 
    396928  return 0; 
    397929}