Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/sommerfeld_i386mp_1]: src/sys/arch/i386/isa Use level-based rather than ...



details:   https://anonhg.NetBSD.org/src/rev/49b930e37102
branches:  sommerfeld_i386mp_1
changeset: 482178:49b930e37102
user:      sommerfeld <sommerfeld%NetBSD.org@localhost>
date:      Sun Feb 20 18:26:41 2000 +0000

description:
Use level-based rather than mask-based interrupt masking.
Compute interrupt masks differently.

In isa_intr_establish, use the apic instead if we have an interrupt
mapping.

diffstat:

 sys/arch/i386/isa/isa_machdep.c |  103 +++++++++++++++++++++++++++++++--------
 1 files changed, 82 insertions(+), 21 deletions(-)

diffs (191 lines):

diff -r 49081232b9c1 -r 49b930e37102 sys/arch/i386/isa/isa_machdep.c
--- a/sys/arch/i386/isa/isa_machdep.c   Sun Feb 20 18:21:27 2000 +0000
+++ b/sys/arch/i386/isa/isa_machdep.c   Sun Feb 20 18:26:41 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: isa_machdep.c,v 1.45 1999/11/12 18:39:38 drochner Exp $        */
+/*     $NetBSD: isa_machdep.c,v 1.45.2.1 2000/02/20 18:26:41 sommerfeld Exp $  */
 
 #define ISA_DMA_STATS
 
@@ -98,6 +98,14 @@
 
 #include <vm/vm.h>
 
+#include "ioapic.h"
+
+#if NIOAPIC > 0
+#include <machine/i82093var.h>
+#include <machine/mpbiosvar.h>
+#endif
+
+
 /*
  * ISA can only DMA to 0-16M.
  */
@@ -232,6 +240,7 @@
 }
 
 int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
+int ilevel[ICU_LEN];
 struct intrhand *intrhand[ICU_LEN];
 
 /*
@@ -251,7 +260,7 @@
        for (irq = 0; irq < ICU_LEN; irq++) {
                int levels = 0;
                for (q = intrhand[irq]; q; q = q->ih_next)
-                       levels |= 1 << q->ih_level;
+                       levels |= 1 << (q->ih_level>>CPSHIFT);
                intrlevel[irq] = levels;
                if (levels)
                        unusedirqs &= ~(1 << irq);
@@ -263,64 +272,92 @@
                for (irq = 0; irq < ICU_LEN; irq++)
                        if (intrlevel[irq] & (1 << level))
                                irqs |= 1 << irq;
-               imask[level] = irqs | unusedirqs;
+               imasks[level] = irqs | unusedirqs;
        }
 
        /*
         * Initialize soft interrupt masks to block themselves.
         */
-       imask[IPL_SOFTCLOCK] = 1 << SIR_CLOCK;
-       imask[IPL_SOFTNET] = 1 << SIR_NET;
-       imask[IPL_SOFTSERIAL] = 1 << SIR_SERIAL;
-
+#if 0
+       IMASK(IPL_AST) |= 1 << SIR_AST;
+#endif
+       IMASK(IPL_SOFTCLOCK) |= 1 << SIR_CLOCK;
+       IMASK(IPL_SOFTNET) |= 1 << SIR_NET;
+       IMASK(IPL_SOFTSERIAL) |= 1 << SIR_SERIAL;
+       
+#if 0
        /*
         * IPL_NONE is used for hardware interrupts that are never blocked,
         * and do not block anything else.
         */
-       imask[IPL_NONE] = 0;
+       IMASK(IPL_NONE) = 0;
+#endif
 
        /*
         * Enforce a hierarchy that gives slow devices a better chance at not
         * dropping data.
         */
