[BACK]Return to wdt.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/wdt.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: wdt.c,v 1.16 2007/08/14 07:16:26 mk Exp $     */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 1998,1999 Alex Nash
        !             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 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:
        !            30: #include <sys/types.h>
        !            31: #include <sys/param.h>
        !            32: #include <sys/device.h>
        !            33: #include <sys/kernel.h>
        !            34: #include <sys/proc.h>
        !            35: #include <sys/systm.h>
        !            36:
        !            37: #include <machine/bus.h>
        !            38:
        !            39: #include <dev/pci/pcivar.h>
        !            40: #include <dev/pci/pcireg.h>
        !            41: #include <dev/pci/pcidevs.h>
        !            42:
        !            43: #include <dev/pci/wdt50x.h>
        !            44:
        !            45: struct wdt_softc {
        !            46:        /* wdt_dev must be the first item in the struct */
        !            47:        struct device           wdt_dev;
        !            48:
        !            49:        /* feature set: 0 = none   1 = temp, buzzer, etc. */
        !            50:        int                     features;
        !            51:
        !            52:        /* device access through bus space */
        !            53:        bus_space_tag_t         iot;
        !            54:        bus_space_handle_t      ioh;
        !            55: };
        !            56:
        !            57: int    wdtprobe(struct device *, void *, void *);
        !            58: void   wdtattach(struct device *, struct device *, void *);
        !            59:
        !            60: int    wdt_is501(struct wdt_softc *);
        !            61: void   wdt_8254_count(struct wdt_softc *, int, u_int16_t);
        !            62: void   wdt_8254_mode(struct wdt_softc *, int, int);
        !            63: int    wdt_set_timeout(void *, int);
        !            64: void   wdt_init_timer(struct wdt_softc *);
        !            65: void   wdt_buzzer_off(struct wdt_softc *);
        !            66: void   wdt_timer_disable(struct wdt_softc *);
        !            67: void   wdt_buzzer_enable(struct wdt_softc *);
        !            68:
        !            69: struct cfattach wdt_ca = {
        !            70:        sizeof(struct wdt_softc), wdtprobe, wdtattach
        !            71: };
        !            72:
        !            73: struct cfdriver wdt_cd = {
        !            74:        NULL, "wdt", DV_DULL
        !            75: };
        !            76:
        !            77: const struct pci_matchid wdt_devices[] = {
        !            78:        { PCI_VENDOR_INDCOMPSRC, PCI_PRODUCT_INDCOMPSRC_WDT50x }
        !            79: };
        !            80:
        !            81: /*
        !            82:  *     8254 counter mappings
        !            83:  */
        !            84: #define WDT_8254_TC_LO         0       /* low 16 bits of timeout counter  */
        !            85: #define        WDT_8254_TC_HI          1       /* high 16 bits of timeout counter */
        !            86: #define WDT_8254_BUZZER                2
        !            87:
        !            88: /*
        !            89:  *     WDT500/501 ports
        !            90:  */
        !            91: #define WDT_8254_BASE          0
        !            92: #define WDT_8254_CTL           (WDT_8254_BASE + 3)
        !            93: #define WDT_DISABLE_TIMER      7
        !            94: #define WDT_ENABLE_TIMER       7
        !            95:
        !            96: /*
        !            97:  *     WDT501 specific ports
        !            98:  */
        !            99: #define WDT_STATUS_REG         4
        !           100: #define WDT_START_BUZZER       4
        !           101: #define WDT_TEMPERATURE                5
        !           102: #define WDT_STOP_BUZZER                5
        !           103:
        !           104: int
        !           105: wdtprobe(struct device *parent, void *match, void *aux)
        !           106: {
        !           107:        return (pci_matchbyid((struct pci_attach_args *)aux, wdt_devices,
        !           108:            sizeof(wdt_devices)/sizeof(wdt_devices[0])));
        !           109: }
        !           110:
        !           111: void
        !           112: wdtattach(struct device *parent, struct device *self, void *aux)
        !           113: {
        !           114:        struct wdt_softc *wdt = (struct wdt_softc *)self;
        !           115:        struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
        !           116:        bus_size_t iosize;
        !           117:
        !           118:        /* retrieve the I/O region (BAR2) */
        !           119:        if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_IO, 0,
        !           120:            &wdt->iot, &wdt->ioh, NULL, &iosize, 0) != 0) {
        !           121:                printf("%s: couldn't find PCI I/O region\n",
        !           122:                    wdt->wdt_dev.dv_xname);
        !           123:                return;
        !           124:        }
        !           125:
        !           126:        /* sanity check I/O size */
        !           127:        if (iosize != (bus_size_t)16) {
        !           128:                printf("%s: invalid I/O region size\n",
        !           129:                    wdt->wdt_dev.dv_xname);
        !           130:                return;
        !           131:        }
        !           132:
        !           133:        /* initialize the watchdog timer structure */
        !           134:
        !           135:        /* check the feature set available */
        !           136:        if (wdt_is501(wdt))
        !           137:                wdt->features = 1;
        !           138:        else
        !           139:                wdt->features = 0;
        !           140:
        !           141:        if (wdt->features) {
        !           142:                /*
        !           143:                 * turn off the buzzer, it may have been activated
        !           144:                 * by a previous timeout
        !           145:                 */
        !           146:                wdt_buzzer_off(wdt);
        !           147:
        !           148:                wdt_buzzer_enable(wdt);
        !           149:        }
        !           150:
        !           151:        /* initialize the timer modes and the lower 16-bit counter */
        !           152:        wdt_init_timer(wdt);
        !           153:
        !           154:        /*
        !           155:         * ensure that the watchdog is disabled
        !           156:         */
        !           157:        wdt_timer_disable(wdt);
        !           158:
        !           159:        /*
        !           160:         * register with the watchdog framework
        !           161:         */
        !           162:        wdog_register(wdt, wdt_set_timeout);
        !           163: }
        !           164:
        !           165: /*
        !           166:  *     wdt_is501
        !           167:  *
        !           168:  *     Returns non-zero if the card is a 501 model.
        !           169:  */
        !           170: int
        !           171: wdt_is501(struct wdt_softc *wdt)
        !           172: {
        !           173:        /*
        !           174:         *      It makes too much sense to detect the card type
        !           175:         *      by the device ID, so we have to resort to testing
        !           176:         *      the presence of a register to determine the type.
        !           177:         */
        !           178:        int v = bus_space_read_1(wdt->iot, wdt->ioh, WDT_TEMPERATURE);
        !           179:
        !           180:        /* XXX may not be reliable */
        !           181:        if (v == 0 || v == 0xFF)
        !           182:                return(0);
        !           183:
        !           184:        return(1);
        !           185: }
        !           186:
        !           187: /*
        !           188:  *     wdt_8254_count
        !           189:  *
        !           190:  *     Loads the specified counter with the 16-bit value 'v'.
        !           191:  */
        !           192: void
        !           193: wdt_8254_count(struct wdt_softc *wdt, int counter, u_int16_t v)
        !           194: {
        !           195:        bus_space_write_1(wdt->iot, wdt->ioh,
        !           196:                        WDT_8254_BASE + counter, v & 0xFF);
        !           197:        bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_BASE + counter, v >> 8);
        !           198: }
        !           199:
        !           200: /*
        !           201:  *     wdt_8254_mode
        !           202:  *
        !           203:  *     Sets the mode of the specified counter.
        !           204:  */
        !           205: void
        !           206: wdt_8254_mode(struct wdt_softc *wdt, int counter, int mode)
        !           207: {
        !           208:        bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_CTL,
        !           209:                (counter << 6) | 0x30 | (mode << 1));
        !           210: }
        !           211:
        !           212: /*
        !           213:  *     wdt_set_timeout
        !           214:  *
        !           215:  *     Load the watchdog timer with the specified number of seconds.
        !           216:  *     Clamp seconds to be in the interval [2; 1800].
        !           217:  */
        !           218: int
        !           219: wdt_set_timeout(void *self, int seconds)
        !           220: {
        !           221:        struct wdt_softc *wdt = (struct wdt_softc *)self;
        !           222:
        !           223:        u_int16_t v;
        !           224:        int s;
        !           225:
        !           226:        s = splclock();
        !           227:
        !           228:        wdt_timer_disable(wdt);
        !           229:
        !           230:        if (seconds == 0) {
        !           231:                splx(s);
        !           232:                return (0);
        !           233:        } else if (seconds < 2)
        !           234:                seconds = 2;
        !           235:        else if (seconds > 1800)
        !           236:                seconds = 1800;
        !           237:
        !           238:        /* 8254 has been programmed with a 2ms period */
        !           239:        v = (u_int16_t)seconds * 50;
        !           240:
        !           241:        /* load the new timeout count */
        !           242:        wdt_8254_count(wdt, WDT_8254_TC_HI, v);
        !           243:
        !           244:        /* enable the timer */
        !           245:        bus_space_write_1(wdt->iot, wdt->ioh, WDT_ENABLE_TIMER, 0);
        !           246:
        !           247:        splx(s);
        !           248:
        !           249:        return (seconds);
        !           250: }
        !           251:
        !           252: /*
        !           253:  *     wdt_timer_disable
        !           254:  *
        !           255:  *     Disables the watchdog timer and cancels the scheduled (if any)
        !           256:  *     kernel timeout.
        !           257:  */
        !           258: void
        !           259: wdt_timer_disable(struct wdt_softc *wdt)
        !           260: {
        !           261:        (void)bus_space_read_1(wdt->iot, wdt->ioh, WDT_DISABLE_TIMER);
        !           262: }
        !           263:
        !           264: /*
        !           265:  *     wdt_init_timer
        !           266:  *
        !           267:  *     Configure the modes for the watchdog counters and initialize
        !           268:  *     the low 16-bits of the watchdog counter to have a period of
        !           269:  *     approximately 1/50th of a second.
        !           270:  */
        !           271: void
        !           272: wdt_init_timer(struct wdt_softc *wdt)
        !           273: {
        !           274:        wdt_8254_mode(wdt, WDT_8254_TC_LO, 3);
        !           275:        wdt_8254_mode(wdt, WDT_8254_TC_HI, 2);
        !           276:        wdt_8254_count(wdt, WDT_8254_TC_LO, 41666);
        !           277: }
        !           278:
        !           279: /*******************************************************************
        !           280:  *     WDT501 specific functions
        !           281:  *******************************************************************/
        !           282:
        !           283: /*
        !           284:  *     wdt_buzzer_off
        !           285:  *
        !           286:  *     Turns the buzzer off.
        !           287:  */
        !           288: void
        !           289: wdt_buzzer_off(struct wdt_softc *wdt)
        !           290: {
        !           291:        bus_space_write_1(wdt->iot, wdt->ioh, WDT_STOP_BUZZER, 0);
        !           292: }
        !           293:
        !           294: #ifndef WDT_DISABLE_BUZZER
        !           295: /*
        !           296:  *     wdt_buzzer_enable
        !           297:  *
        !           298:  *     Enables the buzzer when the watchdog counter expires.
        !           299:  */
        !           300: void
        !           301: wdt_buzzer_enable(struct wdt_softc *wdt)
        !           302: {
        !           303:        bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_BUZZER, 1);
        !           304:        wdt_8254_mode(wdt, WDT_8254_BUZZER, 1);
        !           305: }
        !           306: #else
        !           307: /*
        !           308:  *     wdt_buzzer_disable
        !           309:  *
        !           310:  *     Disables the buzzer from sounding when the watchdog counter
        !           311:  *     expires.
        !           312:  */
        !           313: void
        !           314: wdt_buzzer_disable(struct wdt_softc *wdt)
        !           315: {
        !           316:        wdt_8254_mode(wdt, WDT_8254_BUZZER, 0);
        !           317: }
        !           318: #endif

CVSweb