[BACK]Return to toaster.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Annotation of src/sys/dev/isa/toaster.c, Revision 1.6.4.2

1.6.4.2 ! yamt        1: /* $NetBSD: toaster.c,v 1.6.4.1 2008/05/16 02:24:28 yamt Exp $ */
1.1       joff        2:
                      3: /*-
                      4:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jesse Off.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31: #include <sys/cdefs.h>
1.6.4.2 ! yamt       32: __KERNEL_RCSID(0, "$NetBSD: toaster.c,v 1.6.4.1 2008/05/16 02:24:28 yamt Exp $");
1.1       joff       33:
                     34: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/sysctl.h>
                     37: #include <sys/proc.h>
                     38: #include <sys/poll.h>
                     39: #include <sys/conf.h>
                     40: #include <sys/uio.h>
                     41: #include <sys/types.h>
                     42: #include <sys/kernel.h>
                     43: #include <sys/device.h>
                     44: #include <sys/callout.h>
                     45: #include <sys/select.h>
                     46:
1.5       ad         47: #include <sys/bus.h>
1.1       joff       48: #include <machine/autoconf.h>
                     49:
                     50: #include <dev/isa/tsdiovar.h>
                     51: #include <dev/isa/tsdioreg.h>
                     52:
                     53: struct toaster_softc {
                     54:        struct device sc_dev;
                     55:        bus_space_tag_t sc_iot;
                     56:        bus_space_handle_t sc_gpioh;
                     57:        u_int32_t latch;
                     58:        u_int32_t burner;
                     59:        u_int32_t led_width[4];
                     60:        u_int32_t led_duty[4];
                     61:        u_int32_t led_width_sysctl[4];
                     62:        u_int32_t led_duty_sysctl[4];
1.4       ad         63:        callout_t led_callout[4];
1.1       joff       64: };
                     65:
                     66: static int     toaster_match(struct device *, struct cfdata *, void *);
                     67: static void    toaster_attach(struct device *, struct device *, void *);
                     68:
                     69: extern struct cfdriver toaster_cd;
                     70:
                     71: CFATTACH_DECL(toaster, sizeof(struct toaster_softc),
                     72:     toaster_match, toaster_attach, NULL, NULL);
                     73:
                     74: static struct toaster_softc *toaster_sc = NULL;
                     75:
                     76: static int
1.6.4.2 ! yamt       77: toaster_match(struct device *parent, struct cfdata *match, void *aux)
1.1       joff       78: {
                     79:        /* No more than one toaster per system */
                     80:        if (toaster_sc == NULL)
                     81:                return 1;
                     82:        else
                     83:                return 0;
                     84: }
                     85:
                     86: #define TSDIO_GET(x)   bus_space_read_1(sc->sc_iot, sc->sc_gpioh, \
                     87:        (TSDIO_ ## x))
                     88:
                     89: #define TSDIO_SET(x, y)        bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
                     90:        (TSDIO_ ## x), (y))
                     91:
                     92: #define TSDIO_SETBITS(x, y)    bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
                     93:        (TSDIO_ ## x), TSDIO_GET(x) | (y))
                     94:
                     95: #define TSDIO_CLEARBITS(x, y)  bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
                     96:        (TSDIO_ ## x), TSDIO_GET(x) & (~(y)))
                     97:
                     98: #define LEDCALLOUT_DECL(x)     static void led ## x ## _on(void *);    \
                     99: static void led ## x ## _off(void *);                                  \
                    100: static void                                                            \
                    101: led ## x ## _on(arg)                                                   \
                    102:        void *arg;                                                      \
                    103: {                                                                      \
                    104:        struct toaster_softc *sc = arg;                                 \
                    105:                                                                        \
                    106:        if (sc->led_duty[(x)]) {                                        \
                    107:                TSDIO_CLEARBITS(PBDR, (1 << (4 + (x))));                \
                    108:                callout_reset(&sc->led_callout[(x)],                    \
                    109:                        sc->led_duty[(x)], led ## x ## _off, arg);      \
                    110:        } else {                                                        \
                    111:                TSDIO_SETBITS(PBDR, (1 << (4 + (x))));                  \
                    112:        }                                                               \
                    113: }                                                                      \
                    114:                                                                        \
                    115: static void                                                            \
                    116: led ## x ## _off(arg)                                                  \
                    117:        void *arg;                                                      \
                    118: {                                                                      \
                    119:        struct toaster_softc *sc = arg;                                 \
                    120:        int offtime = sc->led_width[(x)] - sc->led_duty[(x)];           \
                    121:                                                                        \
                    122:        if (offtime > 0) {                                              \
                    123:                TSDIO_SETBITS(PBDR, (1 << (4 + (x))));                  \
                    124:                callout_reset(&sc->led_callout[(x)], offtime,           \
                    125:                        led ## x ## _on, arg);                          \
                    126:        }                                                               \
                    127: }
                    128:
                    129: LEDCALLOUT_DECL(0)
                    130: LEDCALLOUT_DECL(1)
                    131: LEDCALLOUT_DECL(2)
                    132: LEDCALLOUT_DECL(3)
                    133:
                    134: static int
                    135: led_sysctl(SYSCTLFN_ARGS)
                    136: {
                    137:        int error, t;
                    138:        struct sysctlnode node;
                    139:        struct toaster_softc *sc = toaster_sc;
                    140:
                    141:        node = *rnode;
                    142:        t = *(int*)rnode->sysctl_data;
                    143:        node.sysctl_data = &t;
                    144:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    145:        if (error || newp == NULL)
                    146:                return (error);
                    147:
                    148:        if (t < 0) return EINVAL;
                    149:
                    150:        *(int*)rnode->sysctl_data = t;
                    151:
                    152:        if (node.sysctl_num == sc->led_width_sysctl[0] ||
                    153:                node.sysctl_num == sc->led_duty_sysctl[0])
                    154:                led0_on(sc);
                    155:        if (node.sysctl_num == sc->led_width_sysctl[1] ||
                    156:                node.sysctl_num == sc->led_duty_sysctl[1])
                    157:                led1_on(sc);
                    158:        if (node.sysctl_num == sc->led_width_sysctl[2] ||
                    159:                node.sysctl_num == sc->led_duty_sysctl[2])
                    160:                led2_on(sc);
                    161:        if (node.sysctl_num == sc->led_width_sysctl[3] ||
                    162:                node.sysctl_num == sc->led_duty_sysctl[3])
                    163:                led3_on(sc);
                    164:
                    165:        return (0);
                    166: }
                    167:
                    168: static int
                    169: latch_sysctl(SYSCTLFN_ARGS)
                    170: {
                    171:        int error, t;
                    172:        struct sysctlnode node;
                    173:        struct toaster_softc *sc = toaster_sc;
                    174:
                    175:        node = *rnode;
                    176:        t = *(int*)rnode->sysctl_data;
                    177:        node.sysctl_data = &t;
                    178:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    179:        if (error || newp == NULL)
                    180:                return (error);
                    181:
                    182:        if (t != 0 && t != 1) return EINVAL;
                    183:
                    184:        *(int*)rnode->sysctl_data = t;
                    185:
                    186:        if (t)
                    187:                TSDIO_SETBITS(PADR, 0x1);
                    188:        else
                    189:                TSDIO_CLEARBITS(PADR, 0x1);
                    190:
                    191:        return (0);
                    192: }
                    193:
                    194: static int
                    195: burner_sysctl(SYSCTLFN_ARGS)
                    196: {
                    197:        int error, t;
                    198:        struct sysctlnode node;
                    199:        struct toaster_softc *sc = toaster_sc;
                    200:
                    201:        node = *rnode;
                    202:        t = *(int*)rnode->sysctl_data;
                    203:        node.sysctl_data = &t;
                    204:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    205:        if (error || newp == NULL)
                    206:                return (error);
                    207:
                    208:        if (t != 0 && t != 1) return EINVAL;
                    209:
                    210:        *(int*)rnode->sysctl_data = t;
                    211:
                    212:        if (t)
                    213:                TSDIO_SETBITS(PADR, 0x2);
                    214:        else
                    215:                TSDIO_CLEARBITS(PADR, 0x2);
                    216:
                    217:        return (0);
                    218: }
                    219:
                    220:
                    221: static void
1.6.4.2 ! yamt      222: toaster_attach(struct device *parent, struct device *self, void *aux)
1.1       joff      223: {
                    224:        struct toaster_softc *sc = (void *)self;
                    225:        struct tsdio_attach_args *taa = aux;
                    226:         const struct sysctlnode *node, *datnode;
                    227:        int i;
                    228:
                    229:        toaster_sc = sc;
                    230:        sc->sc_iot = taa->ta_iot;
                    231:        sc->sc_gpioh = taa->ta_ioh;
                    232:
                    233:        TSDIO_SETBITS(DDR, 0x2);        /* Port B as outputs */
                    234:        TSDIO_SETBITS(PBDR, 0xf0);      /* Turn off LED's */
                    235:
                    236:        aprint_normal(": internal toaster control outputs\n");
1.6       cegger    237:        aprint_normal_dev(&sc->sc_dev, "using port B, bits 4-7 for front panel LEDs\n");
                    238:        aprint_normal_dev(&sc->sc_dev, "using port A, bit 0 for magnetic latch\n");
                    239:        aprint_normal_dev(&sc->sc_dev, "using port A, bit 1 for burner element\n");
1.1       joff      240:
1.4       ad        241:        callout_init(&sc->led_callout[0], 0);
                    242:        callout_init(&sc->led_callout[1], 0);
                    243:        callout_init(&sc->led_callout[2], 0);
                    244:        callout_init(&sc->led_callout[3], 0);
1.1       joff      245:        sc->led_duty[0] = sc->led_width[0] = 0;
                    246:        sc->led_duty[1] = sc->led_width[1] = 0;
                    247:        sc->led_duty[2] = sc->led_width[2] = 0;
                    248:        sc->led_duty[3] = sc->led_width[3] = 0;
                    249:
                    250:        sc->burner = 0;
                    251:        sc->latch = 0;
                    252:
                    253:        if (sysctl_createv(NULL, 0, NULL, NULL,
                    254:                                CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
                    255:                                NULL, NULL, 0, NULL, 0,
                    256:                                CTL_HW, CTL_EOL) != 0) {
1.6       cegger    257:                aprint_error_dev(&sc->sc_dev, "could not create sysctl\n");
1.1       joff      258:                return;
                    259:        }
                    260:        if (sysctl_createv(NULL, 0, NULL, &node,
1.6       cegger    261:                                0, CTLTYPE_NODE, device_xname(&sc->sc_dev),
1.1       joff      262:                                NULL,
                    263:                                NULL, 0, NULL, 0,
                    264:                                CTL_HW, CTL_CREATE, CTL_EOL) != 0) {
1.6       cegger    265:                 aprint_error_dev(&sc->sc_dev, "could not create sysctl\n");
1.1       joff      266:                return;
                    267:        }
                    268:
                    269: #define LEDSYSCTL_SETUP(x) if ((i = sysctl_createv(NULL,               \
                    270:                                0, NULL, &datnode,                      \
                    271:                                CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,     \
                    272:                                 CTLTYPE_INT,                           \
                    273:                                "led" #x "_duty",                       \
                    274:                                SYSCTL_DESCR(                           \
                    275:                                "LED duty cycle in HZ tick units"),     \
                    276:                                led_sysctl, 0, &sc->led_duty[(x)], 0,   \
                    277:                                CTL_HW, node->sysctl_num,               \
                    278:                                CTL_CREATE, CTL_EOL))                   \
                    279:                                != 0) {                                 \
1.6       cegger    280:                 aprint_error_dev(&sc->sc_dev, "could not create sysctl\n");            \
1.1       joff      281:                return;                                                 \
                    282:        }                                                               \
                    283:        sc->led_duty_sysctl[(x)] = datnode->sysctl_num;                 \
                    284:                                                                        \
                    285:        if ((i = sysctl_createv(NULL, 0, NULL, &datnode,                \
                    286:                                CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,     \
                    287:                                CTLTYPE_INT,                            \
                    288:                                "led" #x "_width",                      \
                    289:                                SYSCTL_DESCR(                           \
                    290:                                "LED cycle width in HZ tick units"),    \
                    291:                                led_sysctl, 0, &sc->led_width[(x)], 0,  \
                    292:                                CTL_HW, node->sysctl_num,               \
                    293:                                CTL_CREATE, CTL_EOL))                   \
                    294:                                != 0) {                                 \
1.6       cegger    295:                 aprint_error_dev(&sc->sc_dev, "could not create sysctl\n");            \
1.1       joff      296:                return;                                                 \
                    297:        }                                                               \
                    298:        sc->led_width_sysctl[(x)] = datnode->sysctl_num;
                    299:
                    300:        LEDSYSCTL_SETUP(0);
                    301:        LEDSYSCTL_SETUP(1);
                    302:        LEDSYSCTL_SETUP(2);
                    303:        LEDSYSCTL_SETUP(3);
                    304:
                    305:        if ((i = sysctl_createv(NULL, 0, NULL, &datnode,
                    306:                                CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
                    307:                                CTLTYPE_INT,
                    308:                                "magnetic_latch",
                    309:                                SYSCTL_DESCR(
                    310:                                "magnetic latch that holds the toast down"),
                    311:                                latch_sysctl, 0, &sc->latch, 0,
                    312:                                CTL_HW, node->sysctl_num,
                    313:                                CTL_CREATE, CTL_EOL))
                    314:                                != 0) {
1.6       cegger    315:                 aprint_error_dev(&sc->sc_dev, "could not create sysctl\n");
1.1       joff      316:                return;
                    317:        }
                    318:
                    319:        if ((i = sysctl_createv(NULL, 0, NULL, &datnode,
                    320:                                CTLFLAG_READWRITE, CTLTYPE_INT,
                    321:                                "burner_element",
                    322:                                SYSCTL_DESCR(
                    323:                                "800-watt burner element control for toasting"),
                    324:                                burner_sysctl, 0, &sc->burner, 0,
                    325:                                CTL_HW, node->sysctl_num,
                    326:                                CTL_CREATE, CTL_EOL))
                    327:                                != 0) {
1.6       cegger    328:                 aprint_error_dev(&sc->sc_dev, "could not create sysctl\n");
1.1       joff      329:                return;
                    330:        }
                    331:
                    332:
                    333: }

CVSweb <webmaster@jp.NetBSD.org>