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

Cache object: 7e64ae02e9631bcad6b0b7f249f74e0e


[ 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.