The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/nslm7x.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: nslm7x.c,v 1.21.2.2 2005/10/15 21:48:44 riz Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Bill Squier.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.21.2.2 2005/10/15 21:48:44 riz Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/proc.h>
   46 #include <sys/device.h>
   47 #include <sys/malloc.h>
   48 #include <sys/errno.h>
   49 #include <sys/queue.h>
   50 #include <sys/lock.h>
   51 #include <sys/ioctl.h>
   52 #include <sys/conf.h>
   53 #include <sys/time.h>
   54 
   55 #include <machine/bus.h>
   56 
   57 #include <dev/isa/isareg.h>
   58 #include <dev/isa/isavar.h>
   59 
   60 #include <dev/sysmon/sysmonvar.h>
   61 
   62 #include <dev/ic/nslm7xvar.h>
   63 
   64 #include <machine/intr.h>
   65 #include <machine/bus.h>
   66 
   67 #if defined(LMDEBUG)
   68 #define DPRINTF(x)              printf x
   69 #else
   70 #define DPRINTF(x)
   71 #endif
   72 
   73 const struct envsys_range lm_ranges[] = {       /* sc->sensors sub-intervals */
   74                                         /* for each unit type */
   75         { 7, 7,    ENVSYS_STEMP   },
   76         { 8, 10,   ENVSYS_SFANRPM },
   77         { 1, 0,    ENVSYS_SVOLTS_AC },  /* None */
   78         { 0, 6,    ENVSYS_SVOLTS_DC },
   79         { 1, 0,    ENVSYS_SOHMS },      /* None */
   80         { 1, 0,    ENVSYS_SWATTS },     /* None */
   81         { 1, 0,    ENVSYS_SAMPS }       /* None */
   82 };
   83 
   84 
   85 static void setup_fan(struct lm_softc *, int, int);
   86 static void setup_temp(struct lm_softc *, int, int);
   87 static void wb_setup_volt(struct lm_softc *);
   88 
   89 int lm_match(struct lm_softc *);
   90 int wb_match(struct lm_softc *);
   91 int itec_match(struct lm_softc *);
   92 int def_match(struct lm_softc *);
   93 void lm_common_match(struct lm_softc *);
   94 static int lm_generic_banksel(struct lm_softc *, int);
   95 
   96 static void generic_stemp(struct lm_softc *, struct envsys_tre_data *);
   97 static void generic_svolt(struct lm_softc *, struct envsys_tre_data *,
   98     struct envsys_basic_info *);
   99 static void generic_fanrpm(struct lm_softc *, struct envsys_tre_data *);
  100 
  101 void lm_refresh_sensor_data(struct lm_softc *);
  102 
  103 static void wb_svolt(struct lm_softc *);
  104 static void wb_stemp(struct lm_softc *, struct envsys_tre_data *, int);
  105 static void wb781_fanrpm(struct lm_softc *, struct envsys_tre_data *);
  106 static void wb_fanrpm(struct lm_softc *, struct envsys_tre_data *);
  107 
  108 void wb781_refresh_sensor_data(struct lm_softc *);
  109 void wb782_refresh_sensor_data(struct lm_softc *);
  110 void wb697_refresh_sensor_data(struct lm_softc *);
  111 
  112 static void itec_svolt(struct lm_softc *, struct envsys_tre_data *,
  113     struct envsys_basic_info *);
  114 static void itec_stemp(struct lm_softc *, struct envsys_tre_data *);
  115 static void itec_fanrpm(struct lm_softc *, struct envsys_tre_data *);
  116 void itec_refresh_sensor_data(struct lm_softc *);
  117 
  118 int lm_gtredata(struct sysmon_envsys *, struct envsys_tre_data *);
  119 
  120 int generic_streinfo_fan(struct lm_softc *, struct envsys_basic_info *,
  121            int, struct envsys_basic_info *);
  122 int lm_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
  123 int wb781_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
  124 int wb782_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
  125 int itec_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
  126 
  127 struct lm_chip {
  128         int (*chip_match)(struct lm_softc *);
  129 };
  130 
  131 struct lm_chip lm_chips[] = {
  132         { itec_match },
  133         { wb_match },
  134         { lm_match },
  135         { def_match } /* Must be last */
  136 };
  137 
  138 
  139 int
  140 lm_generic_banksel(lmsc, bank)
  141         struct lm_softc *lmsc;
  142         int bank;
  143 {
  144 
  145         (*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank);
  146         return 0;
  147 }
  148 
  149 
  150 /*
  151  * bus independent probe
  152  */
  153 int
  154 lm_probe(iot, ioh)
  155         bus_space_tag_t iot;
  156         bus_space_handle_t ioh;
  157 {
  158         u_int8_t cr;
  159         int rv;
  160 
  161         /*
  162          * Check for it8705f, before we do the chip reset.
  163          * In case of an it8705f this might reset all the fan control
  164          * parameters to defaults which would void all settings done by
  165          * the BOOTROM/BIOS.
  166          */
  167         bus_space_write_1(iot, ioh, LMC_ADDR, ITEC_RES48);
  168         cr = bus_space_read_1(iot, ioh, LMC_DATA);
  169 
  170         if (cr == ITEC_RES48_DEFAULT) {
  171                 bus_space_write_1(iot, ioh, LMC_ADDR, ITEC_RES52);
  172                 cr = bus_space_read_1(iot, ioh, LMC_DATA);
  173                 if (cr == ITEC_RES52_DEFAULT)
  174                         return 1;
  175         }
  176 
  177         /* Check for some power-on defaults */
  178         bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
  179 
  180         /* Perform LM78 reset */
  181         bus_space_write_1(iot, ioh, LMC_DATA, 0x80);
  182 
  183         /* XXX - Why do I have to reselect the register? */
  184         bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
  185         cr = bus_space_read_1(iot, ioh, LMC_DATA);
  186 
  187         /* XXX - spec says *only* 0x08! */
  188         if ((cr == 0x08) || (cr == 0x01) || (cr == 0x03))
  189                 rv = 1;
  190         else
  191                 rv = 0;
  192 
  193         DPRINTF(("lm: rv = %d, cr = %x\n", rv, cr));
  194 
  195         return (rv);
  196 }
  197 
  198 
  199 /*
  200  * pre:  lmsc contains valid busspace tag and handle
  201  */
  202 void
  203 lm_attach(lmsc)
  204         struct lm_softc *lmsc;
  205 {
  206         u_int i;
  207 
  208         /* Install default bank selection routine, if none given. */
  209         if (lmsc->lm_banksel == NULL)
  210                 lmsc->lm_banksel = lm_generic_banksel;
  211 
  212         for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
  213                 if (lm_chips[i].chip_match(lmsc))
  214                         break;
  215 
  216         /* Start the monitoring loop */
  217         (*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x01);
  218 
  219         /* Indicate we have never read the registers */
  220         timerclear(&lmsc->lastread);
  221 
  222         /* Initialize sensors */
  223         for (i = 0; i < lmsc->numsensors; ++i) {
  224                 lmsc->sensors[i].sensor = lmsc->info[i].sensor = i;
  225                 lmsc->sensors[i].validflags = (ENVSYS_FVALID|ENVSYS_FCURVALID);
  226                 lmsc->info[i].validflags = ENVSYS_FVALID;
  227                 lmsc->sensors[i].warnflags = ENVSYS_WARN_OK;
  228         }
  229         /*
  230          * Hook into the System Monitor.
  231          */
  232         lmsc->sc_sysmon.sme_ranges = lm_ranges;
  233         lmsc->sc_sysmon.sme_sensor_info = lmsc->info;
  234         lmsc->sc_sysmon.sme_sensor_data = lmsc->sensors;
  235         lmsc->sc_sysmon.sme_cookie = lmsc;
  236 
  237         lmsc->sc_sysmon.sme_gtredata = lm_gtredata;
  238         /* sme_streinfo set in chip-specific attach */
  239 
  240         lmsc->sc_sysmon.sme_nsensors = lmsc->numsensors;
  241         lmsc->sc_sysmon.sme_envsys_version = 1000;
  242 
  243         if (sysmon_envsys_register(&lmsc->sc_sysmon))
  244                 printf("%s: unable to register with sysmon\n",
  245                     lmsc->sc_dev.dv_xname);
  246 }
  247 
  248 int
  249 lm_match(sc)
  250         struct lm_softc *sc;
  251 {
  252         int i;
  253 
  254         /* See if we have an LM78 or LM79 */
  255         i = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
  256         switch(i) {
  257         case LM_ID_LM78:
  258                 printf(": LM78\n");
  259                 break;
  260         case LM_ID_LM78J:
  261                 printf(": LM78J\n");
  262                 break;
  263         case LM_ID_LM79:
  264                 printf(": LM79\n");
  265                 break;
  266         case LM_ID_LM81:
  267                 printf(": LM81\n");
  268                 break;
  269         default:
  270                 return 0;
  271         }
  272         lm_common_match(sc);
  273         return 1;
  274 }
  275 
  276 int
  277 def_match(sc)
  278         struct lm_softc *sc;
  279 {
  280         int i;
  281 
  282         i = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
  283         printf(": Unknown chip (ID %d)\n", i);
  284         lm_common_match(sc);
  285         return 1;
  286 }
  287 
  288 void
  289 lm_common_match(sc)
  290         struct lm_softc *sc;
  291 {
  292         int i;
  293         sc->numsensors = LM_NUM_SENSORS;
  294         sc->refresh_sensor_data = lm_refresh_sensor_data;
  295 
  296         for (i = 0; i < 7; ++i) {
  297                 sc->sensors[i].units = sc->info[i].units =
  298                     ENVSYS_SVOLTS_DC;
  299                 snprintf(sc->info[i].desc, sizeof(sc->info[i].desc),
  300                     "IN %d", i);
  301         }
  302 
  303         /* default correction factors for resistors on higher voltage inputs */
  304         sc->info[0].rfact = sc->info[1].rfact =
  305             sc->info[2].rfact = 10000;
  306         sc->info[3].rfact = (int)(( 90.9 / 60.4) * 10000);
  307         sc->info[4].rfact = (int)(( 38.0 / 10.0) * 10000);
  308         sc->info[5].rfact = (int)((210.0 / 60.4) * 10000);
  309         sc->info[6].rfact = (int)(( 90.9 / 60.4) * 10000);
  310 
  311         sc->sensors[7].units = ENVSYS_STEMP;
  312         strcpy(sc->info[7].desc, "Temp");
  313 
  314         setup_fan(sc, 8, 3);
  315         sc->sc_sysmon.sme_streinfo = lm_streinfo;
  316 }
  317 
  318 int
  319 wb_match(sc)
  320         struct lm_softc *sc;
  321 {
  322         int i, j;
  323 
  324         (*sc->lm_writereg)(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
  325         j = (*sc->lm_readreg)(sc, WB_VENDID) << 8;
  326         (*sc->lm_writereg)(sc, WB_BANKSEL, 0);
  327         j |= (*sc->lm_readreg)(sc, WB_VENDID);
  328         DPRINTF(("winbond vend id 0x%x\n", j));
  329         if (j != WB_VENDID_WINBOND)
  330                 return 0;
  331         /* read device ID */
  332         (*sc->lm_banksel)(sc, 0);
  333         j = (*sc->lm_readreg)(sc, WB_BANK0_CHIPID);
  334         DPRINTF(("winbond chip id 0x%x\n", j));
  335         switch(j) {
  336         case WB_CHIPID_83781:
  337         case WB_CHIPID_83781_2:
  338                 printf(": W83781D\n");
  339 
  340                 for (i = 0; i < 7; ++i) {
  341                         sc->sensors[i].units = sc->info[i].units =
  342                             ENVSYS_SVOLTS_DC;
  343                         snprintf(sc->info[i].desc, sizeof(sc->info[i].desc),
  344                             "IN %d", i);
  345                 }
  346 
  347                 /* default correction factors for higher voltage inputs */
  348                 sc->info[0].rfact = sc->info[1].rfact =
  349                     sc->info[2].rfact = 10000;
  350                 sc->info[3].rfact = (int)(( 90.9 / 60.4) * 10000);
  351                 sc->info[4].rfact = (int)(( 38.0 / 10.0) * 10000);
  352                 sc->info[5].rfact = (int)((210.0 / 60.4) * 10000);
  353                 sc->info[6].rfact = (int)(( 90.9 / 60.4) * 10000);
  354 
  355                 setup_temp(sc, 7, 3);
  356                 setup_fan(sc, 10, 3);
  357 
  358                 sc->numsensors = WB83781_NUM_SENSORS;
  359                 sc->refresh_sensor_data = wb781_refresh_sensor_data;
  360                 sc->sc_sysmon.sme_streinfo = wb781_streinfo;
  361                 return 1;
  362         case WB_CHIPID_83697:
  363                 printf(": W83697HF\n");
  364                 wb_setup_volt(sc);
  365                 setup_temp(sc, 9, 2);
  366                 setup_fan(sc, 11, 3);
  367                 sc->numsensors = WB83697_NUM_SENSORS;
  368                 sc->refresh_sensor_data = wb697_refresh_sensor_data;
  369                 sc->sc_sysmon.sme_streinfo = wb782_streinfo;
  370                 return 1;
  371         case WB_CHIPID_83782:
  372                 printf(": W83782D\n");
  373                 break;
  374         case WB_CHIPID_83627:
  375                 printf(": W83627HF\n");
  376                 break;
  377         case WB_CHIPID_83627THF:
  378                 printf(": W83627THF\n");
  379                 break;
  380         default:
  381                 printf(": unknow winbond chip ID 0x%x\n", j);
  382                 /* handle as a standart lm7x */
  383                 lm_common_match(sc);
  384                 return 1;
  385         }
  386         /* common code for the W83782D and W83627HF */
  387         wb_setup_volt(sc);
  388         setup_temp(sc, 9, 3);
  389         setup_fan(sc, 12, 3);
  390         sc->numsensors = WB_NUM_SENSORS;
  391         sc->refresh_sensor_data = wb782_refresh_sensor_data;
  392         sc->sc_sysmon.sme_streinfo = wb782_streinfo;
  393         return 1;
  394 }
  395 
  396 static void
  397 wb_setup_volt(sc)
  398         struct lm_softc *sc;
  399 {
  400         sc->sensors[0].units = sc->info[0].units = ENVSYS_SVOLTS_DC;
  401         snprintf(sc->info[0].desc, sizeof(sc->info[0].desc), "VCORE A");
  402         sc->info[0].rfact = 10000;
  403         sc->sensors[1].units = sc->info[1].units = ENVSYS_SVOLTS_DC;
  404         snprintf(sc->info[1].desc, sizeof(sc->info[1].desc), "VCORE B");
  405         sc->info[1].rfact = 10000;
  406         sc->sensors[2].units = sc->info[2].units = ENVSYS_SVOLTS_DC;
  407         snprintf(sc->info[2].desc, sizeof(sc->info[2].desc), "+3.3V");
  408         sc->info[2].rfact = 10000;
  409         sc->sensors[3].units = sc->info[3].units = ENVSYS_SVOLTS_DC;
  410         snprintf(sc->info[3].desc, sizeof(sc->info[3].desc), "+5V");
  411         sc->info[3].rfact = 16778;
  412         sc->sensors[4].units = sc->info[4].units = ENVSYS_SVOLTS_DC;
  413         snprintf(sc->info[4].desc, sizeof(sc->info[4].desc), "+12V");
  414         sc->info[4].rfact = 38000;
  415         sc->sensors[5].units = sc->info[5].units = ENVSYS_SVOLTS_DC;
  416         snprintf(sc->info[5].desc, sizeof(sc->info[5].desc), "-12V");
  417         sc->info[5].rfact = 10000;
  418         sc->sensors[6].units = sc->info[6].units = ENVSYS_SVOLTS_DC;
  419         snprintf(sc->info[6].desc, sizeof(sc->info[6].desc), "-5V");
  420         sc->info[6].rfact = 10000;
  421         sc->sensors[7].units = sc->info[7].units = ENVSYS_SVOLTS_DC;
  422         snprintf(sc->info[7].desc, sizeof(sc->info[7].desc), "+5VSB");
  423         sc->info[7].rfact = 15151;
  424         sc->sensors[8].units = sc->info[8].units = ENVSYS_SVOLTS_DC;
  425         snprintf(sc->info[8].desc, sizeof(sc->info[8].desc), "VBAT");
  426         sc->info[8].rfact = 10000;
  427 }
  428 
  429 int
  430 itec_match(sc)
  431         struct lm_softc *sc;
  432 {
  433         int vendor, coreid;
  434 
  435         /* do the same thing as in  lm_probe() */
  436         if ((*sc->lm_readreg)(sc, ITEC_RES48) != ITEC_RES48_DEFAULT)
  437                 return 0;
  438 
  439         if ((*sc->lm_readreg)(sc, ITEC_RES52) != ITEC_RES52_DEFAULT)
  440                 return 0;
  441 
  442         /* We check for the core ID register (0x5B), which is available
  443          * only in the 8712F, if that fails, we check the vendor ID
  444          * register, available on 8705F and 8712F */
  445 
  446         coreid = (*sc->lm_readreg)(sc, ITEC_COREID);
  447 
  448         if (coreid == ITEC_COREID_ITE)
  449                 printf(": ITE8712F\n");
  450         else {
  451                 vendor = (*sc->lm_readreg)(sc, ITEC_VENDID);
  452                 if (vendor == ITEC_VENDID_ITE)
  453                         printf(": ITE8705F\n");
  454                 else
  455                         printf(": unknown ITE87%02x compatible\n", vendor);
  456         }
  457 
  458         /*
  459          * XXX this is a litle bit lame...
  460          * All VIN inputs work exactly the same way, it depends of the
  461          * external wiring what voltages they monitor and which correction
  462          * factors are needed. We assume a pretty standard setup here
  463          */
  464         wb_setup_volt(sc);
  465         strlcpy(sc->info[0].desc, "CPU", sizeof(sc->info[0].desc));
  466         strlcpy(sc->info[1].desc, "AGP", sizeof(sc->info[1].desc));
  467         strlcpy(sc->info[6].desc, "+2.5V", sizeof(sc->info[6].desc));
  468         sc->info[5].rfact = 51100;
  469         sc->info[7].rfact = 16778;
  470 
  471         setup_temp(sc, 9, 3);
  472         setup_fan(sc, 12, 3);
  473         sc->numsensors = ITEC_NUM_SENSORS;
  474         sc->refresh_sensor_data = itec_refresh_sensor_data;
  475         sc->sc_sysmon.sme_streinfo = itec_streinfo;
  476 
  477         return 1;
  478 }
  479 
  480 
  481 static void
  482 setup_temp(sc, start, n)
  483         struct lm_softc *sc;
  484         int start, n;
  485 {
  486         int i;
  487 
  488         for (i = 0; i < n; i++) {
  489                 sc->sensors[start + i].units = ENVSYS_STEMP;
  490                 snprintf(sc->info[start + i].desc,
  491                     sizeof(sc->info[start + i].desc), "Temp %d", i + 1);
  492         }
  493 }
  494 
  495 
  496 static void
  497 setup_fan(sc, start, n)
  498         struct lm_softc *sc;
  499         int start, n;
  500 {
  501         int i;
  502         for (i = 0; i < n; ++i) {
  503                 sc->sensors[start + i].units = ENVSYS_SFANRPM;
  504                 sc->info[start + i].units = ENVSYS_SFANRPM;
  505                 snprintf(sc->info[start + i].desc,
  506                     sizeof(sc->info[start + i].desc), "Fan %d", i + 1);
  507         }
  508 }
  509 
  510 int
  511 lm_gtredata(sme, tred)
  512          struct sysmon_envsys *sme;
  513          struct envsys_tre_data *tred;
  514 {
  515          static const struct timeval onepointfive = { 1, 500000 };
  516          struct timeval t;
  517          struct lm_softc *sc = sme->sme_cookie;
  518          int i, s;
  519 
  520          /* read new values at most once every 1.5 seconds */
  521          timeradd(&sc->lastread, &onepointfive, &t);
  522          s = splclock();
  523          i = timercmp(&mono_time, &t, >);
  524          if (i) {
  525                   sc->lastread.tv_sec  = mono_time.tv_sec;
  526                   sc->lastread.tv_usec = mono_time.tv_usec;
  527          }
  528          splx(s);
  529 
  530          if (i)
  531                   sc->refresh_sensor_data(sc);
  532 
  533          *tred = sc->sensors[tred->sensor];
  534 
  535          return 0;
  536 }
  537 
  538 int
  539 generic_streinfo_fan(sc, info, n, binfo)
  540         struct lm_softc *sc;
  541         struct envsys_basic_info *info;
  542         int n;
  543         struct envsys_basic_info *binfo;
  544 {
  545         u_int8_t sdata;
  546         int divisor;
  547 
  548         /* FAN1 and FAN2 can have divisors set, but not FAN3 */
  549         if ((sc->info[binfo->sensor].units == ENVSYS_SFANRPM)
  550             && (n < 2)) {
  551                 if (binfo->rpms == 0) {
  552                         binfo->validflags = 0;
  553                         return 0;
  554                 }
  555 
  556                 /* write back the nominal FAN speed  */
  557                 info->rpms = binfo->rpms;
  558 
  559                 /* 153 is the nominal FAN speed value */
  560                 divisor = 1350000 / (binfo->rpms * 153);
  561 
  562                 /* ...but we need lg(divisor) */
  563                 if (divisor <= 1)
  564                     divisor = 0;
  565                 else if (divisor <= 2)
  566                     divisor = 1;
  567                 else if (divisor <= 4)
  568                     divisor = 2;
  569                 else
  570                     divisor = 3;
  571 
  572                 /*
  573                  * FAN1 div is in bits <5:4>, FAN2 div is
  574                  * in <7:6>
  575                  */
  576                 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
  577                 if ( n == 0 ) {  /* FAN1 */
  578                     divisor <<= 4;
  579                     sdata = (sdata & 0xCF) | divisor;
  580                 } else { /* FAN2 */
  581                     divisor <<= 6;
  582                     sdata = (sdata & 0x3F) | divisor;
  583                 }
  584 
  585                 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
  586         }
  587         return 0;
  588 
  589 }
  590 
  591 int
  592 lm_streinfo(sme, binfo)
  593          struct sysmon_envsys *sme;
  594          struct envsys_basic_info *binfo;
  595 {
  596          struct lm_softc *sc = sme->sme_cookie;
  597 
  598          if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
  599                   sc->info[binfo->sensor].rfact = binfo->rfact;
  600          else {
  601                 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
  602                         generic_streinfo_fan(sc, &sc->info[binfo->sensor],
  603                             binfo->sensor - 8, binfo);
  604                 }
  605                 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
  606                     sizeof(sc->info[binfo->sensor].desc));
  607                 binfo->validflags = ENVSYS_FVALID;
  608          }
  609          return 0;
  610 }
  611 
  612 int
  613 wb781_streinfo(sme, binfo)
  614          struct sysmon_envsys *sme;
  615          struct envsys_basic_info *binfo;
  616 {
  617          struct lm_softc *sc = sme->sme_cookie;
  618          int divisor;
  619          u_int8_t sdata;
  620          int i;
  621 
  622          if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
  623                   sc->info[binfo->sensor].rfact = binfo->rfact;
  624          else {
  625                 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
  626                         if (binfo->rpms == 0) {
  627                                 binfo->validflags = 0;
  628                                 return 0;
  629                         }
  630 
  631                         /* write back the nominal FAN speed  */
  632                         sc->info[binfo->sensor].rpms = binfo->rpms;
  633 
  634                         /* 153 is the nominal FAN speed value */
  635                         divisor = 1350000 / (binfo->rpms * 153);
  636 
  637                         /* ...but we need lg(divisor) */
  638                         for (i = 0; i < 7; i++) {
  639                                 if (divisor <= (1 << i))
  640                                         break;
  641                         }
  642                         divisor = i;
  643 
  644                         if (binfo->sensor == 10 || binfo->sensor == 11) {
  645                                 /*
  646                                  * FAN1 div is in bits <5:4>, FAN2 div
  647                                  * is in <7:6>
  648                                  */
  649                                 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
  650                                 if ( binfo->sensor == 10 ) {  /* FAN1 */
  651                                          sdata = (sdata & 0xCF) |
  652                                              ((divisor & 0x3) << 4);
  653                                 } else { /* FAN2 */
  654                                          sdata = (sdata & 0x3F) |
  655                                              ((divisor & 0x3) << 6);
  656                                 }
  657                                 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
  658                         } else {
  659                                 /* FAN3 is in WB_PIN <7:6> */
  660                                 sdata = (*sc->lm_readreg)(sc, WB_PIN);
  661                                 sdata = (sdata & 0x3F) |
  662                                      ((divisor & 0x3) << 6);
  663                                 (*sc->lm_writereg)(sc, WB_PIN, sdata);
  664                         }
  665                 }
  666                 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
  667                     sizeof(sc->info[binfo->sensor].desc));
  668                 binfo->validflags = ENVSYS_FVALID;
  669          }
  670          return 0;
  671 }
  672 
  673 int
  674 wb782_streinfo(sme, binfo)
  675          struct sysmon_envsys *sme;
  676          struct envsys_basic_info *binfo;
  677 {
  678          struct lm_softc *sc = sme->sme_cookie;
  679          int divisor;
  680          u_int8_t sdata;
  681          int i;
  682 
  683          if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
  684                   sc->info[binfo->sensor].rfact = binfo->rfact;
  685          else {
  686                 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
  687                         if (binfo->rpms == 0) {
  688                                 binfo->validflags = 0;
  689                                 return 0;
  690                         }
  691 
  692                         /* write back the nominal FAN speed  */
  693                         sc->info[binfo->sensor].rpms = binfo->rpms;
  694 
  695                         /* 153 is the nominal FAN speed value */
  696                         divisor = 1350000 / (binfo->rpms * 153);
  697 
  698                         /* ...but we need lg(divisor) */
  699                         for (i = 0; i < 7; i++) {
  700                                 if (divisor <= (1 << i))
  701                                         break;
  702                         }
  703                         divisor = i;
  704 
  705                         if (binfo->sensor == 12 || binfo->sensor == 13) {
  706                                 /*
  707                                  * FAN1 div is in bits <5:4>, FAN2 div
  708                                  * is in <7:6>
  709                                  */
  710                                 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
  711                                 if ( binfo->sensor == 12 ) {  /* FAN1 */
  712                                          sdata = (sdata & 0xCF) |
  713                                              ((divisor & 0x3) << 4);
  714                                 } else { /* FAN2 */
  715                                          sdata = (sdata & 0x3F) |
  716                                              ((divisor & 0x3) << 6);
  717                                 }
  718                                 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
  719                         } else {
  720                                 /* FAN3 is in WB_PIN <7:6> */
  721                                 sdata = (*sc->lm_readreg)(sc, WB_PIN);
  722                                 sdata = (sdata & 0x3F) |
  723                                      ((divisor & 0x3) << 6);
  724                                 (*sc->lm_writereg)(sc, WB_PIN, sdata);
  725                         }
  726                         /* Bit 2 of divisor is in WB_BANK0_FANBAT */
  727                         (*sc->lm_banksel)(sc, 0);
  728                         sdata = (*sc->lm_readreg)(sc, WB_BANK0_FANBAT);
  729                         sdata &= ~(0x20 << (binfo->sensor - 12));
  730                         sdata |= (divisor & 0x4) << (binfo->sensor - 9);
  731                         (*sc->lm_writereg)(sc, WB_BANK0_FANBAT, sdata);
  732                 }
  733 
  734                 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
  735                     sizeof(sc->info[binfo->sensor].desc));
  736                 binfo->validflags = ENVSYS_FVALID;
  737         }
  738         return 0;
  739 }
  740 
  741 int
  742 itec_streinfo(sme, binfo)
  743          struct sysmon_envsys *sme;
  744          struct envsys_basic_info *binfo;
  745 {
  746          struct lm_softc *sc = sme->sme_cookie;
  747          int divisor;
  748          u_int8_t sdata;
  749          int i;
  750 
  751          if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
  752                   sc->info[binfo->sensor].rfact = binfo->rfact;
  753          else {
  754                 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
  755                         if (binfo->rpms == 0) {
  756                                 binfo->validflags = 0;
  757                                 return 0;
  758                         }
  759 
  760                         /* write back the nominal FAN speed  */
  761                         sc->info[binfo->sensor].rpms = binfo->rpms;
  762 
  763                         /* 153 is the nominal FAN speed value */
  764                         divisor = 1350000 / (binfo->rpms * 153);
  765 
  766                         /* ...but we need lg(divisor) */
  767                         for (i = 0; i < 7; i++) {
  768                                 if (divisor <= (1 << i))
  769                                         break;
  770                         }
  771                         divisor = i;
  772 
  773                         sdata = (*sc->lm_readreg)(sc, ITEC_FANDIV);
  774                         /*
  775                          * FAN1 div is in bits <0:2>, FAN2 is in <3:5>
  776                          * FAN3 is in <6>, if set divisor is 8, else 2
  777                          */
  778                         if ( binfo->sensor == 10 ) {  /* FAN1 */
  779                                  sdata = (sdata & 0xf8) | divisor;
  780                         } else if ( binfo->sensor == 11 ) { /* FAN2 */
  781                                  sdata = (sdata & 0xc7) | divisor << 3;
  782                         } else { /* FAN3 */
  783                                 if (divisor>2)
  784                                         sdata = sdata & 0xbf;
  785                                 else
  786                                         sdata = sdata | 0x40;
  787                         }
  788                         (*sc->lm_writereg)(sc, ITEC_FANDIV, sdata);
  789                 }
  790                 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
  791                     sizeof(sc->info[binfo->sensor].desc));
  792                 binfo->validflags = ENVSYS_FVALID;
  793          }
  794          return 0;
  795 }
  796 
  797 static void
  798 generic_stemp(sc, sensor)
  799         struct lm_softc *sc;
  800         struct envsys_tre_data *sensor;
  801 {
  802         int sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + 7);
  803         DPRINTF(("sdata[temp] 0x%x\n", sdata));
  804         /* temp is given in deg. C, we convert to uK */
  805         sensor->cur.data_us = sdata * 1000000 + 273150000;
  806 }
  807 
  808 static void
  809 generic_svolt(sc, sensors, infos)
  810         struct lm_softc *sc;
  811         struct envsys_tre_data *sensors;
  812         struct envsys_basic_info *infos;
  813 {
  814         int i, sdata;
  815 
  816         for (i = 0; i < 7; i++) {
  817                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i);
  818                 DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
  819                 /* voltage returned as (mV >> 4), we convert to uVDC */
  820                 sensors[i].cur.data_s = (sdata << 4);
  821                 /* rfact is (factor * 10^4) */
  822                 sensors[i].cur.data_s *= infos[i].rfact;
  823                 /* division by 10 gets us back to uVDC */
  824                 sensors[i].cur.data_s /= 10;
  825 
  826                 /* these two are negative voltages */
  827                 if ( (i == 5) || (i == 6) )
  828                         sensors[i].cur.data_s *= -1;
  829         }
  830 }
  831 
  832 static void
  833 generic_fanrpm(sc, sensors)
  834         struct lm_softc *sc;
  835         struct envsys_tre_data *sensors;
  836 {
  837         int i, sdata, divisor;
  838         for (i = 0; i < 3; i++) {
  839                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + 8 + i);
  840                 DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
  841                 if (i == 2)
  842                         divisor = 2;    /* Fixed divisor for FAN3 */
  843                 else if (i == 1)        /* Bits 7 & 6 of VID/FAN  */
  844                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 6) & 0x3;
  845                 else
  846                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 4) & 0x3;
  847 
  848                 if (sdata == 0xff || sdata == 0x00) {
  849                         sensors[i].cur.data_us = 0;
  850                 } else {
  851                         sensors[i].cur.data_us = 1350000 / (sdata << divisor);
  852                 }
  853         }
  854 }
  855 
  856 /*
  857  * pre:  last read occurred >= 1.5 seconds ago
  858  * post: sensors[] current data are the latest from the chip
  859  */
  860 void
  861 lm_refresh_sensor_data(sc)
  862         struct lm_softc *sc;
  863 {
  864         /* Refresh our stored data for every sensor */
  865         generic_stemp(sc, &sc->sensors[7]);
  866         generic_svolt(sc, &sc->sensors[0], &sc->info[0]);
  867         generic_fanrpm(sc, &sc->sensors[8]);
  868 }
  869 
  870 static void
  871 wb_svolt(sc)
  872         struct lm_softc *sc;
  873 {
  874         int i, sdata;
  875         for (i = 0; i < 9; ++i) {
  876                 if (i < 7) {
  877                         sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i);
  878                 } else {
  879                         /* from bank5 */
  880                         (*sc->lm_banksel)(sc, 5);
  881                         sdata = (*sc->lm_readreg)(sc, (i == 7) ?
  882                             WB_BANK5_5VSB : WB_BANK5_VBAT);
  883                 }
  884                 DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
  885                 /* voltage returned as (mV >> 4), we convert to uV */
  886                 sdata =  sdata << 4;
  887                 /* special case for negative voltages */
  888                 if (i == 5) {
  889                         /*
  890                          * -12Vdc, assume Winbond recommended values for
  891                          * resistors
  892                          */
  893                         sdata = ((sdata * 1000) - (3600 * 805)) / 195;
  894                 } else if (i == 6) {
  895                         /*
  896                          * -5Vdc, assume Winbond recommended values for
  897                          * resistors
  898                          */
  899                         sdata = ((sdata * 1000) - (3600 * 682)) / 318;
  900                 }
  901                 /* rfact is (factor * 10^4) */
  902                 sc->sensors[i].cur.data_s = sdata * sc->info[i].rfact;
  903                 /* division by 10 gets us back to uVDC */
  904                 sc->sensors[i].cur.data_s /= 10;
  905         }
  906 }
  907 
  908 static void
  909 wb_stemp(sc, sensors, n)
  910         struct lm_softc *sc;
  911         struct  envsys_tre_data *sensors;
  912         int n;
  913 {
  914         int sdata;
  915         /* temperatures. Given in dC, we convert to uK */
  916         sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + 7);
  917         DPRINTF(("sdata[temp0] 0x%x\n", sdata));
  918         sensors[0].cur.data_us = sdata * 1000000 + 273150000;
  919         /* from bank1 */
  920         if ((*sc->lm_banksel)(sc, 1))
  921                 sensors[1].validflags &= ~ENVSYS_FCURVALID;
  922         else {
  923                 sdata = (*sc->lm_readreg)(sc, WB_BANK1_T2H) << 1;
  924                 sdata |=  ((*sc->lm_readreg)(sc, WB_BANK1_T2L) & 0x80) >> 7;
  925                 DPRINTF(("sdata[temp1] 0x%x\n", sdata));
  926                 sensors[1].cur.data_us = (sdata * 1000000) / 2 + 273150000;
  927         }
  928         if (n < 3)
  929                 return;
  930         /* from bank2 */
  931         if ((*sc->lm_banksel)(sc, 2))
  932                 sensors[2].validflags &= ~ENVSYS_FCURVALID;
  933         else {
  934                 sdata = (*sc->lm_readreg)(sc, WB_BANK2_T3H) << 1;
  935                 sdata |=  ((*sc->lm_readreg)(sc, WB_BANK2_T3L) & 0x80) >> 7;
  936                 DPRINTF(("sdata[temp2] 0x%x\n", sdata));
  937                 sensors[2].cur.data_us = (sdata * 1000000) / 2 + 273150000;
  938         }
  939 }
  940 
  941 static void
  942 wb781_fanrpm(sc, sensors)
  943         struct lm_softc *sc;
  944         struct envsys_tre_data *sensors;
  945 {
  946         int i, divisor, sdata;
  947         (*sc->lm_banksel)(sc, 0);
  948         for (i = 0; i < 3; i++) {
  949                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i + 8);
  950                 DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
  951                 if (i == 0)
  952                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 4) & 0x3;
  953                 else if (i == 1)
  954                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 6) & 0x3;
  955                 else
  956                         divisor = ((*sc->lm_readreg)(sc, WB_PIN) >> 6) & 0x3;
  957 
  958                 DPRINTF(("sdata[%d] 0x%x div 0x%x\n", i, sdata, divisor));
  959                 if (sdata == 0xff || sdata == 0x00) {
  960                         sensors[i].cur.data_us = 0;
  961                 } else {
  962                         sensors[i].cur.data_us = 1350000 /
  963                             (sdata << divisor);
  964                 }
  965         }
  966 }
  967 
  968 static void
  969 wb_fanrpm(sc, sensors)
  970         struct lm_softc *sc;
  971         struct envsys_tre_data *sensors;
  972 {
  973         int i, divisor, sdata;
  974         (*sc->lm_banksel)(sc, 0);
  975         for (i = 0; i < 3; i++) {
  976                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i + 8);
  977                 DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
  978                 if (i == 0)
  979                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 4) & 0x3;
  980                 else if (i == 1)
  981                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 6) & 0x3;
  982                 else
  983                         divisor = ((*sc->lm_readreg)(sc, WB_PIN) >> 6) & 0x3;
  984                 divisor |= ((*sc->lm_readreg)(sc, WB_BANK0_FANBAT) >> (i + 3)) & 0x4;
  985 
  986                 DPRINTF(("sdata[%d] 0x%x div 0x%x\n", i, sdata, divisor));
  987                 if (sdata == 0xff || sdata == 0x00) {
  988                         sensors[i].cur.data_us = 0;
  989                 } else {
  990                         sensors[i].cur.data_us = 1350000 /
  991                             (sdata << divisor);
  992                 }
  993         }
  994 }
  995 
  996 void
  997 wb781_refresh_sensor_data(sc)
  998         struct lm_softc *sc;
  999 {
 1000         /* Refresh our stored data for every sensor */
 1001         /* we need to reselect bank0 to access common registers */
 1002         (*sc->lm_banksel)(sc, 0);
 1003         generic_svolt(sc, &sc->sensors[0], &sc->info[0]);
 1004         (*sc->lm_banksel)(sc, 0);
 1005         wb_stemp(sc, &sc->sensors[7], 3);
 1006         (*sc->lm_banksel)(sc, 0);
 1007         wb781_fanrpm(sc, &sc->sensors[10]);
 1008 }
 1009 
 1010 void
 1011 wb782_refresh_sensor_data(sc)
 1012         struct lm_softc *sc;
 1013 {
 1014         /* Refresh our stored data for every sensor */
 1015         wb_svolt(sc);
 1016         wb_stemp(sc, &sc->sensors[9], 3);
 1017         wb_fanrpm(sc, &sc->sensors[12]);
 1018 }
 1019 
 1020 void
 1021 wb697_refresh_sensor_data(sc)
 1022         struct lm_softc *sc;
 1023 {
 1024         /* Refresh our stored data for every sensor */
 1025         wb_svolt(sc);
 1026         wb_stemp(sc, &sc->sensors[9], 2);
 1027         wb_fanrpm(sc, &sc->sensors[11]);
 1028 }
 1029 
 1030 static void
 1031 itec_svolt(sc, sensors, infos)
 1032         struct lm_softc *sc;
 1033         struct envsys_tre_data *sensors;
 1034         struct envsys_basic_info *infos;
 1035 {
 1036         int i, sdata;
 1037 
 1038         for (i = 0; i < 9; i++) {
 1039                 sdata = (*sc->lm_readreg)(sc, ITEC_VIN0 + i);
 1040                 DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
 1041                 /* voltage returned as (mV >> 4), we convert to uVDC */
 1042                 sensors[i].cur.data_s = ( sdata << 4 );
 1043                 /* rfact is (factor * 10^4) */
 1044 
 1045                 sensors[i].cur.data_s *= infos[i].rfact;
 1046                 /*
 1047                  * XXX We assume input 5 is wired the way iTE suggests to
 1048                  * monitor a negative voltage. I'd prefer using negative rfacts
 1049                  * for detecting those cases but since rfact is an u_int this
 1050                  * isn't possible.
 1051                  */
 1052                 if (i == 5)
 1053                         sensors[i].cur.data_s -=
 1054                             (infos[i].rfact - 10000) * ITEC_VREF;
 1055                 /* division by 10 gets us back to uVDC */
 1056                 sensors[i].cur.data_s /= 10;
 1057         }
 1058 }
 1059 
 1060 static void
 1061 itec_stemp(sc, sensors)
 1062         struct lm_softc *sc;
 1063         struct  envsys_tre_data *sensors;
 1064 {
 1065         int i, sdata;
 1066 
 1067         /* temperatures. Given in dC, we convert to uK */
 1068         for (i = 0; i < 3; i++) {
 1069                 sdata = (*sc->lm_readreg)(sc, ITEC_TEMP1 + i);
 1070                 DPRINTF(("sdata[temp%d] 0x%x\n",i, sdata));
 1071                 sensors[i].cur.data_us = sdata * 1000000 + 273150000;
 1072         }
 1073 }
 1074 
 1075 static void
 1076 itec_fanrpm(sc, sensors)
 1077         struct lm_softc *sc;
 1078         struct envsys_tre_data *sensors;
 1079 {
 1080         int i, fandiv, divisor, sdata;
 1081         (*sc->lm_banksel)(sc, 0);
 1082         fandiv = ((*sc->lm_readreg)(sc, ITEC_FANDIV));
 1083 
 1084         for (i = 0; i < 3; i++) {
 1085                 sdata = (*sc->lm_readreg)(sc, ITEC_FAN1 + i);
 1086                 DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
 1087                 switch (i) {
 1088                 case 0:
 1089                         divisor = fandiv & 0x7;
 1090                         break;
 1091                 case 1:
 1092                         divisor = (fandiv >> 3) & 0x7;
 1093                         break;
 1094                 case 2:
 1095                 default:        /* XXX */
 1096                         divisor = (fandiv & 0x40) ? 3 : 1;
 1097                         break;
 1098                 }
 1099                 DPRINTF(("sdata[%d] 0x%x div 0x%x\n", i, sdata, divisor));
 1100                 if (sdata == 0xff || sdata == 0x00) {
 1101                         sensors[i].cur.data_us = 0;
 1102                 } else {
 1103                         sensors[i].cur.data_us = 1350000 /
 1104                             (sdata << divisor);
 1105                 }
 1106         }
 1107 
 1108 }
 1109 
 1110 void
 1111 itec_refresh_sensor_data(sc)
 1112         struct lm_softc *sc;
 1113 {
 1114         itec_svolt(sc, &sc->sensors[0], &sc->info[0]);
 1115         itec_stemp(sc, &sc->sensors[9]);
 1116         itec_fanrpm(sc, &sc->sensors[12]);
 1117 }

Cache object: e04b93c356dd9aaf5e01095a087508fc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.