diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-12-04 00:00:37 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-12-04 00:00:37 +0000 |
commit | 9bf62191c2a2e2d5aeb7537858d4a8164ea9ebcc (patch) | |
tree | 2bdc2c594e23844416a8dc77a6c5a4b0f5517b74 /sys/arch/i386/isa | |
parent | 1354afe4470c3aeace3d9c3ea0857e8ba5499de4 (diff) |
New try at a level based irq system.
Diffstat (limited to 'sys/arch/i386/isa')
-rw-r--r-- | sys/arch/i386/isa/icu.h | 5 | ||||
-rw-r--r-- | sys/arch/i386/isa/icu.s | 20 | ||||
-rw-r--r-- | sys/arch/i386/isa/isa_machdep.c | 57 | ||||
-rw-r--r-- | sys/arch/i386/isa/npx.c | 6 | ||||
-rw-r--r-- | sys/arch/i386/isa/vector.s | 14 |
5 files changed, 59 insertions, 43 deletions
diff --git a/sys/arch/i386/isa/icu.h b/sys/arch/i386/isa/icu.h index 231a4404cbc..5279822d3cd 100644 --- a/sys/arch/i386/isa/icu.h +++ b/sys/arch/i386/isa/icu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: icu.h,v 1.6 2001/11/18 20:46:49 aaron Exp $ */ +/* $OpenBSD: icu.h,v 1.7 2001/12/04 00:00:36 niklas Exp $ */ /* $NetBSD: icu.h,v 1.19 1996/02/01 22:31:21 mycroft Exp $ */ /*- @@ -65,6 +65,9 @@ extern unsigned imen; /* interrupt mask enable */ /* * Interrupt Control offset into Interrupt descriptor table (IDT) + * XXX ICU_OFFSET is actually a property of our architecture not of the ICU + * XXX and therefore ought to use the architecture manifest constant IDTVECOFF + * XXX for its definition instead. */ #define ICU_OFFSET 32 /* 0-31 are processor exceptions */ #define ICU_LEN 16 /* 32-47 are ISA interrupts */ diff --git a/sys/arch/i386/isa/icu.s b/sys/arch/i386/isa/icu.s index 8be1d64520b..57b11456f29 100644 --- a/sys/arch/i386/isa/icu.s +++ b/sys/arch/i386/isa/icu.s @@ -1,4 +1,4 @@ -/* $OpenBSD: icu.s,v 1.17 2001/11/18 20:46:49 aaron Exp $ */ +/* $OpenBSD: icu.s,v 1.18 2001/12/04 00:00:36 niklas Exp $ */ /* $NetBSD: icu.s,v 1.45 1996/01/07 03:59:34 mycroft Exp $ */ /*- @@ -45,7 +45,7 @@ _C_LABEL(imen): ALIGN_TEXT _C_LABEL(splhigh): - movl $-1,%eax + movl $IPL_HIGH,%eax xchgl %eax,_C_LABEL(cpl) ret @@ -72,8 +72,9 @@ IDTVEC(spllower) pushl %edi movl _C_LABEL(cpl),%ebx # save priority movl $1f,%esi # address to resume loop at -1: movl %ebx,%eax - notl %eax +1: movl %ebx,%eax # get cpl + shrl $4,%eax # find its mask. + movl _C_LABEL(iunmask)(,%eax,4),%eax andl _C_LABEL(ipending),%eax jz 2f bsfl %eax,%eax @@ -97,8 +98,9 @@ IDTVEC(doreti) popl %ebx # get previous priority movl %ebx,_C_LABEL(cpl) movl $1f,%esi # address to resume loop at -1: movl %ebx,%eax - notl %eax +1: movl %ebx,%eax # get cpl + shrl $4,%eax # find its mask + movl _C_LABEL(iunmask)(,%eax,4),%eax andl _C_LABEL(ipending),%eax jz 2f bsfl %eax,%eax # slow, but not worth optimizing @@ -132,7 +134,7 @@ IDTVEC(doreti) IDTVEC(softtty) #if NPCCOM > 0 - leal SIR_TTYMASK(%ebx),%eax + movl $IPL_SOFTTTY,%eax movl %eax,_C_LABEL(cpl) call _C_LABEL(comsoft) movl %ebx,_C_LABEL(cpl) @@ -147,7 +149,7 @@ IDTVEC(softtty) 1: IDTVEC(softnet) - leal SIR_NETMASK(%ebx),%eax + movl $IPL_SOFTNET,%eax movl %eax,_C_LABEL(cpl) xorl %edi,%edi xchgl _C_LABEL(netisr),%edi @@ -157,7 +159,7 @@ IDTVEC(softnet) #undef DONETISR IDTVEC(softclock) - leal SIR_CLOCKMASK(%ebx),%eax + movl $IPL_SOFTCLOCK,%eax movl %eax,_C_LABEL(cpl) call _C_LABEL(softclock) movl %ebx,_C_LABEL(cpl) diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c index 19d352fe8ad..2ca2f0173af 100644 --- a/sys/arch/i386/isa/isa_machdep.c +++ b/sys/arch/i386/isa/isa_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isa_machdep.c,v 1.42 2001/11/18 20:46:49 aaron Exp $ */ +/* $OpenBSD: isa_machdep.c,v 1.43 2001/12/04 00:00:36 niklas Exp $ */ /* $NetBSD: isa_machdep.c,v 1.22 1997/06/12 23:57:32 thorpej Exp $ */ #define ISA_DMA_STATS @@ -129,6 +129,7 @@ #define _I386_BUS_DMA_PRIVATE #include <machine/bus.h> +#include <machine/intr.h> #include <machine/pio.h> #include <machine/cpufunc.h> @@ -221,8 +222,8 @@ isa_defaultirq() /* icu vectors */ for (i = 0; i < ICU_LEN; i++) - setgate(&idt[ICU_OFFSET + i], IDTVEC(intr)[i], 0, SDT_SYS386IGT, - SEL_KPL, GICODE_SEL); + setgate(&idt[ICU_OFFSET + i], IDTVEC(intr)[i], 0, + SDT_SYS386IGT, SEL_KPL, GICODE_SEL); /* initialize 8259's */ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ @@ -260,13 +261,13 @@ isa_defaultirq() int isa_nmi() { - /* This is historic garbage; these ports are not readable */ log(LOG_CRIT, "No-maskable interrupt, may be parity error\n"); return(0); } -u_long intrstray[ICU_LEN] = {0}; +u_long intrstray[ICU_LEN]; + /* * Caught a stray interrupt, notify */ @@ -287,6 +288,7 @@ isa_strayintr(irq) int fastvec; int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN]; +int iminlevel[ICU_LEN], imaxlevel[ICU_LEN]; struct intrhand *intrhand[ICU_LEN]; /* @@ -305,45 +307,49 @@ intr_calculatemasks() for (irq = 0; irq < ICU_LEN; irq++) { register int levels = 0; for (q = intrhand[irq]; q; q = q->ih_next) - levels |= 1 << q->ih_level; + levels |= 1 << IPL(q->ih_level); intrlevel[irq] = levels; } /* Then figure out which IRQs use each level. */ - for (level = 0; level < 5; level++) { + for (level = 0; level < NIPL; level++) { register int irqs = 0; for (irq = 0; irq < ICU_LEN; irq++) if (intrlevel[irq] & (1 << level)) irqs |= 1 << irq; - imask[level] = irqs | SIR_ALLMASK; + imask[level] = irqs; } /* - * There are tty, network and disk drivers that use free() at interrupt - * time, so imp > (tty | net | bio). + * Initialize soft interrupt masks to block themselves. */ - imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO]; - imask[IPL_AUDIO] |= imask[IPL_IMP]; + IMASK(IPL_SOFTCLOCK) |= 1 << SIR_CLOCK; + IMASK(IPL_SOFTNET) |= 1 << SIR_NET; + IMASK(IPL_SOFTTTY) |= 1 << SIR_TTY; /* * Enforce a hierarchy that gives slow devices a better chance at not * dropping data. */ - imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO]; - imask[IPL_NET] |= imask[IPL_BIO]; - - /* - * These are pseudo-levels. - */ - imask[IPL_NONE] = 0x00000000; - imask[IPL_HIGH] = 0xffffffff; + for (level = 0; level < NIPL - 1; level++) + imask[level + 1] |= imask[level]; /* And eventually calculate the complete masks. */ for (irq = 0; irq < ICU_LEN; irq++) { register int irqs = 1 << irq; - for (q = intrhand[irq]; q; q = q->ih_next) - irqs |= imask[q->ih_level]; - intrmask[irq] = irqs | SIR_ALLMASK; + int minlevel = IPL_NONE; + int maxlevel = IPL_NONE; + + for (q = intrhand[irq]; q; q = q->ih_next) { + irqs |= IMASK(q->ih_level); + if (minlevel == IPL_NONE || q->ih_level < minlevel) + minlevel = q->ih_level; + if (q->ih_level > maxlevel) + maxlevel = q->ih_level; + } + intrmask[irq] = irqs; + iminlevel[irq] = minlevel; + imaxlevel[irq] = maxlevel; } /* Lastly, determine which IRQs are actually in use. */ @@ -357,13 +363,16 @@ intr_calculatemasks() imen = ~irqs; SET_ICUS(); } + + /* For speed of splx, provide the inverse of the interrupt masks. */ + for (irq = 0; irq < ICU_LEN; irq++) + iunmask[irq] = ~imask[irq]; } int fakeintr(arg) void *arg; { - return 0; } diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c index 04fb03b0533..b6fa7145ff1 100644 --- a/sys/arch/i386/isa/npx.c +++ b/sys/arch/i386/isa/npx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npx.c,v 1.22 2001/11/18 20:46:49 aaron Exp $ */ +/* $OpenBSD: npx.c,v 1.23 2001/12/04 00:00:36 niklas Exp $ */ /* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */ #if 0 @@ -537,7 +537,7 @@ npxdna(p) } #ifdef DIAGNOSTIC - if (cpl != 0 || npx_nointr != 0) + if (cpl != IPL_NONE || npx_nointr != 0) panic("npxdna: masked"); #endif @@ -612,7 +612,7 @@ npxsave() { #ifdef DIAGNOSTIC - if (cpl != 0 || npx_nointr != 0) + if (cpl != IPL_NONE || npx_nointr != 0) panic("npxsave: masked"); #endif iprintf(("Fork")); diff --git a/sys/arch/i386/isa/vector.s b/sys/arch/i386/isa/vector.s index 664477530e9..b445c720ef1 100644 --- a/sys/arch/i386/isa/vector.s +++ b/sys/arch/i386/isa/vector.s @@ -1,4 +1,4 @@ -/* $OpenBSD: vector.s,v 1.13 2001/11/18 20:46:49 aaron Exp $ */ +/* $OpenBSD: vector.s,v 1.14 2001/12/04 00:00:36 niklas Exp $ */ /* $NetBSD: vector.s,v 1.32 1996/01/07 21:29:47 mycroft Exp $ */ /* @@ -218,13 +218,15 @@ _Xintr/**/irq_num/**/: ;\ MASK(irq_num, icu) /* mask it in hardware */ ;\ ack(irq_num) /* and allow other intrs */ ;\ incl MY_COUNT+V_INTR /* statistical info */ ;\ - testb $IRQ_BIT(irq_num),_cpl + IRQ_BYTE(irq_num) ;\ - jnz _Xhold/**/irq_num /* currently masked; hold it */ ;\ + movl _C_LABEL(iminlevel) + (irq_num) * 4, %eax ;\ + movzbl _C_LABEL(cpl),%ebx ;\ + cmpl %eax,%ebx ;\ + jae _C_LABEL(Xhold/**/irq_num)/* currently masked; hold it */;\ _Xresume/**/irq_num/**/: ;\ - movl _cpl,%eax /* cpl to restore on exit */ ;\ + movzbl _C_LABEL(cpl),%eax /* cpl to restore on exit */ ;\ pushl %eax ;\ - orl _intrmask + (irq_num) * 4,%eax ;\ - movl %eax,_cpl /* add in this intr's mask */ ;\ + movl _C_LABEL(imaxlevel) + (irq_num) * 4,%eax ;\ + movl %eax,_C_LABEL(cpl) /* block enough for this irq */ ;\ sti /* safe to take intrs now */ ;\ movl _intrhand + (irq_num) * 4,%ebx /* head of chain */ ;\ testl %ebx,%ebx ;\ |