Annotation of sys/arch/landisk/landisk/intr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: intr.c,v 1.5 2007/04/09 13:23:25 miod Exp $ */
2: /* $NetBSD: intr.c,v 1.1 2006/09/01 21:26:18 uwe Exp $ */
3:
4: /*-
5: * Copyright (c) 2005 NONAKA Kimihiro
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: #include <sys/param.h>
31: #include <sys/systm.h>
32: #include <sys/kernel.h>
33: #include <sys/malloc.h>
34: #include <sys/device.h>
35: #include <sys/evcount.h>
36:
37: #include <sh/trap.h>
38:
39: #include <machine/intr.h>
40:
41: #define _N_EXTINTR 8
42:
43: #define LANDISK_INTEN 0xb0000005
44: #define INTEN_ALL_MASK 0x00
45:
46: struct intrhand {
47: int (*ih_fun)(void *);
48: void *ih_arg;
49: struct intrhand *ih_next;
50: int ih_enable;
51: int ih_level;
52: int ih_irq;
53: struct evcount ih_count;
54: const char *ih_name;
55: };
56:
57: struct extintr_handler {
58: int (*eih_func)(void *eih_arg);
59: void *eih_arg;
60: struct intrhand *eih_ih;
61: int eih_nih;
62: };
63:
64: static struct extintr_handler extintr_handler[_N_EXTINTR];
65:
66: static int fakeintr(void *arg);
67: static int extintr_intr_handler(void *arg);
68:
69: void
70: intc_intr(int ssr, int spc, int ssp)
71: {
72: struct intc_intrhand *ih;
73: struct clockframe cf;
74: int evtcode;
75:
76: evtcode = _reg_read_4(SH4_INTEVT);
77: ih = EVTCODE_IH(evtcode);
78: KDASSERT(ih->ih_func);
79:
80: switch (evtcode) {
81: #if 0
82: #define IRL(irq) (0x200 + ((irq) << 5))
83: case IRL(5): case IRL(6): case IRL(7): case IRL(8):
84: case IRL(9): case IRL(10): case IRL(11): case IRL(12):
85: {
86: int level;
87: uint8_t inten, bit;
88:
89: bit = 1 << (EVTCODE_TO_MAP_INDEX(evtcode) - 5);
90: inten = _reg_read_1(LANDISK_INTEN);
91: _reg_write_1(LANDISK_INTEN, inten & ~bit);
92: level = (_IPL_NSOFT + 1) << 4; /* disable softintr */
93: ssr &= 0xf0;
94: if (level < ssr)
95: level = ssr;
96: (void)_cpu_intr_resume(level);
97: if ((*ih->ih_func)(ih->ih_arg) != 0)
98: ih->ih_count.ec_count++;
99: _reg_write_1(LANDISK_INTEN, inten);
100: break;
101: }
102: #endif
103: default:
104: (void)_cpu_intr_resume(ih->ih_level);
105: if ((*ih->ih_func)(ih->ih_arg) != 0)
106: ih->ih_count.ec_count++;
107: break;
108:
109: case SH_INTEVT_TMU0_TUNI0:
110: (void)_cpu_intr_resume(ih->ih_level);
111: cf.spc = spc;
112: cf.ssr = ssr;
113: cf.ssp = ssp;
114: if ((*ih->ih_func)(&cf) != 0)
115: ih->ih_count.ec_count++;
116: break;
117:
118: case SH_INTEVT_NMI:
119: printf("NMI ignored.\n");
120: break;
121: }
122: }
123:
124: void
125: intr_init(void)
126: {
127: _reg_write_1(LANDISK_INTEN, INTEN_ALL_MASK);
128: }
129:
130: void *
131: extintr_establish(int irq, int level, int (*ih_fun)(void *), void *ih_arg,
132: const char *ih_name)
133: {
134: static struct intrhand fakehand = {fakeintr};
135: struct extintr_handler *eih;
136: struct intrhand **p, *q, *ih;
137: int evtcode;
138: int s;
139:
140: KDASSERT(irq >= 5 && irq < 13);
141:
142: ih = malloc(sizeof(*ih), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
143: if (ih == NULL)
144: panic("intr_establish: can't malloc handler info");
145:
146: s = _cpu_intr_suspend();
147:
148: switch (level) {
149: default:
150: #if defined(DEBUG)
151: panic("extintr_establish: unknown level %d", level);
152: /*NOTREACHED*/
153: #endif
154: case IPL_BIO:
155: case IPL_NET:
156: case IPL_TTY:
157: break;
158: }
159:
160: eih = &extintr_handler[irq - 5];
161: if (eih->eih_func == NULL) {
162: evtcode = 0x200 + (irq << 5);
163: eih->eih_func = intc_intr_establish(evtcode, IST_LEVEL, level,
164: extintr_intr_handler, eih, NULL);
165: }
166:
167: /*
168: * Figure out where to put the handler.
169: * This is O(N^2), but we want to preserve the order, and N is
170: * generally small.
171: */
172: for (p = &eih->eih_ih; (q = *p) != NULL; p = &q->ih_next)
173: continue;
174:
175: /*
176: * Actually install a fake handler momentarily, since we might be doing
177: * this with interrupts enabled and don't want the real routine called
178: * until masking is set up.
179: */
180: fakehand.ih_level = level;
181: *p = &fakehand;
182:
183: /*
184: * Poke the real handler in now.
185: */
186: memset(ih, 0, sizeof(*ih));
187: ih->ih_fun = ih_fun;
188: ih->ih_arg = ih_arg;
189: ih->ih_next = NULL;
190: ih->ih_enable = 1;
191: ih->ih_level = level;
192: ih->ih_irq = irq;
193: ih->ih_name = ih_name;
194:
195: if (ih_name != NULL)
196: evcount_attach(&ih->ih_count, ih_name, (void *)&ih->ih_irq,
197: &evcount_intr);
198: *p = ih;
199:
200: if (++eih->eih_nih == 1) {
201: /* Unmask interrupt */
202: _reg_bset_1(LANDISK_INTEN, (1 << (irq - 5)));
203: }
204:
205: _cpu_intr_resume(s);
206:
207: return (ih);
208: }
209:
210: void
211: extintr_disestablish(void *aux)
212: {
213: struct intrhand *ih = aux;
214: struct intrhand **p, *q;
215: struct extintr_handler *eih;
216: int irq;
217: int s;
218:
219: KDASSERT(ih != NULL);
220:
221: s = _cpu_intr_suspend();
222:
223: irq = ih->ih_irq - 5;
224: eih = &extintr_handler[irq];
225: /*
226: * Remove the handler from the chain.
227: * This is O(n^2), too.
228: */
229: for (p = &eih->eih_ih; (q = *p) != NULL && q != ih; p = &q->ih_next)
230: continue;
231: if (q == NULL)
232: panic("extintr_disestablish: handler not registered");
233:
234: *p = q->ih_next;
235:
236: #if 0
237: if (ih->ih_name != NULL)
238: evcount_detach(&ih->ih_count);
239: #endif
240:
241: free((void *)ih, M_DEVBUF);
242:
243: if (--eih->eih_nih == 0) {
244: intc_intr_disestablish(eih->eih_func);
245:
246: /* Mask interrupt */
247: _reg_bclr_1(LANDISK_INTEN, (1 << irq));
248: }
249:
250: _cpu_intr_resume(s);
251: }
252:
253: void
254: extintr_enable(void *aux)
255: {
256: struct intrhand *ih = aux;
257: struct intrhand *p, *q;
258: struct extintr_handler *eih;
259: int irq;
260: int cnt;
261: int s;
262:
263: KDASSERT(ih != NULL);
264:
265: s = _cpu_intr_suspend();
266:
267: irq = ih->ih_irq - 5;
268: KDASSERT(irq >= 0 && irq < 8);
269: eih = &extintr_handler[irq];
270: for (cnt = 0, p = eih->eih_ih, q = NULL; p != NULL; p = p->ih_next) {
271: if (p->ih_enable) {
272: cnt++;
273: }
274: if (p == ih) {
275: q = p;
276: p->ih_enable = 1;
277: }
278: }
279: KDASSERT(q != NULL);
280:
281: if (cnt == 0) {
282: /* Unmask interrupt */
283: _reg_bset_1(LANDISK_INTEN, (1 << irq));
284: }
285:
286: _cpu_intr_resume(s);
287: }
288:
289: void
290: extintr_disable(void *aux)
291: {
292: struct intrhand *ih = aux;
293: struct intrhand *p, *q;
294: struct extintr_handler *eih;
295: int irq;
296: int cnt;
297: int s;
298:
299: KDASSERT(ih != NULL);
300:
301: s = _cpu_intr_suspend();
302:
303: irq = ih->ih_irq - 5;
304: KDASSERT(irq >= 0 && irq < 8);
305: eih = &extintr_handler[irq];
306: for (cnt = 0, p = eih->eih_ih, q = NULL; p != NULL; p = p->ih_next) {
307: if (p == ih) {
308: q = p;
309: p->ih_enable = 0;
310: }
311: if (!ih->ih_enable) {
312: cnt++;
313: }
314: }
315: KDASSERT(q != NULL);
316:
317: if (cnt == 0) {
318: /* Mask interrupt */
319: _reg_bclr_1(LANDISK_INTEN, (1 << irq));
320: }
321:
322: _cpu_intr_resume(s);
323: }
324:
325: void
326: extintr_disable_by_num(int irq)
327: {
328: struct extintr_handler *eih;
329: struct intrhand *ih;
330: int s;
331:
332: irq -= 5;
333: KDASSERT(irq >= 0 && irq < 8);
334:
335: s = _cpu_intr_suspend();
336: eih = &extintr_handler[irq];
337: for (ih = eih->eih_ih; ih != NULL; ih = ih->ih_next) {
338: ih->ih_enable = 0;
339: }
340: /* Mask interrupt */
341: _reg_bclr_1(LANDISK_INTEN, (1 << irq));
342: _cpu_intr_resume(s);
343: }
344:
345: static int
346: fakeintr(void *arg)
347: {
348: return 0;
349: }
350:
351: static int
352: extintr_intr_handler(void *arg)
353: {
354: struct extintr_handler *eih = arg;
355: struct intrhand *ih;
356: int r;
357:
358: if (__predict_true(eih != NULL)) {
359: for (ih = eih->eih_ih; ih != NULL; ih = ih->ih_next) {
360: if (__predict_true(ih->ih_enable)) {
361: r = (*ih->ih_fun)(ih->ih_arg);
362: if (__predict_true(r != 0)) {
363: ih->ih_count.ec_count++;
364: }
365: }
366: }
367: return 1;
368: }
369: return 0;
370: }
371:
372: #ifdef DIAGNOSTIC
373: void
374: splassert_check(int wantipl, const char *func)
375: {
376: register_t sr;
377: int oldipl;
378:
379: __asm__ __volatile__ ("stc sr,%0" : "=r" (sr));
380:
381: oldipl = (sr & 0xf0) >> 4;
382: if (oldipl < wantipl) {
383: splassert_fail(wantipl, oldipl, func);
384: /*
385: * If the splassert_ctl is set to not panic, raise the ipl
386: * in a feeble attempt to reduce damage.
387: */
388: _cpu_intr_raise(wantipl << 4);
389: }
390: }
391: #endif
CVSweb