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>