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/isa/lm78_isa.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 /*      $OpenBSD: lm78_isa.c,v 1.12 2022/04/06 18:59:28 naddy Exp $     */
    2 
    3 /*
    4  * Copyright (c) 2005, 2006 Mark Kettenis
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/device.h>
   22 #include <sys/sensors.h>
   23 #include <machine/bus.h>
   24 
   25 #include <dev/isa/isavar.h>
   26 
   27 #include <dev/ic/lm78var.h>
   28 
   29 /* ISA registers */
   30 #define LMC_ADDR        0x05
   31 #define LMC_DATA        0x06
   32 
   33 extern struct cfdriver lm_cd;
   34 
   35 #if defined(LMDEBUG)
   36 #define DPRINTF(x)              do { printf x; } while (0)
   37 #else
   38 #define DPRINTF(x)
   39 #endif
   40 
   41 struct lm_isa_softc {
   42         struct lm_softc sc_lmsc;
   43 
   44         bus_space_tag_t sc_iot;
   45         bus_space_handle_t sc_ioh;
   46 };
   47 
   48 int  lm_isa_match(struct device *, void *, void *);
   49 int  lm_wbsio_match(struct device *, void *, void *);
   50 void lm_isa_attach(struct device *, struct device *, void *);
   51 u_int8_t lm_isa_readreg(struct lm_softc *, int);
   52 void lm_isa_writereg(struct lm_softc *, int, int);
   53 void lm_isa_remove_alias(struct lm_softc *, const char *);
   54 
   55 const struct cfattach lm_isa_ca = {
   56         sizeof(struct lm_isa_softc),
   57         lm_isa_match,
   58         lm_isa_attach
   59 };
   60 
   61 const struct cfattach lm_wbsio_ca = {
   62         sizeof(struct lm_isa_softc),
   63         lm_wbsio_match,
   64         lm_isa_attach
   65 };
   66 
   67 int
   68 lm_wbsio_match(struct device *parent, void *match, void *aux)
   69 {
   70         bus_space_tag_t iot;
   71         bus_addr_t iobase;
   72         bus_space_handle_t ioh;
   73         struct isa_attach_args *ia = aux;
   74         int banksel, vendid;
   75 
   76         iot = ia->ia_iot;
   77         iobase = ia->ipa_io[0].base;
   78 
   79         if (bus_space_map(iot, iobase, 8, 0, &ioh)) {
   80                 DPRINTF(("%s: can't map i/o space\n", __func__));
   81                 return (0);
   82         }
   83 
   84         /* Probe for Winbond chips. */
   85         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
   86         banksel = bus_space_read_1(iot, ioh, LMC_DATA);
   87         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
   88         bus_space_write_1(iot, ioh, LMC_DATA, WB_BANKSEL_HBAC);
   89         bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
   90         vendid = bus_space_read_1(iot, ioh, LMC_DATA) << 8;
   91         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
   92         bus_space_write_1(iot, ioh, LMC_DATA, 0);
   93         bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
   94         vendid |= bus_space_read_1(iot, ioh, LMC_DATA);
   95         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
   96         bus_space_write_1(iot, ioh, LMC_DATA, banksel);
   97 
   98         bus_space_unmap(iot, ioh, 8);
   99 
  100         if (vendid != WB_VENDID_WINBOND)
  101                 return (0);
  102 
  103         ia->ipa_nio = 1;
  104         ia->ipa_io[0].length = 8;
  105 
  106         ia->ipa_nmem = 0;
  107         ia->ipa_nirq = 0;
  108         ia->ipa_ndrq = 0;
  109 
  110         return (1);
  111 
  112 }
  113 
  114 int
  115 lm_isa_match(struct device *parent, void *match, void *aux)
  116 {
  117         bus_space_tag_t iot;
  118         bus_addr_t iobase;
  119         bus_space_handle_t ioh;
  120         struct isa_attach_args *ia = aux;
  121         int banksel, vendid, chipid, addr;
  122 
  123         iot = ia->ia_iot;
  124         iobase = ia->ipa_io[0].base;
  125 
  126         if (bus_space_map(iot, iobase, 8, 0, &ioh)) {
  127                 DPRINTF(("%s: can't map i/o space\n", __func__));
  128                 return (0);
  129         }
  130 
  131         /* Probe for Winbond chips. */
  132         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
  133         banksel = bus_space_read_1(iot, ioh, LMC_DATA);
  134         bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
  135         vendid = bus_space_read_1(iot, ioh, LMC_DATA);
  136         if (((banksel & 0x80) && vendid == (WB_VENDID_WINBOND >> 8)) ||
  137             (!(banksel & 0x80) && vendid == (WB_VENDID_WINBOND & 0xff)))
  138                 goto found;
  139 
  140         /* Probe for ITE chips (and don't attach if we find one). */
  141         bus_space_write_1(iot, ioh, LMC_ADDR, 0x58);
  142         if ((vendid = bus_space_read_1(iot, ioh, LMC_DATA)) == 0x90)
  143                 goto notfound;
  144 
  145         /*
  146          * Probe for National Semiconductor LM78/79/81.
  147          *
  148          * XXX This assumes the address has not been changed from the
  149          * power up default.  This is probably a reasonable
  150          * assumption, and if it isn't true, we should be able to
  151          * access the chip using the serial bus.
  152          */
  153         bus_space_write_1(iot, ioh, LMC_ADDR, LM_SBUSADDR);
  154         addr = bus_space_read_1(iot, ioh, LMC_DATA);
  155         if ((addr & 0xfc) == 0x2c) {
  156                 bus_space_write_1(iot, ioh, LMC_ADDR, LM_CHIPID);
  157                 chipid = bus_space_read_1(iot, ioh, LMC_DATA);
  158 
  159                 switch (chipid & LM_CHIPID_MASK) {
  160                 case LM_CHIPID_LM78:
  161                 case LM_CHIPID_LM78J:
  162                 case LM_CHIPID_LM79:
  163                 case LM_CHIPID_LM81:
  164                         goto found;
  165                 }
  166         }
  167 
  168  notfound:
  169         bus_space_unmap(iot, ioh, 8);
  170 
  171         return (0);
  172 
  173  found:
  174         bus_space_unmap(iot, ioh, 8);
  175 
  176         ia->ipa_nio = 1;
  177         ia->ipa_io[0].length = 8;
  178 
  179         ia->ipa_nmem = 0;
  180         ia->ipa_nirq = 0;
  181         ia->ipa_ndrq = 0;
  182 
  183         return (1);
  184 }
  185 
  186 void
  187 lm_isa_attach(struct device *parent, struct device *self, void *aux)
  188 {
  189         struct lm_isa_softc *sc = (struct lm_isa_softc *)self;
  190         struct isa_attach_args *ia = aux;
  191         struct lm_softc *lmsc;
  192         bus_addr_t iobase;
  193         int i;
  194         u_int8_t sbusaddr;
  195 
  196         sc->sc_iot = ia->ia_iot;
  197         iobase = ia->ipa_io[0].base;
  198 
  199         if (bus_space_map(sc->sc_iot, iobase, 8, 0, &sc->sc_ioh)) {
  200                 printf(": can't map i/o space\n");
  201                 return;
  202         }
  203 
  204         /* Bus-independent attachment */
  205         sc->sc_lmsc.lm_writereg = lm_isa_writereg;
  206         sc->sc_lmsc.lm_readreg = lm_isa_readreg;
  207 
  208         /* pass through wbsio(4) devid */
  209         if (ia->ia_aux)
  210                 sc->sc_lmsc.sioid = (u_int8_t)(u_long)ia->ia_aux;
  211 
  212         lm_attach(&sc->sc_lmsc);
  213 
  214         /*
  215          * Most devices supported by this driver can attach to iic(4)
  216          * as well.  However, we prefer to attach them to isa(4) since
  217          * that causes less overhead and is more reliable.  We look
  218          * through all previously attached devices, and if we find an
  219          * identical chip at the same serial bus address, we stop
  220          * updating its sensors and mark them as invalid.
  221          */
  222 
  223         sbusaddr = lm_isa_readreg(&sc->sc_lmsc, LM_SBUSADDR);
  224         if (sbusaddr == 0)
  225                 return;
  226 
  227         for (i = 0; i < lm_cd.cd_ndevs; i++) {
  228                 lmsc = lm_cd.cd_devs[i];
  229                 if (lmsc == &sc->sc_lmsc)
  230                         continue;
  231                 if (lmsc && lmsc->sbusaddr == sbusaddr &&
  232                     lmsc->chipid == sc->sc_lmsc.chipid) {
  233                         lm_isa_remove_alias(lmsc, sc->sc_lmsc.sc_dev.dv_xname);
  234                         break;
  235                 }
  236         }
  237 }
  238 
  239 /* Remove sensors of the i2c alias, since we prefer to use the isa access */
  240 void
  241 lm_isa_remove_alias(struct lm_softc *sc, const char *isa)
  242 {
  243         int i;
  244 
  245         printf("%s: disabling sensors due to alias with %s\n",
  246             sc->sc_dev.dv_xname, isa);
  247         sensordev_deinstall(&sc->sensordev);
  248         for (i = 0; i < sc->numsensors; i++)
  249                 sensor_detach(&sc->sensordev, &sc->sensors[i]);
  250         if (sc->sensortask != NULL)
  251                 sensor_task_unregister(sc->sensortask);
  252         sc->sensortask = NULL;
  253 }
  254 
  255 u_int8_t
  256 lm_isa_readreg(struct lm_softc *lmsc, int reg)
  257 {
  258         struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
  259 
  260         bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
  261         return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, LMC_DATA));
  262 }
  263 
  264 void
  265 lm_isa_writereg(struct lm_softc *lmsc, int reg, int val)
  266 {
  267         struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
  268 
  269         bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
  270         bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_DATA, val);
  271 }

Cache object: 499c84f4afefee882d609fb3a733efb3


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