Changeset 28

Show
Ignore:
Timestamp:
12/04/98 00:15:17 (15 years ago)
Author:
frodo
Message:

Simplification of /proc files functions in chip drivers

I moved a large part of the proc and sysctl call-back functions into
sensors.c. The result saved about 100 lines in lm78.c; it now uses only
2 pages according to lsmod, instead of 3! Also, other modules can use
the same functions, saving coding efforts and keeping them small.

I also fixed a fan_div display error.

Expect more code to be moved to sensors.c: I am writing lm75.c, and
most things which are in both modules (and so probably general purpose)
will be moved to sensors.c.

Location:
lm-sensors/trunk
Files:
6 modified

Legend:

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

    r27 r28  
    3434#include "compat.h" 
    3535 
    36 /* Many LM78 constants needed below */ 
     36/* Many LM78 constants specified below */ 
    3737 
    3838/* Length of ISA address segment */ 
     
    8282#define ALARMS_FROM_REG(val) (val) 
    8383 
    84 #define DIV_FROM_REG(val) (1 >> (val)) 
     84#define DIV_FROM_REG(val) (1 << (val)) 
    8585#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) 
    8686 
     
    204204static void lm78_init_client(struct i2c_client *client); 
    205205 
    206 static int lm78_sysctl (ctl_table *table, int *name, int nlen, void *oldval,  
    207                         size_t *oldlenp, void *newval, size_t newlen, 
    208                         void **context); 
    209 static int lm78_proc (ctl_table *ctl, int write, struct file * filp, 
    210                       void *buffer, size_t *lenp); 
    211  
    212  
    213 static void write_in(struct i2c_client *client, int nr, int nrels,  
    214                      long *results); 
    215 static void read_in(struct i2c_client *client, int nr, long *results); 
    216 static void write_fan(struct i2c_client *client, int nr, int nrels,  
    217                       long *results); 
    218 static void read_fan(struct i2c_client *client, int nr, long *results); 
    219 static void write_temp(struct i2c_client *client, int nrels, long *results); 
    220 static void read_temp(struct i2c_client *client, long *results); 
    221 static void read_vid(struct i2c_client *client, long *results); 
    222 static void read_alarms(struct i2c_client *client, long *results); 
    223 static void write_fan_div(struct i2c_client *client, int nrels, long *results); 
    224 static void read_fan_div(struct i2c_client *client, long *results); 
    225  
    226  
     206 
     207void lm78_in(struct i2c_client *client, int operation, int ctl_name, 
     208             int *nrels_mag, long *results); 
     209void lm78_fan(struct i2c_client *client, int operation, int ctl_name, 
     210              int *nrels_mag, long *results); 
     211void lm78_temp(struct i2c_client *client, int operation, int ctl_name, 
     212               int *nrels_mag, long *results); 
     213void lm78_vid(struct i2c_client *client, int operation, int ctl_name, 
     214              int *nrels_mag, long *results); 
     215void lm78_alarms(struct i2c_client *client, int operation, int ctl_name, 
     216                 int *nrels_mag, long *results); 
     217void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name, 
     218                  int *nrels_mag, long *results); 
    227219 
    228220/* I choose here for semi-static LM78 allocation. Complete dynamic 
     
    255247   when a new copy is allocated. */ 
    256248static ctl_table lm78_dir_table_template[] = { 
    257   { LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    258   { LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    259   { LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    260   { LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    261   { LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    262   { LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    263   { LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    264   { LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    265   { LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    266   { LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    267   { LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    268   { LM78_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    269   { LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    270   { LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     249  { LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real, 
     250    &sensors_sysctl_real, NULL, &lm78_in }, 
     251  { LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real, 
     252    &sensors_sysctl_real, NULL, &lm78_in }, 
     253  { LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real, 
     254    &sensors_sysctl_real, NULL, &lm78_in }, 
     255  { LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real, 
     256    &sensors_sysctl_real, NULL, &lm78_in }, 
     257  { LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real, 
     258    &sensors_sysctl_real, NULL, &lm78_in }, 
     259  { LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real, 
     260    &sensors_sysctl_real, NULL, &lm78_in }, 
     261  { LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real, 
     262    &sensors_sysctl_real, NULL, &lm78_in }, 
     263  { LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real, 
     264    &sensors_sysctl_real, NULL, &lm78_fan }, 
     265  { LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real, 
     266    &sensors_sysctl_real, NULL, &lm78_fan }, 
     267  { LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real, 
     268    &sensors_sysctl_real, NULL, &lm78_fan }, 
     269  { LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, 
     270    &sensors_sysctl_real, NULL, &lm78_temp }, 
     271  { LM78_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real, 
     272    &sensors_sysctl_real, NULL, &lm78_vid }, 
     273  { LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real, 
     274    &sensors_sysctl_real, NULL, &lm78_fan_div }, 
     275  { LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real, 
     276    &sensors_sysctl_real, NULL, &lm78_alarms }, 
    271277  { 0 } 
    272278}; 
     
    700706} 
    701707 
    702 /* This function is called when /proc/sys/dev/lm78-???/... is accessed */ 
    703 int lm78_proc (ctl_table *ctl, int write, struct file * filp, 
    704                void *buffer, size_t *lenp) 
    705 { 
    706   int nrels,mag; 
    707   long results[7]; 
    708   struct i2c_client *client = ctl -> extra1; 
    709  
    710   /* If buffer is size 0, or we try to read when not at the start, we  
    711      return nothing. Note that I think writing when not at the start 
    712      does not work either, but anyway, this is straight from the kernel 
    713      sources. */ 
    714   if (!*lenp || (filp->f_pos && !write)) { 
    715     *lenp = 0; 
    716     return 0; 
    717   } 
    718  
    719   /* How many numbers are found within these files, and how to scale them? */ 
    720   switch (ctl->ctl_name) { 
    721     case LM78_SYSCTL_IN0: case LM78_SYSCTL_IN1: case LM78_SYSCTL_IN2:  
    722     case LM78_SYSCTL_IN3: case LM78_SYSCTL_IN4: case LM78_SYSCTL_IN5: 
    723     case LM78_SYSCTL_IN6: 
    724       nrels=3; 
    725       mag=2; 
    726       break; 
    727     case LM78_SYSCTL_TEMP: 
    728       nrels=3; 
    729       mag=1; 
    730       break; 
    731     case LM78_SYSCTL_FAN_DIV: 
    732       nrels=3; 
    733       mag=0; 
    734       break; 
    735     case LM78_SYSCTL_FAN1: case LM78_SYSCTL_FAN2: case LM78_SYSCTL_FAN3: 
    736       nrels=2; 
    737       mag=0; 
    738       break; 
    739     case LM78_SYSCTL_VID: 
    740       nrels=1; 
    741       mag=2; 
    742       break; 
    743     case LM78_SYSCTL_ALARMS: 
    744       nrels=1; 
    745       mag=0; 
    746       break; 
    747     default: /* Should never be called */ 
    748       return -EINVAL; 
    749   } 
    750   
    751   /* OK, try writing stuff. */ 
    752   if (write) { 
    753     sensors_parse_reals(&nrels,buffer,*lenp,results,mag); 
    754     if (nrels == 0) 
    755       return 0; 
    756     switch (ctl->ctl_name) { 
    757       case LM78_SYSCTL_IN0: write_in(client,0,nrels,results); break; 
    758       case LM78_SYSCTL_IN1: write_in(client,1,nrels,results); break; 
    759       case LM78_SYSCTL_IN2: write_in(client,2,nrels,results); break; 
    760       case LM78_SYSCTL_IN3: write_in(client,3,nrels,results); break; 
    761       case LM78_SYSCTL_IN4: write_in(client,4,nrels,results); break; 
    762       case LM78_SYSCTL_IN5: write_in(client,5,nrels,results); break; 
    763       case LM78_SYSCTL_IN6: write_in(client,6,nrels,results); break; 
    764       case LM78_SYSCTL_FAN1: write_fan(client,1,nrels,results); break; 
    765       case LM78_SYSCTL_FAN2: write_fan(client,2,nrels,results); break; 
    766       case LM78_SYSCTL_FAN3: write_fan(client,3,nrels,results); break; 
    767       case LM78_SYSCTL_FAN_DIV: write_fan_div(client,nrels,results);break; 
    768       case LM78_SYSCTL_TEMP: write_temp(client,nrels,results);break; 
    769       case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: break; 
    770       default: /* Should never be called */ *lenp=0; return -EINVAL; break; 
    771     } 
    772     filp->f_pos += *lenp; 
    773     return 0; 
    774   } else { /* read */ 
    775     /* Update all values in LM_Sensor_Data */ 
    776  
    777     lm78_update_client((struct i2c_client *) (ctl->extra1)); 
    778  
    779     /* Read the values to print into results */ 
    780     switch (ctl->ctl_name) { 
    781       case LM78_SYSCTL_IN0: read_in(client,0,results);break; 
    782       case LM78_SYSCTL_IN1: read_in(client,1,results);break; 
    783       case LM78_SYSCTL_IN2: read_in(client,2,results);break; 
    784       case LM78_SYSCTL_IN3: read_in(client,3,results);break; 
    785       case LM78_SYSCTL_IN4: read_in(client,4,results);break; 
    786       case LM78_SYSCTL_IN5: read_in(client,5,results);break; 
    787       case LM78_SYSCTL_IN6: read_in(client,6,results);break; 
    788       case LM78_SYSCTL_FAN1: read_fan(client,1,results);break; 
    789       case LM78_SYSCTL_FAN2: read_fan(client,2,results);break; 
    790       case LM78_SYSCTL_FAN3: read_fan(client,3,results);break; 
    791       case LM78_SYSCTL_TEMP: read_temp(client,results);break; 
    792       case LM78_SYSCTL_FAN_DIV: read_fan_div(client,results);break; 
    793       case LM78_SYSCTL_VID: read_vid(client,results);break; 
    794       case LM78_SYSCTL_ALARMS: read_alarms(client,results);break; 
    795       default: /* Should never be called */ return -EINVAL; 
    796     } 
    797     /* OK, print it now */ 
    798     sensors_write_reals(nrels,buffer,lenp,results,mag); 
    799     filp->f_pos += *lenp; 
    800     return 0; 
    801   } 
    802 } 
    803  
    804 /* This function is called when a sysctl on a lm78 file is done */ 
    805 int lm78_sysctl (ctl_table *table, int *name, int nlen, void *oldval,  
    806                size_t *oldlenp, void *newval, size_t newlen, 
    807                void **context) 
    808 { 
    809   long results[7]; 
    810   int nrels,oldlen; 
    811   struct i2c_client *client = table -> extra1; 
    812   
    813   /* How many numbers are found within these files, and how to scale them? */ 
    814   switch (table->ctl_name) { 
    815     case LM78_SYSCTL_IN0: case LM78_SYSCTL_IN1: case LM78_SYSCTL_IN2:  
    816     case LM78_SYSCTL_IN3: case LM78_SYSCTL_IN4: case LM78_SYSCTL_IN5:  
    817     case LM78_SYSCTL_IN6: case LM78_SYSCTL_TEMP:  
    818     case LM78_SYSCTL_FAN_DIV: 
    819       nrels=3; 
    820       break; 
    821     case LM78_SYSCTL_FAN1: case LM78_SYSCTL_FAN2: case LM78_SYSCTL_FAN3: 
    822       nrels=2; 
    823       break; 
    824     case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: 
    825       nrels=1; 
    826       break; 
    827     default: /* Should never be called */ 
    828       return -EINVAL; 
    829   } 
    830  
    831   /* Check if we need to output the old values */ 
    832   if (oldval && oldlenp && ! get_user_data(oldlen,oldlenp) && oldlen) { 
    833  
    834     /* Update all values in LM_Sensor_Data */ 
    835     lm78_update_client((struct i2c_client *) (table->extra1)); 
    836     switch (table->ctl_name) { 
    837       case LM78_SYSCTL_IN0: read_in(client,0,results);break; 
    838       case LM78_SYSCTL_IN1: read_in(client,1,results);break; 
    839       case LM78_SYSCTL_IN2: read_in(client,2,results);break; 
    840       case LM78_SYSCTL_IN3: read_in(client,3,results);break; 
    841       case LM78_SYSCTL_IN4: read_in(client,4,results);break; 
    842       case LM78_SYSCTL_IN5: read_in(client,5,results);break; 
    843       case LM78_SYSCTL_IN6: read_in(client,6,results);break; 
    844       case LM78_SYSCTL_FAN1: read_fan(client,1,results);break; 
    845       case LM78_SYSCTL_FAN2: read_fan(client,2,results);break; 
    846       case LM78_SYSCTL_FAN3: read_fan(client,3,results);break; 
    847       case LM78_SYSCTL_TEMP: read_temp(client,results);break; 
    848       case LM78_SYSCTL_FAN_DIV: read_fan_div(client,results);break; 
    849       case LM78_SYSCTL_VID: read_vid(client,results);break; 
    850       case LM78_SYSCTL_ALARMS: read_alarms(client,results);break; 
    851       default: /* Should never be called */ return -EINVAL; 
    852     } 
    853      
    854     /* Note the rounding factor! */ 
    855     if (nrels * sizeof(long) < oldlen) 
    856       oldlen = nrels * sizeof(long); 
    857     oldlen = (oldlen / sizeof(long)) * sizeof(long); 
    858     copy_to_user(oldval,results,oldlen); 
    859     put_user(oldlen,oldlenp); 
    860   } 
    861  
    862   /* Check to see whether we need to read the new values */ 
    863   if (newval && newlen) { 
    864     if (nrels * sizeof(long) < newlen) 
    865       newlen = nrels * sizeof(long); 
    866     nrels = newlen / sizeof(long); 
    867     newlen = (newlen / sizeof(long)) * sizeof(long); 
    868     copy_from_user(results,newval,newlen); 
    869      
    870     switch (table->ctl_name) { 
    871       case LM78_SYSCTL_IN0: write_in(client,0,nrels,results); break; 
    872       case LM78_SYSCTL_IN1: write_in(client,1,nrels,results); break; 
    873       case LM78_SYSCTL_IN2: write_in(client,2,nrels,results); break; 
    874       case LM78_SYSCTL_IN3: write_in(client,3,nrels,results); break; 
    875       case LM78_SYSCTL_IN4: write_in(client,4,nrels,results); break; 
    876       case LM78_SYSCTL_IN5: write_in(client,5,nrels,results); break; 
    877       case LM78_SYSCTL_IN6: write_in(client,6,nrels,results); break; 
    878       case LM78_SYSCTL_FAN1: write_fan(client,1,nrels,results); break; 
    879       case LM78_SYSCTL_FAN2: write_fan(client,2,nrels,results); break; 
    880       case LM78_SYSCTL_FAN3: write_fan(client,3,nrels,results); break; 
    881       case LM78_SYSCTL_TEMP: write_temp(client,nrels,results); break; 
    882       case LM78_SYSCTL_FAN_DIV: write_fan_div(client,nrels,results);break; 
    883       case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: break; 
    884       default: /* Should never be called */ return -EINVAL; break; 
    885     } 
    886   } 
    887   return 1; /* We have done all the work */ 
    888 } 
    889  
    890 void write_in(struct i2c_client *client, int nr, int nrels, long *results) 
     708 
     709/* The next few functions are the call-back functions of the /proc/sys and 
     710   sysctl files. Which function is used is defined in the ctl_table in 
     711   the extra1 field. 
     712   Each function must return the magnitude (power of 10 to divide the date 
     713   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must 
     714   put a maximum of *nrels elements in results reflecting the data of this 
     715   file, and set *nrels to the number it actually put in it, if operation== 
     716   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from 
     717   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE. 
     718   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is 
     719   large enough (by checking the incoming value of *nrels). This is not very 
     720   good practice, but as long as you put less than about 5 values in results, 
     721   you can assume it is large enough. */ 
     722void lm78_in(struct i2c_client *client, int operation, int ctl_name,  
     723             int *nrels_mag, long *results) 
    891724{ 
    892725  struct lm78_data *data = client->data; 
    893   if (nrels >= 1) { 
    894     data->in_min[nr] = IN_TO_REG(results[0],nr); 
    895     lm78_write_value(client,LM78_REG_IN_MIN(nr),data->in_min[nr]); 
    896   } 
    897   if (nrels >= 2) { 
    898     data->in_max[nr] = IN_TO_REG(results[1],nr); 
    899     lm78_write_value(client,LM78_REG_IN_MAX(nr),data->in_max[nr]); 
    900   } 
    901 } 
    902  
    903 void read_in(struct i2c_client *client, int nr, long *results) 
     726  int nr = ctl_name - LM78_SYSCTL_IN0; 
     727 
     728  if (operation == SENSORS_PROC_REAL_INFO) 
     729    *nrels_mag = 2; 
     730  else if (operation == SENSORS_PROC_REAL_READ) { 
     731    lm78_update_client(client); 
     732    results[0] = IN_FROM_REG(data->in_min[nr],nr); 
     733    results[1] = IN_FROM_REG(data->in_max[nr],nr); 
     734    results[2] = IN_FROM_REG(data->in[nr],nr); 
     735    *nrels_mag = 3; 
     736  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     737      if (*nrels_mag >= 1) { 
     738        data->in_min[nr] = IN_TO_REG(results[0],nr); 
     739        lm78_write_value(client,LM78_REG_IN_MIN(nr),data->in_min[nr]); 
     740      } 
     741      if (*nrels_mag >= 2) { 
     742      data->in_max[nr] = IN_TO_REG(results[1],nr); 
     743      lm78_write_value(client,LM78_REG_IN_MAX(nr),data->in_max[nr]); 
     744    } 
     745  } 
     746} 
     747 
     748void lm78_fan(struct i2c_client *client, int operation, int ctl_name, 
     749              int *nrels_mag, long *results) 
    904750{ 
    905751  struct lm78_data *data = client->data; 
    906   results[0] = IN_FROM_REG(data->in_min[nr],nr); 
    907   results[1] = IN_FROM_REG(data->in_max[nr],nr); 
    908   results[2] = IN_FROM_REG(data->in[nr],nr); 
    909 } 
    910  
    911 void write_fan(struct i2c_client *client, int nr, int nrels, long *results) 
     752  int nr = ctl_name - LM78_SYSCTL_FAN1 + 1; 
     753 
     754  if (operation == SENSORS_PROC_REAL_INFO) 
     755    *nrels_mag = 0; 
     756  else if (operation == SENSORS_PROC_REAL_READ) { 
     757    lm78_update_client(client); 
     758    results[0] = FAN_FROM_REG(data->fan_min[nr-1]); 
     759    results[1] = FAN_FROM_REG(data->fan[nr-1]); 
     760    *nrels_mag = 2; 
     761  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     762    if (*nrels_mag >= 1) { 
     763      data->fan_min[nr-1] = FAN_TO_REG(results[0]); 
     764      lm78_write_value(client,LM78_REG_FAN_MIN(nr),data->fan_min[nr-1]); 
     765    } 
     766  } 
     767} 
     768 
     769 
     770void lm78_temp(struct i2c_client *client, int operation, int ctl_name, 
     771               int *nrels_mag, long *results) 
    912772{ 
    913773  struct lm78_data *data = client->data; 
    914   if (nrels >= 1) { 
    915     data->fan_min[nr-1] = FAN_TO_REG(results[0]); 
    916     lm78_write_value(client,LM78_REG_FAN_MIN(nr),data->fan_min[nr-1]); 
    917   } 
    918 } 
    919  
    920 void read_fan(struct i2c_client *client, int nr, long *results) 
     774  if (operation == SENSORS_PROC_REAL_INFO) 
     775    *nrels_mag = 1; 
     776  else if (operation == SENSORS_PROC_REAL_READ) { 
     777    lm78_update_client(client); 
     778    results[0] = TEMP_FROM_REG(data->temp_over); 
     779    results[1] = TEMP_FROM_REG(data->temp_hyst); 
     780    results[2] = TEMP_FROM_REG(data->temp); 
     781    *nrels_mag = 3; 
     782  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     783    if (*nrels_mag >= 1) { 
     784      data->temp_over = TEMP_TO_REG(results[0]); 
     785      lm78_write_value(client,LM78_REG_TEMP_OVER,data->temp_over); 
     786    } 
     787    if (*nrels_mag >= 2) { 
     788      data->temp_hyst = TEMP_TO_REG(results[1]); 
     789      lm78_write_value(client,LM78_REG_TEMP_HYST,data->temp_hyst); 
     790    } 
     791  } 
     792} 
     793 
     794void lm78_vid(struct i2c_client *client, int operation, int ctl_name, 
     795              int *nrels_mag, long *results) 
    921796{ 
    922797  struct lm78_data *data = client->data; 
    923   results[0] = FAN_FROM_REG(data->fan_min[nr-1]); 
    924   results[1] = FAN_FROM_REG(data->fan[nr-1]); 
    925 } 
    926  
    927 void write_temp(struct i2c_client *client, int nrels, long *results) 
     798  if (operation == SENSORS_PROC_REAL_INFO) 
     799    *nrels_mag = 0; 
     800  else if (operation == SENSORS_PROC_REAL_READ) { 
     801    lm78_update_client(client); 
     802    results[0] = VID_FROM_REG(data->vid); 
     803    *nrels_mag = 1; 
     804  } 
     805} 
     806 
     807void lm78_alarms(struct i2c_client *client, int operation, int ctl_name, 
     808                 int *nrels_mag, long *results) 
    928809{ 
    929810  struct lm78_data *data = client->data; 
    930   if (nrels >= 1) { 
    931     data->temp_over = TEMP_TO_REG(results[0]); 
    932     lm78_write_value(client,LM78_REG_TEMP_OVER,data->temp_over); 
    933   } 
    934   if (nrels >= 2) { 
    935     data->temp_hyst = TEMP_TO_REG(results[1]); 
    936     lm78_write_value(client,LM78_REG_TEMP_HYST,data->temp_hyst); 
    937   } 
    938 } 
    939  
    940 void read_temp(struct i2c_client *client, long *results) 
     811  if (operation == SENSORS_PROC_REAL_INFO) 
     812    *nrels_mag = 0; 
     813  else if (operation == SENSORS_PROC_REAL_READ) { 
     814    lm78_update_client(client); 
     815    results[0] = ALARMS_FROM_REG(data->alarms); 
     816    *nrels_mag = 1; 
     817  } 
     818} 
     819 
     820void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name, 
     821                  int *nrels_mag, long *results) 
    941822{ 
    942823  struct lm78_data *data = client->data; 
    943   results[0] = TEMP_FROM_REG(data->temp_over); 
    944   results[1] = TEMP_FROM_REG(data->temp_hyst); 
    945   results[2] = TEMP_FROM_REG(data->temp); 
    946 } 
    947  
    948 void read_vid(struct i2c_client *client, long *results) 
    949 { 
    950   struct lm78_data *data = client->data; 
    951   results[0] = VID_FROM_REG(data->vid); 
    952 } 
    953  
    954 void read_alarms(struct i2c_client *client, long *results) 
    955 { 
    956   struct lm78_data *data = client->data; 
    957   results[0] = ALARMS_FROM_REG(data->alarms); 
    958 } 
    959  
    960 void read_fan_div(struct i2c_client *client, long *results) 
    961 { 
    962   struct lm78_data *data = client->data; 
    963   results[0] = DIV_FROM_REG(data->fan_div[0]); 
    964   results[1] = DIV_FROM_REG(data->fan_div[1]); 
    965   results[2] = 2; 
    966 } 
    967   
    968 void write_fan_div(struct i2c_client *client, int nrels, long *results) 
    969 { 
    970   struct lm78_data *data = client->data; 
    971   if (nrels >= 2) 
    972     data->fan_div[1] = DIV_TO_REG(results[1]); 
    973   if (nrels >= 1) { 
    974     data->fan_div[0] = DIV_TO_REG(results[0]); 
    975     lm78_write_value(client,LM78_REG_VID_FANDIV, 
    976                      (data->fan_div[0] >> 4) | (data->fan_div[1] >> 6)); 
     824  if (operation == SENSORS_PROC_REAL_INFO) 
     825    *nrels_mag = 0; 
     826  else if (operation == SENSORS_PROC_REAL_READ) { 
     827    lm78_update_client(client); 
     828    results[0] = DIV_FROM_REG(data->fan_div[0]); 
     829    results[1] = DIV_FROM_REG(data->fan_div[1]); 
     830    results[2] = 2; 
     831    *nrels_mag = 3; 
     832  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     833    if (*nrels_mag >= 2) 
     834      data->fan_div[1] = DIV_TO_REG(results[1]); 
     835    if (*nrels_mag >= 1) { 
     836      data->fan_div[0] = DIV_TO_REG(results[0]); 
     837      lm78_write_value(client,LM78_REG_VID_FANDIV, 
     838                       (data->fan_div[0] >> 4) | (data->fan_div[1] >> 6)); 
     839    } 
    977840  } 
    978841} 
     
    1013876 
    1014877MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); 
    1015 MODULE_DESCRIPTION("LM78 driver"); 
     878MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver"); 
    1016879 
    1017880int init_module(void) 
  • lm-sensors/trunk/kernel/include/sensors.h

    r27 r28  
    2424 
    2525#ifdef __KERNEL__ 
     26 
     27/* The type of callback functions used in sensors_{proc,sysctl}_real */ 
     28typedef void (*sensors_real_callback) (struct i2c_client *client, 
     29                                       int operation, int ctl_name, 
     30                                       int *nrels_mag, long *results); 
     31 
     32/* Values for the operation field in the above function type */ 
     33#define SENSORS_PROC_REAL_INFO 1 
     34#define SENSORS_PROC_REAL_READ 2 
     35#define SENSORS_PROC_REAL_WRITE 3 
     36 
     37/* These funcion reads or writes a 'real' value (encoded by the combination 
     38   of an integer and a magnitude, the last is the power of ten the value 
     39   should be divided with) to a /proc/sys directory. To use these functions, 
     40   you must (before registering the ctl_table) set the extra2 field to the 
     41   client, and the extra1 field to a function of the form: 
     42      void func(struct i2c_client *client, int operation, int ctl_name, 
     43                int *nrels_mag, long *results) 
     44   This last function can be called for three values of operation. If 
     45   operation equals SENSORS_PROC_REAL_INFO, the magnitude should be returned 
     46   in nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should 
     47   be read into results. nrels_mag should return the number of elements 
     48   read; the maximum number is put in it on entry. Finally, if operation 
     49   equals SENSORS_PROC_REAL_WRITE, the values in results should be 
     50   written to the chip. nrels_mag contains on entry the number of elements 
     51   found. 
     52   In all cases, client points to the client we wish to interact with, 
     53   and ctl_name is the SYSCTL id of the file we are accessing. */ 
     54extern int sensors_sysctl_real (ctl_table *table, int *name, int nlen, 
     55                                void *oldval, size_t *oldlenp, void *newval, 
     56                                size_t newlen, void **context); 
     57extern int sensors_proc_real(ctl_table *ctl, int write, struct file * filp, 
     58                             void *buffer, size_t *lenp); 
     59 
     60 
     61 
     62/* These rather complex functions must be called when you want to add or 
     63   delete an entry in /proc/sys/dev/sensors/chips (not yet implemented). It 
     64   also creates a new directory within /proc/sys/dev/sensors/. 
     65   ctl_template should be a template of the newly created directory. It is 
     66   copied in memory. The extra2 field of each file is set to point to client. 
     67   If any driver wants subdirectories within the newly created directory, 
     68   these functions must be updated! */ 
    2669extern int sensors_register_entry(struct i2c_client *client, 
    2770                                  const char *prefix, ctl_table *ctl_template); 
    2871extern void sensors_deregister_entry(int id); 
    29 extern void sensors_parse_reals(int *nrels, void *buffer, int bufsize, 
    30                                 long *results, int magnitude); 
    31 extern void sensors_write_reals(int nrels,void *buffer,int *bufsize, 
    32                                 long *results, int magnitude); 
     72 
    3373 
    3474#endif /* def __KERNEL__ */ 
  • lm-sensors/trunk/kernel/sensors.c

    r20 r28  
    2929#include "sensors.h" 
    3030 
     31 
    3132#ifdef MODULE 
    3233extern int init_module(void); 
     
    3435#endif /* MODULE */ 
    3536 
    36 int sensors_register_entry(struct i2c_client *client ,const char *prefix,  
    37                            ctl_table *ctl_template); 
    3837static int sensors_create_name(char **name, const char *prefix, 
    3938                               struct i2c_adapter * adapter, int addr); 
     39static void sensors_parse_reals(int *nrels, void *buffer, int bufsize, 
     40                                long *results, int magnitude); 
     41static void sensors_write_reals(int nrels,void *buffer,int *bufsize, 
     42                                long *results, int magnitude); 
     43 
    4044static int sensors_init(void); 
    4145static int sensors_cleanup(void); 
     
    7882   a new directory within /proc/sys/dev/sensors/. 
    7983   ctl_template should be a template of the newly created directory. It is 
    80    copied in memory. The extra1 field of each file is set to point to client. 
     84   copied in memory. The extra2 field of each file is set to point to client. 
    8185   If any driver wants subdirectories within the newly created directory, 
    8286   this function must be updated! */ 
     
    122126  memcpy(new_table+6,ctl_template,(len-6) * sizeof(ctl_table)); 
    123127  for (i = 6; i < len; i++) 
    124     new_table[i].extra1 = client; 
     128    new_table[i].extra2 = client; 
    125129 
    126130  if (! (new_header = register_sysctl_table(new_table,0))) { 
     
    147151  } 
    148152} 
     153 
     154/* This funcion reads or writes a 'real' value (encoded by the combination 
     155   of an integer and a magnitude, the last is the power of ten the value 
     156   should be divided with) to a /proc/sys directory. To use this function, 
     157   you must (before registering the ctl_table) set the extra2 field to the 
     158   client, and the extra1 field to a function of the form: 
     159      void func(struct i2c_client *client, int operation, int ctl_name, 
     160                int *nrels_mag, long *results) 
     161   This function can be called for three values of operation. If operation 
     162   equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in  
     163   nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should 
     164   be read into results. nrels_mag should return the number of elements 
     165   read; the maximum number is put in it on entry. Finally, if operation 
     166   equals SENSORS_PROC_REAL_WRITE, the values in results should be 
     167   written to the chip. nrels_mag contains on entry the number of elements 
     168   found. 
     169   In all cases, client points to the client we wish to interact with, 
     170   and ctl_name is the SYSCTL id of the file we are accessing. */ 
     171int sensors_proc_real(ctl_table *ctl, int write, struct file * filp, 
     172                      void *buffer, size_t *lenp) 
     173{ 
     174#define MAX_RESULTS 20 
     175  int mag,nrels=MAX_RESULTS; 
     176  long results[MAX_RESULTS]; 
     177  sensors_real_callback callback = ctl -> extra1; 
     178  struct i2c_client *client = ctl -> extra2; 
     179 
     180  /* If buffer is size 0, or we try to read when not at the start, we 
     181     return nothing. Note that I think writing when not at the start 
     182     does not work either, but anyway, this is straight from the kernel 
     183     sources. */ 
     184  if (!*lenp || (filp->f_pos && !write)) { 
     185    *lenp = 0; 
     186    return 0; 
     187  } 
     188 
     189  /* Get the magnitude */ 
     190  callback(client,SENSORS_PROC_REAL_INFO,ctl->ctl_name,&mag,NULL); 
     191 
     192  if (write) { 
     193    /* Read the complete input into results, converting to longs */ 
     194    sensors_parse_reals(&nrels,buffer,*lenp,results,mag); 
     195 
     196    if (! nrels) 
     197      return 0; 
     198 
     199    /* Now feed this information back to the client */ 
     200    callback(client,SENSORS_PROC_REAL_WRITE,ctl->ctl_name,&nrels,results); 
     201     
     202    filp->f_pos += *lenp; 
     203    return 0; 
     204  } else { /* read */ 
     205    /* Get the information from the client into results */ 
     206    callback(client,SENSORS_PROC_REAL_READ,ctl->ctl_name,&nrels,results); 
     207 
     208    /* And write them to buffer, converting to reals */ 
     209    sensors_write_reals(nrels,buffer,lenp,results,mag); 
     210    sensors_write_reals(nrels,buffer,lenp,results,mag); 
     211    filp->f_pos += *lenp; 
     212    return 0; 
     213  } 
     214} 
     215 
     216/* This function is equivalent to sensors_proc_real, only it interacts with 
     217   the sysctl(2) syscall, and returns no reals, but integers */ 
     218int sensors_sysctl_real (ctl_table *table, int *name, int nlen, void *oldval, 
     219               size_t *oldlenp, void *newval, size_t newlen, 
     220               void **context) 
     221{ 
     222  long results[MAX_RESULTS]; 
     223  int oldlen,nrels=MAX_RESULTS; 
     224  sensors_real_callback callback = table -> extra1; 
     225  struct i2c_client *client = table -> extra2; 
     226 
     227  /* Check if we need to output the old values */ 
     228  if (oldval && oldlenp && ! get_user_data(oldlen,oldlenp) && oldlen) { 
     229    callback(client,SENSORS_PROC_REAL_READ,table->ctl_name,&nrels,results); 
     230 
     231    /* Note the rounding factor! */ 
     232    if (nrels * sizeof(long) < oldlen) 
     233      oldlen = nrels * sizeof(long); 
     234    oldlen = (oldlen / sizeof(long)) * sizeof(long); 
     235    copy_to_user(oldval,results,oldlen); 
     236    put_user(oldlen,oldlenp); 
     237  } 
     238 
     239  if (newval && newlen) { 
     240    /* Note the rounding factor! */ 
     241    newlen -= newlen % sizeof(long); 
     242    nrels = newlen / sizeof(long); 
     243    copy_from_user(results,newval,newlen); 
     244     
     245    /* Get the new values back to the client */ 
     246    callback(client,SENSORS_PROC_REAL_WRITE,table->ctl_name,&nrels,results); 
     247  } 
     248  return 0; 
     249} 
     250     
    149251 
    150252/* nrels contains initially the maximum number of elements which can be 
  • lm-sensors/trunk/src/lm78.c

    r27 r28  
    3434#include "compat.h" 
    3535 
    36 /* Many LM78 constants needed below */ 
     36/* Many LM78 constants specified below */ 
    3737 
    3838/* Length of ISA address segment */ 
     
    8282#define ALARMS_FROM_REG(val) (val) 
    8383 
    84 #define DIV_FROM_REG(val) (1 >> (val)) 
     84#define DIV_FROM_REG(val) (1 << (val)) 
    8585#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) 
    8686 
     
    204204static void lm78_init_client(struct i2c_client *client); 
    205205 
    206 static int lm78_sysctl (ctl_table *table, int *name, int nlen, void *oldval,  
    207                         size_t *oldlenp, void *newval, size_t newlen, 
    208                         void **context); 
    209 static int lm78_proc (ctl_table *ctl, int write, struct file * filp, 
    210                       void *buffer, size_t *lenp); 
    211  
    212  
    213 static void write_in(struct i2c_client *client, int nr, int nrels,  
    214                      long *results); 
    215 static void read_in(struct i2c_client *client, int nr, long *results); 
    216 static void write_fan(struct i2c_client *client, int nr, int nrels,  
    217                       long *results); 
    218 static void read_fan(struct i2c_client *client, int nr, long *results); 
    219 static void write_temp(struct i2c_client *client, int nrels, long *results); 
    220 static void read_temp(struct i2c_client *client, long *results); 
    221 static void read_vid(struct i2c_client *client, long *results); 
    222 static void read_alarms(struct i2c_client *client, long *results); 
    223 static void write_fan_div(struct i2c_client *client, int nrels, long *results); 
    224 static void read_fan_div(struct i2c_client *client, long *results); 
    225  
    226  
     206 
     207void lm78_in(struct i2c_client *client, int operation, int ctl_name, 
     208             int *nrels_mag, long *results); 
     209void lm78_fan(struct i2c_client *client, int operation, int ctl_name, 
     210              int *nrels_mag, long *results); 
     211void lm78_temp(struct i2c_client *client, int operation, int ctl_name, 
     212               int *nrels_mag, long *results); 
     213void lm78_vid(struct i2c_client *client, int operation, int ctl_name, 
     214              int *nrels_mag, long *results); 
     215void lm78_alarms(struct i2c_client *client, int operation, int ctl_name, 
     216                 int *nrels_mag, long *results); 
     217void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name, 
     218                  int *nrels_mag, long *results); 
    227219 
    228220/* I choose here for semi-static LM78 allocation. Complete dynamic 
     
    255247   when a new copy is allocated. */ 
    256248static ctl_table lm78_dir_table_template[] = { 
    257   { LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    258   { LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    259   { LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    260   { LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    261   { LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    262   { LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    263   { LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    264   { LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    265   { LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    266   { LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    267   { LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    268   { LM78_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    269   { LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
    270   { LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &lm78_proc, &lm78_sysctl }, 
     249  { LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real, 
     250    &sensors_sysctl_real, NULL, &lm78_in }, 
     251  { LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real, 
     252    &sensors_sysctl_real, NULL, &lm78_in }, 
     253  { LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real, 
     254    &sensors_sysctl_real, NULL, &lm78_in }, 
     255  { LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real, 
     256    &sensors_sysctl_real, NULL, &lm78_in }, 
     257  { LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real, 
     258    &sensors_sysctl_real, NULL, &lm78_in }, 
     259  { LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real, 
     260    &sensors_sysctl_real, NULL, &lm78_in }, 
     261  { LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real, 
     262    &sensors_sysctl_real, NULL, &lm78_in }, 
     263  { LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real, 
     264    &sensors_sysctl_real, NULL, &lm78_fan }, 
     265  { LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real, 
     266    &sensors_sysctl_real, NULL, &lm78_fan }, 
     267  { LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real, 
     268    &sensors_sysctl_real, NULL, &lm78_fan }, 
     269  { LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, 
     270    &sensors_sysctl_real, NULL, &lm78_temp }, 
     271  { LM78_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real, 
     272    &sensors_sysctl_real, NULL, &lm78_vid }, 
     273  { LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real, 
     274    &sensors_sysctl_real, NULL, &lm78_fan_div }, 
     275  { LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real, 
     276    &sensors_sysctl_real, NULL, &lm78_alarms }, 
    271277  { 0 } 
    272278}; 
     
    700706} 
    701707 
    702 /* This function is called when /proc/sys/dev/lm78-???/... is accessed */ 
    703 int lm78_proc (ctl_table *ctl, int write, struct file * filp, 
    704                void *buffer, size_t *lenp) 
    705 { 
    706   int nrels,mag; 
    707   long results[7]; 
    708   struct i2c_client *client = ctl -> extra1; 
    709  
    710   /* If buffer is size 0, or we try to read when not at the start, we  
    711      return nothing. Note that I think writing when not at the start 
    712      does not work either, but anyway, this is straight from the kernel 
    713      sources. */ 
    714   if (!*lenp || (filp->f_pos && !write)) { 
    715     *lenp = 0; 
    716     return 0; 
    717   } 
    718  
    719   /* How many numbers are found within these files, and how to scale them? */ 
    720   switch (ctl->ctl_name) { 
    721     case LM78_SYSCTL_IN0: case LM78_SYSCTL_IN1: case LM78_SYSCTL_IN2:  
    722     case LM78_SYSCTL_IN3: case LM78_SYSCTL_IN4: case LM78_SYSCTL_IN5: 
    723     case LM78_SYSCTL_IN6: 
    724       nrels=3; 
    725       mag=2; 
    726       break; 
    727     case LM78_SYSCTL_TEMP: 
    728       nrels=3; 
    729       mag=1; 
    730       break; 
    731     case LM78_SYSCTL_FAN_DIV: 
    732       nrels=3; 
    733       mag=0; 
    734       break; 
    735     case LM78_SYSCTL_FAN1: case LM78_SYSCTL_FAN2: case LM78_SYSCTL_FAN3: 
    736       nrels=2; 
    737       mag=0; 
    738       break; 
    739     case LM78_SYSCTL_VID: 
    740       nrels=1; 
    741       mag=2; 
    742       break; 
    743     case LM78_SYSCTL_ALARMS: 
    744       nrels=1; 
    745       mag=0; 
    746       break; 
    747     default: /* Should never be called */ 
    748       return -EINVAL; 
    749   } 
    750   
    751   /* OK, try writing stuff. */ 
    752   if (write) { 
    753     sensors_parse_reals(&nrels,buffer,*lenp,results,mag); 
    754     if (nrels == 0) 
    755       return 0; 
    756     switch (ctl->ctl_name) { 
    757       case LM78_SYSCTL_IN0: write_in(client,0,nrels,results); break; 
    758       case LM78_SYSCTL_IN1: write_in(client,1,nrels,results); break; 
    759       case LM78_SYSCTL_IN2: write_in(client,2,nrels,results); break; 
    760       case LM78_SYSCTL_IN3: write_in(client,3,nrels,results); break; 
    761       case LM78_SYSCTL_IN4: write_in(client,4,nrels,results); break; 
    762       case LM78_SYSCTL_IN5: write_in(client,5,nrels,results); break; 
    763       case LM78_SYSCTL_IN6: write_in(client,6,nrels,results); break; 
    764       case LM78_SYSCTL_FAN1: write_fan(client,1,nrels,results); break; 
    765       case LM78_SYSCTL_FAN2: write_fan(client,2,nrels,results); break; 
    766       case LM78_SYSCTL_FAN3: write_fan(client,3,nrels,results); break; 
    767       case LM78_SYSCTL_FAN_DIV: write_fan_div(client,nrels,results);break; 
    768       case LM78_SYSCTL_TEMP: write_temp(client,nrels,results);break; 
    769       case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: break; 
    770       default: /* Should never be called */ *lenp=0; return -EINVAL; break; 
    771     } 
    772     filp->f_pos += *lenp; 
    773     return 0; 
    774   } else { /* read */ 
    775     /* Update all values in LM_Sensor_Data */ 
    776  
    777     lm78_update_client((struct i2c_client *) (ctl->extra1)); 
    778  
    779     /* Read the values to print into results */ 
    780     switch (ctl->ctl_name) { 
    781       case LM78_SYSCTL_IN0: read_in(client,0,results);break; 
    782       case LM78_SYSCTL_IN1: read_in(client,1,results);break; 
    783       case LM78_SYSCTL_IN2: read_in(client,2,results);break; 
    784       case LM78_SYSCTL_IN3: read_in(client,3,results);break; 
    785       case LM78_SYSCTL_IN4: read_in(client,4,results);break; 
    786       case LM78_SYSCTL_IN5: read_in(client,5,results);break; 
    787       case LM78_SYSCTL_IN6: read_in(client,6,results);break; 
    788       case LM78_SYSCTL_FAN1: read_fan(client,1,results);break; 
    789       case LM78_SYSCTL_FAN2: read_fan(client,2,results);break; 
    790       case LM78_SYSCTL_FAN3: read_fan(client,3,results);break; 
    791       case LM78_SYSCTL_TEMP: read_temp(client,results);break; 
    792       case LM78_SYSCTL_FAN_DIV: read_fan_div(client,results);break; 
    793       case LM78_SYSCTL_VID: read_vid(client,results);break; 
    794       case LM78_SYSCTL_ALARMS: read_alarms(client,results);break; 
    795       default: /* Should never be called */ return -EINVAL; 
    796     } 
    797     /* OK, print it now */ 
    798     sensors_write_reals(nrels,buffer,lenp,results,mag); 
    799     filp->f_pos += *lenp; 
    800     return 0; 
    801   } 
    802 } 
    803  
    804 /* This function is called when a sysctl on a lm78 file is done */ 
    805 int lm78_sysctl (ctl_table *table, int *name, int nlen, void *oldval,  
    806                size_t *oldlenp, void *newval, size_t newlen, 
    807                void **context) 
    808 { 
    809   long results[7]; 
    810   int nrels,oldlen; 
    811   struct i2c_client *client = table -> extra1; 
    812   
    813   /* How many numbers are found within these files, and how to scale them? */ 
    814   switch (table->ctl_name) { 
    815     case LM78_SYSCTL_IN0: case LM78_SYSCTL_IN1: case LM78_SYSCTL_IN2:  
    816     case LM78_SYSCTL_IN3: case LM78_SYSCTL_IN4: case LM78_SYSCTL_IN5:  
    817     case LM78_SYSCTL_IN6: case LM78_SYSCTL_TEMP:  
    818     case LM78_SYSCTL_FAN_DIV: 
    819       nrels=3; 
    820       break; 
    821     case LM78_SYSCTL_FAN1: case LM78_SYSCTL_FAN2: case LM78_SYSCTL_FAN3: 
    822       nrels=2; 
    823       break; 
    824     case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: 
    825       nrels=1; 
    826       break; 
    827     default: /* Should never be called */ 
    828       return -EINVAL; 
    829   } 
    830  
    831   /* Check if we need to output the old values */ 
    832   if (oldval && oldlenp && ! get_user_data(oldlen,oldlenp) && oldlen) { 
    833  
    834     /* Update all values in LM_Sensor_Data */ 
    835     lm78_update_client((struct i2c_client *) (table->extra1)); 
    836     switch (table->ctl_name) { 
    837       case LM78_SYSCTL_IN0: read_in(client,0,results);break; 
    838       case LM78_SYSCTL_IN1: read_in(client,1,results);break; 
    839       case LM78_SYSCTL_IN2: read_in(client,2,results);break; 
    840       case LM78_SYSCTL_IN3: read_in(client,3,results);break; 
    841       case LM78_SYSCTL_IN4: read_in(client,4,results);break; 
    842       case LM78_SYSCTL_IN5: read_in(client,5,results);break; 
    843       case LM78_SYSCTL_IN6: read_in(client,6,results);break; 
    844       case LM78_SYSCTL_FAN1: read_fan(client,1,results);break; 
    845       case LM78_SYSCTL_FAN2: read_fan(client,2,results);break; 
    846       case LM78_SYSCTL_FAN3: read_fan(client,3,results);break; 
    847       case LM78_SYSCTL_TEMP: read_temp(client,results);break; 
    848       case LM78_SYSCTL_FAN_DIV: read_fan_div(client,results);break; 
    849       case LM78_SYSCTL_VID: read_vid(client,results);break; 
    850       case LM78_SYSCTL_ALARMS: read_alarms(client,results);break; 
    851       default: /* Should never be called */ return -EINVAL; 
    852     } 
    853      
    854     /* Note the rounding factor! */ 
    855     if (nrels * sizeof(long) < oldlen) 
    856       oldlen = nrels * sizeof(long); 
    857     oldlen = (oldlen / sizeof(long)) * sizeof(long); 
    858     copy_to_user(oldval,results,oldlen); 
    859     put_user(oldlen,oldlenp); 
    860   } 
    861  
    862   /* Check to see whether we need to read the new values */ 
    863   if (newval && newlen) { 
    864     if (nrels * sizeof(long) < newlen) 
    865       newlen = nrels * sizeof(long); 
    866     nrels = newlen / sizeof(long); 
    867     newlen = (newlen / sizeof(long)) * sizeof(long); 
    868     copy_from_user(results,newval,newlen); 
    869      
    870     switch (table->ctl_name) { 
    871       case LM78_SYSCTL_IN0: write_in(client,0,nrels,results); break; 
    872       case LM78_SYSCTL_IN1: write_in(client,1,nrels,results); break; 
    873       case LM78_SYSCTL_IN2: write_in(client,2,nrels,results); break; 
    874       case LM78_SYSCTL_IN3: write_in(client,3,nrels,results); break; 
    875       case LM78_SYSCTL_IN4: write_in(client,4,nrels,results); break; 
    876       case LM78_SYSCTL_IN5: write_in(client,5,nrels,results); break; 
    877       case LM78_SYSCTL_IN6: write_in(client,6,nrels,results); break; 
    878       case LM78_SYSCTL_FAN1: write_fan(client,1,nrels,results); break; 
    879       case LM78_SYSCTL_FAN2: write_fan(client,2,nrels,results); break; 
    880       case LM78_SYSCTL_FAN3: write_fan(client,3,nrels,results); break; 
    881       case LM78_SYSCTL_TEMP: write_temp(client,nrels,results); break; 
    882       case LM78_SYSCTL_FAN_DIV: write_fan_div(client,nrels,results);break; 
    883       case LM78_SYSCTL_VID: case LM78_SYSCTL_ALARMS: break; 
    884       default: /* Should never be called */ return -EINVAL; break; 
    885     } 
    886   } 
    887   return 1; /* We have done all the work */ 
    888 } 
    889  
    890 void write_in(struct i2c_client *client, int nr, int nrels, long *results) 
     708 
     709/* The next few functions are the call-back functions of the /proc/sys and 
     710   sysctl files. Which function is used is defined in the ctl_table in 
     711   the extra1 field. 
     712   Each function must return the magnitude (power of 10 to divide the date 
     713   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must 
     714   put a maximum of *nrels elements in results reflecting the data of this 
     715   file, and set *nrels to the number it actually put in it, if operation== 
     716   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from 
     717   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE. 
     718   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is 
     719   large enough (by checking the incoming value of *nrels). This is not very 
     720   good practice, but as long as you put less than about 5 values in results, 
     721   you can assume it is large enough. */ 
     722void lm78_in(struct i2c_client *client, int operation, int ctl_name,  
     723             int *nrels_mag, long *results) 
    891724{ 
    892725  struct lm78_data *data = client->data; 
    893   if (nrels >= 1) { 
    894     data->in_min[nr] = IN_TO_REG(results[0],nr); 
    895     lm78_write_value(client,LM78_REG_IN_MIN(nr),data->in_min[nr]); 
    896   } 
    897   if (nrels >= 2) { 
    898     data->in_max[nr] = IN_TO_REG(results[1],nr); 
    899     lm78_write_value(client,LM78_REG_IN_MAX(nr),data->in_max[nr]); 
    900   } 
    901 } 
    902  
    903 void read_in(struct i2c_client *client, int nr, long *results) 
     726  int nr = ctl_name - LM78_SYSCTL_IN0; 
     727 
     728  if (operation == SENSORS_PROC_REAL_INFO) 
     729    *nrels_mag = 2; 
     730  else if (operation == SENSORS_PROC_REAL_READ) { 
     731    lm78_update_client(client); 
     732    results[0] = IN_FROM_REG(data->in_min[nr],nr); 
     733    results[1] = IN_FROM_REG(data->in_max[nr],nr); 
     734    results[2] = IN_FROM_REG(data->in[nr],nr); 
     735    *nrels_mag = 3; 
     736  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     737      if (*nrels_mag >= 1) { 
     738        data->in_min[nr] = IN_TO_REG(results[0],nr); 
     739        lm78_write_value(client,LM78_REG_IN_MIN(nr),data->in_min[nr]); 
     740      } 
     741      if (*nrels_mag >= 2) { 
     742      data->in_max[nr] = IN_TO_REG(results[1],nr); 
     743      lm78_write_value(client,LM78_REG_IN_MAX(nr),data->in_max[nr]); 
     744    } 
     745  } 
     746} 
     747 
     748void lm78_fan(struct i2c_client *client, int operation, int ctl_name, 
     749              int *nrels_mag, long *results) 
    904750{ 
    905751  struct lm78_data *data = client->data; 
    906   results[0] = IN_FROM_REG(data->in_min[nr],nr); 
    907   results[1] = IN_FROM_REG(data->in_max[nr],nr); 
    908   results[2] = IN_FROM_REG(data->in[nr],nr); 
    909 } 
    910  
    911 void write_fan(struct i2c_client *client, int nr, int nrels, long *results) 
     752  int nr = ctl_name - LM78_SYSCTL_FAN1 + 1; 
     753 
     754  if (operation == SENSORS_PROC_REAL_INFO) 
     755    *nrels_mag = 0; 
     756  else if (operation == SENSORS_PROC_REAL_READ) { 
     757    lm78_update_client(client); 
     758    results[0] = FAN_FROM_REG(data->fan_min[nr-1]); 
     759    results[1] = FAN_FROM_REG(data->fan[nr-1]); 
     760    *nrels_mag = 2; 
     761  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     762    if (*nrels_mag >= 1) { 
     763      data->fan_min[nr-1] = FAN_TO_REG(results[0]); 
     764      lm78_write_value(client,LM78_REG_FAN_MIN(nr),data->fan_min[nr-1]); 
     765    } 
     766  } 
     767} 
     768 
     769 
     770void lm78_temp(struct i2c_client *client, int operation, int ctl_name, 
     771               int *nrels_mag, long *results) 
    912772{ 
    913773  struct lm78_data *data = client->data; 
    914   if (nrels >= 1) { 
    915     data->fan_min[nr-1] = FAN_TO_REG(results[0]); 
    916     lm78_write_value(client,LM78_REG_FAN_MIN(nr),data->fan_min[nr-1]); 
    917   } 
    918 } 
    919  
    920 void read_fan(struct i2c_client *client, int nr, long *results) 
     774  if (operation == SENSORS_PROC_REAL_INFO) 
     775    *nrels_mag = 1; 
     776  else if (operation == SENSORS_PROC_REAL_READ) { 
     777    lm78_update_client(client); 
     778    results[0] = TEMP_FROM_REG(data->temp_over); 
     779    results[1] = TEMP_FROM_REG(data->temp_hyst); 
     780    results[2] = TEMP_FROM_REG(data->temp); 
     781    *nrels_mag = 3; 
     782  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     783    if (*nrels_mag >= 1) { 
     784      data->temp_over = TEMP_TO_REG(results[0]); 
     785      lm78_write_value(client,LM78_REG_TEMP_OVER,data->temp_over); 
     786    } 
     787    if (*nrels_mag >= 2) { 
     788      data->temp_hyst = TEMP_TO_REG(results[1]); 
     789      lm78_write_value(client,LM78_REG_TEMP_HYST,data->temp_hyst); 
     790    } 
     791  } 
     792} 
     793 
     794void lm78_vid(struct i2c_client *client, int operation, int ctl_name, 
     795              int *nrels_mag, long *results) 
    921796{ 
    922797  struct lm78_data *data = client->data; 
    923   results[0] = FAN_FROM_REG(data->fan_min[nr-1]); 
    924   results[1] = FAN_FROM_REG(data->fan[nr-1]); 
    925 } 
    926  
    927 void write_temp(struct i2c_client *client, int nrels, long *results) 
     798  if (operation == SENSORS_PROC_REAL_INFO) 
     799    *nrels_mag = 0; 
     800  else if (operation == SENSORS_PROC_REAL_READ) { 
     801    lm78_update_client(client); 
     802    results[0] = VID_FROM_REG(data->vid); 
     803    *nrels_mag = 1; 
     804  } 
     805} 
     806 
     807void lm78_alarms(struct i2c_client *client, int operation, int ctl_name, 
     808                 int *nrels_mag, long *results) 
    928809{ 
    929810  struct lm78_data *data = client->data; 
    930   if (nrels >= 1) { 
    931     data->temp_over = TEMP_TO_REG(results[0]); 
    932     lm78_write_value(client,LM78_REG_TEMP_OVER,data->temp_over); 
    933   } 
    934   if (nrels >= 2) { 
    935     data->temp_hyst = TEMP_TO_REG(results[1]); 
    936     lm78_write_value(client,LM78_REG_TEMP_HYST,data->temp_hyst); 
    937   } 
    938 } 
    939  
    940 void read_temp(struct i2c_client *client, long *results) 
     811  if (operation == SENSORS_PROC_REAL_INFO) 
     812    *nrels_mag = 0; 
     813  else if (operation == SENSORS_PROC_REAL_READ) { 
     814    lm78_update_client(client); 
     815    results[0] = ALARMS_FROM_REG(data->alarms); 
     816    *nrels_mag = 1; 
     817  } 
     818} 
     819 
     820void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name, 
     821                  int *nrels_mag, long *results) 
    941822{ 
    942823  struct lm78_data *data = client->data; 
    943   results[0] = TEMP_FROM_REG(data->temp_over); 
    944   results[1] = TEMP_FROM_REG(data->temp_hyst); 
    945   results[2] = TEMP_FROM_REG(data->temp); 
    946 } 
    947  
    948 void read_vid(struct i2c_client *client, long *results) 
    949 { 
    950   struct lm78_data *data = client->data; 
    951   results[0] = VID_FROM_REG(data->vid); 
    952 } 
    953  
    954 void read_alarms(struct i2c_client *client, long *results) 
    955 { 
    956   struct lm78_data *data = client->data; 
    957   results[0] = ALARMS_FROM_REG(data->alarms); 
    958 } 
    959  
    960 void read_fan_div(struct i2c_client *client, long *results) 
    961 { 
    962   struct lm78_data *data = client->data; 
    963   results[0] = DIV_FROM_REG(data->fan_div[0]); 
    964   results[1] = DIV_FROM_REG(data->fan_div[1]); 
    965   results[2] = 2; 
    966 } 
    967   
    968 void write_fan_div(struct i2c_client *client, int nrels, long *results) 
    969 { 
    970   struct lm78_data *data = client->data; 
    971   if (nrels >= 2) 
    972     data->fan_div[1] = DIV_TO_REG(results[1]); 
    973   if (nrels >= 1) { 
    974     data->fan_div[0] = DIV_TO_REG(results[0]); 
    975     lm78_write_value(client,LM78_REG_VID_FANDIV, 
    976                      (data->fan_div[0] >> 4) | (data->fan_div[1] >> 6)); 
     824  if (operation == SENSORS_PROC_REAL_INFO) 
     825    *nrels_mag = 0; 
     826  else if (operation == SENSORS_PROC_REAL_READ) { 
     827    lm78_update_client(client); 
     828    results[0] = DIV_FROM_REG(data->fan_div[0]); 
     829    results[1] = DIV_FROM_REG(data->fan_div[1]); 
     830    results[2] = 2; 
     831    *nrels_mag = 3; 
     832  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     833    if (*nrels_mag >= 2) 
     834      data->fan_div[1] = DIV_TO_REG(results[1]); 
     835    if (*nrels_mag >= 1) { 
     836      data->fan_div[0] = DIV_TO_REG(results[0]); 
     837      lm78_write_value(client,LM78_REG_VID_FANDIV, 
     838                       (data->fan_div[0] >> 4) | (data->fan_div[1] >> 6)); 
     839    } 
    977840  } 
    978841} 
     
    1013876 
    1014877MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); 
    1015 MODULE_DESCRIPTION("LM78 driver"); 
     878MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver"); 
    1016879 
    1017880int init_module(void) 
  • lm-sensors/trunk/src/sensors.c

    r20 r28  
    2929#include "sensors.h" 
    3030 
     31 
    3132#ifdef MODULE 
    3233extern int init_module(void); 
     
    3435#endif /* MODULE */ 
    3536 
    36 int sensors_register_entry(struct i2c_client *client ,const char *prefix,  
    37                            ctl_table *ctl_template); 
    3837static int sensors_create_name(char **name, const char *prefix, 
    3938                               struct i2c_adapter * adapter, int addr); 
     39static void sensors_parse_reals(int *nrels, void *buffer, int bufsize, 
     40                                long *results, int magnitude); 
     41static void sensors_write_reals(int nrels,void *buffer,int *bufsize, 
     42                                long *results, int magnitude); 
     43 
    4044static int sensors_init(void); 
    4145static int sensors_cleanup(void); 
     
    7882   a new directory within /proc/sys/dev/sensors/. 
    7983   ctl_template should be a template of the newly created directory. It is 
    80    copied in memory. The extra1 field of each file is set to point to client. 
     84   copied in memory. The extra2 field of each file is set to point to client. 
    8185   If any driver wants subdirectories within the newly created directory, 
    8286   this function must be updated! */ 
     
    122126  memcpy(new_table+6,ctl_template,(len-6) * sizeof(ctl_table)); 
    123127  for (i = 6; i < len; i++) 
    124     new_table[i].extra1 = client; 
     128    new_table[i].extra2 = client; 
    125129 
    126130  if (! (new_header = register_sysctl_table(new_table,0))) { 
     
    147151  } 
    148152} 
     153 
     154/* This funcion reads or writes a 'real' value (encoded by the combination 
     155   of an integer and a magnitude, the last is the power of ten the value 
     156   should be divided with) to a /proc/sys directory. To use this function, 
     157   you must (before registering the ctl_table) set the extra2 field to the 
     158   client, and the extra1 field to a function of the form: 
     159      void func(struct i2c_client *client, int operation, int ctl_name, 
     160                int *nrels_mag, long *results) 
     161   This function can be called for three values of operation. If operation 
     162   equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in  
     163   nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should 
     164   be read into results. nrels_mag should return the number of elements 
     165   read; the maximum number is put in it on entry. Finally, if operation 
     166   equals SENSORS_PROC_REAL_WRITE, the values in results should be 
     167   written to the chip. nrels_mag contains on entry the number of elements 
     168   found. 
     169   In all cases, client points to the client we wish to interact with, 
     170   and ctl_name is the SYSCTL id of the file we are accessing. */ 
     171int sensors_proc_real(ctl_table *ctl, int write, struct file * filp, 
     172                      void *buffer, size_t *lenp) 
     173{ 
     174#define MAX_RESULTS 20 
     175  int mag,nrels=MAX_RESULTS; 
     176  long results[MAX_RESULTS]; 
     177  sensors_real_callback callback = ctl -> extra1; 
     178  struct i2c_client *client = ctl -> extra2; 
     179 
     180  /* If buffer is size 0, or we try to read when not at the start, we 
     181     return nothing. Note that I think writing when not at the start 
     182     does not work either, but anyway, this is straight from the kernel 
     183     sources. */ 
     184  if (!*lenp || (filp->f_pos && !write)) { 
     185    *lenp = 0; 
     186    return 0; 
     187  } 
     188 
     189  /* Get the magnitude */ 
     190  callback(client,SENSORS_PROC_REAL_INFO,ctl->ctl_name,&mag,NULL); 
     191 
     192  if (write) { 
     193    /* Read the complete input into results, converting to longs */ 
     194    sensors_parse_reals(&nrels,buffer,*lenp,results,mag); 
     195 
     196    if (! nrels) 
     197      return 0; 
     198 
     199    /* Now feed this information back to the client */ 
     200    callback(client,SENSORS_PROC_REAL_WRITE,ctl->ctl_name,&nrels,results); 
     201     
     202    filp->f_pos += *lenp; 
     203    return 0; 
     204  } else { /* read */ 
     205    /* Get the information from the client into results */ 
     206    callback(client,SENSORS_PROC_REAL_READ,ctl->ctl_name,&nrels,results); 
     207 
     208    /* And write them to buffer, converting to reals */ 
     209    sensors_write_reals(nrels,buffer,lenp,results,mag); 
     210    sensors_write_reals(nrels,buffer,lenp,results,mag); 
     211    filp->f_pos += *lenp; 
     212    return 0; 
     213  } 
     214} 
     215 
     216/* This function is equivalent to sensors_proc_real, only it interacts with 
     217   the sysctl(2) syscall, and returns no reals, but integers */ 
     218int sensors_sysctl_real (ctl_table *table, int *name, int nlen, void *oldval, 
     219               size_t *oldlenp, void *newval, size_t newlen, 
     220               void **context) 
     221{ 
     222  long results[MAX_RESULTS]; 
     223  int oldlen,nrels=MAX_RESULTS; 
     224  sensors_real_callback callback = table -> extra1; 
     225  struct i2c_client *client = table -> extra2; 
     226 
     227  /* Check if we need to output the old values */ 
     228  if (oldval && oldlenp && ! get_user_data(oldlen,oldlenp) && oldlen) { 
     229    callback(client,SENSORS_PROC_REAL_READ,table->ctl_name,&nrels,results); 
     230 
     231    /* Note the rounding factor! */ 
     232    if (nrels * sizeof(long) < oldlen) 
     233      oldlen = nrels * sizeof(long); 
     234    oldlen = (oldlen / sizeof(long)) * sizeof(long); 
     235    copy_to_user(oldval,results,oldlen); 
     236    put_user(oldlen,oldlenp); 
     237  } 
     238 
     239  if (newval && newlen) { 
     240    /* Note the rounding factor! */ 
     241    newlen -= newlen % sizeof(long); 
     242    nrels = newlen / sizeof(long); 
     243    copy_from_user(results,newval,newlen); 
     244     
     245    /* Get the new values back to the client */ 
     246    callback(client,SENSORS_PROC_REAL_WRITE,table->ctl_name,&nrels,results); 
     247  } 
     248  return 0; 
     249} 
     250     
    149251 
    150252/* nrels contains initially the maximum number of elements which can be 
  • lm-sensors/trunk/src/sensors.h

    r27 r28  
    2424 
    2525#ifdef __KERNEL__ 
     26 
     27/* The type of callback functions used in sensors_{proc,sysctl}_real */ 
     28typedef void (*sensors_real_callback) (struct i2c_client *client, 
     29                                       int operation, int ctl_name, 
     30                                       int *nrels_mag, long *results); 
     31 
     32/* Values for the operation field in the above function type */ 
     33#define SENSORS_PROC_REAL_INFO 1 
     34#define SENSORS_PROC_REAL_READ 2 
     35#define SENSORS_PROC_REAL_WRITE 3 
     36 
     37/* These funcion reads or writes a 'real' value (encoded by the combination 
     38   of an integer and a magnitude, the last is the power of ten the value 
     39   should be divided with) to a /proc/sys directory. To use these functions, 
     40   you must (before registering the ctl_table) set the extra2 field to the 
     41   client, and the extra1 field to a function of the form: 
     42      void func(struct i2c_client *client, int operation, int ctl_name, 
     43                int *nrels_mag, long *results) 
     44   This last function can be called for three values of operation. If 
     45   operation equals SENSORS_PROC_REAL_INFO, the magnitude should be returned 
     46   in nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should 
     47   be read into results. nrels_mag should return the number of elements 
     48   read; the maximum number is put in it on entry. Finally, if operation 
     49   equals SENSORS_PROC_REAL_WRITE, the values in results should be 
     50   written to the chip. nrels_mag contains on entry the number of elements 
     51   found. 
     52   In all cases, client points to the client we wish to interact with, 
     53   and ctl_name is the SYSCTL id of the file we are accessing. */ 
     54extern int sensors_sysctl_real (ctl_table *table, int *name, int nlen, 
     55                                void *oldval, size_t *oldlenp, void *newval, 
     56                                size_t newlen, void **context); 
     57extern int sensors_proc_real(ctl_table *ctl, int write, struct file * filp, 
     58                             void *buffer, size_t *lenp); 
     59 
     60 
     61 
     62/* These rather complex functions must be called when you want to add or 
     63   delete an entry in /proc/sys/dev/sensors/chips (not yet implemented). It 
     64   also creates a new directory within /proc/sys/dev/sensors/. 
     65   ctl_template should be a template of the newly created directory. It is 
     66   copied in memory. The extra2 field of each file is set to point to client. 
     67   If any driver wants subdirectories within the newly created directory, 
     68   these functions must be updated! */ 
    2669extern int sensors_register_entry(struct i2c_client *client, 
    2770                                  const char *prefix, ctl_table *ctl_template); 
    2871extern void sensors_deregister_entry(int id); 
    29 extern void sensors_parse_reals(int *nrels, void *buffer, int bufsize, 
    30                                 long *results, int magnitude); 
    31 extern void sensors_write_reals(int nrels,void *buffer,int *bufsize, 
    32                                 long *results, int magnitude); 
     72 
    3373 
    3474#endif /* def __KERNEL__ */