vrled.c revision 1.2 1 /* $NetBSD: vrled.c,v 1.2 2000/12/27 12:08:03 sato Exp $ */
2
3 /*
4 * Copyright (c) 2000 SATO Kazumi. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/device.h>
31 #include <sys/reboot.h>
32
33 #include <machine/bus.h>
34 #include <machine/config_hook.h>
35
36 #include <hpcmips/vr/vripvar.h>
37 #include <hpcmips/vr/vrledvar.h>
38 #include <hpcmips/vr/vrledreg.h>
39
40
41 #ifdef VRLEDDEBUG
42 #ifndef VRLEDDEBUG_CONF
43 #define VRLEDDEBUG_CONF 0
44 #endif /* VRLEDDEBUG_CONF */
45 int vrleddebug = VRLEDDEBUG_CONF;
46 #define DPRINTF(arg) if (vrleddebug) printf arg;
47 #define VPRINTF(arg) if (bootverbose||vrleddebug) printf arg;
48 #else /* VRLEDDEBUG */
49 #define DPRINTF(arg)
50 #define VPRINTF(arg) if (bootverbose) printf arg;
51 #endif /* VRLEDDEBUG */
52
53 static int vrledmatch __P((struct device *, struct cfdata *, void *));
54 static void vrledattach __P((struct device *, struct device *, void *));
55
56 static void vrled_write __P((struct vrled_softc *, int, unsigned short));
57 static unsigned short vrled_read __P((struct vrled_softc *, int));
58
59 static void vrled_stop __P((struct vrled_softc *));
60 static void vrled_on __P((struct vrled_softc *));
61 static void vrled_blink __P((struct vrled_softc *));
62 static void vrled_flash __P((struct vrled_softc *));
63 static void vrled_change_state __P((struct vrled_softc *));
64 static int vrled_event __P((void *, int, long, void *));
65
66 int vrled_intr __P((void *));
67
68 struct cfattach vrled_ca = {
69 sizeof(struct vrled_softc), vrledmatch, vrledattach
70 };
71
72 struct vrled_softc *this_led;
73
74 static inline void
75 vrled_write(sc, port, val)
76 struct vrled_softc *sc;
77 int port;
78 unsigned short val;
79 {
80 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
81 }
82
83 static inline unsigned short
84 vrled_read(sc, port)
85 struct vrled_softc *sc;
86 int port;
87 {
88 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
89 }
90
91 static int
92 vrledmatch(parent, cf, aux)
93 struct device *parent;
94 struct cfdata *cf;
95 void *aux;
96 {
97 return 1;
98 }
99
100 static void
101 vrledattach(parent, self, aux)
102 struct device *parent;
103 struct device *self;
104 void *aux;
105 {
106 struct vrled_softc *sc = (struct vrled_softc *)self;
107 struct vrip_attach_args *va = aux;
108
109 bus_space_tag_t iot = va->va_iot;
110 bus_space_handle_t ioh;
111
112 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
113 printf(": can't map bus space\n");
114 return;
115 }
116
117 sc->sc_iot = iot;
118 sc->sc_ioh = ioh;
119
120 if (!(sc->sc_handler =
121 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
122 vrled_intr, sc))) {
123 printf (": can't map interrupt line.\n");
124 return;
125 }
126
127 printf("\n");
128 /* clear interrupt status */
129 vrled_write(sc, LEDINT_REG_W, LEDINT_ALL);
130
131 /* basic setup */
132 sc->sc_state_cnt = 1;
133 vrled_write(sc, LEDASTC_REG_W, 1); /* 1time */
134 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP);
135 vrled_stop(sc);
136
137 sc->sc_hook = config_hook(CONFIG_HOOK_SET,
138 CONFIG_HOOK_LED,
139 CONFIG_HOOK_SHARE,
140 vrled_event, sc);
141 this_led = sc;
142 }
143
144
145 /*
146 * LED interrupt handler.
147 *
148 */
149 int
150 vrled_intr(arg)
151 void *arg;
152 {
153 struct vrled_softc *sc = arg;
154 unsigned int intstat;
155
156 intstat = vrled_read(sc, LEDINT_REG_W);
157 /* clear interrupt status */
158 vrled_write(sc, LEDINT_REG_W, intstat);
159 if (intstat&LEDINT_AUTOSTOP) {
160 vrled_change_state(sc);
161 }
162 return 0;
163 }
164
165 /*
166 * LED turn OFF
167 *
168 */
169 void
170 vrled_stop(sc)
171 struct vrled_softc *sc;
172 {
173 vrled_write(sc, LEDHTS_REG_W, LEDHTS_DIV16SEC);
174 vrled_write(sc, LEDLTS_REG_W, LEDLTS_4SEC);
175 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
176 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP);
177
178 sc->sc_state = LEDOFF;
179 sc->sc_next = LEDOFF;
180 }
181
182 /*
183 * LED turn ON
184 *
185 */
186 void
187 vrled_on(sc)
188 struct vrled_softc *sc;
189 {
190 vrled_write(sc, LEDHTS_REG_W, LEDHTS_SEC);
191 vrled_write(sc, LEDLTS_REG_W, LEDLTS_DIV16SEC);
192 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
193 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK);
194
195 sc->sc_state = LEDON;
196 sc->sc_next = LEDON;
197 }
198
199 /*
200 * LED blink
201 *
202 */
203 void
204 vrled_blink(sc)
205 struct vrled_softc *sc;
206 {
207 int ledhts;
208 int ledlts;
209
210 switch (sc->sc_next) {
211 case LED1SB:
212 ledhts = LEDHTS_DIV2SEC;
213 ledlts = LEDLTS_DIV2SEC;
214 break;
215 case LED2SB:
216 ledhts = LEDHTS_SEC;
217 ledlts = LEDLTS_SEC;
218 break;
219 default:
220 vrled_stop(sc);
221 return;
222 }
223
224 vrled_write(sc, LEDHTS_REG_W, ledhts);
225 vrled_write(sc, LEDLTS_REG_W, ledlts);
226 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
227 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP);
228 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK);
229
230 sc->sc_state = sc->sc_next;
231 }
232
233 /*
234 * LED flash once
235 *
236 */
237 void
238 vrled_flash(sc)
239 struct vrled_softc *sc;
240 {
241 int ledhts;
242 int ledlts;
243
244 switch (sc->sc_next) {
245 case LED8DIVF:
246 ledhts = LEDHTS_DIV16SEC;
247 ledlts = LEDLTS_DIV16SEC;
248 break;
249 case LED4DIVF:
250 ledhts = LEDHTS_DIV8SEC;
251 ledlts = LEDLTS_DIV8SEC;
252 break;
253 case LED2DIVF:
254 ledhts = LEDHTS_DIV4SEC;
255 ledlts = LEDLTS_DIV4SEC;
256 break;
257 case LED1SF:
258 ledhts = LEDHTS_DIV2SEC;
259 ledlts = LEDLTS_DIV2SEC;
260 break;
261 default:
262 vrled_stop(sc);
263 return;
264 }
265
266 vrled_write(sc, LEDHTS_REG_W, ledhts);
267 vrled_write(sc, LEDLTS_REG_W, ledlts);
268 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */
269 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK);
270
271 sc->sc_state = sc->sc_next;
272 sc->sc_next = LEDOFF;
273 sc->sc_state_cnt = 1;
274 }
275
276 /*
277 * Change LED state
278 *
279 */
280 void
281 vrled_change_state(sc)
282 struct vrled_softc *sc;
283 {
284
285 switch (sc->sc_next) {
286 case LEDOFF:
287 vrled_stop(sc);
288 break;
289 case LEDON:
290 vrled_on(sc);
291 break;
292 case LED1SB:
293 case LED2SB:
294 vrled_blink(sc);
295 break;
296 case LED8DIVF:
297 case LED4DIVF:
298 case LED2DIVF:
299 case LED1SF:
300 vrled_flash(sc);
301 break;
302 default:
303 vrled_stop(sc);
304 break;
305 }
306 }
307
308 /*
309 * Set LED state
310 *
311 */
312 void
313 vrled_set_state(sc, state)
314 struct vrled_softc *sc;
315 vrled_status state;
316 {
317
318 int ledstate;
319
320 ledstate = vrled_read(sc, LEDCNT_REG_W);
321 if (ledstate&LEDCNT_BLINK) { /* currently processing */
322 if (sc->sc_next == state)
323 sc->sc_state_cnt++;
324 switch (sc->sc_next) {
325 case LEDOFF:
326 case LEDON:
327 sc->sc_next = state;
328 break;
329 case LED8DIVF:
330 case LED4DIVF:
331 case LED2DIVF:
332 case LED1SF:
333 switch (state) {
334 case LEDOFF:
335 case LED8DIVF:
336 case LED4DIVF:
337 case LED2DIVF:
338 case LED1SF:
339 sc->sc_next = state;
340 break;
341 default:
342 break;
343 }
344 break;
345 case LED1SB:
346 case LED2SB:
347 switch (state) {
348 case LEDOFF:
349 case LEDON:
350 case LED1SB:
351 case LED2SB:
352 sc->sc_next = state;
353 break;
354 default:
355 break;
356 }
357 break;
358 default:
359 sc->sc_next = LEDOFF;
360 break;
361 }
362 return;
363 }
364 sc->sc_next = state;
365 vrled_change_state(sc);
366 }
367
368 /*
369 * LED config hook events
370 *
371 */
372 int
373 vrled_event(ctx, type, id, msg)
374 void *ctx;
375 int type;
376 long id;
377 void *msg;
378 {
379 struct vrled_softc *sc = (struct vrled_softc *)ctx;
380 int why =*(int *)msg;
381
382 if (type != CONFIG_HOOK_SET
383 || id != CONFIG_HOOK_LED)
384 return 1;
385 if (msg == NULL)
386 return 1;
387
388 switch (why) {
389 case CONFIG_HOOK_LED_OFF:
390 vrled_set_state(sc, LEDOFF);
391 break;
392 case CONFIG_HOOK_LED_ON:
393 vrled_set_state(sc, LEDON);
394 break;
395 case CONFIG_HOOK_LED_FLASH:
396 vrled_set_state(sc, LED8DIVF);
397 break;
398 case CONFIG_HOOK_LED_FLASH2:
399 vrled_set_state(sc, LED4DIVF);
400 break;
401 case CONFIG_HOOK_LED_FLASH5:
402 vrled_set_state(sc, LED2DIVF);
403 break;
404 case CONFIG_HOOK_LED_BLINK:
405 vrled_set_state(sc, LED1SB);
406 break;
407 case CONFIG_HOOK_LED_BLINK2:
408 vrled_set_state(sc, LED2SB);
409 break;
410 default:
411 vrled_set_state(sc, LEDOFF);
412 }
413 return (0);
414 }
415
416 /* end */
417