au_icu.c revision 1.2.2.2 1 1.2.2.2 nathanw /* $NetBSD: au_icu.c,v 1.2.2.2 2002/10/18 02:38:42 nathanw Exp $ */
2 1.2.2.2 nathanw
3 1.2.2.2 nathanw /*-
4 1.2.2.2 nathanw * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 1.2.2.2 nathanw * All rights reserved.
6 1.2.2.2 nathanw *
7 1.2.2.2 nathanw * This code is derived from software contributed to The NetBSD Foundation
8 1.2.2.2 nathanw * by Jason R. Thorpe.
9 1.2.2.2 nathanw *
10 1.2.2.2 nathanw * Redistribution and use in source and binary forms, with or without
11 1.2.2.2 nathanw * modification, are permitted provided that the following conditions
12 1.2.2.2 nathanw * are met:
13 1.2.2.2 nathanw * 1. Redistributions of source code must retain the above copyright
14 1.2.2.2 nathanw * notice, this list of conditions and the following disclaimer.
15 1.2.2.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
16 1.2.2.2 nathanw * notice, this list of conditions and the following disclaimer in the
17 1.2.2.2 nathanw * documentation and/or other materials provided with the distribution.
18 1.2.2.2 nathanw * 3. All advertising materials mentioning features or use of this software
19 1.2.2.2 nathanw * must display the following acknowledgement:
20 1.2.2.2 nathanw * This product includes software developed by the NetBSD
21 1.2.2.2 nathanw * Foundation, Inc. and its contributors.
22 1.2.2.2 nathanw * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.2.2.2 nathanw * contributors may be used to endorse or promote products derived
24 1.2.2.2 nathanw * from this software without specific prior written permission.
25 1.2.2.2 nathanw *
26 1.2.2.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.2.2.2 nathanw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.2.2.2 nathanw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.2.2.2 nathanw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.2.2.2 nathanw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.2.2.2 nathanw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.2.2.2 nathanw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.2.2.2 nathanw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.2.2.2 nathanw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.2.2.2 nathanw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.2.2.2 nathanw * POSSIBILITY OF SUCH DAMAGE.
37 1.2.2.2 nathanw */
38 1.2.2.2 nathanw
39 1.2.2.2 nathanw /*
40 1.2.2.2 nathanw * Interrupt support for the Alchemy Semiconductor Au1x00 CPUs.
41 1.2.2.2 nathanw *
42 1.2.2.2 nathanw * The Alchemy Semiconductor Au1x00's interrupts are wired to two internal
43 1.2.2.2 nathanw * interrupt controllers.
44 1.2.2.2 nathanw */
45 1.2.2.2 nathanw
46 1.2.2.2 nathanw #include "opt_ddb.h"
47 1.2.2.2 nathanw
48 1.2.2.2 nathanw #include <sys/param.h>
49 1.2.2.2 nathanw #include <sys/queue.h>
50 1.2.2.2 nathanw #include <sys/malloc.h>
51 1.2.2.2 nathanw #include <sys/systm.h>
52 1.2.2.2 nathanw #include <sys/device.h>
53 1.2.2.2 nathanw #include <sys/kernel.h>
54 1.2.2.2 nathanw
55 1.2.2.2 nathanw #include <machine/bus.h>
56 1.2.2.2 nathanw #include <machine/intr.h>
57 1.2.2.2 nathanw
58 1.2.2.2 nathanw #include <mips/locore.h>
59 1.2.2.2 nathanw #include <mips/alchemy/include/aureg.h>
60 1.2.2.2 nathanw #include <mips/alchemy/include/auvar.h>
61 1.2.2.2 nathanw
62 1.2.2.2 nathanw #define REGVAL(x) *((__volatile u_int32_t *)(MIPS_PHYS_TO_KSEG1((x))))
63 1.2.2.2 nathanw
64 1.2.2.2 nathanw /*
65 1.2.2.2 nathanw * This is a mask of bits to clear in the SR when we go to a
66 1.2.2.2 nathanw * given hardware interrupt priority level.
67 1.2.2.2 nathanw */
68 1.2.2.2 nathanw
69 1.2.2.2 nathanw const u_int32_t ipl_sr_bits[_IPL_N] = {
70 1.2.2.2 nathanw 0, /* 0: IPL_NONE */
71 1.2.2.2 nathanw
72 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* 1: IPL_SOFT */
73 1.2.2.2 nathanw
74 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* 2: IPL_SOFTCLOCK */
75 1.2.2.2 nathanw
76 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* 3: IPL_SOFTNET */
77 1.2.2.2 nathanw
78 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* 4: IPL_SOFTSERIAL */
79 1.2.2.2 nathanw
80 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0|
81 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_1|
82 1.2.2.2 nathanw MIPS_INT_MASK_0, /* 5: IPL_BIO */
83 1.2.2.2 nathanw
84 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0|
85 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_1|
86 1.2.2.2 nathanw MIPS_INT_MASK_0, /* 6: IPL_NET */
87 1.2.2.2 nathanw
88 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0|
89 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_1|
90 1.2.2.2 nathanw MIPS_INT_MASK_0, /* 7: IPL_{SERIAL,TTY} */
91 1.2.2.2 nathanw
92 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0|
93 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_1|
94 1.2.2.2 nathanw MIPS_INT_MASK_0|
95 1.2.2.2 nathanw MIPS_INT_MASK_1|
96 1.2.2.2 nathanw MIPS_INT_MASK_2|
97 1.2.2.2 nathanw MIPS_INT_MASK_3|
98 1.2.2.2 nathanw MIPS_INT_MASK_4|
99 1.2.2.2 nathanw MIPS_INT_MASK_5, /* 8: IPL_{CLOCK,HIGH} */
100 1.2.2.2 nathanw };
101 1.2.2.2 nathanw
102 1.2.2.2 nathanw /*
103 1.2.2.2 nathanw * This is a mask of bits to clear in the SR when we go to a
104 1.2.2.2 nathanw * given software interrupt priority level.
105 1.2.2.2 nathanw * Hardware ipls are port/board specific.
106 1.2.2.2 nathanw */
107 1.2.2.2 nathanw const u_int32_t ipl_si_to_sr[_IPL_NSOFT] = {
108 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
109 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */
110 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* IPL_SOFTNET */
111 1.2.2.2 nathanw MIPS_SOFT_INT_MASK_0, /* IPL_SOFTSERIAL */
112 1.2.2.2 nathanw };
113 1.2.2.2 nathanw
114 1.2.2.2 nathanw #define NIRQS 64
115 1.2.2.2 nathanw
116 1.2.2.2 nathanw const char *au1000_intrnames[NIRQS] = {
117 1.2.2.2 nathanw "uart0",
118 1.2.2.2 nathanw "uart1",
119 1.2.2.2 nathanw "uart2",
120 1.2.2.2 nathanw "uart3",
121 1.2.2.2 nathanw "ssi0",
122 1.2.2.2 nathanw "ssi1",
123 1.2.2.2 nathanw "dma0",
124 1.2.2.2 nathanw "dma1",
125 1.2.2.2 nathanw "dma2",
126 1.2.2.2 nathanw "dma3",
127 1.2.2.2 nathanw "dma4",
128 1.2.2.2 nathanw "dma5",
129 1.2.2.2 nathanw "dma6",
130 1.2.2.2 nathanw "dma7",
131 1.2.2.2 nathanw "pc0",
132 1.2.2.2 nathanw "pc0 match1",
133 1.2.2.2 nathanw "pc0 match2",
134 1.2.2.2 nathanw "pc0 match3",
135 1.2.2.2 nathanw "pc1",
136 1.2.2.2 nathanw "pc1 match1",
137 1.2.2.2 nathanw "pc1 match2",
138 1.2.2.2 nathanw "pc1 match3",
139 1.2.2.2 nathanw "irda tx",
140 1.2.2.2 nathanw "irda rx",
141 1.2.2.2 nathanw "usb intr",
142 1.2.2.2 nathanw "usb suspend",
143 1.2.2.2 nathanw "usb host",
144 1.2.2.2 nathanw "ac97",
145 1.2.2.2 nathanw "mac0",
146 1.2.2.2 nathanw "mac1",
147 1.2.2.2 nathanw "i2s",
148 1.2.2.2 nathanw "ac97 cmd",
149 1.2.2.2 nathanw
150 1.2.2.2 nathanw "gpio 0",
151 1.2.2.2 nathanw "gpio 1",
152 1.2.2.2 nathanw "gpio 2",
153 1.2.2.2 nathanw "gpio 3",
154 1.2.2.2 nathanw "gpio 4",
155 1.2.2.2 nathanw "gpio 5",
156 1.2.2.2 nathanw "gpio 6",
157 1.2.2.2 nathanw "gpio 7",
158 1.2.2.2 nathanw "gpio 8",
159 1.2.2.2 nathanw "gpio 9",
160 1.2.2.2 nathanw "gpio 10",
161 1.2.2.2 nathanw "gpio 11",
162 1.2.2.2 nathanw "gpio 12",
163 1.2.2.2 nathanw "gpio 13",
164 1.2.2.2 nathanw "gpio 14",
165 1.2.2.2 nathanw "gpio 15",
166 1.2.2.2 nathanw "gpio 16",
167 1.2.2.2 nathanw "gpio 17",
168 1.2.2.2 nathanw "gpio 18",
169 1.2.2.2 nathanw "gpio 19",
170 1.2.2.2 nathanw "gpio 20",
171 1.2.2.2 nathanw "gpio 21",
172 1.2.2.2 nathanw "gpio 22",
173 1.2.2.2 nathanw "gpio 23",
174 1.2.2.2 nathanw "gpio 24",
175 1.2.2.2 nathanw "gpio 25",
176 1.2.2.2 nathanw "gpio 26",
177 1.2.2.2 nathanw "gpio 27",
178 1.2.2.2 nathanw "gpio 28",
179 1.2.2.2 nathanw "gpio 29",
180 1.2.2.2 nathanw "gpio 30",
181 1.2.2.2 nathanw "gpio 31",
182 1.2.2.2 nathanw };
183 1.2.2.2 nathanw
184 1.2.2.2 nathanw struct au1000_intrhead {
185 1.2.2.2 nathanw struct evcnt intr_count;
186 1.2.2.2 nathanw int intr_refcnt;
187 1.2.2.2 nathanw };
188 1.2.2.2 nathanw struct au1000_intrhead au1000_intrtab[NIRQS];
189 1.2.2.2 nathanw
190 1.2.2.2 nathanw #define NINTRS 4 /* MIPS INT0 - INT3 */
191 1.2.2.2 nathanw
192 1.2.2.2 nathanw struct au1000_cpuintr {
193 1.2.2.2 nathanw LIST_HEAD(, evbmips_intrhand) cintr_list;
194 1.2.2.2 nathanw struct evcnt cintr_count;
195 1.2.2.2 nathanw };
196 1.2.2.2 nathanw
197 1.2.2.2 nathanw struct au1000_cpuintr au1000_cpuintrs[NINTRS];
198 1.2.2.2 nathanw const char *au1000_cpuintrnames[NINTRS] = {
199 1.2.2.2 nathanw "icu 0, req 0",
200 1.2.2.2 nathanw "icu 0, req 1",
201 1.2.2.2 nathanw "icu 1, req 0",
202 1.2.2.2 nathanw "icu 1, req 1",
203 1.2.2.2 nathanw };
204 1.2.2.2 nathanw
205 1.2.2.2 nathanw void
206 1.2.2.2 nathanw au_intr_init(void)
207 1.2.2.2 nathanw {
208 1.2.2.2 nathanw int i;
209 1.2.2.2 nathanw
210 1.2.2.2 nathanw for (i = 0; i < NINTRS; i++) {
211 1.2.2.2 nathanw LIST_INIT(&au1000_cpuintrs[i].cintr_list);
212 1.2.2.2 nathanw evcnt_attach_dynamic(&au1000_cpuintrs[i].cintr_count,
213 1.2.2.2 nathanw EVCNT_TYPE_INTR, NULL, "mips", au1000_cpuintrnames[i]);
214 1.2.2.2 nathanw }
215 1.2.2.2 nathanw
216 1.2.2.2 nathanw evcnt_attach_static(&mips_int5_evcnt);
217 1.2.2.2 nathanw
218 1.2.2.2 nathanw for (i = 0; i < NIRQS; i++) {
219 1.2.2.2 nathanw /* XXX steering - use an irqmap array? */
220 1.2.2.2 nathanw
221 1.2.2.2 nathanw au1000_intrtab[i].intr_refcnt = 0;
222 1.2.2.2 nathanw evcnt_attach_dynamic(&au1000_intrtab[i].intr_count,
223 1.2.2.2 nathanw EVCNT_TYPE_INTR, NULL, "au1000", au1000_intrnames[i]);
224 1.2.2.2 nathanw }
225 1.2.2.2 nathanw }
226 1.2.2.2 nathanw
227 1.2.2.2 nathanw void *
228 1.2.2.2 nathanw au_intr_establish(int irq, int req, int level, int type,
229 1.2.2.2 nathanw int (*func)(void *), void *arg)
230 1.2.2.2 nathanw {
231 1.2.2.2 nathanw struct evbmips_intrhand *ih;
232 1.2.2.2 nathanw uint32_t icu_base;
233 1.2.2.2 nathanw int cpu_intr, s;
234 1.2.2.2 nathanw
235 1.2.2.2 nathanw if (irq >= NIRQS)
236 1.2.2.2 nathanw panic("au_intr_establish: bogus IRQ %d", irq);
237 1.2.2.2 nathanw if (req > 1)
238 1.2.2.2 nathanw panic("au_intr_establish: bogus request %d", req);
239 1.2.2.2 nathanw
240 1.2.2.2 nathanw ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
241 1.2.2.2 nathanw if (ih == NULL)
242 1.2.2.2 nathanw return (NULL);
243 1.2.2.2 nathanw
244 1.2.2.2 nathanw ih->ih_func = func;
245 1.2.2.2 nathanw ih->ih_arg = arg;
246 1.2.2.2 nathanw ih->ih_irq = irq;
247 1.2.2.2 nathanw
248 1.2.2.2 nathanw s = splhigh();
249 1.2.2.2 nathanw
250 1.2.2.2 nathanw /*
251 1.2.2.2 nathanw * First, link it into the tables.
252 1.2.2.2 nathanw * XXX do we want a separate list (really, should only be one item, not
253 1.2.2.2 nathanw * a list anyway) per irq, not per cpu interrupt?
254 1.2.2.2 nathanw */
255 1.2.2.2 nathanw cpu_intr = (irq < 32 ? 0 : 2);
256 1.2.2.2 nathanw LIST_INSERT_HEAD(&au1000_cpuintrs[cpu_intr].cintr_list, ih, ih_q);
257 1.2.2.2 nathanw
258 1.2.2.2 nathanw /*
259 1.2.2.2 nathanw * Now enable it.
260 1.2.2.2 nathanw */
261 1.2.2.2 nathanw if (au1000_intrtab[irq].intr_refcnt++ == 0) {
262 1.2.2.2 nathanw icu_base = (irq < 32) ? IC0_BASE : IC1_BASE;
263 1.2.2.2 nathanw
264 1.2.2.2 nathanw irq &= 31; /* throw away high bit if set */
265 1.2.2.2 nathanw irq = 1 << irq; /* only used as a mask from here on */
266 1.2.2.2 nathanw
267 1.2.2.2 nathanw /* XXX Only high-level interrupts for now */
268 1.2.2.2 nathanw switch (type) {
269 1.2.2.2 nathanw case IST_NONE:
270 1.2.2.2 nathanw case IST_PULSE:
271 1.2.2.2 nathanw case IST_EDGE:
272 1.2.2.2 nathanw panic("unsupported irq type %d", type);
273 1.2.2.2 nathanw case IST_LEVEL:
274 1.2.2.2 nathanw REGVAL(icu_base + IC_CONFIG2_SET) = irq;
275 1.2.2.2 nathanw REGVAL(icu_base + IC_CONFIG1_CLEAR) = irq;
276 1.2.2.2 nathanw REGVAL(icu_base + IC_CONFIG0_SET) = irq;
277 1.2.2.2 nathanw }
278 1.2.2.2 nathanw
279 1.2.2.2 nathanw /* XXX handle GPIO interrupts - not done at all yet */
280 1.2.2.2 nathanw if (cpu_intr & 0x1)
281 1.2.2.2 nathanw REGVAL(icu_base + IC_ASSIGN_REQUEST_CLEAR) = irq;
282 1.2.2.2 nathanw else
283 1.2.2.2 nathanw REGVAL(icu_base + IC_ASSIGN_REQUEST_SET) = irq;
284 1.2.2.2 nathanw
285 1.2.2.2 nathanw /* Associate interrupt with peripheral */
286 1.2.2.2 nathanw REGVAL(icu_base + IC_SOURCE_SET) = irq;
287 1.2.2.2 nathanw
288 1.2.2.2 nathanw /* Actually enable the interrupt */
289 1.2.2.2 nathanw REGVAL(icu_base + IC_MASK_SET) = irq;
290 1.2.2.2 nathanw
291 1.2.2.2 nathanw /* And allow the interrupt to interrupt idle */
292 1.2.2.2 nathanw REGVAL(icu_base + IC_WAKEUP_SET) = irq;
293 1.2.2.2 nathanw }
294 1.2.2.2 nathanw splx(s);
295 1.2.2.2 nathanw
296 1.2.2.2 nathanw return (ih);
297 1.2.2.2 nathanw }
298 1.2.2.2 nathanw
299 1.2.2.2 nathanw void
300 1.2.2.2 nathanw au_intr_disestablish(void *cookie)
301 1.2.2.2 nathanw {
302 1.2.2.2 nathanw struct evbmips_intrhand *ih = cookie;
303 1.2.2.2 nathanw uint32_t icu_base;
304 1.2.2.2 nathanw int irq, s;
305 1.2.2.2 nathanw
306 1.2.2.2 nathanw irq = ih->ih_irq;
307 1.2.2.2 nathanw
308 1.2.2.2 nathanw s = splhigh();
309 1.2.2.2 nathanw
310 1.2.2.2 nathanw /*
311 1.2.2.2 nathanw * First, remove it from the table.
312 1.2.2.2 nathanw */
313 1.2.2.2 nathanw LIST_REMOVE(ih, ih_q);
314 1.2.2.2 nathanw
315 1.2.2.2 nathanw /*
316 1.2.2.2 nathanw * Now, disable it, if there is nothing remaining on the
317 1.2.2.2 nathanw * list.
318 1.2.2.2 nathanw */
319 1.2.2.2 nathanw if (au1000_intrtab[irq].intr_refcnt-- == 1) {
320 1.2.2.2 nathanw icu_base = (irq < 32) ? IC0_BASE : IC1_BASE;
321 1.2.2.2 nathanw
322 1.2.2.2 nathanw irq &= 31; /* throw away high bit if set */
323 1.2.2.2 nathanw irq = 1 << irq; /* only used as a mask from here on */
324 1.2.2.2 nathanw
325 1.2.2.2 nathanw REGVAL(icu_base + IC_CONFIG2_CLEAR) = irq;
326 1.2.2.2 nathanw REGVAL(icu_base + IC_CONFIG1_CLEAR) = irq;
327 1.2.2.2 nathanw REGVAL(icu_base + IC_CONFIG0_CLEAR) = irq;
328 1.2.2.2 nathanw
329 1.2.2.2 nathanw /* XXX disable with MASK_CLEAR and WAKEUP_CLEAR */
330 1.2.2.2 nathanw }
331 1.2.2.2 nathanw
332 1.2.2.2 nathanw splx(s);
333 1.2.2.2 nathanw
334 1.2.2.2 nathanw free(ih, M_DEVBUF);
335 1.2.2.2 nathanw }
336 1.2.2.2 nathanw
337 1.2.2.2 nathanw void
338 1.2.2.2 nathanw au_iointr(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
339 1.2.2.2 nathanw {
340 1.2.2.2 nathanw struct evbmips_intrhand *ih;
341 1.2.2.2 nathanw int level;
342 1.2.2.2 nathanw u_int32_t icu_base, irqmask;
343 1.2.2.2 nathanw
344 1.2.2.2 nathanw for (level = 3; level >= 0; level--) {
345 1.2.2.2 nathanw if ((ipending & (MIPS_INT_MASK_0 << level)) == 0)
346 1.2.2.2 nathanw continue;
347 1.2.2.2 nathanw
348 1.2.2.2 nathanw /*
349 1.2.2.2 nathanw * XXX the following may well be slow to execute.
350 1.2.2.2 nathanw * investigate and possibly speed up.
351 1.2.2.2 nathanw *
352 1.2.2.2 nathanw * is something like:
353 1.2.2.2 nathanw *
354 1.2.2.2 nathanw * irqmask = REGVAL(
355 1.2.2.2 nathanw * (level & 4 == 0) ? IC0_BASE ? IC1_BASE +
356 1.2.2.2 nathanw * (level & 2 == 0) ? IC_REQUEST0_INT : IC_REQUEST1_INT);
357 1.2.2.2 nathanw *
358 1.2.2.2 nathanw * be any better?
359 1.2.2.2 nathanw *
360 1.2.2.2 nathanw */
361 1.2.2.2 nathanw switch (level) {
362 1.2.2.2 nathanw case 0:
363 1.2.2.2 nathanw icu_base = IC0_BASE;
364 1.2.2.2 nathanw irqmask = REGVAL(icu_base + IC_REQUEST0_INT);
365 1.2.2.2 nathanw break;
366 1.2.2.2 nathanw case 1:
367 1.2.2.2 nathanw icu_base = IC0_BASE;
368 1.2.2.2 nathanw irqmask = REGVAL(icu_base + IC_REQUEST1_INT);
369 1.2.2.2 nathanw break;
370 1.2.2.2 nathanw case 2:
371 1.2.2.2 nathanw icu_base = IC1_BASE;
372 1.2.2.2 nathanw irqmask = REGVAL(icu_base + IC_REQUEST0_INT);
373 1.2.2.2 nathanw break;
374 1.2.2.2 nathanw case 3:
375 1.2.2.2 nathanw icu_base = IC1_BASE;
376 1.2.2.2 nathanw irqmask = REGVAL(icu_base + IC_REQUEST1_INT);
377 1.2.2.2 nathanw break;
378 1.2.2.2 nathanw }
379 1.2.2.2 nathanw au1000_cpuintrs[level].cintr_count.ev_count++;
380 1.2.2.2 nathanw LIST_FOREACH(ih, &au1000_cpuintrs[level].cintr_list, ih_q) {
381 1.2.2.2 nathanw /* XXX should check is see if interrupt is masked? */
382 1.2.2.2 nathanw if (1 << ih->ih_irq & irqmask) {
383 1.2.2.2 nathanw au1000_intrtab[ih->ih_irq].intr_count.ev_count++;
384 1.2.2.2 nathanw (*ih->ih_func)(ih->ih_arg);
385 1.2.2.2 nathanw
386 1.2.2.2 nathanw REGVAL(icu_base + IC_MASK_CLEAR) = 1 << ih->ih_irq;
387 1.2.2.2 nathanw REGVAL(icu_base + IC_MASK_SET) = 1 << ih->ih_irq;
388 1.2.2.2 nathanw }
389 1.2.2.2 nathanw }
390 1.2.2.2 nathanw cause &= ~(MIPS_INT_MASK_0 << level);
391 1.2.2.2 nathanw }
392 1.2.2.2 nathanw
393 1.2.2.2 nathanw /* Re-enable anything that we have processed. */
394 1.2.2.2 nathanw _splset(MIPS_SR_INT_IE | ((status & ~cause) & MIPS_HARD_INT_MASK));
395 1.2.2.2 nathanw }
396