Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/isa Device driver that exposes the burner element, m...



details:   https://anonhg.NetBSD.org/src/rev/750de31b76a7
branches:  trunk
changeset: 583598:750de31b76a7
user:      joff <joff%NetBSD.org@localhost>
date:      Sun Aug 14 04:14:35 2005 +0000

description:
Device driver that exposes the burner element, magnetic latch, and front-panel
LEDs of the TS-7200 NetBSD/toaster via sysctl.

diffstat:

 sys/dev/isa/toaster.c |  353 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 353 insertions(+), 0 deletions(-)

diffs (truncated from 357 to 300 lines):

diff -r 20d76256828f -r 750de31b76a7 sys/dev/isa/toaster.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/isa/toaster.c     Sun Aug 14 04:14:35 2005 +0000
@@ -0,0 +1,353 @@
+/* $NetBSD: toaster.c,v 1.1 2005/08/14 04:14:35 joff Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jesse Off.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: toaster.c,v 1.1 2005/08/14 04:14:35 joff Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/poll.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/callout.h>
+#include <sys/select.h>
+#include <sys/conf.h>
+
+#include <machine/bus.h>
+#include <machine/autoconf.h>
+
+#include <dev/isa/tsdiovar.h>
+#include <dev/isa/tsdioreg.h>
+
+struct toaster_softc {
+       struct device sc_dev;
+       bus_space_tag_t sc_iot;
+       bus_space_handle_t sc_gpioh;
+       u_int32_t latch;
+       u_int32_t burner;
+       u_int32_t led_width[4];
+       u_int32_t led_duty[4];
+       u_int32_t led_width_sysctl[4];
+       u_int32_t led_duty_sysctl[4];
+       struct callout led_callout[4];
+};
+
+static int     toaster_match(struct device *, struct cfdata *, void *);
+static void    toaster_attach(struct device *, struct device *, void *);
+
+extern struct cfdriver toaster_cd;
+
+CFATTACH_DECL(toaster, sizeof(struct toaster_softc),
+    toaster_match, toaster_attach, NULL, NULL);
+
+static struct toaster_softc *toaster_sc = NULL;
+
+static int
+toaster_match(parent, match, aux)
+       struct device *parent;
+       struct cfdata *match;
+       void *aux;
+{
+       /* No more than one toaster per system */
+       if (toaster_sc == NULL)
+               return 1;
+       else
+               return 0;
+}
+
+#define TSDIO_GET(x)   bus_space_read_1(sc->sc_iot, sc->sc_gpioh, \
+       (TSDIO_ ## x))
+
+#define TSDIO_SET(x, y)        bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
+       (TSDIO_ ## x), (y))
+
+#define TSDIO_SETBITS(x, y)    bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
+       (TSDIO_ ## x), TSDIO_GET(x) | (y))
+
+#define TSDIO_CLEARBITS(x, y)  bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
+       (TSDIO_ ## x), TSDIO_GET(x) & (~(y)))
+
+#define LEDCALLOUT_DECL(x)     static void led ## x ## _on(void *);    \
+static void led ## x ## _off(void *);                                  \
+static void                                                            \
+led ## x ## _on(arg)                                                   \
+       void *arg;                                                      \
+{                                                                      \
+       struct toaster_softc *sc = arg;                                 \
+                                                                       \
+       if (sc->led_duty[(x)]) {                                        \
+               TSDIO_CLEARBITS(PBDR, (1 << (4 + (x))));                \
+               callout_reset(&sc->led_callout[(x)],                    \
+                       sc->led_duty[(x)], led ## x ## _off, arg);      \
+       } else {                                                        \
+               TSDIO_SETBITS(PBDR, (1 << (4 + (x))));                  \
+       }                                                               \
+}                                                                      \
+                                                                       \
+static void                                                            \
+led ## x ## _off(arg)                                                  \
+       void *arg;                                                      \
+{                                                                      \
+       struct toaster_softc *sc = arg;                                 \
+       int offtime = sc->led_width[(x)] - sc->led_duty[(x)];           \
+                                                                       \
+       if (offtime > 0) {                                              \
+               TSDIO_SETBITS(PBDR, (1 << (4 + (x))));                  \
+               callout_reset(&sc->led_callout[(x)], offtime,           \
+                       led ## x ## _on, arg);                          \
+       }                                                               \
+}
+
+LEDCALLOUT_DECL(0)
+LEDCALLOUT_DECL(1)
+LEDCALLOUT_DECL(2)
+LEDCALLOUT_DECL(3)
+
+static int
+led_sysctl(SYSCTLFN_ARGS)
+{
+       int error, t;
+       struct sysctlnode node;
+       struct toaster_softc *sc = toaster_sc;
+
+       node = *rnode;
+       t = *(int*)rnode->sysctl_data;
+       node.sysctl_data = &t;
+       error = sysctl_lookup(SYSCTLFN_CALL(&node));
+       if (error || newp == NULL)
+               return (error);
+
+       if (t < 0) return EINVAL;
+
+       *(int*)rnode->sysctl_data = t;
+
+       if (node.sysctl_num == sc->led_width_sysctl[0] ||
+               node.sysctl_num == sc->led_duty_sysctl[0])
+               led0_on(sc);
+       if (node.sysctl_num == sc->led_width_sysctl[1] ||
+               node.sysctl_num == sc->led_duty_sysctl[1])
+               led1_on(sc);
+       if (node.sysctl_num == sc->led_width_sysctl[2] ||
+               node.sysctl_num == sc->led_duty_sysctl[2])
+               led2_on(sc);
+       if (node.sysctl_num == sc->led_width_sysctl[3] ||
+               node.sysctl_num == sc->led_duty_sysctl[3])
+               led3_on(sc);
+
+       return (0);
+}
+
+static int
+latch_sysctl(SYSCTLFN_ARGS)
+{
+       int error, t;
+       struct sysctlnode node;
+       struct toaster_softc *sc = toaster_sc;
+
+       node = *rnode;
+       t = *(int*)rnode->sysctl_data;
+       node.sysctl_data = &t;
+       error = sysctl_lookup(SYSCTLFN_CALL(&node));
+       if (error || newp == NULL)
+               return (error);
+
+       if (t != 0 && t != 1) return EINVAL;
+
+       *(int*)rnode->sysctl_data = t;
+
+       if (t)
+               TSDIO_SETBITS(PADR, 0x1);
+       else
+               TSDIO_CLEARBITS(PADR, 0x1);
+
+       return (0);
+}
+
+static int
+burner_sysctl(SYSCTLFN_ARGS)
+{
+       int error, t;
+       struct sysctlnode node;
+       struct toaster_softc *sc = toaster_sc;
+
+       node = *rnode;
+       t = *(int*)rnode->sysctl_data;
+       node.sysctl_data = &t;
+       error = sysctl_lookup(SYSCTLFN_CALL(&node));
+       if (error || newp == NULL)
+               return (error);
+
+       if (t != 0 && t != 1) return EINVAL;
+
+       *(int*)rnode->sysctl_data = t;
+
+       if (t)
+               TSDIO_SETBITS(PADR, 0x2);
+       else
+               TSDIO_CLEARBITS(PADR, 0x2);
+
+       return (0);
+}
+
+
+static void
+toaster_attach(parent, self, aux)
+       struct device *parent;
+       struct device *self;
+       void *aux;
+{
+       struct toaster_softc *sc = (void *)self;
+       struct tsdio_attach_args *taa = aux;
+        const struct sysctlnode *node, *datnode;
+       int i;
+
+       toaster_sc = sc;
+       sc->sc_iot = taa->ta_iot;
+       sc->sc_gpioh = taa->ta_ioh;
+
+       TSDIO_SETBITS(DDR, 0x2);        /* Port B as outputs */
+       TSDIO_SETBITS(PBDR, 0xf0);      /* Turn off LED's */
+
+       aprint_normal(": internal toaster control outputs\n");
+       aprint_normal("%s: using port B, bits 4-7 for front panel LEDs\n", sc->sc_dev.dv_xname);
+       aprint_normal("%s: using port A, bit 0 for magnetic latch\n", sc->sc_dev.dv_xname);
+       aprint_normal("%s: using port A, bit 1 for burner element\n", sc->sc_dev.dv_xname);
+       
+       callout_init(&sc->led_callout[0]);
+       callout_init(&sc->led_callout[1]);
+       callout_init(&sc->led_callout[2]);
+       callout_init(&sc->led_callout[3]);
+       sc->led_duty[0] = sc->led_width[0] = 0;
+       sc->led_duty[1] = sc->led_width[1] = 0;
+       sc->led_duty[2] = sc->led_width[2] = 0;
+       sc->led_duty[3] = sc->led_width[3] = 0;
+
+       sc->burner = 0;
+       sc->latch = 0;
+
+       if (sysctl_createv(NULL, 0, NULL, NULL,
+                               CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
+                               NULL, NULL, 0, NULL, 0,
+                               CTL_HW, CTL_EOL) != 0) {
+               printf("%s: could not create sysctl\n",
+                       sc->sc_dev.dv_xname);
+               return;
+       }
+       if (sysctl_createv(NULL, 0, NULL, &node,
+                               0, CTLTYPE_NODE, sc->sc_dev.dv_xname,
+                               NULL,
+                               NULL, 0, NULL, 0,
+                               CTL_HW, CTL_CREATE, CTL_EOL) != 0) {
+                printf("%s: could not create sysctl\n",
+                       sc->sc_dev.dv_xname);
+               return;
+       }
+
+#define LEDSYSCTL_SETUP(x) if ((i = sysctl_createv(NULL,               \
+                               0, NULL, &datnode,                      \
+                               CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,     \
+                                CTLTYPE_INT,                           \
+                               "led" #x "_duty",                       \
+                               SYSCTL_DESCR(                           \
+                               "LED duty cycle in HZ tick units"),     \
+                               led_sysctl, 0, &sc->led_duty[(x)], 0,   \
+                               CTL_HW, node->sysctl_num,               \
+                               CTL_CREATE, CTL_EOL))                   \
+                               != 0) {                                 \
+                printf("%s: could not create sysctl\n",                \



Home | Main Index | Thread Index | Old Index