tx39icu.c revision 1.12 1 /* $NetBSD: tx39icu.c,v 1.12 2001/06/14 11:09:55 uch Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "opt_tx39_debug.h"
40 #include "opt_use_poll.h"
41 #include "opt_tx39icudebug.h"
42 #include "opt_tx39_watchdogtimer.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/device.h>
47 #include <sys/malloc.h>
48 #include <sys/queue.h>
49
50 #include <mips/cpuregs.h>
51 #include <machine/bus.h>
52
53 #include <hpcmips/tx/tx39var.h>
54 #include <hpcmips/tx/tx39icureg.h>
55 #include <hpcmips/tx/tx39clockvar.h>
56
57 #include <machine/clock_machdep.h>
58 #include <machine/cpu.h>
59 #include <dev/dec/clockvar.h>
60
61 #undef TX39ICUDEBUG_PRINT_PENDING_INTERRUPT /* For explorer. good luck! */
62
63 #ifdef TX39ICUDEBUG
64 #define DPRINTF(arg) printf arg
65 #else
66 #define DPRINTF(arg)
67 #endif
68 u_int32_t tx39intrvec;
69
70 /* IRQHIGH lines list */
71 static const struct irqhigh_list {
72 int qh_pri; /* IRQHIGH priority */
73 int qh_set; /* Register set */
74 int qh_bit; /* bit offset in the register set */
75 } irqhigh_list[] = {
76 {15, 5, 25}, /* POSPWROKINT */
77 {15, 5, 24}, /* NEGPWROKINT */
78 {14, 5, 30}, /* ALARMINT*/
79 {13, 5, 29}, /* PERINT */
80 #ifdef TX391X
81 {12, 2, 3}, /* MBUSPOSINT */
82 {12, 2, 2}, /* MBUSNEGINT */
83 {11, 2, 31}, /* UARTARXINT */
84 {10, 2, 21}, /* UARTBRXINT */
85 {9, 3, 19}, /* MFIOPOSINT19 */
86 {9, 3, 18}, /* MFIOPOSINT18 */
87 {9, 3, 17}, /* MFIOPOSINT17 */
88 {9, 3, 16}, /* MFIOPOSINT16 */
89 {8, 3, 1}, /* MFIOPOSINT1 */
90 {8, 3, 0}, /* MFIOPOSINT0 */
91 {8, 5, 13}, /* IOPOSINT6 */
92 {8, 5, 12}, /* IOPOSINT5 */
93 {7, 4, 19}, /* MFIONEGINT19 */
94 {7, 4, 18}, /* MFIONEGINT18 */
95 {7, 4, 17}, /* MFIONEGINT17 */
96 {7, 4, 16}, /* MFIONEGINT16 */
97 {6, 4, 1}, /* MFIONEGINT1 */
98 {6, 4, 0}, /* MFIONEGINT0 */
99 {6, 5, 6}, /* IONEGINT6 */
100 {6, 5, 5}, /* IONEGINT5 */
101 {5, 2, 5}, /* MBUSDMAFULLINT */
102 #endif /* TX391X */
103 #ifdef TX392X
104 {12, 2, 31}, /* UARTARXINT */
105 {12, 2, 21}, /* UARTBRXINT */
106 {11, 3, 19}, /* MFIOPOSINT19 */
107 {11, 3, 18}, /* MFIOPOSINT18 */
108 {11, 3, 17}, /* MFIOPOSINT17 */
109 {11, 3, 16}, /* MFIOPOSINT16 */
110 {10, 3, 1}, /* MFIOPOSINT1 */
111 {10, 3, 0}, /* MFIOPOSINT0 */
112 {10, 5, 13}, /* IOPOSINT6 */
113 {10, 5, 12}, /* IOPOSINT5 */
114 {9, 4, 19}, /* MFIONEGINT19 */
115 {9, 4, 18}, /* MFIONEGINT18 */
116 {9, 4, 17}, /* MFIONEGINT17 */
117 {9, 4, 16}, /* MFIONEGINT16 */
118 {8, 4, 1}, /* MFIONEGINT1 */
119 {8, 4, 0}, /* MFIONEGINT0 */
120 {8, 5, 6}, /* IONEGINT6 */
121 {8, 5, 5}, /* IONEGINT5 */
122 {5, 7, 19}, /* IRRXCINT */
123 {5, 7, 17}, /* IRRXEINT */
124 #endif /* TX392X */
125 {4, 1, 18}, /* SNDDMACNTINT */
126 {3, 1, 17}, /* TELDMACNTINT */
127 {2, 1, 27}, /* CHIDMACNTINT */
128 {1, 5, 7}, /* IOPOSINT0 */
129 {1, 5, 0} /* IONEGINT0 */
130 };
131
132 struct txintr_high_entry {
133 int he_set;
134 txreg_t he_mask;
135 int (*he_fun)(void *);
136 void *he_arg;
137 TAILQ_ENTRY(txintr_high_entry) he_link;
138 };
139
140 #ifdef USE_POLL
141 struct txpoll_entry{
142 int p_cnt; /* dispatch interval */
143 int p_desc;
144 int (*p_fun)(void *);
145 void *p_arg;
146 TAILQ_ENTRY(txpoll_entry) p_link;
147 };
148 int tx39_poll_intr(void *);
149 #endif /* USE_POLL */
150
151 struct tx39icu_softc {
152 struct device sc_dev;
153 tx_chipset_tag_t sc_tc;
154 /* IRQLOW */
155 txreg_t sc_le_mask[TX39_INTRSET_MAX + 1];
156 int (*sc_le_fun[TX39_INTRSET_MAX + 1][32])(void *);
157 void *sc_le_arg[TX39_INTRSET_MAX + 1][32];
158 /* IRQHIGH */
159 TAILQ_HEAD(, txintr_high_entry) sc_he_head[TX39_IRQHIGH_MAX];
160 /* Register */
161 txreg_t sc_regs[TX39_INTRSET_MAX + 1];
162 #ifdef USE_POLL
163 unsigned sc_pollcnt;
164 int sc_polling;
165 void *sc_poll_ih;
166 TAILQ_HEAD(, txpoll_entry) sc_p_head;
167 #endif /* USE_POLL */
168 };
169
170 int tx39icu_match(struct device *, struct cfdata *, void *);
171 void tx39icu_attach(struct device *, struct device *, void *);
172 int tx39icu_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
173
174 void tx39_intr_dump(struct tx39icu_softc *);
175 void tx39_intr_decode(int, int *, int *);
176 void tx39_irqhigh_disestablish(tx_chipset_tag_t, int, int, int);
177 void tx39_irqhigh_establish(tx_chipset_tag_t, int, int, int,
178 int (*)(void *), void *);
179 void tx39_irqhigh_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
180 int tx39_irqhigh(int, int);
181
182 struct cfattach tx39icu_ca = {
183 sizeof(struct tx39icu_softc), tx39icu_match, tx39icu_attach
184 };
185
186 int
187 tx39icu_match(struct device *parent, struct cfdata *cf, void *aux)
188 {
189 return (ATTACH_FIRST);
190 }
191
192 void
193 tx39icu_attach(struct device *parent, struct device *self, void *aux)
194 {
195 struct txsim_attach_args *ta = aux;
196 struct tx39icu_softc *sc = (void *)self;
197 tx_chipset_tag_t tc = ta->ta_tc;
198 txreg_t reg, *regs;
199 int i;
200
201 printf("\n");
202 sc->sc_tc = ta->ta_tc;
203
204 regs = sc->sc_regs;
205 regs[0] = tx_conf_read(tc, TX39_INTRSTATUS6_REG);
206 regs[1] = tx_conf_read(tc, TX39_INTRSTATUS1_REG);
207 regs[2] = tx_conf_read(tc, TX39_INTRSTATUS2_REG);
208 regs[3] = tx_conf_read(tc, TX39_INTRSTATUS3_REG);
209 regs[4] = tx_conf_read(tc, TX39_INTRSTATUS4_REG);
210 regs[5] = tx_conf_read(tc, TX39_INTRSTATUS5_REG);
211 #ifdef TX392X
212 regs[7] = tx_conf_read(tc, TX39_INTRSTATUS7_REG);
213 regs[8] = tx_conf_read(tc, TX39_INTRSTATUS8_REG);
214 #endif
215 #ifdef TX39ICUDEBUG
216 printf("\t[Windows CE setting]\n");
217 tx39_intr_dump(sc);
218 #endif /* TX39ICUDEBUG */
219
220 #ifdef WINCE_DEFAULT_SETTING
221 #warning WINCE_DEFAULT_SETTING
222 #else /* WINCE_DEFAULT_SETTING */
223 /* Disable IRQLOW */
224 tx_conf_write(tc, TX39_INTRENABLE1_REG, 0);
225 tx_conf_write(tc, TX39_INTRENABLE2_REG, 0);
226 tx_conf_write(tc, TX39_INTRENABLE3_REG, 0);
227 tx_conf_write(tc, TX39_INTRENABLE4_REG, 0);
228 tx_conf_write(tc, TX39_INTRENABLE5_REG, 0);
229 #ifdef TX392X
230 tx_conf_write(tc, TX39_INTRENABLE7_REG, 0);
231 tx_conf_write(tc, TX39_INTRENABLE8_REG, 0);
232 #endif /* TX392X */
233
234 /* Disable IRQHIGH */
235 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG);
236 reg &= ~TX39_INTRENABLE6_PRIORITYMASK_MASK;
237 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg);
238 #endif /* WINCE_DEFAULT_SETTING */
239
240 /* Clear all pending interrupts */
241 tx_conf_write(tc, TX39_INTRCLEAR1_REG,
242 tx_conf_read(tc, TX39_INTRSTATUS1_REG));
243 tx_conf_write(tc, TX39_INTRCLEAR2_REG,
244 tx_conf_read(tc, TX39_INTRSTATUS2_REG));
245 tx_conf_write(tc, TX39_INTRCLEAR3_REG,
246 tx_conf_read(tc, TX39_INTRSTATUS3_REG));
247 tx_conf_write(tc, TX39_INTRCLEAR4_REG,
248 tx_conf_read(tc, TX39_INTRSTATUS4_REG));
249 tx_conf_write(tc, TX39_INTRCLEAR5_REG,
250 tx_conf_read(tc, TX39_INTRSTATUS5_REG));
251 #ifdef TX392X
252 tx_conf_write(tc, TX39_INTRCLEAR7_REG,
253 tx_conf_read(tc, TX39_INTRSTATUS7_REG));
254 tx_conf_write(tc, TX39_INTRCLEAR8_REG,
255 tx_conf_read(tc, TX39_INTRSTATUS8_REG));
256 #endif /* TX392X */
257
258 /* Enable global interrupts */
259 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG);
260 reg |= TX39_INTRENABLE6_GLOBALEN;
261 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg);
262
263 /* Initialize IRQHIGH interrupt handler holder*/
264 for (i = 0; i < TX39_IRQHIGH_MAX; i++) {
265 TAILQ_INIT(&sc->sc_he_head[i]);
266 }
267 #ifdef USE_POLL
268 /* Initialize polling handler holder */
269 TAILQ_INIT(&sc->sc_p_head);
270 #endif /* USE_POLL */
271
272 /* Register interrupt module myself */
273 tx_conf_register_intr(tc, self);
274 }
275
276 int
277 tx39icu_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
278 u_int32_t ipending)
279 {
280 struct tx39icu_softc *sc;
281 tx_chipset_tag_t tc;
282 txreg_t reg, pend, *regs;
283 int i, j;
284
285 tc = tx_conf_get_tag();
286 sc = tc->tc_intrt;
287 /*
288 * Read regsiter ASAP
289 */
290 regs = sc->sc_regs;
291 regs[0] = tx_conf_read(tc, TX39_INTRSTATUS6_REG);
292 regs[1] = tx_conf_read(tc, TX39_INTRSTATUS1_REG);
293 regs[2] = tx_conf_read(tc, TX39_INTRSTATUS2_REG);
294 regs[3] = tx_conf_read(tc, TX39_INTRSTATUS3_REG);
295 regs[4] = tx_conf_read(tc, TX39_INTRSTATUS4_REG);
296 regs[5] = tx_conf_read(tc, TX39_INTRSTATUS5_REG);
297 #ifdef TX392X
298 regs[7] = tx_conf_read(tc, TX39_INTRSTATUS7_REG);
299 regs[8] = tx_conf_read(tc, TX39_INTRSTATUS8_REG);
300 #endif
301
302 #ifdef TX39ICUDEBUG
303 if (!(ipending & MIPS_INT_MASK_4) && !(ipending & MIPS_INT_MASK_2)) {
304 bitdisp(ipending);
305 panic("bogus HwInt");
306 }
307 #ifdef TX39_DEBUG
308 if (tx39debugflag) {
309 tx39_intr_dump(sc);
310 }
311 #endif
312 #endif /* TX39ICUDEBUG */
313
314 /* IRQHIGH */
315 if (ipending & MIPS_INT_MASK_4) {
316 tx39_irqhigh_intr(ipending, pc, status, cause);
317
318 return (0);
319 }
320
321 /* IRQLOW */
322 if (ipending & MIPS_INT_MASK_2) {
323 for (i = 1; i <= TX39_INTRSET_MAX; i++) {
324 int ofs;
325 #ifdef TX392X
326 if (i == 6)
327 continue;
328 #endif /* TX392X */
329 ofs = TX39_INTRSTATUS_REG(i);
330 pend = sc->sc_regs[i];
331 reg = sc->sc_le_mask[i] & pend;
332 /* Clear interrupts */
333 tx_conf_write(tc, ofs, reg);
334 /* Dispatch handler */
335 for (j = 0 ; j < 32; j++) {
336 if ((reg & (1 << j)) &&
337 sc->sc_le_fun[i][j]) {
338 #ifdef TX39_DEBUG
339 tx39intrvec = (i << 16) | j;
340 if (tx39debugflag) {
341 DPRINTF(("IRQLOW %d:%d\n",
342 i, j));
343 }
344 #endif /* TX39_DEBUG */
345 (*sc->sc_le_fun[i][j])
346 (sc->sc_le_arg[i][j]);
347
348 }
349 }
350 #ifdef TX39ICUDEBUG_PRINT_PENDING_INTERRUPT
351 pend &= ~reg;
352 if (pend) {
353 printf("%d pending:", i);
354 __bitdisp(pend, 0, 31, 0, 1);
355 }
356 #endif
357
358 }
359 }
360 #ifdef TX39_WATCHDOGTIMER
361 {
362 extern int tx39biu_intr(void *);
363 /* Bus error (If watch dog timer is enabled)*/
364 if (ipending & MIPS_INT_MASK_1) {
365 tx39biu_intr(0); /* Clear bus error */
366 }
367 }
368 #endif
369 #if 0
370 /* reset priority mask */
371 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG);
372 reg = TX39_INTRENABLE6_PRIORITYMASK_SET(reg, 0xffff);
373 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg);
374 #endif
375 return (MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
376 }
377
378 int
379 tx39_irqhigh(int set, int bit)
380 {
381 int i, n;
382
383 n = sizeof irqhigh_list / sizeof (struct irqhigh_list);
384 for (i = 0; i < n; i++) {
385 if (irqhigh_list[i].qh_set == set &&
386 irqhigh_list[i].qh_bit == bit)
387 return (irqhigh_list[i].qh_pri);
388 }
389
390 return (0);
391 }
392
393 void
394 tx39_irqhigh_intr(u_int32_t ipending, u_int32_t pc, u_int32_t status,
395 u_int32_t cause)
396 {
397 struct txintr_high_entry *he;
398 struct tx39icu_softc *sc;
399 struct clockframe cf;
400 tx_chipset_tag_t tc;
401 int i, pri, ofs, set;
402 txreg_t he_mask;
403
404 tc = tx_conf_get_tag();
405 sc = tc->tc_intrt;
406 pri = TX39_INTRSTATUS6_INTVECT(sc->sc_regs[0]);
407
408 if (pri == TX39_INTRPRI13_TIMER_PERIODIC) {
409 tx_conf_write(tc, TX39_INTRCLEAR5_REG,
410 TX39_INTRSTATUS5_PERINT);
411 cf.pc = pc;
412 cf.sr = status;
413 hardclock(&cf);
414 intrcnt[HARDCLOCK]++;
415
416 return;
417 }
418
419 /* Handle all pending IRQHIGH interrupts */
420 for (i = pri; i > 0; i--) {
421 TAILQ_FOREACH(he, &sc->sc_he_head[i], he_link) {
422 set = he->he_set;
423 he_mask = he->he_mask;
424 if (he_mask & (sc->sc_regs[set])) {
425 ofs = TX39_INTRSTATUS_REG(set);
426 /* Clear interrupt */
427 tx_conf_write(tc, ofs, he_mask);
428 #ifdef TX39_DEBUG
429 tx39intrvec = (set << 16) |
430 (ffs(he_mask) - 1);
431 if (tx39debugflag) {
432 DPRINTF(("IRQHIGH: %d:%d\n",
433 set, ffs(he_mask) - 1));
434 }
435 #endif /* TX39_DEBUG */
436 /* Dispatch handler */
437 (*he->he_fun)(he->he_arg);
438 }
439 }
440 }
441 }
442
443 void
444 tx39_intr_decode(int intr, int *set, int *bit)
445 {
446 if (!intr || intr >= (TX39_INTRSET_MAX + 1) * 32
447 #ifdef TX392X
448 || intr == 6
449 #endif /* TX392X */
450 ) {
451 panic("tx39icu_decode: bogus intrrupt line. %d", intr);
452 }
453 *set = intr / 32;
454 *bit = intr % 32;
455 }
456
457 void
458 tx39_irqhigh_establish(tx_chipset_tag_t tc, int set, int bit, int pri,
459 int (*ih_fun)(void *), void *ih_arg)
460 {
461 struct tx39icu_softc *sc;
462 struct txintr_high_entry *he;
463 txreg_t reg;
464
465 sc = tc->tc_intrt;
466 /*
467 * Add new entry to `pri' priority
468 */
469 if (!(he = malloc(sizeof(struct txintr_high_entry),
470 M_DEVBUF, M_NOWAIT))) {
471 panic ("tx39_irqhigh_establish: no memory.");
472 }
473 memset(he, 0, sizeof(struct txintr_high_entry));
474 he->he_set = set;
475 he->he_mask= (1 << bit);
476 he->he_fun = ih_fun;
477 he->he_arg = ih_arg;
478 TAILQ_INSERT_TAIL(&sc->sc_he_head[pri], he, he_link);
479 /*
480 * Enable interrupt on this priority.
481 */
482 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG);
483 reg = TX39_INTRENABLE6_PRIORITYMASK_SET(reg, (1 << pri));
484 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg);
485 }
486
487 void
488 tx39_irqhigh_disestablish(tx_chipset_tag_t tc, int set, int bit, int pri)
489 {
490 struct tx39icu_softc *sc;
491 struct txintr_high_entry *he;
492 txreg_t reg;
493
494 sc = tc->tc_intrt;
495 TAILQ_FOREACH(he, &sc->sc_he_head[pri], he_link) {
496 if (he->he_set == set && he->he_mask == (1 << bit)) {
497 TAILQ_REMOVE(&sc->sc_he_head[pri], he, he_link);
498 free(he, M_DEVBUF);
499 break;
500 }
501 }
502
503 if (TAILQ_EMPTY(&sc->sc_he_head[pri])) {
504 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG);
505 reg &= ~(1 << pri);
506 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg);
507 }
508 }
509
510
511 void *
512 tx_intr_establish(tx_chipset_tag_t tc, int line, int mode, int level,
513 int (*ih_fun)(void *), void *ih_arg)
514 {
515 struct tx39icu_softc *sc;
516 txreg_t reg;
517 int bit, set, highpri, ofs;
518
519 sc = tc->tc_intrt;
520
521 tx39_intr_decode(line, &set, &bit);
522
523 sc->sc_le_fun[set][bit] = ih_fun;
524 sc->sc_le_arg[set][bit] = ih_arg;
525 DPRINTF(("tx_intr_establish: %d:%d", set, bit));
526
527 if ((highpri = tx39_irqhigh(set, bit))) {
528 tx39_irqhigh_establish(tc, set, bit, highpri,
529 ih_fun, ih_arg);
530 DPRINTF(("(high)\n"));
531 } else {
532 /* Set mask for acknowledge. */
533 sc->sc_le_mask[set] |= (1 << bit);
534 /* Enable interrupt */
535 ofs = TX39_INTRENABLE_REG(set);
536 reg = tx_conf_read(tc, ofs);
537 reg |= (1 << bit);
538 tx_conf_write(tc, ofs, reg);
539 DPRINTF(("(low)\n"));
540 }
541
542 return ((void *)line);
543 }
544
545 void
546 tx_intr_disestablish(tx_chipset_tag_t tc, void *arg)
547 {
548 struct tx39icu_softc *sc;
549 int set, bit, highpri, ofs;
550 txreg_t reg;
551
552 sc = tc->tc_intrt;
553
554 tx39_intr_decode((int)arg, &set, &bit);
555 DPRINTF(("tx_intr_disestablish: %d:%d", set, bit));
556
557 if ((highpri = tx39_irqhigh(set, bit))) {
558 tx39_irqhigh_disestablish(tc, set, bit, highpri);
559 DPRINTF(("(high)\n"));
560 } else {
561 sc->sc_le_fun[set][bit] = 0;
562 sc->sc_le_arg[set][bit] = 0;
563 sc->sc_le_mask[set] &= ~(1 << bit);
564 ofs = TX39_INTRENABLE_REG(set);
565 reg = tx_conf_read(tc, ofs);
566 reg &= ~(1 << bit);
567 tx_conf_write(tc, ofs, reg);
568 DPRINTF(("(low)\n"));
569 }
570 }
571
572 u_int32_t
573 tx_intr_status(tx_chipset_tag_t tc, int r)
574 {
575 struct tx39icu_softc *sc = tc->tc_intrt;
576
577 if (r < 0 || r >= TX39_INTRSET_MAX + 1)
578 panic("tx_intr_status: invalid index %d", r);
579
580 return (u_int32_t)(sc->sc_regs[r]);
581 }
582
583 #ifdef USE_POLL
584 void *
585 tx39_poll_establish(tx_chipset_tag_t tc, int interval, int level,
586 int (*ih_fun)(void *), void *ih_arg)
587 {
588 struct tx39icu_softc *sc;
589 struct txpoll_entry *p;
590 int s;
591 void *ret;
592
593 s = splhigh();
594 sc = tc->tc_intrt;
595
596 if (!(p = malloc(sizeof(struct txpoll_entry),
597 M_DEVBUF, M_NOWAIT))) {
598 panic ("tx39_poll_establish: no memory.");
599 }
600 memset(p, 0, sizeof(struct txpoll_entry));
601
602 p->p_fun = ih_fun;
603 p->p_arg = ih_arg;
604 p->p_cnt = interval;
605
606 if (!sc->sc_polling) {
607 tx39clock_alarm_set(tc, 33); /* 33 msec */
608
609 if (!(sc->sc_poll_ih =
610 tx_intr_establish(
611 tc, MAKEINTR(5, TX39_INTRSTATUS5_ALARMINT),
612 IST_EDGE, level, tx39_poll_intr, sc))) {
613 printf("tx39_poll_establish: can't hook\n");
614
615 splx(s);
616 return (0);
617 }
618 }
619
620 sc->sc_polling++;
621 p->p_desc = sc->sc_polling;
622 TAILQ_INSERT_TAIL(&sc->sc_p_head, p, p_link);
623 ret = (void *)p->p_desc;
624
625 splx(s);
626 return (ret);
627 }
628
629 void
630 tx39_poll_disestablish(tx_chipset_tag_t tc, void *arg)
631 {
632 struct tx39icu_softc *sc;
633 struct txpoll_entry *p;
634 int s, desc;
635
636 s = splhigh();
637 sc = tc->tc_intrt;
638
639 desc = (int)arg;
640 TAILQ_FOREACH(p, &sc->sc_p_head, p_link) {
641 if (p->p_desc == desc) {
642 TAILQ_REMOVE(&sc->sc_p_head, p, p_link);
643 free(p, M_DEVBUF);
644 break;
645 }
646 }
647
648 if (TAILQ_EMPTY(&sc->sc_p_head)) {
649 sc->sc_polling = 0;
650 tx_intr_disestablish(tc, sc->sc_poll_ih);
651 }
652
653 splx(s);
654 return;
655 }
656
657 int
658 tx39_poll_intr(void *arg)
659 {
660 struct tx39icu_softc *sc = arg;
661 struct txpoll_entry *p;
662
663 tx39clock_alarm_refill(sc->sc_tc);
664
665 if (!sc->sc_polling) {
666 return (0);
667 }
668 sc->sc_pollcnt++;
669 TAILQ_FOREACH(p, &sc->sc_p_head, p_link) {
670 if (sc->sc_pollcnt % p->p_cnt == 0) {
671 if ((*p->p_fun)(p->p_arg) == POLL_END)
672 goto disestablish;
673 }
674 }
675
676 return (0);
677
678 disestablish:
679 TAILQ_REMOVE(&sc->sc_p_head, p, p_link);
680 free(p, M_DEVBUF);
681 if (TAILQ_EMPTY(&sc->sc_p_head)) {
682 sc->sc_polling = 0;
683 tx_intr_disestablish(sc->sc_tc, sc->sc_poll_ih);
684 }
685
686 return (0);
687 }
688 #endif /* USE_POLL */
689
690 void
691 tx39_intr_dump(struct tx39icu_softc *sc)
692 {
693 tx_chipset_tag_t tc = sc->sc_tc;
694 int i, j, ofs;
695 txreg_t reg;
696 char msg[16];
697
698 for (i = 1; i <= TX39_INTRSET_MAX; i++) {
699 #ifdef TX392X
700 if (i == 6)
701 continue;
702 #endif /* TX392X */
703 for (reg = j = 0; j < 32; j++) {
704 if (tx39_irqhigh(i, j)) {
705 reg |= (1 << j);
706 }
707 }
708 sprintf(msg, "%d high", i);
709 __bitdisp(reg, 32, 0, msg, 1);
710 sprintf(msg, "%d status", i);
711 __bitdisp(sc->sc_regs[i], 0, 31, msg, 1);
712 ofs = TX39_INTRENABLE_REG(i);
713 reg = tx_conf_read(tc, ofs);
714 sprintf(msg, "%d enable", i);
715 __bitdisp(reg, 0, 31, msg, 1);
716 }
717 reg = sc->sc_regs[0];
718 printf("<%s><%s> vector=%2d\t\t[6 status]\n",
719 reg & TX39_INTRSTATUS6_IRQHIGH ? "HI" : "--",
720 reg & TX39_INTRSTATUS6_IRQLOW ? "LO" : "--",
721 TX39_INTRSTATUS6_INTVECT(reg));
722 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG);
723 __bitdisp(reg, 0, 18, "6 enable", 1);
724
725 }
726