diff options
author | Dale S. Rahn <rahnds@cvs.openbsd.org> | 1998-10-09 02:19:13 +0000 |
---|---|---|
committer | Dale S. Rahn <rahnds@cvs.openbsd.org> | 1998-10-09 02:19:13 +0000 |
commit | b80df668c887ff7e0ba795d4fbba3d261b21ca27 (patch) | |
tree | 18804f57d01af64cff49518b6a23524c6a0ec080 /sys/arch/powerpc/isa/isabus.c | |
parent | 1df6993601aef9d664846efd80e497cc3afacdd9 (diff) |
Support nested interrupts for the powerpc interrupt controller.
Diffstat (limited to 'sys/arch/powerpc/isa/isabus.c')
-rw-r--r-- | sys/arch/powerpc/isa/isabus.c | 129 |
1 files changed, 96 insertions, 33 deletions
diff --git a/sys/arch/powerpc/isa/isabus.c b/sys/arch/powerpc/isa/isabus.c index 3b3bb7afd3c..721b12e13ad 100644 --- a/sys/arch/powerpc/isa/isabus.c +++ b/sys/arch/powerpc/isa/isabus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isabus.c,v 1.8 1998/08/25 14:28:58 pefo Exp $ */ +/* $OpenBSD: isabus.c,v 1.9 1998/10/09 02:19:12 rahnds Exp $ */ /*- * Copyright (c) 1995 Per Fogelstrom @@ -241,6 +241,11 @@ isabrprint(aux, pnp) int imen = 0xffffffff; int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN]; +struct { + int irq; + int o_imen; +} pending_intr_stack[ICU_LEN]; +int pending_intr_index = 0; struct intrhand *intrhand[ICU_LEN]; int fakeintr(void *a) {return 0;} @@ -431,32 +436,62 @@ isa_do_pending_int() int pcpl; int hwpend; int emsr, dmsr; + int oldsint; static int processing; - if(processing) + ppc_intr_disable(); + if(processing) { + ppc_intr_enable(); return; + } processing = 1; - __asm__ volatile("mfmsr %0" : "=r"(emsr)); - dmsr = emsr & ~PSL_EE; - __asm__ volatile("mtmsr %0" :: "r"(dmsr)); pcpl = splhigh(); /* Turn off all */ - hwpend = ipending & ~pcpl; /* Do now unmasked pendings */ - hwpend &= ((1L << ICU_LEN) - 1); - ipending &= ~hwpend; - imen &= ~hwpend; - while(hwpend) { + + + while(ipending & 0xffff) { + pending_intr_index--; + vector = pending_intr_stack[pending_intr_index].irq; + if (pcpl & (1L << vector)) { + /* this, and presumably all lower pri, are blocked */ + break; + } + cpl = pcpl | imen | intrmask[vector]; +#if 1 + ppc_intr_enable(); +#endif evirq[ICU_LEN].ev_count++; - vector = ffs(hwpend) - 1; - hwpend &= ~(1L << vector); - ih = intrhand[vector]; evirq[ICU_LEN+vector].ev_count++; + ih = intrhand[vector]; while(ih) { (*ih->ih_fun)(ih->ih_arg); ih = ih->ih_next; } +#if 1 + ppc_intr_disable(); +#endif + imen = pending_intr_stack[pending_intr_index].o_imen; + ipending &= ~(1 << vector); + + /* interrupt taken care of, reenable */ + /* imen does not deal with spurious interrupts in any manner */ + isa_outb(IO_ICU1 + 1, imen); + isa_outb(IO_ICU2 + 1, imen >> 8); +#ifdef NO_SPECIAL_MASK_MODE + isa_outb(IO_ICU1, 0x20); + isa_outb(IO_ICU2, 0x20); +#else + if(vector > 7) { + isa_outb(IO_ICU2, 0x60 | vector & 0x07); + } + isa_outb(IO_ICU1, 0x60 | (vector > 7 ? 2 : vector)); +#endif + } +#if 1 + ppc_intr_enable(); +#endif if((ipending & SINT_CLOCK) & ~pcpl) { ipending &= ~SINT_CLOCK; softclock(); @@ -468,13 +503,15 @@ static int processing; ipending &= ~SINT_NET; softnet(pisr); } +#if 1 + ppc_intr_disable(); +#endif cpl = pcpl; /* Don't use splx... we are here already! */ - isa_outb(IO_ICU1 + 1, imen); - isa_outb(IO_ICU2 + 1, imen >> 8); - - __asm__ volatile("mtmsr %0" :: "r"(emsr)); processing = 0; +#if 1 + ppc_intr_enable(); +#endif } /* @@ -504,17 +541,40 @@ isabr_iointr(mask, cf) o_imen = imen; r_imen = 1 << isa_vector; - imen |= r_imen; + imen |= r_imen | intrmask[isa_vector]; isa_outb(IO_ICU1 + 1, imen); isa_outb(IO_ICU2 + 1, imen >> 8); if((pcpl & r_imen) != 0) { - ipending |= r_imen; /* Masked! Mark this as pending */ + if ((ipending & (1 << isa_vector)) == 0) { + ipending |= (1 << isa_vector); + pending_intr_stack[pending_intr_index].irq = isa_vector; + pending_intr_stack[pending_intr_index].o_imen = o_imen; + pending_intr_index++; + + /* + evirq[isa_vector].ev_count++; + */ + } else { + evirq[7].ev_count++; + } + +#if 1 + ppc_intr_enable(); +#endif + } else { evirq[isa_vector].ev_count++; - } - else { + +#if 1 + /* dont mask other interrupts and yet, + * we dont want to run end of interrupt processing + * either + */ + cpl = pcpl | r_imen; + ppc_intr_enable(); +#endif + ih = intrhand[isa_vector]; - evirq[isa_vector].ev_count++; if(ih == NULL) printf("isa: spurious interrupt %d\n", isa_vector); @@ -523,21 +583,25 @@ isabr_iointr(mask, cf) ih = ih->ih_next; } imen = o_imen; - } - isa_outb(IO_ICU1 + 1, imen); - isa_outb(IO_ICU2 + 1, imen >> 8); + /* interrupt taken care of, reenable */ + isa_outb(IO_ICU1 + 1, imen); + isa_outb(IO_ICU2 + 1, imen >> 8); #ifdef NO_SPECIAL_MASK_MODE - isa_outb(IO_ICU1, 0x20); - isa_outb(IO_ICU2, 0x20); + isa_outb(IO_ICU1, 0x20); + isa_outb(IO_ICU2, 0x20); #else - if(isa_vector > 7) { - isa_outb(IO_ICU2, 0x60 | isa_vector & 0x07); - } - isa_outb(IO_ICU1, 0x60 | (isa_vector > 7 ? 2 : isa_vector)); + if(isa_vector > 7) { + isa_outb(IO_ICU2, 0x60 | isa_vector & 0x07); + } + isa_outb(IO_ICU1, 0x60 | (isa_vector > 7 ? 2 : isa_vector)); #endif - splx(pcpl); /* Process pendings. */ + } + splx(pcpl); /* allow other interrupts */ +#if 1 + ppc_intr_disable(); +#endif } @@ -586,4 +650,3 @@ isabr_initicu() #endif isa_outb(IO_ICU2, 0x0a); /* Read IRR by default */ } - |