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