Annotation of sys/arch/hppa/hppa/intr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: intr.c,v 1.23 2007/05/27 16:36:07 kettenis Exp $ */
2:
3: /*
4: * Copyright (c) 2002-2004 Michael Shalayeff
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * 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 copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26: * THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: #include <sys/param.h>
30: #include <sys/systm.h>
31: #include <sys/kernel.h>
32: #include <sys/device.h>
33: #include <sys/evcount.h>
34: #include <sys/malloc.h>
35:
36: #include <net/netisr.h>
37:
38: #include <uvm/uvm_extern.h> /* for uvmexp */
39:
40: #include <machine/autoconf.h>
41: #include <machine/frame.h>
42: #include <machine/reg.h>
43:
44: void softnet(void);
45: void softtty(void);
46:
47: struct hppa_iv {
48: char pri;
49: char irq;
50: char flags;
51: #define HPPA_IV_CALL 0x01
52: #define HPPA_IV_SOFT 0x02
53: char pad;
54: int pad2;
55: int (*handler)(void *);
56: void *arg;
57: u_int bit;
58: struct hppa_iv *share;
59: struct hppa_iv *next;
60: struct evcount *cnt;
61: } __packed;
62:
63: register_t kpsw = PSL_Q | PSL_P | PSL_C | PSL_D;
64: volatile int cpu_inintr, cpl = IPL_NESTED;
65: u_long cpu_mask;
66: struct hppa_iv intr_store[8*2*CPU_NINTS] __attribute__ ((aligned(32))),
67: *intr_more = intr_store, *intr_list;
68: struct hppa_iv intr_table[CPU_NINTS] __attribute__ ((aligned(32))) = {
69: { IPL_SOFTCLOCK, 0, HPPA_IV_SOFT, 0, 0, (int (*)(void *))&softclock },
70: { IPL_SOFTNET , 0, HPPA_IV_SOFT, 0, 0, (int (*)(void *))&softnet },
71: { 0 }, { 0 },
72: { IPL_SOFTTTY , 0, HPPA_IV_SOFT, 0, 0, (int (*)(void *))&softtty }
73: };
74: volatile u_long ipending, imask[NIPL] = {
75: 0,
76: 1 << (IPL_SOFTCLOCK - 1),
77: 1 << (IPL_SOFTNET - 1),
78: 0, 0,
79: 1 << (IPL_SOFTTTY - 1)
80: };
81:
82: #ifdef DIAGNOSTIC
83: void
84: splassert_check(int wantipl, const char *func)
85: {
86: if (cpl < wantipl) {
87: splassert_fail(wantipl, cpl, func);
88: }
89: }
90: #endif
91:
92: void
93: softnet(void)
94: {
95: int ni;
96:
97: /* use atomic "load & clear" */
98: __asm __volatile(
99: "ldcws 0(%2), %0": "=&r" (ni), "+m" (netisr): "r" (&netisr));
100: #define DONETISR(m,c) if (ni & (1 << (m))) c()
101: #include <net/netisr_dispatch.h>
102: }
103:
104: void
105: softtty(void)
106: {
107:
108: }
109:
110: void
111: cpu_intr_init(void)
112: {
113: u_long mask = cpu_mask | SOFTINT_MASK;
114: struct hppa_iv *iv;
115: int level, bit;
116:
117: /* map the shared ints */
118: while (intr_list) {
119: iv = intr_list;
120: intr_list = iv->next;
121: bit = ffs(imask[(int)iv->pri]);
122: if (!bit--) {
123: bit = ffs(~mask);
124: if (!bit--)
125: panic("cpu_intr_init: out of bits");
126:
127: iv->next = NULL;
128: iv->bit = 1 << bit;
129: intr_table[bit] = *iv;
130: mask |= (1 << bit);
131: imask[(int)iv->pri] |= (1 << bit);
132: } else {
133: iv->bit = 1 << bit;
134: iv->next = intr_table[bit].next;
135: intr_table[bit].next = iv;
136: }
137: }
138:
139: for (level = 0; level < NIPL - 1; level++)
140: imask[level + 1] |= imask[level];
141:
142: printf("biomask 0x%lx netmask 0x%lx ttymask 0x%lx\n",
143: imask[IPL_BIO], imask[IPL_NET], imask[IPL_TTY]);
144:
145: /* XXX the whacky trick is to prevent hardclock from happenning */
146: mfctl(CR_ITMR, mask);
147: mtctl(mask - 1, CR_ITMR);
148:
149: mtctl(cpu_mask, CR_EIEM);
150: /* ack the unwanted interrupts */
151: mfctl(CR_EIRR, mask);
152: mtctl(mask & (1 << 31), CR_EIRR);
153:
154: /* in spl*() we trust, clock is started in initclocks() */
155: kpsw |= PSL_I;
156: ssm(PSL_I, mask);
157: }
158:
159: int
160: cpu_intr_findirq(void)
161: {
162: int irq;
163:
164: for (irq = 0; irq < CPU_NINTS; irq++)
165: if (intr_table[irq].handler == NULL)
166: return irq;
167:
168: return -1;
169: }
170:
171: void *
172: cpu_intr_map(void *v, int pri, int irq, int (*handler)(void *), void *arg,
173: const char *name)
174: {
175: struct hppa_iv *iv, *pv = v, *ivb = pv->next;
176: struct evcount *cnt;
177:
178: if (irq < 0 || irq >= CPU_NINTS)
179: return (NULL);
180:
181: MALLOC(cnt, struct evcount *, sizeof *cnt, M_DEVBUF, M_NOWAIT);
182: if (!cnt)
183: return (NULL);
184:
185: iv = &ivb[irq];
186: if (iv->handler) {
187: if (!pv->share) {
188: FREE(cnt, M_DEVBUF);
189: return (NULL);
190: } else {
191: iv = pv->share;
192: pv->share = iv->share;
193: iv->share = ivb[irq].share;
194: ivb[irq].share = iv;
195: }
196: }
197:
198: evcount_attach(cnt, name, NULL, &evcount_intr);
199: iv->pri = pri;
200: iv->irq = irq;
201: iv->flags = 0;
202: iv->handler = handler;
203: iv->arg = arg;
204: iv->cnt = cnt;
205: iv->next = intr_list;
206: intr_list = iv;
207:
208: return (iv);
209: }
210:
211: void *
212: cpu_intr_establish(int pri, int irq, int (*handler)(void *), void *arg,
213: const char *name)
214: {
215: struct hppa_iv *iv, *ev;
216: struct evcount *cnt;
217:
218: if (irq < 0 || irq >= CPU_NINTS || intr_table[irq].handler)
219: return (NULL);
220:
221: MALLOC(cnt, struct evcount *, sizeof *cnt, M_DEVBUF, M_NOWAIT);
222: if (!cnt)
223: return (NULL);
224:
225: cpu_mask |= (1 << irq);
226: imask[pri] |= (1 << irq);
227:
228: iv = &intr_table[irq];
229: iv->pri = pri;
230: iv->irq = irq;
231: iv->bit = 1 << irq;
232: iv->flags = 0;
233: iv->handler = handler;
234: iv->arg = arg;
235: iv->cnt = cnt;
236: iv->next = NULL;
237: iv->share = NULL;
238:
239: if (pri == IPL_NESTED) {
240: iv->flags = HPPA_IV_CALL;
241: iv->next = intr_more;
242: intr_more += 2 * CPU_NINTS;
243: for (ev = iv->next + CPU_NINTS; ev < intr_more; ev++)
244: ev->share = iv->share, iv->share = ev;
245: FREE(cnt, M_DEVBUF);
246: iv->cnt = NULL;
247: } else
248: evcount_attach(cnt, name, NULL, &evcount_intr);
249:
250: return (iv);
251: }
252:
253: int
254: fls(u_int mask)
255: {
256: int bit;
257:
258: bit = 32;
259: if (!(mask & 0xffff0000)) {
260: bit -= 16;
261: mask <<= 16;
262: }
263:
264: if (!(mask & 0xff000000)) {
265: bit -= 8;
266: mask <<= 8;
267: }
268:
269: if (!(mask & 0xf0000000)) {
270: bit -= 4;
271: mask <<= 4;
272: }
273:
274: if (!(mask & 0xc0000000)) {
275: bit -= 2;
276: mask <<= 2;
277: }
278:
279: if (!(mask & 0x80000000)) {
280: bit -= 1;
281: mask <<= 1;
282: }
283:
284: return mask? bit : 0;
285: }
286:
287: void
288: cpu_intr(void *v)
289: {
290: struct trapframe *frame = v;
291: u_long mask;
292: int s = cpl;
293:
294: if (cpu_inintr++)
295: frame->tf_flags |= TFF_INTR;
296:
297: while ((mask = ipending & ~imask[s])) {
298: int r, bit = fls(mask) - 1;
299: struct hppa_iv *iv = &intr_table[bit];
300:
301: ipending &= ~(1L << bit);
302: if (iv->flags & HPPA_IV_CALL)
303: continue;
304:
305: uvmexp.intrs++;
306: if (iv->flags & HPPA_IV_SOFT)
307: uvmexp.softs++;
308:
309: cpl = iv->pri;
310: mtctl(frame->tf_eiem, CR_EIEM);
311: for (r = iv->flags & HPPA_IV_SOFT;
312: iv && iv->handler; iv = iv->next)
313: /* no arg means pass the frame */
314: if ((iv->handler)(iv->arg? iv->arg : v) == 1) {
315: if (iv->cnt)
316: iv->cnt->ec_count++;
317: r |= 1;
318: }
319: #if 0 /* XXX this does not work, lasi gives us double ints */
320: if (!r) {
321: cpl = 0;
322: printf("stray interrupt %d\n", bit);
323: }
324: #endif
325: mtctl(0, CR_EIEM);
326: }
327: cpu_inintr--;
328: cpl = s;
329: }
CVSweb