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/nsclpcsio_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 /* $NetBSD: nsclpcsio_isa.c,v 1.5 2002/10/22 16:18:26 drochner Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2002
    5  *      Matthias Drochner.  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 AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: nsclpcsio_isa.c,v 1.5 2002/10/22 16:18:26 drochner Exp $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/device.h>
   35 #include <machine/bus.h>
   36 
   37 #include <dev/isa/isareg.h>
   38 #include <dev/isa/isavar.h>
   39 #include <dev/sysmon/sysmonvar.h>
   40 
   41 static int nsclpcsio_isa_match __P((struct device *, struct cfdata *, void *));
   42 static void nsclpcsio_isa_attach __P((struct device *, struct device *,
   43                                       void *));
   44 
   45 struct nsclpcsio_softc {
   46         struct device sc_dev;
   47         bus_space_tag_t sc_iot, sc_tms_iot;
   48         bus_space_handle_t sc_ioh, sc_tms_ioh;
   49 
   50         struct envsys_tre_data sc_data[3];
   51         struct envsys_basic_info sc_info[3];
   52         struct sysmon_envsys sc_sysmon;
   53 };
   54 
   55 CFATTACH_DECL(nsclpcsio_isa, sizeof(struct nsclpcsio_softc),
   56     nsclpcsio_isa_match, nsclpcsio_isa_attach, NULL, NULL);
   57 
   58 static const struct envsys_range tms_ranges[] = {
   59         { 0, 2, ENVSYS_STEMP },
   60 };
   61 
   62 static u_int8_t nsread(bus_space_tag_t, bus_space_handle_t, int);
   63 static void nswrite(bus_space_tag_t, bus_space_handle_t, int, u_int8_t);
   64 static int nscheck(bus_space_tag_t, int);
   65 
   66 static void tms_update(struct nsclpcsio_softc *, int);
   67 static int tms_gtredata(struct sysmon_envsys *, struct envsys_tre_data *);
   68 static int tms_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
   69 
   70 static u_int8_t
   71 nsread(iot, ioh, idx)
   72         bus_space_tag_t iot;
   73         bus_space_handle_t ioh;
   74         int idx;
   75 {
   76 
   77         bus_space_write_1(iot, ioh, 0, idx);
   78         return (bus_space_read_1(iot, ioh, 1));
   79 }
   80 
   81 static void
   82 nswrite(iot, ioh, idx, data)
   83         bus_space_tag_t iot;
   84         bus_space_handle_t ioh;
   85         int idx;
   86         u_int8_t data;
   87 {
   88 
   89         bus_space_write_1(iot, ioh, 0, idx);
   90         bus_space_write_1(iot, ioh, 1, data);
   91 }
   92 
   93 static int
   94 nscheck(iot, base)
   95         bus_space_tag_t iot;
   96         int base;
   97 {
   98         bus_space_handle_t ioh;
   99         int rv = 0;
  100 
  101         if (bus_space_map(iot, base, 2, 0, &ioh))
  102                 return (0);
  103 
  104         /* XXX this is for PC87366 only for now */
  105         if (nsread(iot, ioh, 0x20) == 0xe9)
  106                 rv = 1;
  107 
  108         bus_space_unmap(iot, ioh, 2);
  109         return (rv);
  110 }
  111 
  112 static int
  113 nsclpcsio_isa_match(parent, match, aux)
  114         struct device *parent;
  115         struct cfdata *match;
  116         void *aux;
  117 {
  118         struct isa_attach_args *ia = aux;
  119         int iobase;
  120 
  121         if (ISA_DIRECT_CONFIG(ia))
  122                 return (0);
  123 
  124         if (ia->ia_nio > 0 && ia->ia_io[0].ir_addr != ISACF_PORT_DEFAULT) {
  125                 /* XXX check for legal iobase ??? */
  126                 if (nscheck(ia->ia_iot, ia->ia_io[0].ir_addr)) {
  127                         iobase = ia->ia_io[0].ir_addr;
  128                         goto found;
  129                 }
  130                 return (0);
  131         }
  132 
  133         /* PC87366 has two possible locations depending on wiring */
  134         if (nscheck(ia->ia_iot, 0x2e)) {
  135                 iobase = 0x2e;
  136                 goto found;
  137         }
  138         if (nscheck(ia->ia_iot, 0x4e)) {
  139                 iobase = 0x4e;
  140                 goto found;
  141         }
  142         return (0);
  143 
  144 found:
  145         ia->ia_nio = 1;
  146         ia->ia_io[0].ir_addr = iobase;
  147         ia->ia_io[0].ir_size = 2;
  148         ia->ia_niomem = 0;
  149         ia->ia_nirq = 0;
  150         ia->ia_ndrq = 0;
  151         return (1);
  152 }
  153 
  154 static void
  155 nsclpcsio_isa_attach(parent, self, aux)
  156         struct device *parent, *self;
  157         void *aux;
  158 {
  159         struct nsclpcsio_softc *sc = (void *)self;
  160         struct isa_attach_args *ia = aux;
  161         bus_space_tag_t iot;
  162         bus_space_handle_t ioh;
  163         u_int8_t val;
  164         int tms_iobase;
  165         int i;
  166 
  167         sc->sc_iot = iot = ia->ia_iot;
  168         if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) {
  169                 printf(": can't map i/o space\n");
  170                 return;
  171         }
  172         sc->sc_ioh = ioh;
  173         printf(": NSC PC87366 rev. %d\n", nsread(iot, ioh, 0x27));
  174 
  175         nswrite(iot, ioh, 0x07, 0x0e); /* select tms */
  176 
  177         val = nsread(iot, ioh, 0x30); /* control register */
  178         if (!(val & 1)) {
  179                 printf("%s: TMS disabled\n", sc->sc_dev.dv_xname);
  180                 return;
  181         }
  182 
  183         tms_iobase = (nsread(iot, ioh, 0x60) << 8) | nsread(iot, ioh, 0x61);
  184         sc->sc_tms_iot = iot;
  185         if (bus_space_map(iot, tms_iobase, 16, 0, &sc->sc_tms_ioh)) {
  186                 printf("%s: can't map TMS i/o space\n", sc->sc_dev.dv_xname);
  187                 return;
  188         }
  189         printf("%s: TMS at 0x%x\n", sc->sc_dev.dv_xname, tms_iobase);
  190 
  191         if (bus_space_read_1(sc->sc_tms_iot, sc->sc_tms_ioh, 0x08) & 1) {
  192                 printf("%s: TMS in standby mode\n", sc->sc_dev.dv_xname);
  193                 /* XXX awake it ??? */
  194                 return;
  195         }
  196 
  197         /* Initialize sensor meta data */
  198         for (i = 0; i < 3; i++) {
  199                 sc->sc_data[i].sensor = sc->sc_info[i].sensor = i;
  200                 sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_STEMP;
  201         }
  202         strcpy(sc->sc_info[0].desc, "TSENS1");
  203         strcpy(sc->sc_info[1].desc, "TSENS2");
  204         strcpy(sc->sc_info[2].desc, "TNSC");
  205 
  206         /* Get initial set of sensor values. */
  207         for (i = 0; i < 3; i++)
  208                 tms_update(sc, i);
  209 
  210         /*
  211          * Hook into the System Monitor.
  212          */
  213         sc->sc_sysmon.sme_ranges = tms_ranges;
  214         sc->sc_sysmon.sme_sensor_info = sc->sc_info;
  215         sc->sc_sysmon.sme_sensor_data = sc->sc_data;
  216         sc->sc_sysmon.sme_cookie = sc;
  217 
  218         sc->sc_sysmon.sme_gtredata = tms_gtredata;
  219         sc->sc_sysmon.sme_streinfo = tms_streinfo;
  220 
  221         sc->sc_sysmon.sme_nsensors = 3;
  222         sc->sc_sysmon.sme_envsys_version = 1000;
  223 
  224         if (sysmon_envsys_register(&sc->sc_sysmon))
  225                 printf("%s: unable to register with sysmon\n",
  226                     sc->sc_dev.dv_xname);
  227 }
  228 
  229 static void
  230 tms_update(sc, chan)
  231         struct nsclpcsio_softc *sc;
  232         int chan;
  233 {
  234         bus_space_tag_t iot = sc->sc_tms_iot;
  235         bus_space_handle_t ioh = sc->sc_tms_ioh;
  236         u_int8_t status;
  237         int8_t temp, ctemp; /* signed!! */
  238 
  239         bus_space_write_1(iot, ioh, 0x09, chan); /* select */
  240 
  241         status = bus_space_read_1(iot, ioh, 0x0a); /* config/status */
  242         if (status & 0x01) {
  243                 /* enabled */
  244                 sc->sc_info[chan].validflags = ENVSYS_FVALID;
  245         }else {
  246                 sc->sc_info[chan].validflags = 0;
  247                 return;
  248         }
  249 
  250         /*
  251          * If the channel is enabled, it is considered valid.
  252          * An "open circuit" might be temporary.
  253          */
  254         sc->sc_data[chan].validflags = ENVSYS_FVALID;
  255         if (status & 0x40) {
  256                 /*
  257                  * open circuit
  258                  * XXX should have a warning for it
  259                  */
  260                 sc->sc_data[chan].warnflags = ENVSYS_WARN_OK; /* XXX */
  261                 return;
  262         }
  263 
  264         /* get current temperature in signed degree celsius */
  265         temp = bus_space_read_1(iot, ioh, 0x0b);
  266         sc->sc_data[chan].cur.data_us = (int)temp * 1000000 + 273150000;
  267         sc->sc_data[chan].validflags |= ENVSYS_FCURVALID;
  268 
  269         if (status & 0x0e) { /* any temperature warning? */
  270                 /*
  271                  * XXX the chip documentation is a bit fuzzy - it doesn't state
  272                  * that the hardware OTS output depends on the "overtemp"
  273                  * warning bit.
  274                  * It seems the output gets cleared if the warning bit is reset.
  275                  * This sucks.
  276                  * The hardware might do something useful with output pins, eg
  277                  * throttling the CPU, so we must do the comparision in
  278                  * software, and only reset the bits if the reason is gone.
  279                  */
  280                 if (status & 0x02) { /* low limit */
  281                         sc->sc_data[chan].warnflags = ENVSYS_WARN_UNDER;
  282                         /* read low limit */
  283                         ctemp = bus_space_read_1(iot, ioh, 0x0d);
  284                         if (temp <= ctemp) /* still valid, don't reset */
  285                                 status &= ~0x02;
  286                 }
  287                 if (status & 0x04) { /* high limit */
  288                         sc->sc_data[chan].warnflags = ENVSYS_WARN_OVER;
  289                         /* read high limit */
  290                         ctemp = bus_space_read_1(iot, ioh, 0x0c);
  291                         if (temp >= ctemp) /* still valid, don't reset */
  292                                 status &= ~0x04;
  293                 }
  294                 if (status & 0x08) { /* overtemperature */
  295                         sc->sc_data[chan].warnflags = ENVSYS_WARN_CRITOVER;
  296                         /* read overtemperature limit */
  297                         ctemp = bus_space_read_1(iot, ioh, 0x0e);
  298                         if (temp >= ctemp) /* still valid, don't reset */
  299                                 status &= ~0x08;
  300                 }
  301 
  302                 /* clear outdated warnings */
  303                 if (status & 0x0e)
  304                         bus_space_write_1(iot, ioh, 0x0a, status);
  305         }
  306 }
  307 
  308 static int
  309 tms_gtredata(sme, data)
  310         struct sysmon_envsys *sme;
  311         struct envsys_tre_data *data;
  312 {
  313         struct nsclpcsio_softc *sc = sme->sme_cookie;
  314 
  315         tms_update(sc, data->sensor);
  316 
  317         *data = sc->sc_data[data->sensor];
  318         return (0);
  319 }
  320 
  321 static int
  322 tms_streinfo(sme, info)
  323         struct sysmon_envsys *sme;
  324         struct envsys_basic_info *info;
  325 {
  326 #if 0
  327         struct nsclpcsio_softc *sc = sme->sme_cookie;
  328 #endif
  329         /* XXX Not implemented */
  330         info->validflags = 0;
  331         
  332         return (0);
  333 }

Cache object: 1cf335cb6b6aefa0a5ff39b97b1c5c24


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