LCOV - code coverage report
Current view: top level - dev/isa - lm78_isa.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 103 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: lm78_isa.c,v 1.10 2015/03/14 03:38:47 jsg 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             : struct cfattach lm_isa_ca = {
      56             :         sizeof(struct lm_isa_softc),
      57             :         lm_isa_match,
      58             :         lm_isa_attach
      59             : };
      60             : 
      61             : struct cfattach lm_wbsio_ca = {
      62             :         sizeof(struct lm_isa_softc),
      63             :         lm_wbsio_match,
      64             :         lm_isa_attach
      65             : };
      66             : 
      67             : int
      68           0 : lm_wbsio_match(struct device *parent, void *match, void *aux)
      69             : {
      70             :         bus_space_tag_t iot;
      71             :         bus_addr_t iobase;
      72           0 :         bus_space_handle_t ioh;
      73           0 :         struct isa_attach_args *ia = aux;
      74             :         int banksel, vendid;
      75             : 
      76           0 :         iot = ia->ia_iot;
      77           0 :         iobase = ia->ipa_io[0].base;
      78             : 
      79           0 :         if (bus_space_map(iot, iobase, 8, 0, &ioh)) {
      80             :                 DPRINTF(("%s: can't map i/o space\n", __func__));
      81           0 :                 return (0);
      82             :         }
      83             : 
      84             :         /* Probe for Winbond chips. */
      85           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
      86           0 :         banksel = bus_space_read_1(iot, ioh, LMC_DATA);
      87           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
      88           0 :         bus_space_write_1(iot, ioh, LMC_DATA, WB_BANKSEL_HBAC);
      89           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
      90           0 :         vendid = bus_space_read_1(iot, ioh, LMC_DATA) << 8;
      91           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
      92           0 :         bus_space_write_1(iot, ioh, LMC_DATA, 0);
      93           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
      94           0 :         vendid |= bus_space_read_1(iot, ioh, LMC_DATA);
      95           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
      96           0 :         bus_space_write_1(iot, ioh, LMC_DATA, banksel);
      97             : 
      98           0 :         bus_space_unmap(iot, ioh, 8);
      99             : 
     100           0 :         if (vendid != WB_VENDID_WINBOND)
     101           0 :                 return (0);
     102             : 
     103           0 :         ia->ipa_nio = 1;
     104           0 :         ia->ipa_io[0].length = 8;
     105             : 
     106           0 :         ia->ipa_nmem = 0;
     107           0 :         ia->ipa_nirq = 0;
     108           0 :         ia->ipa_ndrq = 0;
     109             : 
     110           0 :         return (1);
     111             : 
     112           0 : }
     113             : 
     114             : int
     115           0 : lm_isa_match(struct device *parent, void *match, void *aux)
     116             : {
     117             :         bus_space_tag_t iot;
     118             :         bus_addr_t iobase;
     119           0 :         bus_space_handle_t ioh;
     120           0 :         struct isa_attach_args *ia = aux;
     121             :         int banksel, vendid, chipid, addr;
     122             : 
     123           0 :         iot = ia->ia_iot;
     124           0 :         iobase = ia->ipa_io[0].base;
     125             : 
     126           0 :         if (bus_space_map(iot, iobase, 8, 0, &ioh)) {
     127             :                 DPRINTF(("%s: can't map i/o space\n", __func__));
     128           0 :                 return (0);
     129             :         }
     130             : 
     131             :         /* Probe for Winbond chips. */
     132           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
     133           0 :         banksel = bus_space_read_1(iot, ioh, LMC_DATA);
     134           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
     135           0 :         vendid = bus_space_read_1(iot, ioh, LMC_DATA);
     136           0 :         if (((banksel & 0x80) && vendid == (WB_VENDID_WINBOND >> 8)) ||
     137           0 :             (!(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           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, 0x58);
     142           0 :         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           0 :         bus_space_write_1(iot, ioh, LMC_ADDR, LM_SBUSADDR);
     154           0 :         addr = bus_space_read_1(iot, ioh, LMC_DATA);
     155           0 :         if ((addr & 0xfc) == 0x2c) {
     156           0 :                 bus_space_write_1(iot, ioh, LMC_ADDR, LM_CHIPID);
     157           0 :                 chipid = bus_space_read_1(iot, ioh, LMC_DATA);
     158             : 
     159           0 :                 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           0 :         bus_space_unmap(iot, ioh, 8);
     170             : 
     171           0 :         return (0);
     172             : 
     173             :  found:
     174           0 :         bus_space_unmap(iot, ioh, 8);
     175             : 
     176           0 :         ia->ipa_nio = 1;
     177           0 :         ia->ipa_io[0].length = 8;
     178             : 
     179           0 :         ia->ipa_nmem = 0;
     180           0 :         ia->ipa_nirq = 0;
     181           0 :         ia->ipa_ndrq = 0;
     182             : 
     183           0 :         return (1);
     184           0 : }
     185             : 
     186             : void
     187           0 : lm_isa_attach(struct device *parent, struct device *self, void *aux)
     188             : {
     189           0 :         struct lm_isa_softc *sc = (struct lm_isa_softc *)self;
     190           0 :         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           0 :         sc->sc_iot = ia->ia_iot;
     197           0 :         iobase = ia->ipa_io[0].base;
     198             : 
     199           0 :         if (bus_space_map(sc->sc_iot, iobase, 8, 0, &sc->sc_ioh)) {
     200           0 :                 printf(": can't map i/o space\n");
     201           0 :                 return;
     202             :         }
     203             : 
     204             :         /* Bus-independant attachment */
     205           0 :         sc->sc_lmsc.lm_writereg = lm_isa_writereg;
     206           0 :         sc->sc_lmsc.lm_readreg = lm_isa_readreg;
     207             : 
     208             :         /* pass through wbsio(4) devid */
     209           0 :         if (ia->ia_aux)
     210           0 :                 sc->sc_lmsc.sioid = (u_int8_t)(u_long)ia->ia_aux;
     211             : 
     212           0 :         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           0 :         sbusaddr = lm_isa_readreg(&sc->sc_lmsc, LM_SBUSADDR);
     224           0 :         if (sbusaddr == 0)
     225           0 :                 return;
     226             : 
     227           0 :         for (i = 0; i < lm_cd.cd_ndevs; i++) {
     228           0 :                 lmsc = lm_cd.cd_devs[i];
     229           0 :                 if (lmsc == &sc->sc_lmsc)
     230             :                         continue;
     231           0 :                 if (lmsc && lmsc->sbusaddr == sbusaddr &&
     232           0 :                     lmsc->chipid == sc->sc_lmsc.chipid) {
     233           0 :                         lm_isa_remove_alias(lmsc, sc->sc_lmsc.sc_dev.dv_xname);
     234           0 :                         break;
     235             :                 }
     236             :         }
     237           0 : }
     238             : 
     239             : /* Remove sensors of the i2c alias, since we prefer to use the isa access */
     240             : void
     241           0 : lm_isa_remove_alias(struct lm_softc *sc, const char *isa)
     242             : {
     243             :         int i;
     244             : 
     245           0 :         printf("%s: disabling sensors due to alias with %s\n",
     246           0 :             sc->sc_dev.dv_xname, isa);
     247           0 :         sensordev_deinstall(&sc->sensordev);
     248           0 :         for (i = 0; i < sc->numsensors; i++)
     249           0 :                 sensor_detach(&sc->sensordev, &sc->sensors[i]);
     250           0 :         if (sc->sensortask != NULL)
     251           0 :                 sensor_task_unregister(sc->sensortask);
     252           0 :         sc->sensortask = NULL;
     253           0 : }
     254             : 
     255             : u_int8_t
     256           0 : lm_isa_readreg(struct lm_softc *lmsc, int reg)
     257             : {
     258           0 :         struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
     259             : 
     260           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
     261           0 :         return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, LMC_DATA));
     262             : }
     263             : 
     264             : void
     265           0 : lm_isa_writereg(struct lm_softc *lmsc, int reg, int val)
     266             : {
     267           0 :         struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
     268             : 
     269           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
     270           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_DATA, val);
     271           0 : }

Generated by: LCOV version 1.13