Annotation of sys/arch/arm/sa11x0/sa11x0_intr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pxa2x0_intr.c,v 1.15 2007/05/19 15:47:16 miod Exp $ */
2: /* $NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $ */
3:
4: /*
5: * Copyright (c) 2002 Genetec Corporation. All rights reserved.
6: * Written by Hiroyuki Bessho for Genetec Corporation.
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: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed for the NetBSD Project by
19: * Genetec Corporation.
20: * 4. The name of Genetec Corporation may not be used to endorse or
21: * promote products derived from this software without specific prior
22: * written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
28: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34: * POSSIBILITY OF SUCH DAMAGE.
35: */
36:
37: /*
38: * IRQ handler for the Intel StrongARM SA-11[01]0 processor.
39: * It has integrated interrupt controller.
40: */
41:
42: #include <sys/cdefs.h>
43: /*
44: __KERNEL_RCSID(0, "$NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $");
45: */
46:
47: #include <sys/cdefs.h>
48:
49: #include <sys/param.h>
50: #include <sys/systm.h>
51: #include <sys/malloc.h>
52: #include <sys/evcount.h>
53: #include <sys/queue.h>
54: #include <uvm/uvm_extern.h>
55:
56: #include <machine/bus.h>
57: #include <machine/intr.h>
58: #include <machine/lock.h>
59:
60: #include <arm/sa11x0/sa11x0_reg.h>
61: #include <arm/sa11x0/sa11x0_var.h>
62: #include <arm/sa11x0/sa11x0_intr.h>
63:
64: /*
65: * INTC autoconf glue
66: */
67: int saic_match(struct device *, void *, void *);
68: void saic_attach(struct device *, struct device *, void *);
69:
70: struct cfattach saic_ca = {
71: sizeof(struct device), saic_match, saic_attach
72: };
73:
74: struct cfdriver saic_cd = {
75: NULL, "saic", DV_DULL
76: };
77:
78: static int saic_attached;
79: vaddr_t saic_base;
80:
81: int sa11x0_stray_interrupt(void *);
82: void sa11x0_init_interrupt_masks(void);
83: void *_sa11x0_intr_establish(int irqno, int level,
84: int (*func)(void *), void *arg, char *name);
85: void sa11x0_intr_disestablish(void *cookie);
86:
87: /* XXX defined in arch/arm/sa11x0/sa11x0_intr.h */
88: #define read_icu(offset) (*(volatile uint32_t *)(saic_base+(offset)))
89: #define write_icu(offset,value) \
90: (*(volatile uint32_t *)(saic_base+(offset))=(value))
91:
92:
93: /*
94: * interrupt dispatch table.
95: */
96: #if 1
97: #define MULTIPLE_HANDLERS_ON_ONE_IRQ
98: #endif
99: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
100: struct intrhand {
101: TAILQ_ENTRY(intrhand) ih_list; /* link on intrq list */
102: int (*ih_func)(void *); /* handler */
103: void *ih_arg; /* arg for handler */
104: char *ih_name;
105: struct evcount ih_count;
106: int ih_irq;
107: int ih_level;
108: };
109: #endif
110:
111: static struct intrhandler{
112: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
113: TAILQ_HEAD(,intrhand) list;
114: #else
115: sa11x0_irq_handler_t func;
116: char *name;
117: void *arg; /* NULL for stackframe */
118: int ih_irq;
119: struct evcount ih_count;
120: #endif
121: } handler[ICU_LEN];
122:
123: __volatile int softint_pending;
124: __volatile int current_spl_level;
125: /* interrupt masks for each level */
126: int sa11x0_imask[NIPL];
127: static int extirq_level[ICU_LEN];
128:
129:
130: int
131: saic_match(struct device *parent, void *cf, void *aux)
132: {
133: struct saip_attach_args *saa = aux;
134:
135: if (saic_attached || saa->sai_addr != SAIPIC_BASE)
136: return (0);
137:
138: return (1);
139: }
140:
141: void
142: saic_attach(struct device *parent, struct device *self, void *args)
143: {
144: int i;
145:
146: saic_attached = 1;
147:
148: printf(": SA-11x0 Interrupt Controller\n");
149:
150: //#define SAIPIC_ICCR 0x14 /* XXX what's this? typo or err in spec?? */
151:
152: write_icu(SAIPIC_CR, 1);
153: write_icu(SAIPIC_MR, 0);
154:
155: for(i = 0; i < sizeof handler / sizeof handler[0]; ++i){
156: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
157: TAILQ_INIT(&handler[i].list);
158: extirq_level[i] = IPL_NONE;
159: #else
160: handler[i].name = "stray";
161: handler[i].func = sa11x0_stray_interrupt;
162: handler[i].arg = (void *)(u_int32_t) i;
163: extirq_level[i] = IPL_SERIAL;
164: #endif
165:
166: }
167:
168: sa11x0_init_interrupt_masks();
169:
170: _splraise(IPL_TTY);
171: enable_interrupts(I32_bit);
172: }
173:
174: /*
175: * Invoked very early on from the board-specific initarm(), in order to
176: * inform us the virtual address of the interrupt controller's registers.
177: */
178: void
179: sa11x0_intr_bootstrap(vaddr_t addr)
180: {
181:
182: saic_base = addr;
183: }
184:
185: #if 0
186: /*
187: * PXA27x has MSL interface and SSP3 interrupts [0,1], USIM interface
188: * and SSP2 interrupts [15,16]. PXA255 has bits [0..6,15] reserved and
189: * bit [16] network SSP interrupt. We don't need any of those, so we
190: * map software interrupts to bits [0..1,15..16]. Sadly there are no
191: * four contiguous bits safe enough to use on both processors.
192: */
193: #define SI_TO_IRQBIT(si) ((si) < 2 ? 1U<<(si) : 1U<<(15-2+(si)))
194: #else
195: #define SI_TO_IRQBIT(si) (1 << (si))
196: #endif /* 0 */
197:
198: /*
199: * Map a software interrupt queue to an interrupt priority level.
200: */
201: static const int si_to_ipl[SI_NQUEUES] = {
202: IPL_SOFT, /* SI_SOFT */
203: IPL_SOFTCLOCK, /* SI_SOFTCLOCK */
204: IPL_SOFTNET, /* SI_SOFTNET */
205: IPL_SOFTSERIAL, /* SI_SOFTSERIAL */
206: };
207:
208: /*
209: * called from irq_entry.
210: */
211: void
212: sa11x0_irq_handler(void *arg)
213: {
214: struct clockframe *frame = arg;
215: uint32_t irqbits;
216: int irqno;
217: int saved_spl_level;
218: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
219: struct intrhand *ih;
220: #endif
221:
222: saved_spl_level = current_spl_level;
223:
224: /* get pending IRQs */
225: irqbits = read_icu(SAIPIC_IP);
226:
227: while ((irqno = find_first_bit(irqbits)) >= 0) {
228: /* XXX: Should we handle IRQs in priority order? */
229:
230: /* raise spl to stop interrupts of lower priorities */
231: if (saved_spl_level < extirq_level[irqno])
232: sa11x0_setipl(extirq_level[irqno]);
233:
234: /* Enable interrupt */
235: enable_interrupts(I32_bit);
236:
237: #ifndef MULTIPLE_HANDLERS_ON_ONE_IRQ
238: (* handler[irqno].func)(
239: handler[irqno].arg == 0
240: ? frame : handler[irqno].arg );
241: handler[irqno].ih_count.ec_count++;
242: #else
243: TAILQ_FOREACH(ih, &handler[irqno].list, ih_list) {
244: if ((ih->ih_func)( ih->ih_arg == 0
245: ? frame : ih->ih_arg))
246: ih->ih_count.ec_count++;
247: }
248: #endif
249:
250: /* Disable interrupt */
251: disable_interrupts(I32_bit);
252:
253: irqbits &= ~(1<<irqno);
254: }
255:
256: /* restore spl to that was when this interrupt happen */
257: sa11x0_setipl(saved_spl_level);
258:
259: if(softint_pending & sa11x0_imask[current_spl_level])
260: sa11x0_do_pending();
261: }
262:
263: int
264: sa11x0_stray_interrupt(void *cookie)
265: {
266: int irqno = (int)cookie;
267: printf("stray interrupt %d\n", irqno);
268:
269: if (1 <= irqno && irqno < ICU_LEN){
270: int save = disable_interrupts(I32_bit);
271: write_icu(SAIPIC_MR,
272: read_icu(SAIPIC_MR) & ~(1U<<irqno));
273: restore_interrupts(save);
274: }
275:
276: return 0;
277: }
278:
279:
280:
281: /*
282: * Interrupt Mask Handling
283: */
284:
285: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
286: void sa11x0_update_intr_masks(void);
287:
288: void
289: sa11x0_update_intr_masks()
290: #else
291: void sa11x0_update_intr_masks(int irqno, int level);
292:
293: void
294: sa11x0_update_intr_masks(int irqno, int irqlevel)
295: #endif
296: {
297: int psw;
298:
299: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
300: int irq;
301: #ifdef DEBUG
302: int level;
303: #endif
304: struct intrhand *ih;
305: psw = disable_interrupts(I32_bit);
306:
307: /* First figure out which levels each IRQ uses. */
308: for (irq = 0; irq < ICU_LEN; irq++) {
309: int i;
310: int max = IPL_NONE;
311: int min = IPL_HIGH; /* XXX kill IPL_SERIAL */
312: TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
313: if (ih->ih_level > max)
314: max = ih->ih_level;
315:
316: if (ih->ih_level < min)
317: min = ih->ih_level;
318: }
319:
320: extirq_level[irq] = max;
321:
322: if (min == IPL_HIGH)
323: min = IPL_NONE;
324:
325: /* Enable interrupt at lower level */
326: for(i = 0; i < min; ++i)
327: sa11x0_imask[i] |= (1 << irq);
328:
329: /* Disable interrupt at upper level */
330: for( ; i < NIPL-1; ++i)
331: sa11x0_imask[i] &= ~(1 << irq);
332: }
333:
334: /* fixup */
335: sa11x0_imask[IPL_NONE] |=
336: SI_TO_IRQBIT(SI_SOFT) |
337: SI_TO_IRQBIT(SI_SOFTCLOCK) |
338: SI_TO_IRQBIT(SI_SOFTNET) |
339: SI_TO_IRQBIT(SI_SOFTSERIAL);
340: sa11x0_imask[IPL_SOFT] |=
341: SI_TO_IRQBIT(SI_SOFTCLOCK) |
342: SI_TO_IRQBIT(SI_SOFTNET) |
343: SI_TO_IRQBIT(SI_SOFTSERIAL);
344: sa11x0_imask[IPL_SOFTCLOCK] |=
345: SI_TO_IRQBIT(SI_SOFTNET) |
346: SI_TO_IRQBIT(SI_SOFTSERIAL);
347: sa11x0_imask[IPL_SOFTNET] |=
348: SI_TO_IRQBIT(SI_SOFTSERIAL);
349: sa11x0_imask[IPL_SOFTSERIAL] |=
350: 0;
351: #else
352: int level; /* debug */
353: int mask = 1U<<irqno;
354: int i;
355: psw = disable_interrupts(I32_bit);
356:
357: for(i = 0; i < irqlevel; ++i)
358: sa11x0_imask[i] |= mask; /* Enable interrupt at lower level */
359:
360: for( ; i < NIPL-1; ++i)
361: sa11x0_imask[i] &= ~mask; /* Disable interrupt at upper level */
362: #endif
363:
364: /*
365: * Enforce a hierarchy that gives "slow" device (or devices with
366: * limited input buffer space/"real-time" requirements) a better
367: * chance at not dropping data.
368: */
369: sa11x0_imask[IPL_BIO] &= sa11x0_imask[IPL_SOFTNET];
370: sa11x0_imask[IPL_NET] &= sa11x0_imask[IPL_BIO];
371: sa11x0_imask[IPL_SOFTSERIAL] &= sa11x0_imask[IPL_NET];
372: sa11x0_imask[IPL_TTY] &= sa11x0_imask[IPL_SOFTSERIAL];
373:
374: /*
375: * splvm() blocks all interrupts that use the kernel memory
376: * allocation facilities.
377: */
378: sa11x0_imask[IPL_VM] &= sa11x0_imask[IPL_TTY];
379:
380: /*
381: * Audio devices are not allowed to perform memory allocation
382: * in their interrupt routines, and they have fairly "real-time"
383: * requirements, so give them a high interrupt priority.
384: */
385: sa11x0_imask[IPL_AUDIO] &= sa11x0_imask[IPL_VM];
386:
387: /*
388: * splclock() must block anything that uses the scheduler.
389: */
390: sa11x0_imask[IPL_CLOCK] &= sa11x0_imask[IPL_AUDIO];
391:
392: /*
393: * splhigh() must block "everything".
394: */
395: sa11x0_imask[IPL_HIGH] &= sa11x0_imask[IPL_STATCLOCK];
396:
397: /*
398: * XXX We need serial drivers to run at the absolute highest priority
399: * in order to avoid overruns, so serial > high.
400: */
401: sa11x0_imask[IPL_TTY] &= sa11x0_imask[IPL_HIGH];
402:
403: #ifdef DEBUG
404: for (level = IPL_NONE; level < NIPL; level++) {
405: printf("imask %d, %x\n", level, sa11x0_imask[level]);
406: }
407: #endif
408:
409: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
410: for (irq = 0; irq < ICU_LEN; irq++) {
411: int max_irq = IPL_NONE;
412: TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
413: if (ih->ih_level > max_irq)
414: max_irq = ih->ih_level;
415: }
416: extirq_level[irq] = max_irq;
417: }
418: #endif
419:
420: write_icu(SAIPIC_MR, sa11x0_imask[current_spl_level]);
421:
422: restore_interrupts(psw);
423: }
424:
425:
426: void
427: sa11x0_init_interrupt_masks(void)
428: {
429:
430: memset(sa11x0_imask, 0, sizeof(sa11x0_imask));
431:
432: /*
433: * IPL_NONE has soft interrupts enabled only, at least until
434: * hardware handlers are installed.
435: */
436: sa11x0_imask[IPL_NONE] =
437: SI_TO_IRQBIT(SI_SOFT) |
438: SI_TO_IRQBIT(SI_SOFTCLOCK) |
439: SI_TO_IRQBIT(SI_SOFTNET) |
440: SI_TO_IRQBIT(SI_SOFTSERIAL);
441:
442: /*
443: * Initialize the soft interrupt masks to block themselves.
444: */
445: sa11x0_imask[IPL_SOFT] = ~SI_TO_IRQBIT(SI_SOFT);
446: sa11x0_imask[IPL_SOFTCLOCK] = ~SI_TO_IRQBIT(SI_SOFTCLOCK);
447: sa11x0_imask[IPL_SOFTNET] = ~SI_TO_IRQBIT(SI_SOFTNET);
448: sa11x0_imask[IPL_SOFTSERIAL] = ~SI_TO_IRQBIT(SI_SOFTSERIAL);
449:
450: sa11x0_imask[IPL_SOFT] &= sa11x0_imask[IPL_NONE];
451:
452: /*
453: * splsoftclock() is the only interface that users of the
454: * generic software interrupt facility have to block their
455: * soft intrs, so splsoftclock() must also block IPL_SOFT.
456: */
457: sa11x0_imask[IPL_SOFTCLOCK] &= sa11x0_imask[IPL_SOFT];
458:
459: /*
460: * splsoftnet() must also block splsoftclock(), since we don't
461: * want timer-driven network events to occur while we're
462: * processing incoming packets.
463: */
464: sa11x0_imask[IPL_SOFTNET] &= sa11x0_imask[IPL_SOFTCLOCK];
465: }
466:
467: void
468: sa11x0_do_pending(void)
469: {
470: static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED;
471: int oldirqstate, spl_save;
472:
473: if (__cpu_simple_lock_try(&processing) == 0)
474: return;
475:
476: spl_save = current_spl_level;
477:
478: oldirqstate = disable_interrupts(I32_bit);
479:
480: #if 1
481: #define DO_SOFTINT(si,ipl) \
482: if ((softint_pending & sa11x0_imask[current_spl_level]) & \
483: SI_TO_IRQBIT(si)) { \
484: softint_pending &= ~SI_TO_IRQBIT(si); \
485: if (current_spl_level < ipl) \
486: sa11x0_setipl(ipl); \
487: restore_interrupts(oldirqstate); \
488: softintr_dispatch(si); \
489: oldirqstate = disable_interrupts(I32_bit); \
490: sa11x0_setipl(spl_save); \
491: }
492:
493: do {
494: DO_SOFTINT(SI_SOFTSERIAL,IPL_SOFTSERIAL);
495: DO_SOFTINT(SI_SOFTNET, IPL_SOFTNET);
496: DO_SOFTINT(SI_SOFTCLOCK, IPL_SOFTCLOCK);
497: DO_SOFTINT(SI_SOFT, IPL_SOFT);
498: } while( softint_pending & sa11x0_imask[current_spl_level] );
499: #else
500: while( (si = find_first_bit(softint_pending & sa11x0_imask[current_spl_level])) >= 0 ){
501: softint_pending &= ~SI_TO_IRQBIT(si);
502: if (current_spl_level < ipl)
503: sa11x0_setipl(ipl);
504: restore_interrupts(oldirqstate);
505: softintr_dispatch(si);
506: oldirqstate = disable_interrupts(I32_bit);
507: sa11x0_setipl(spl_save);
508: }
509: #endif
510:
511: __cpu_simple_unlock(&processing);
512:
513: restore_interrupts(oldirqstate);
514: }
515:
516:
517: #undef splx
518: void
519: splx(int ipl)
520: {
521:
522: sa11x0_splx(ipl);
523: }
524:
525: #undef _splraise
526: int
527: _splraise(int ipl)
528: {
529:
530: return sa11x0_splraise(ipl);
531: }
532:
533: #undef _spllower
534: int
535: _spllower(int ipl)
536: {
537:
538: return sa11x0_spllower(ipl);
539: }
540:
541: #undef _setsoftintr
542: void
543: _setsoftintr(int si)
544: {
545:
546: return sa11x0_setsoftintr(si);
547: }
548:
549: void *
550: _sa11x0_intr_establish(int irqno, int level,
551: int (*func)(void *), void *arg, char *name)
552: {
553: int psw;
554: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
555: struct intrhand *ih;
556: #else
557: struct intrhandler *ih;
558: #endif
559:
560: if (irqno < 0 || irqno >= ICU_LEN - 1)
561: panic("intr_establish: bogus irq number %d", irqno);
562:
563: psw = disable_interrupts(I32_bit);
564:
565: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
566: /* no point in sleeping unless someone can free memory. */
567: MALLOC(ih, struct intrhand *, sizeof *ih, M_DEVBUF,
568: cold ? M_NOWAIT : M_WAITOK);
569: if (ih == NULL)
570: panic("intr_establish: can't malloc handler info");
571: ih->ih_func = func;
572: ih->ih_arg = arg;
573: ih->ih_level = level;
574: ih->ih_irq = irqno;
575:
576: TAILQ_INSERT_TAIL(&handler[irqno].list, ih, ih_list);
577: #else
578: ih = &handler[irqno];
579: ih->arg = arg;
580: ih->func = func;
581: ih->name = name;
582: ih->ih_irq = irqno;
583: extirq_level[irqno] = level;
584: #endif
585:
586: if (name != NULL)
587: evcount_attach(&ih->ih_count, name, (void *)&ih->ih_irq,
588: &evcount_intr);
589:
590: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
591: sa11x0_update_intr_masks();
592: #else
593: sa11x0_update_intr_masks(irqno, level);
594: #endif
595:
596: restore_interrupts(psw);
597:
598: return (ih);
599: }
600:
601: void
602: sa11x0_intr_disestablish(void *cookie)
603: {
604:
605: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
606: int psw;
607: struct intrhand *ih = cookie;
608: int irqno = ih->ih_irq;
609:
610: psw = disable_interrupts(I32_bit);
611: TAILQ_REMOVE(&handler[irqno].list, ih, ih_list);
612:
613: FREE(ih, M_DEVBUF);
614:
615: sa11x0_update_intr_masks();
616:
617: restore_interrupts(psw);
618: #else
619: struct intrhandler *lhandler = cookie;
620: int irqno;
621: int psw;
622: struct intrhandler *ih;
623: irqno = lhandler - handler;
624:
625: if (irqno < 1 || irqno >= ICU_LEN)
626: panic("intr_disestablish: bogus irq number %d", irqno);
627:
628: psw = disable_interrupts(I32_bit);
629:
630: ih = &handler[irqno];
631: if (ih->name != NULL)
632: evcount_detach(&ih->ih_count);
633:
634: ih->arg = (void *) irqno;
635: ih->func = sa11x0_stray_interrupt;
636: ih->name = "stray";
637: extirq_level[irqno] = IPL_SERIAL;
638: sa11x0_update_intr_masks(irqno, IPL_SERIAL);
639:
640: restore_interrupts(psw);
641: #endif
642: }
643:
644: /*
645: * Glue for drivers of sa11x0 compatible integrated logic.
646: */
647:
648: void *
649: sa11x0_intr_establish(sa11x0_chipset_tag_t ic, int irq, int type, int level,
650: int (*ih_fun)(void *), void *ih_arg, char *name)
651: {
652: /* XXX */
653: return _sa11x0_intr_establish(irq, level, ih_fun, ih_arg, name);
654: }
655:
656: void
657: sa11x0_setipl(int new)
658: {
659: u_int32_t intr_mask;
660:
661: intr_mask = sa11x0_imask[new];
662: current_spl_level = new;
663: write_icu( SAIPIC_MR, intr_mask );
664: }
665:
666:
667: void
668: sa11x0_splx(int new)
669: {
670: int psw;
671:
672: psw = disable_interrupts(I32_bit);
673: sa11x0_setipl(new);
674: restore_interrupts(psw);
675:
676: /* If there are pending software interrupts, process them. */
677: if (softint_pending & sa11x0_imask[current_spl_level])
678: sa11x0_do_pending();
679: }
680:
681:
682: int
683: sa11x0_splraise(int ipl)
684: {
685: int old, psw;
686:
687: old = current_spl_level;
688: if( ipl > current_spl_level ){
689: psw = disable_interrupts(I32_bit);
690: sa11x0_setipl(ipl);
691: restore_interrupts(psw);
692: }
693:
694: return (old);
695: }
696:
697: int
698: sa11x0_spllower(int ipl)
699: {
700: int old = current_spl_level;
701: int psw = disable_interrupts(I32_bit);
702: sa11x0_splx(ipl);
703: restore_interrupts(psw);
704: return(old);
705: }
706:
707: void
708: sa11x0_setsoftintr(int si)
709: {
710: #if 0
711: atomic_set_bit( (u_int *)&softint_pending, SI_TO_IRQBIT(si) );
712: #else
713: softint_pending |= SI_TO_IRQBIT(si);
714: #endif
715:
716: /* Process unmasked pending soft interrupts. */
717: if ( softint_pending & sa11x0_imask[current_spl_level] )
718: sa11x0_do_pending();
719: }
720:
721: const char *
722: sa11x0_intr_string(void *cookie)
723: {
724: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
725: struct intrhand *ih = cookie;
726: #else
727: struct intrhandler *lhandler = cookie;
728: #endif
729: static char irqstr[32];
730:
731: if (ih == NULL)
732: snprintf(irqstr, sizeof irqstr, "couldn't establish interrupt");
733: else
734: snprintf(irqstr, sizeof irqstr, "irq %ld", ih->ih_irq);
735:
736: return irqstr;
737: }
738:
739: #ifdef DIAGNOSTIC
740: void
741: sa11x0_splassert_check(int wantipl, const char *func)
742: {
743: int oldipl = current_spl_level, psw;
744:
745: if (oldipl < wantipl) {
746: splassert_fail(wantipl, oldipl, func);
747: /*
748: * If the splassert_ctl is set to not panic, raise the ipl
749: * in a feeble attempt to reduce damage.
750: */
751: psw = disable_interrupts(I32_bit);
752: sa11x0_setipl(wantipl);
753: restore_interrupts(psw);
754: }
755: }
756: #endif
CVSweb