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