root/dev/isa/it.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. it_match
  2. it_attach
  3. it_readreg
  4. it_writereg
  5. it_setup_volt
  6. it_setup_temp
  7. it_setup_fan
  8. it_generic_stemp
  9. it_generic_svolt
  10. it_generic_fanrpm
  11. it_refresh_sensor_data
  12. it_refresh

    1 /*      $OpenBSD: it.c,v 1.23 2007/06/24 05:34:35 dlg Exp $     */
    2 
    3 /*
    4  * Copyright (c) 2003 Julien Bordet <zejames@greyhats.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/param.h>
   29 #include <sys/systm.h>
   30 #include <sys/device.h>
   31 #include <sys/kernel.h>
   32 #include <sys/sensors.h>
   33 #include <machine/bus.h>
   34 
   35 #include <dev/isa/isareg.h>
   36 #include <dev/isa/isavar.h>
   37 
   38 #include <dev/isa/itvar.h>
   39 
   40 #if defined(ITDEBUG)
   41 #define DPRINTF(x)              do { printf x; } while (0)
   42 #else
   43 #define DPRINTF(x)
   44 #endif
   45 
   46 /*
   47  * IT87-compatible chips can typically measure voltages up to 4.096 V.
   48  * To measure higher voltages the input is attenuated with (external)
   49  * resistors.  Negative voltages are measured using a reference
   50  * voltage.  So we have to convert the sensor values back to real
   51  * voltages by applying the appropriate resistor factor.
   52  */
   53 #define RFACT_NONE      10000
   54 #define RFACT(x, y)     (RFACT_NONE * ((x) + (y)) / (y))
   55 
   56 int  it_match(struct device *, void *, void *);
   57 void it_attach(struct device *, struct device *, void *);
   58 u_int8_t it_readreg(struct it_softc *, int);
   59 void it_writereg(struct it_softc *, int, int);
   60 void it_setup_volt(struct it_softc *, int, int);
   61 void it_setup_temp(struct it_softc *, int, int);
   62 void it_setup_fan(struct it_softc *, int, int);
   63 
   64 void it_generic_stemp(struct it_softc *, struct ksensor *);
   65 void it_generic_svolt(struct it_softc *, struct ksensor *);
   66 void it_generic_fanrpm(struct it_softc *, struct ksensor *);
   67 
   68 void it_refresh_sensor_data(struct it_softc *);
   69 void it_refresh(void *);
   70 
   71 struct cfattach it_ca = {
   72         sizeof(struct it_softc),
   73         it_match,
   74         it_attach
   75 };
   76 
   77 struct cfdriver it_cd = {
   78         NULL, "it", DV_DULL
   79 };
   80 
   81 const int it_vrfact[] = {
   82         RFACT_NONE,
   83         RFACT_NONE,
   84         RFACT_NONE,
   85         RFACT(68, 100),
   86         RFACT(30, 10),
   87         RFACT(21, 10),
   88         RFACT(83, 20),
   89         RFACT(68, 100),
   90         RFACT_NONE
   91 };
   92 
   93 int
   94 it_match(struct device *parent, void *match, void *aux)
   95 {
   96         bus_space_tag_t iot;
   97         bus_space_handle_t ioh;
   98         struct isa_attach_args *ia = aux;
   99         int iobase;
  100         u_int8_t cr;
  101 
  102         iot = ia->ia_iot;
  103         iobase = ia->ipa_io[0].base;
  104 
  105         if (bus_space_map(iot, iobase, 8, 0, &ioh)) {
  106                 DPRINTF(("it: can't map i/o space\n"));
  107                 return (0);
  108         }
  109 
  110         /* Check Vendor ID */
  111         bus_space_write_1(iot, ioh, ITC_ADDR, ITD_CHIPID);
  112         cr = bus_space_read_1(iot, ioh, ITC_DATA);
  113         bus_space_unmap(iot, ioh, 8);
  114         DPRINTF(("it: vendor id 0x%x\n", cr));
  115         if (cr != IT_ID_IT87)
  116                 return (0);
  117 
  118         ia->ipa_nio = 1;
  119         ia->ipa_io[0].length = 8;
  120         ia->ipa_nmem = 0;
  121         ia->ipa_nirq = 0;
  122         ia->ipa_ndrq = 0;
  123 
  124         return (1);
  125 }
  126 
  127 void
  128 it_attach(struct device *parent, struct device *self, void *aux)
  129 {
  130         struct it_softc *sc = (void *)self;
  131         int iobase;
  132         bus_space_tag_t iot;
  133         struct isa_attach_args *ia = aux;
  134         int i;
  135         u_int8_t cr;
  136 
  137         iobase = ia->ipa_io[0].base;
  138         iot = sc->it_iot = ia->ia_iot;
  139 
  140         if (bus_space_map(iot, iobase, 8, 0, &sc->it_ioh)) {
  141                 printf(": can't map i/o space\n");
  142                 return;
  143         }
  144 
  145         i = it_readreg(sc, ITD_CHIPID);
  146         switch (i) {
  147                 case IT_ID_IT87:
  148                         printf(": IT87\n");
  149                         break;
  150         }
  151 
  152         sc->numsensors = IT_NUM_SENSORS;
  153 
  154         it_setup_fan(sc, 0, 3);
  155         it_setup_volt(sc, 3, 9);
  156         it_setup_temp(sc, 12, 3);
  157 
  158         if (sensor_task_register(sc, it_refresh, 5) == NULL) {
  159                 printf("%s: unable to register update task\n",
  160                     sc->sc_dev.dv_xname);
  161                 return;
  162         }
  163 
  164         /* Activate monitoring */
  165         cr = it_readreg(sc, ITD_CONFIG);
  166         cr |= 0x01 | 0x08;
  167         it_writereg(sc, ITD_CONFIG, cr);
  168 
  169         /* Initialize sensors */
  170         strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
  171             sizeof(sc->sensordev.xname));
  172         for (i = 0; i < sc->numsensors; ++i)
  173                 sensor_attach(&sc->sensordev, &sc->sensors[i]);
  174         sensordev_install(&sc->sensordev);
  175 }
  176 
  177 u_int8_t
  178 it_readreg(struct it_softc *sc, int reg)
  179 {
  180         bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_ADDR, reg);
  181         return (bus_space_read_1(sc->it_iot, sc->it_ioh, ITC_DATA));
  182 }
  183 
  184 void
  185 it_writereg(struct it_softc *sc, int reg, int val)
  186 {
  187         bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_ADDR, reg);
  188         bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_DATA, val);
  189 }
  190 
  191 void
  192 it_setup_volt(struct it_softc *sc, int start, int n)
  193 {
  194         int i;
  195 
  196         for (i = 0; i < n; ++i) {
  197                 sc->sensors[start + i].type = SENSOR_VOLTS_DC;
  198         }
  199 
  200         snprintf(sc->sensors[start + 0].desc, sizeof(sc->sensors[0].desc),
  201             "VCORE_A");
  202         snprintf(sc->sensors[start + 1].desc, sizeof(sc->sensors[1].desc),
  203             "VCORE_B");
  204         snprintf(sc->sensors[start + 2].desc, sizeof(sc->sensors[2].desc),
  205             "+3.3V");
  206         snprintf(sc->sensors[start + 3].desc, sizeof(sc->sensors[3].desc),
  207             "+5V");
  208         snprintf(sc->sensors[start + 4].desc, sizeof(sc->sensors[4].desc),
  209             "+12V");
  210         snprintf(sc->sensors[start + 5].desc, sizeof(sc->sensors[5].desc),
  211             "Unused");
  212         snprintf(sc->sensors[start + 6].desc, sizeof(sc->sensors[6].desc),
  213             "-12V");
  214         snprintf(sc->sensors[start + 7].desc, sizeof(sc->sensors[7].desc),
  215             "+5VSB");
  216         snprintf(sc->sensors[start + 8].desc, sizeof(sc->sensors[8].desc),
  217             "VBAT");
  218 }
  219 
  220 void
  221 it_setup_temp(struct it_softc *sc, int start, int n)
  222 {
  223         int i;
  224 
  225         for (i = 0; i < n; ++i)
  226                 sc->sensors[start + i].type = SENSOR_TEMP;
  227 }
  228 
  229 void
  230 it_setup_fan(struct it_softc *sc, int start, int n)
  231 {
  232         int i;
  233 
  234         for (i = 0; i < n; ++i)
  235                 sc->sensors[start + i].type = SENSOR_FANRPM;
  236 }
  237 
  238 void
  239 it_generic_stemp(struct it_softc *sc, struct ksensor *sensors)
  240 {
  241         int i, sdata;
  242 
  243         for (i = 0; i < 3; i++) {
  244                 sdata = it_readreg(sc, ITD_SENSORTEMPBASE + i);
  245                 /* Convert temperature to Fahrenheit degres */
  246                 sensors[i].value = sdata * 1000000 + 273150000;
  247         }
  248 }
  249 
  250 void
  251 it_generic_svolt(struct it_softc *sc, struct ksensor *sensors)
  252 {
  253         int i, sdata;
  254 
  255         for (i = 0; i < 9; i++) {
  256                 sdata = it_readreg(sc, ITD_SENSORVOLTBASE + i);
  257                 DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
  258                 /* voltage returned as (mV >> 4) */
  259                 sensors[i].value = (sdata << 4);
  260                 /* these two values are negative and formula is different */
  261                 if (i == 5 || i == 6)
  262                         sensors[i].value = ((sdata << 4) - IT_VREF);
  263                 /* rfact is (factor * 10^4) */
  264                 sensors[i].value *= it_vrfact[i];
  265                 /* division by 10 gets us back to uVDC */
  266                 sensors[i].value /= 10;
  267                 if (i == 5 || i == 6)
  268                         sensors[i].value += IT_VREF * 1000;
  269         }
  270 }
  271 
  272 void
  273 it_generic_fanrpm(struct it_softc *sc, struct ksensor *sensors)
  274 {
  275         int i, sdata, divisor, odivisor, ndivisor;
  276 
  277         odivisor = ndivisor = divisor = it_readreg(sc, ITD_FAN);
  278         for (i = 0; i < 3; i++, divisor >>= 3) {
  279                 sensors[i].flags &= ~SENSOR_FINVALID;
  280                 if ((sdata = it_readreg(sc, ITD_SENSORFANBASE + i)) == 0xff) {
  281                         sensors[i].flags |= SENSOR_FINVALID;
  282                         if (i == 2)
  283                                 ndivisor ^= 0x40;
  284                         else {
  285                                 ndivisor &= ~(7 << (i * 3));
  286                                 ndivisor |= ((divisor + 1) & 7) << (i * 3);
  287                         }
  288                 } else if (sdata == 0) {
  289                         sensors[i].value = 0;
  290                 } else {
  291                         if (i == 2)
  292                                 divisor = divisor & 1 ? 3 : 1;
  293                         sensors[i].value = 1350000 / (sdata << (divisor & 7));
  294                 }
  295         }
  296         if (ndivisor != odivisor)
  297                 it_writereg(sc, ITD_FAN, ndivisor);
  298 }
  299 
  300 /*
  301  * pre:  last read occurred >= 1.5 seconds ago
  302  * post: sensors[] current data are the latest from the chip
  303  */
  304 void
  305 it_refresh_sensor_data(struct it_softc *sc)
  306 {
  307         /* Refresh our stored data for every sensor */
  308         it_generic_stemp(sc, &sc->sensors[12]);
  309         it_generic_svolt(sc, &sc->sensors[3]);
  310         it_generic_fanrpm(sc, &sc->sensors[0]);
  311 }
  312 
  313 void
  314 it_refresh(void *arg)
  315 {
  316         struct it_softc *sc = (struct it_softc *)arg;
  317 
  318         it_refresh_sensor_data(sc);
  319 }

/* [<][>][^][v][top][bottom][index][help] */