Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / mips / rmi / rmixl_intr.c
blobca356d907f7ea590b362fa33c928d42635551130
1 /* $NetBSD$ */
3 /*-
4 * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
9 * conditions are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * 3. The names of the authors may not be used to endorse or promote
17 * products derived from this software without specific prior
18 * written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
27 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31 * OF SUCH DAMAGE.
33 /*-
34 * Copyright (c) 2001 The NetBSD Foundation, Inc.
35 * All rights reserved.
37 * This code is derived from software contributed to The NetBSD Foundation
38 * by Jason R. Thorpe.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
49 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
50 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
53 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 * POSSIBILITY OF SUCH DAMAGE.
63 * Platform-specific interrupt support for the RMI XLP, XLR, XLS
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD$");
69 #include "opt_ddb.h"
71 #include <sys/param.h>
72 #include <sys/queue.h>
73 #include <sys/malloc.h>
74 #include <sys/systm.h>
75 #include <sys/device.h>
76 #include <sys/kernel.h>
78 #include <machine/bus.h>
79 #include <machine/intr.h>
81 #include <mips/cpu.h>
82 #include <mips/locore.h>
84 #include <mips/rmi/rmixlreg.h>
85 #include <mips/rmi/rmixlvar.h>
87 #include <dev/pci/pcireg.h>
88 #include <dev/pci/pcivar.h>
90 #ifdef IOINTR_DEBUG
91 int iointr_debug = IOINTR_DEBUG;
92 # define DPRINTF(x) do { if (iointr_debug) printf x ; } while(0)
93 #else
94 # define DPRINTF(x)
95 #endif
97 #define RMIXL_PICREG_READ(off) \
98 RMIXL_IOREG_READ(RMIXL_IO_DEV_PIC + (off))
99 #define RMIXL_PICREG_WRITE(off, val) \
100 RMIXL_IOREG_WRITE(RMIXL_IO_DEV_PIC + (off), (val))
102 * This is a mask of bits to clear in the SR when we go to a
103 * given hardware interrupt priority level.
104 * _SR_BITS_DFLT bits are to be always clear (disabled)
106 #define _SR_BITS_DFLT (MIPS_INT_MASK_2|MIPS_INT_MASK_3|MIPS_INT_MASK_4)
107 const uint32_t ipl_sr_bits[_IPL_N] = {
108 [IPL_NONE] = _SR_BITS_DFLT,
109 [IPL_SOFTCLOCK] =
110 _SR_BITS_DFLT
111 | MIPS_SOFT_INT_MASK_0,
112 [IPL_SOFTNET] =
113 _SR_BITS_DFLT
114 | MIPS_SOFT_INT_MASK_0
115 | MIPS_SOFT_INT_MASK_1,
116 [IPL_VM] =
117 _SR_BITS_DFLT
118 | MIPS_SOFT_INT_MASK_0
119 | MIPS_SOFT_INT_MASK_1
120 | MIPS_INT_MASK_0,
121 [IPL_SCHED] =
122 MIPS_INT_MASK,
126 * 'IRQs' here are indiividual interrupt sources
127 * each has a slot in the Interrupt Redirection Table (IRT)
128 * in the order listed
130 * NOTE: many irq sources depend on the chip family
131 * XLS1xx vs. XLS2xx vs. XLS3xx vs. XLS6xx
132 * use the right table for the CPU that's running.
136 * rmixl_irqnames_xls1xx
137 * - use for XLS1xx, XLS2xx, XLS4xx-Lite
139 #define NIRQS 32
140 static const char *rmixl_irqnames_xls1xx[NIRQS] = {
141 "int 0 (watchdog)", /* 0 */
142 "int 1 (timer0)", /* 1 */
143 "int 2 (timer1)", /* 2 */
144 "int 3 (timer2)", /* 3 */
145 "int 4 (timer3)", /* 4 */
146 "int 5 (timer4)", /* 5 */
147 "int 6 (timer5)", /* 6 */
148 "int 7 (timer6)", /* 7 */
149 "int 8 (timer7)", /* 8 */
150 "int 9 (uart0)", /* 9 */
151 "int 10 (uart1)", /* 10 */
152 "int 11 (i2c0)", /* 11 */
153 "int 12 (i2c1)", /* 12 */
154 "int 13 (pcmcia)", /* 13 */
155 "int 14 (gpio_a)", /* 14 */
156 "int 15 (irq15)", /* 15 */
157 "int 16 (bridge_tb)", /* 16 */
158 "int 17 (gmac0)", /* 17 */
159 "int 18 (gmac1)", /* 18 */
160 "int 19 (gmac2)", /* 19 */
161 "int 20 (gmac3)", /* 20 */
162 "int 21 (irq21)", /* 21 */
163 "int 22 (irq22)", /* 22 */
164 "int 23 (irq23)", /* 23 */
165 "int 24 (irq24)", /* 24 */
166 "int 25 (bridge_err)", /* 25 */
167 "int 26 (pcie_link0)", /* 26 */
168 "int 27 (pcie_link1)", /* 27 */
169 "int 28 (irq28)", /* 28 */
170 "int 29 (irq29)", /* 29 */
171 "int 30 (gpio_b)", /* 30 */
172 "int 31 (usb)", /* 31 */
176 * rmixl_irqnames_xls4xx:
177 * - use for XLS4xx, XLS6xx
179 static const char *rmixl_irqnames_xls4xx[NIRQS] = {
180 "int 0 (watchdog)", /* 0 */
181 "int 1 (timer0)", /* 1 */
182 "int 2 (timer1)", /* 2 */
183 "int 3 (timer2)", /* 3 */
184 "int 4 (timer3)", /* 4 */
185 "int 5 (timer4)", /* 5 */
186 "int 6 (timer5)", /* 6 */
187 "int 7 (timer6)", /* 7 */
188 "int 8 (timer7)", /* 8 */
189 "int 9 (uart0)", /* 9 */
190 "int 10 (uart1)", /* 10 */
191 "int 11 (i2c0)", /* 11 */
192 "int 12 (i2c1)", /* 12 */
193 "int 13 (pcmcia)", /* 13 */
194 "int 14 (gpio_a)", /* 14 */
195 "int 15 (irq15)", /* 15 */
196 "int 16 (bridge_tb)", /* 16 */
197 "int 17 (gmac0)", /* 17 */
198 "int 18 (gmac1)", /* 18 */
199 "int 19 (gmac2)", /* 19 */
200 "int 20 (gmac3)", /* 20 */
201 "int 21 (irq21)", /* 21 */
202 "int 22 (irq22)", /* 22 */
203 "int 23 (irq23)", /* 23 */
204 "int 24 (irq24)", /* 24 */
205 "int 25 (bridge_err)", /* 25 */
206 "int 26 (pcie_link0)", /* 26 */
207 "int 27 (pcie_link1)", /* 27 */
208 "int 28 (pcie_link2)", /* 28 */
209 "int 29 (pcie_link3)", /* 29 */
210 "int 30 (gpio_b)", /* 30 */
211 "int 31 (usb)", /* 31 */
215 * rmixl_irqnames_xls4xx:
216 * - use for unknown cpu implementation
218 static const char *rmixl_irqnames_generic[NIRQS] = {
219 "int 0", /* 0 */
220 "int 1", /* 1 */
221 "int 2", /* 2 */
222 "int 3", /* 3 */
223 "int 4", /* 4 */
224 "int 5", /* 5 */
225 "int 6", /* 6 */
226 "int 7", /* 7 */
227 "int 8", /* 8 */
228 "int 9", /* 9 */
229 "int 10", /* 10 */
230 "int 11", /* 11 */
231 "int 12", /* 12 */
232 "int 13", /* 13 */
233 "int 14", /* 14 */
234 "int 15", /* 15 */
235 "int 16", /* 16 */
236 "int 17", /* 17 */
237 "int 18", /* 18 */
238 "int 19", /* 19 */
239 "int 20", /* 20 */
240 "int 21", /* 21 */
241 "int 22", /* 22 */
242 "int 23", /* 23 */
243 "int 24", /* 24 */
244 "int 25", /* 25 */
245 "int 26", /* 26 */
246 "int 27", /* 27 */
247 "int 28", /* 28 */
248 "int 29", /* 29 */
249 "int 30", /* 30 */
250 "int 31", /* 31 */
254 * per-IRQ event stats
256 struct rmixl_irqtab {
257 struct evcnt irq_count;
258 void *irq_ih;
260 static struct rmixl_irqtab rmixl_irqtab[NIRQS];
264 * 'vectors' here correspond to IRT Entry vector numbers
265 * - IRT Entry vector# is bit# in EIRR
266 * - note that EIRR[7:0] == CAUSE[15:8]
267 * - we actually only use the first _IPL_N bits
268 * (less than 8)
270 * each IRT entry gets routed to a vector
271 * (if and when that interrupt is established)
272 * the vectors are shared on a per-IPL basis
273 * which simplifies dispatch
275 * XXX use of mips64 extended IRQs is TBD
277 #define NINTRVECS _IPL_N
280 * translate IPL to vector number
282 static const int rmixl_iplvec[_IPL_N] = {
283 [IPL_NONE] = -1, /* XXX */
284 [IPL_SOFTCLOCK] = 0,
285 [IPL_SOFTNET] = 1,
286 [IPL_VM] = 2,
287 [IPL_SCHED] = 3,
291 * list and ref count manage sharing of each vector
293 struct rmixl_intrvec {
294 LIST_HEAD(, evbmips_intrhand) iv_list;
295 uint32_t iv_ack;
296 rmixl_intr_trigger_t iv_trigger;
297 rmixl_intr_polarity_t iv_polarity;
298 u_int iv_refcnt;
300 static struct rmixl_intrvec rmixl_intrvec[NINTRVECS];
302 #ifdef DIAGNOSTIC
303 static int evbmips_intr_init_done;
304 #endif
307 static void rmixl_intr_irt_init(int);
308 static void rmixl_intr_irt_disestablish(int);
309 static void rmixl_intr_irt_establish(int, int, rmixl_intr_trigger_t,
310 rmixl_intr_polarity_t, int);
313 static inline void
314 pic_irt_print(const char *s, const int n, u_int irq)
316 #ifdef IOINTR_DEBUG
317 uint32_t c0, c1;
319 c0 = RMIXL_PICREG_READ(RMIXL_PIC_IRTENTRYC0(irq));
320 c1 = RMIXL_PICREG_READ(RMIXL_PIC_IRTENTRYC1(irq));
321 printf("%s:%d: irq %d: c0 %#x, c1 %#x\n", s, n, irq, c0, c1);
322 #endif
325 void
326 evbmips_intr_init(void)
328 uint32_t r;
329 int i;
331 KASSERT(cpu_rmixls(mycpu));
333 #ifdef DIAGNOSTIC
334 if (evbmips_intr_init_done != 0)
335 panic("%s: evbmips_intr_init_done %d",
336 __func__, evbmips_intr_init_done);
337 #endif
339 for (i=0; i < NIRQS; i++) {
340 evcnt_attach_dynamic(&rmixl_irqtab[i].irq_count,
341 EVCNT_TYPE_INTR, NULL, "rmixl", rmixl_intr_string(i));
342 rmixl_irqtab[i].irq_ih = NULL;
345 for (i=0; i < NINTRVECS; i++) {
346 LIST_INIT(&rmixl_intrvec[i].iv_list);
347 rmixl_intrvec[i].iv_ack = 0;
348 rmixl_intrvec[i].iv_refcnt = 0;
352 * disable watchdog NMI, timers
354 * XXX
355 * WATCHDOG_ENB is preserved because clearing it causes
356 * hang on the XLS616 (but not on the XLS408)
358 r = RMIXL_PICREG_READ(RMIXL_PIC_CONTROL);
359 r &= RMIXL_PIC_CONTROL_RESV|RMIXL_PIC_CONTROL_WATCHDOG_ENB;
360 RMIXL_PICREG_WRITE(RMIXL_PIC_CONTROL, r);
363 * initialize all IRT Entries
365 for (i=0; i < NIRQS; i++)
366 rmixl_intr_irt_init(i);
369 * establish IRT entry for mips3 clock interrupt
371 rmixl_intr_irt_establish(7, IPL_CLOCK, RMIXL_INTR_LEVEL,
372 RMIXL_INTR_HIGH, rmixl_iplvec[IPL_CLOCK]);
374 #ifdef DIAGNOSTIC
375 evbmips_intr_init_done = 1;
376 #endif
379 const char *
380 rmixl_intr_string(int irq)
382 const char *name;
384 if (irq < 0 || irq >= NIRQS)
385 panic("%s: irq %d out of range, max %d",
386 __func__, irq, NIRQS - 1);
388 switch (MIPS_PRID_IMPL(cpu_id)) {
389 case MIPS_XLS104:
390 case MIPS_XLS108:
391 case MIPS_XLS204:
392 case MIPS_XLS208:
393 case MIPS_XLS404LITE:
394 case MIPS_XLS408LITE:
395 name = rmixl_irqnames_xls1xx[irq];
396 break;
397 case MIPS_XLS404:
398 case MIPS_XLS408:
399 case MIPS_XLS416:
400 case MIPS_XLS608:
401 case MIPS_XLS616:
402 name = rmixl_irqnames_xls4xx[irq];
403 break;
404 default:
405 name = rmixl_irqnames_generic[irq];
406 break;
409 return name;
413 * rmixl_intr_irt_init
414 * - invalidate IRT Entry for irq
415 * - unmask Thread#0 in low word (assume we only have 1 thread)
417 static void
418 rmixl_intr_irt_init(int irq)
420 RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC1(irq), 0); /* high word */
421 RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC0(irq), 1); /* low word */
425 * rmixl_intr_irt_disestablish
426 * - invalidate IRT Entry for irq
427 * - writes to IRTENTRYC1 only; leave IRTENTRYC0 as-is
429 static void
430 rmixl_intr_irt_disestablish(int irq)
432 DPRINTF(("%s: irq %d, irtc1 %#x\n", __func__, irq, 0));
433 RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC1(irq), 0); /* high word */
437 * rmixl_intr_irt_establish
438 * - construct and IRT Entry for irq and write to PIC
439 * - writes to IRTENTRYC1 only; assumes IRTENTRYC0 has been initialized
441 static void
442 rmixl_intr_irt_establish(int irq, int ipl, rmixl_intr_trigger_t trigger,
443 rmixl_intr_polarity_t polarity, int vec)
445 uint32_t irtc1;
447 irtc1 = RMIXL_PIC_IRTENTRYC1_VALID;
448 irtc1 |= RMIXL_PIC_IRTENTRYC1_GL; /* local */
450 if (trigger == RMIXL_INTR_LEVEL)
451 irtc1 |= RMIXL_PIC_IRTENTRYC1_TRG;
453 if ((polarity == RMIXL_INTR_FALLING) || (polarity == RMIXL_INTR_LOW))
454 irtc1 |= RMIXL_PIC_IRTENTRYC1_P;
456 irtc1 |= vec;
459 * write IRT Entry to PIC (high word only)
461 DPRINTF(("%s: irq %d, irtc1 %#x\n", __func__, irq, irtc1));
462 RMIXL_PICREG_WRITE(RMIXL_PIC_IRTENTRYC1(irq), irtc1);
465 void *
466 rmixl_intr_establish(int irq, int ipl, rmixl_intr_trigger_t trigger,
467 rmixl_intr_polarity_t polarity, int (*func)(void *), void *arg)
469 struct evbmips_intrhand *ih;
470 struct rmixl_intrvec *ivp;
471 int vec;
472 int s;
474 #ifdef DIAGNOSTIC
475 if (evbmips_intr_init_done == 0)
476 panic("%s: called before evbmips_intr_init", __func__);
477 #endif
480 * check args and assemble an IRT Entry
482 if (irq < 0 || irq >= NIRQS)
483 panic("%s: irq %d out of range, max %d",
484 __func__, irq, NIRQS - 1);
485 if (ipl <= 0 || ipl >= _IPL_N)
486 panic("%s: ipl %d out of range, min %d, max %d",
487 __func__, ipl, 1, _IPL_N - 1);
488 if (rmixl_irqtab[irq].irq_ih != NULL)
489 panic("%s: irq %d busy", __func__, irq);
491 switch (trigger) {
492 case RMIXL_INTR_EDGE:
493 case RMIXL_INTR_LEVEL:
494 break;
495 default:
496 panic("%s: bad trigger %d\n", __func__, trigger);
499 switch (polarity) {
500 case RMIXL_INTR_RISING:
501 case RMIXL_INTR_HIGH:
502 case RMIXL_INTR_FALLING:
503 case RMIXL_INTR_LOW:
504 break;
505 default:
506 panic("%s: bad polarity %d\n", __func__, polarity);
510 * ipl determines which vector to use
512 vec = rmixl_iplvec[ipl];
513 DPRINTF(("%s: irq %d, ipl %d, vec %d\n", __func__, irq, ipl, vec));
514 KASSERT((vec & ~RMIXL_PIC_IRTENTRYC1_INTVEC) == 0);
516 s = splhigh();
518 ivp = &rmixl_intrvec[vec];
519 if (ivp->iv_refcnt == 0) {
520 ivp->iv_trigger = trigger;
521 ivp->iv_polarity = polarity;
522 } else {
523 if (ivp->iv_trigger != trigger) {
524 #ifdef DIAGNOSTIC
525 printf("%s: vec %d, irqs {", __func__, vec);
526 LIST_FOREACH(ih, &ivp->iv_list, ih_q) {
527 printf(" %d", ih->ih_irq);
529 printf(" } trigger type %d; irq %d wants type %d\n",
530 ivp->iv_trigger, irq, trigger);
531 #endif
532 panic("%s: trigger mismatch at vec %d\n",
533 __func__, vec);
535 if (ivp->iv_polarity != polarity) {
536 #ifdef DIAGNOSTIC
537 printf("%s: vec %d, irqs {", __func__, vec);
538 LIST_FOREACH(ih, &ivp->iv_list, ih_q) {
539 printf(" %d", ih->ih_irq);
541 printf(" } polarity type %d; irq %d wants type %d\n",
542 ivp->iv_polarity, irq, polarity);
543 #endif
544 panic("%s: polarity mismatch at vec %d\n",
545 __func__, vec);
548 ivp->iv_ack |= (1 << irq);
551 * allocate and initialize an interrupt handle
553 ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
554 if (ih == NULL)
555 return NULL;
557 ih->ih_func = func;
558 ih->ih_arg = arg;
559 ih->ih_irq = irq;
560 ih->ih_ipl = ipl;
563 * mark this irq as established, busy
565 rmixl_irqtab[irq].irq_ih = ih;
568 * link this ih into the tables and bump reference count
570 LIST_INSERT_HEAD(&ivp->iv_list, ih, ih_q);
571 ivp->iv_refcnt++;
574 * establish IRT Entry
576 rmixl_intr_irt_establish(irq, ipl, trigger, polarity, vec);
578 splx(s);
580 return ih;
583 void
584 rmixl_intr_disestablish(void *cookie)
586 struct evbmips_intrhand *ih = cookie;
587 struct rmixl_intrvec *ivp;
588 int irq;
589 int vec;
590 int s;
592 irq = ih->ih_irq;
593 vec = rmixl_iplvec[ih->ih_ipl];
594 ivp = &rmixl_intrvec[vec];
596 s = splhigh();
599 * disable the IRT Entry (high word only)
601 rmixl_intr_irt_disestablish(irq);
604 * remove from the table and adjust the reference count
606 LIST_REMOVE(ih, ih_q);
607 ivp->iv_refcnt--;
608 ivp->iv_ack &= ~(1 << irq);
611 * this irq now disestablished, not busy
613 rmixl_irqtab[irq].irq_ih = NULL;
615 splx(s);
617 free(ih, M_DEVBUF);
620 static inline void
621 pci_int_status(const char *s, const int n)
623 #ifdef IOINTR_DEBUG
624 uint32_t r;
625 r = RMIXL_IOREG_READ(RMIXL_IO_DEV_PCIE_LE + 0xa0);
626 printf("%s:%d: PCIE_LINK0_INT_STATUS0 %#x\n", s, n, r);
627 #endif
630 void
631 evbmips_iointr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending)
633 struct evbmips_intrhand *ih;
634 struct rmixl_intrvec *ivp;
635 int vec;
636 uint64_t eirr;
637 #ifdef IOINTR_DEBUG
638 uint64_t eimr;
640 printf("%s: status %#x, cause %#x, pc %#x, ipending %#x\n",
641 __func__, status, cause, pc, ipending);
643 asm volatile("dmfc0 %0, $9, 6;" : "=r"(eirr));
644 asm volatile("dmfc0 %0, $9, 7;" : "=r"(eimr));
645 printf("%s:%d: eirr %#lx, eimr %#lx\n", __func__, __LINE__, eirr, eimr);
646 pci_int_status(__func__, __LINE__);
647 #endif
649 for (vec = NINTRVECS - 1; vec >= 2; vec--) {
650 if ((ipending & (MIPS_SOFT_INT_MASK_0 << vec)) == 0)
651 continue;
653 ivp = &rmixl_intrvec[vec];
655 eirr = 1ULL << vec;
656 asm volatile("dmtc0 %0, $9, 6;" :: "r"(eirr));
658 #ifdef IOINTR_DEBUG
659 printf("%s: interrupt at vec %d\n",
660 __func__, vec);
661 if (LIST_EMPTY(&ivp->iv_list))
662 printf("%s: unexpected interrupt at vec %d\n",
663 __func__, vec);
664 #endif
665 LIST_FOREACH(ih, &ivp->iv_list, ih_q) {
666 pic_irt_print(__func__, __LINE__, ih->ih_irq);
667 RMIXL_PICREG_WRITE(RMIXL_PIC_INTRACK,
668 (1 << ih->ih_irq));
669 if ((*ih->ih_func)(ih->ih_arg) != 0) {
670 rmixl_irqtab[ih->ih_irq].irq_count.ev_count++;
674 pci_int_status(__func__, __LINE__);
676 cause &= ~(MIPS_SOFT_INT_MASK_0 << vec);
680 /* Re-enable anything that we have processed. */
681 _splset(MIPS_SR_INT_IE | ((status & ~cause) & MIPS_HARD_INT_MASK));
684 #ifdef DEBUG
685 int rmixl_intrvec_print(void);
687 rmixl_intrvec_print(void)
689 struct evbmips_intrhand *ih;
690 struct rmixl_intrvec *ivp;
691 int vec;
693 ivp = &rmixl_intrvec[0];
694 for (vec=0; vec < NINTRVECS ; vec++) {
695 printf("vec %d, irqs {", vec);
696 LIST_FOREACH(ih, &ivp->iv_list, ih_q)
697 printf(" %d", ih->ih_irq);
698 printf(" } trigger type %d\n", ivp->iv_trigger);
699 ivp++;
701 return 0;
703 #endif