-       imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
-       imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
-       imask[IPL_BIO] |= imask[IPL_SOFTNET];
-       imask[IPL_NET] |= imask[IPL_BIO];
-       imask[IPL_SOFTSERIAL] |= imask[IPL_NET];
-       imask[IPL_TTY] |= imask[IPL_SOFTSERIAL];
+       for (level = 0; level<(NIPL-1); level++)
+               imasks[level+1] |= imasks[level];
+       
+#if 0
+       IMASK(IPL_SOFTCLOCK) |= IMASK(IPL_NONE);
+       IMASK(IPL_SOFTNET) |= IMASK(IPL_SOFTCLOCK);
+       IMASK(IPL_BIO) |= IMASK(IPL_SOFTNET);
+       IMASK(IPL_NET) |= IMASK(IPL_BIO);
+       IMASK(IPL_SOFTSERIAL) |= IMASK(IPL_NET);
+       IMASK(IPL_TTY) |= IMASK(IPL_SOFTSERIAL);
 
        /*
         * There are tty, network and disk drivers that use free() at interrupt
         * time, so imp > (tty | net | bio).
         */
-       imask[IPL_IMP] |= imask[IPL_TTY];
+       IMASK(IPL_IMP) |= IMASK(IPL_TTY);
 
-       imask[IPL_AUDIO] |= imask[IPL_IMP];
+       IMASK(IPL_AUDIO) |= IMASK(IPL_IMP);
 
        /*
         * Since run queues may be manipulated by both the statclock and tty,
         * network, and disk drivers, clock > imp.
         */
-       imask[IPL_CLOCK] |= imask[IPL_AUDIO];
+       IMASK(IPL_CLOCK) |= IMASK(IPL_AUDIO);
 
        /*
         * IPL_HIGH must block everything that can manipulate a run queue.
         */
-       imask[IPL_HIGH] |= imask[IPL_CLOCK];
+       IMASK(IPL_HIGH) |= IMASK(IPL_CLOCK);
 
        /*
         * We need serial drivers to run at the absolute highest priority to
         * avoid overruns, so serial > high.
         */
-       imask[IPL_SERIAL] |= imask[IPL_HIGH];
+       IMASK(IPL_SERIAL) |= IMASK(IPL_HIGH);
+#endif
 
        /* And eventually calculate the complete masks. */
        for (irq = 0; irq < ICU_LEN; irq++) {
                int irqs = 1 << irq;
-               for (q = intrhand[irq]; q; q = q->ih_next)
-                       irqs |= imask[q->ih_level];
+               int level = 0;
+
+               if (intrhand[irq] == NULL) {
+                       level = IPL_HIGH;
+                       irqs = IMASK(IPL_HIGH);
+               } else {
+                       for (q = intrhand[irq]; q; q = q->ih_next) {
+                               irqs |= IMASK(q->ih_level);
+                               if (q->ih_level > level)
+                                       level = q->ih_level;
+                       }
+               }
+               if (irqs != IMASK(level))
+                       panic("irq %d level %x mask mismatch: %x vs %x", irq, level, irqs, IMASK(level));
+               
+               ilevel[irq] = level;
                intrmask[irq] = irqs;
+#if 0
+               printf("irq %d: level %x, mask 0x%x (%x)\n",
+                   irq, ilevel[irq], intrmask[irq], IMASK(ilevel[irq]));
+#endif
        }
 
        /* Lastly, determine which IRQs are actually in use. */
@@ -333,6 +370,8 @@
                        irqs |= 1 << IRQ_SLAVE;
                imen = ~irqs;
        }
+       for (irq = 0; irq < ICU_LEN; irq++)
+               iunmask[irq] = ~imasks[irq];
 }
 
 int
@@ -433,6 +472,28 @@
 {
        struct intrhand **p, *q, *ih;
        static struct intrhand fakehand = {fakeintr};
+#if NIOAPIC > 0
+       struct mp_intr_map *mip;
+       
+       if (mp_busses != NULL) {
+               int mpspec_pin = irq;
+               int bus = mp_isa_bus;
+               int airq;
+               
+               for (mip = mp_busses[bus].mb_intrs; mip != NULL; mip=mip->next) {
+                       if (mip->bus_pin == mpspec_pin) {
+                               airq = mip->ioapic_ih | irq;
+                               break;
+                       }
+               }
+               if (mip == NULL)
+                       printf("isa_intr_establish: no MP mapping found\n");
+               else {
+                       return apic_intr_establish (airq, type, level, ih_fun, ih_arg);
+               }
+       }
+#endif
+
 
        /* no point in sleeping unless someone can free memory. */
        ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);



Home | Main Index | Thread Index | Old Index