summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1997-06-02 08:19:06 +0000
committerdfr <dfr@FreeBSD.org>1997-06-02 08:19:06 +0000
commit6ba14cc686e7f472a6937088de33f356556bf759 (patch)
treec7c4bcee2063b32a59ec0918ff2f82386e367571
parent33ddef35e6191fb2cd19ec096f2d855851331a45 (diff)
downloadFreeBSD-src-6ba14cc686e7f472a6937088de33f356556bf759.zip
FreeBSD-src-6ba14cc686e7f472a6937088de33f356556bf759.tar.gz
Move interrupt handling code from isa.c to a new file. This should make
isa.c (slightly) more portable and will make my life developing the really portable version much easier. Reviewed by: peter, fsmp
-rw-r--r--sys/amd64/amd64/fpu.c3
-rw-r--r--sys/amd64/amd64/identcpu.c4
-rw-r--r--sys/amd64/amd64/machdep.c3
-rw-r--r--sys/amd64/amd64/mem.c3
-rw-r--r--sys/amd64/amd64/trap.c4
-rw-r--r--sys/amd64/amd64/tsc.c4
-rw-r--r--sys/amd64/isa/clock.c4
-rw-r--r--sys/amd64/isa/intr_machdep.c418
-rw-r--r--sys/amd64/isa/intr_machdep.h105
-rw-r--r--sys/amd64/isa/isa.c358
-rw-r--r--sys/amd64/isa/nmi.c418
-rw-r--r--sys/amd64/isa/npx.c3
-rw-r--r--sys/conf/files.i3863
-rw-r--r--sys/i386/conf/files.i3863
-rw-r--r--sys/i386/i386/identcpu.c4
-rw-r--r--sys/i386/i386/machdep.c3
-rw-r--r--sys/i386/i386/mem.c3
-rw-r--r--sys/i386/i386/trap.c4
-rw-r--r--sys/i386/i386/tsc.c4
-rw-r--r--sys/i386/isa/clock.c4
-rw-r--r--sys/i386/isa/intr_machdep.c418
-rw-r--r--sys/i386/isa/intr_machdep.h105
-rw-r--r--sys/i386/isa/isa.c358
-rw-r--r--sys/i386/isa/isa_device.h55
-rw-r--r--sys/i386/isa/nmi.c418
-rw-r--r--sys/i386/isa/npx.c3
-rw-r--r--sys/isa/atrtc.c4
-rw-r--r--sys/kern/kern_intr.c6
-rw-r--r--sys/kern/subr_trap.c4
-rw-r--r--sys/net/ppp_tty.c4
30 files changed, 1930 insertions, 800 deletions
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index d364f4f..aca74fa 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)npx.c 7.2 (Berkeley) 5/12/91
- * $Id: npx.c,v 1.43 1997/05/07 19:58:13 peter Exp $
+ * $Id: npx.c,v 1.44 1997/05/31 09:27:31 peter Exp $
*/
#include "npx.h"
@@ -69,6 +69,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/isa.h>
/*
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c
index 30b17d8..474a1a9 100644
--- a/sys/amd64/amd64/identcpu.c
+++ b/sys/amd64/amd64/identcpu.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
- * $Id: identcpu.c,v 1.21 1997/05/23 06:22:47 charnier Exp $
+ * $Id: identcpu.c,v 1.22 1997/05/31 08:45:23 kato Exp $
*/
#include "opt_cpu.h"
@@ -56,7 +56,7 @@
#include <machine/sysarch.h>
#include <machine/md_var.h>
-#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
/* XXX - should be in header file */
void i486_bzero __P((void *buf, size_t len));
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 8a9a8d3..186541c 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.244 1997/05/26 09:23:29 fsmp Exp $
+ * $Id: machdep.c,v 1.245 1997/05/26 18:40:45 fsmp Exp $
*/
#include "npx.h"
@@ -117,6 +117,7 @@
#endif
#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/rtc.h>
#include <machine/random.h>
diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c
index ae8e95c..c6eb954 100644
--- a/sys/amd64/amd64/mem.c
+++ b/sys/amd64/amd64/mem.c
@@ -38,7 +38,7 @@
*
* from: Utah $Hdr: mem.c 1.13 89/10/08$
* from: @(#)mem.c 7.2 (Berkeley) 5/9/91
- * $Id: mem.c,v 1.43 1997/05/07 20:02:37 peter Exp $
+ * $Id: mem.c,v 1.44 1997/05/07 20:32:41 peter Exp $
*/
/*
@@ -65,6 +65,7 @@
#ifdef PERFMON
#include <machine/perfmon.h>
#endif
+#include <i386/isa/intr_machdep.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index d508788..f73c4f2 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.96 1997/05/29 05:04:30 peter Exp $
+ * $Id: trap.c,v 1.97 1997/05/31 09:27:29 peter Exp $
*/
/*
@@ -76,7 +76,7 @@
#include <machine/psl.h>
#include <machine/reg.h>
#include <machine/trap.h>
-#include <machine/../isa/isa_device.h>
+#include <machine/../isa/intr_machdep.h>
#include <machine/smp.h>
#ifdef POWERFAIL_NMI
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c
index 13e66f5..4ae5c36 100644
--- a/sys/amd64/amd64/tsc.c
+++ b/sys/amd64/amd64/tsc.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.85 1997/05/29 05:00:35 peter Exp $
+ * $Id: clock.c,v 1.86 1997/05/31 09:27:30 peter Exp $
*/
/*
@@ -67,7 +67,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
-#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index 13e66f5..4ae5c36 100644
--- a/sys/amd64/isa/clock.c
+++ b/sys/amd64/isa/clock.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.85 1997/05/29 05:00:35 peter Exp $
+ * $Id: clock.c,v 1.86 1997/05/31 09:27:30 peter Exp $
*/
/*
@@ -67,7 +67,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
-#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c
new file mode 100644
index 0000000..40acb8e
--- /dev/null
+++ b/sys/amd64/isa/intr_machdep.c
@@ -0,0 +1,418 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
+ * $Id: isa.c,v 1.85 1997/05/26 14:42:24 se Exp $
+ */
+
+#include "opt_auto_eoi.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <machine/ipl.h>
+#include <machine/md_var.h>
+#include <machine/segments.h>
+#if defined(APIC_IO)
+#include <machine/smp.h>
+#include <machine/apic.h>
+#endif /* APIC_IO */
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/isa.h>
+#include <i386/isa/icu.h>
+#include <i386/isa/ic/i8237.h>
+#include "vector.h"
+
+#include <i386/isa/intr_machdep.h>
+#include <sys/interrupt.h>
+
+#ifdef APIC_IO
+/*
+ * This is to accommodate "mixed-mode" programming for
+ * motherboards that don't connect the 8254 to the IO APIC.
+ */
+#define AUTO_EOI_1
+#endif
+
+u_long *intr_countp[ICU_LEN];
+inthand2_t *intr_handler[ICU_LEN];
+u_int intr_mask[ICU_LEN];
+u_int* intr_mptr[ICU_LEN];
+int intr_unit[ICU_LEN];
+
+static inthand_t *fastintr[ICU_LEN] = {
+ &IDTVEC(fastintr0), &IDTVEC(fastintr1),
+ &IDTVEC(fastintr2), &IDTVEC(fastintr3),
+ &IDTVEC(fastintr4), &IDTVEC(fastintr5),
+ &IDTVEC(fastintr6), &IDTVEC(fastintr7),
+ &IDTVEC(fastintr8), &IDTVEC(fastintr9),
+ &IDTVEC(fastintr10), &IDTVEC(fastintr11),
+ &IDTVEC(fastintr12), &IDTVEC(fastintr13),
+ &IDTVEC(fastintr14), &IDTVEC(fastintr15)
+#if defined(APIC_IO)
+ , &IDTVEC(fastintr16), &IDTVEC(fastintr17),
+ &IDTVEC(fastintr18), &IDTVEC(fastintr19),
+ &IDTVEC(fastintr20), &IDTVEC(fastintr21),
+ &IDTVEC(fastintr22), &IDTVEC(fastintr23)
+#endif /* APIC_IO */
+};
+
+static inthand_t *slowintr[ICU_LEN] = {
+ &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
+ &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
+ &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
+ &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
+#if defined(APIC_IO)
+ , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
+ &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23)
+#endif /* APIC_IO */
+};
+
+static inthand2_t isa_strayintr;
+
+#define NMI_PARITY (1 << 7)
+#define NMI_IOCHAN (1 << 6)
+#define ENMI_WATCHDOG (1 << 7)
+#define ENMI_BUSTIMER (1 << 6)
+#define ENMI_IOSTATUS (1 << 5)
+
+/*
+ * Handle a NMI, possibly a machine check.
+ * return true to panic system, false to ignore.
+ */
+int
+isa_nmi(cd)
+ int cd;
+{
+ int isa_port = inb(0x61);
+ int eisa_port = inb(0x461);
+ if(isa_port & NMI_PARITY) {
+ panic("RAM parity error, likely hardware failure.");
+ } else if(isa_port & NMI_IOCHAN) {
+ panic("I/O channel check, likely hardware failure.");
+ } else if(eisa_port & ENMI_WATCHDOG) {
+ panic("EISA watchdog timer expired, likely hardware failure.");
+ } else if(eisa_port & ENMI_BUSTIMER) {
+ panic("EISA bus timeout, likely hardware failure.");
+ } else if(eisa_port & ENMI_IOSTATUS) {
+ panic("EISA I/O port status error.");
+ } else {
+ printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
+ return(0);
+ }
+}
+
+/*
+ * Fill in default interrupt table (in case of spuruious interrupt
+ * during configuration of kernel, setup interrupt control unit
+ */
+void
+isa_defaultirq()
+{
+ int i;
+
+ /* icu vectors */
+ for (i = 0; i < ICU_LEN; i++)
+ icu_unset(i, (inthand2_t *)NULL);
+
+ /* initialize 8259's */
+ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
+ outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
+#ifdef AUTO_EOI_1
+ outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU1+1, 1); /* 8086 mode */
+#endif
+ outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU1, 0x0a); /* default to IRR on read */
+ outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
+
+ outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */
+ outb(IO_ICU2+1,2); /* my slave id is 2 */
+#ifdef AUTO_EOI_2
+ outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU2+1,1); /* 8086 mode */
+#endif
+ outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU2, 0x0a); /* default to IRR on read */
+}
+
+/*
+ * Caught a stray interrupt, notify
+ */
+static void
+isa_strayintr(d)
+ int d;
+{
+
+ /* DON'T BOTHER FOR NOW! */
+ /* for some reason, we get bursts of intr #7, even if not enabled! */
+ /*
+ * Well the reason you got bursts of intr #7 is because someone
+ * raised an interrupt line and dropped it before the 8259 could
+ * prioritize it. This is documented in the intel data book. This
+ * means you have BAD hardware! I have changed this so that only
+ * the first 5 get logged, then it quits logging them, and puts
+ * out a special message. rgrimes 3/25/1993
+ */
+ /*
+ * XXX TODO print a different message for #7 if it is for a
+ * glitch. Glitches can be distinguished from real #7's by
+ * testing that the in-service bit is _not_ set. The test
+ * must be done before sending an EOI so it can't be done if
+ * we are using AUTO_EOI_1.
+ */
+ if (intrcnt[NR_DEVICES + d] <= 5)
+ log(LOG_ERR, "stray irq %d\n", d);
+ if (intrcnt[NR_DEVICES + d] == 5)
+ log(LOG_CRIT,
+ "too many stray irq %d's; not logging any more\n", d);
+}
+
+/*
+ * Return nonzero if a (masked) irq is pending for a given device.
+ */
+#if defined(APIC_IO)
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ /* read APIC IRR containing the 16 ISA INTerrupts */
+ return ((lapic__irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+}
+
+/*
+ * an 8259 specific routine,
+ * for use by boot probes in certain device drivers.
+ */
+int
+icu_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#else /* APIC_IO */
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#endif /* APIC_IO */
+
+int
+update_intr_masks(void)
+{
+ int intr, n=0;
+ u_int mask,*maskptr;
+
+ for (intr=0; intr < ICU_LEN; intr ++) {
+#if defined(APIC_IO)
+ /* no 8259 SLAVE to ignore */
+#else
+ if (intr==2) continue; /* ignore 8259 SLAVE output */
+#endif /* APIC_IO */
+ maskptr = intr_mptr[intr];
+ if (!maskptr) continue;
+ *maskptr |= 1 << intr;
+ mask = *maskptr;
+ if (mask != intr_mask[intr]) {
+#if 0
+ printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
+ intr, intr_mask[intr], mask, maskptr);
+#endif
+ intr_mask[intr]=mask;
+ n++;
+ }
+
+ }
+ return (n);
+}
+
+/*
+ * The find_device_id function is only required because of the way the
+ * device names are currently stored for reporting in systat or vmstat.
+ * In fact, those programs should be modified to use the sysctl interface
+ * to obtain a list of driver names by traversing intreclist_head[irq].
+ */
+static int
+find_device_id(int irq)
+{
+ char buf[16];
+ char *cp;
+ int free_id, id;
+
+ sprintf(buf, "pci irq%d", irq);
+ cp = intrnames;
+ /* default to 0, which corresponds to clk0 */
+ free_id = 0;
+
+ for (id = 0; id < NR_DEVICES; id++) {
+ if (strcmp(cp, buf) == 0)
+ return (id);
+ if (free_id == 0 && strcmp(cp, "pci irqnn") == 0)
+ free_id = id;
+ while (*cp++ != '\0');
+ }
+#if 0
+ if (free_id == 0) {
+ /*
+ * All pci irq counters are in use, perhaps because config
+ * is old so there aren't any. Abuse the clk0 counter.
+ */
+ printf("\tcounting shared irq%d as clk0 irq\n", irq);
+ }
+#endif
+ return (free_id);
+}
+
+void
+update_intrname(int intr, int device_id)
+{
+ char *cp;
+ int id;
+
+ if (device_id == -1)
+ device_id = find_device_id(intr);
+
+ if ((u_int)device_id >= NR_DEVICES)
+ return;
+
+ intr_countp[intr] = &intrcnt[device_id];
+
+ for (cp = intrnames, id = 0; id <= device_id; id++)
+ while (*cp++ != '\0')
+ ;
+ if (cp > eintrnames)
+ return;
+ if (intr < 10) {
+ cp[-3] = intr + '0';
+ cp[-2] = ' ';
+ } else if (intr < 20) {
+ cp[-3] = '1';
+ cp[-2] = intr - 10 + '0';
+ } else {
+ cp[-3] = '2';
+ cp[-2] = intr - 20 + '0';
+ }
+}
+
+
+int
+icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
+{
+ u_long ef;
+ u_int mask = (maskptr ? *maskptr : 0);
+
+#if defined(APIC_IO)
+ if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
+#else
+ if ((u_int)intr >= ICU_LEN || intr == 2)
+#endif /* APIC_IO */
+ if (intr_handler[intr] != isa_strayintr)
+ return (EBUSY);
+
+ ef = read_eflags();
+ disable_intr();
+ intr_handler[intr] = handler;
+ intr_mptr[intr] = maskptr;
+ intr_mask[intr] = mask | (1 << intr);
+ intr_unit[intr] = (int) arg;
+ setidt(ICU_OFFSET + intr,
+ flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ INTREN(1 << intr);
+ write_eflags(ef);
+ return (0);
+}
+
+void
+register_imask(dvp, mask)
+ struct isa_device *dvp;
+ u_int mask;
+{
+ if (dvp->id_alive && dvp->id_irq) {
+ int intr;
+
+ intr = ffs(dvp->id_irq) - 1;
+ intr_mask[intr] = mask | (1 <<intr);
+ }
+ (void) update_intr_masks();
+}
+
+int
+icu_unset(intr, handler)
+ int intr;
+ inthand2_t *handler;
+{
+ u_long ef;
+
+ if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
+ return (EINVAL);
+
+ INTRDIS(1 << intr);
+ ef = read_eflags();
+ disable_intr();
+ intr_countp[intr] = &intrcnt[NR_DEVICES + intr];
+ intr_handler[intr] = isa_strayintr;
+ intr_mptr[intr] = NULL;
+ intr_mask[intr] = HWI_MASK | SWI_MASK;
+ intr_unit[intr] = intr;
+ setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+ write_eflags(ef);
+ return (0);
+}
diff --git a/sys/amd64/isa/intr_machdep.h b/sys/amd64/isa/intr_machdep.h
new file mode 100644
index 0000000..a9a512e
--- /dev/null
+++ b/sys/amd64/isa/intr_machdep.h
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
+ * $Id: isa_device.h,v 1.39 1997/04/27 21:18:58 fsmp Exp $
+ */
+
+#ifndef _I386_ISA_INTR_MACHDEP_H_
+#define _I386_ISA_INTR_MACHDEP_H_
+
+/*
+ * Low level interrupt code.
+ */
+
+#ifdef KERNEL
+
+/*
+ * Type of the first (asm) part of an interrupt handler.
+ */
+typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
+
+#define IDTVEC(name) __CONCAT(X,name)
+
+extern char eintrnames[]; /* end of intrnames[] */
+extern u_long intrcnt[]; /* counts for for each device and stray */
+extern char intrnames[]; /* string table containing device names */
+extern u_long *intr_countp[]; /* pointers into intrcnt[] */
+extern inthand2_t *intr_handler[]; /* C entry points of intr handlers */
+extern u_int intr_mask[]; /* sets of intrs masked during handling of 1 */
+extern int intr_unit[]; /* cookies to pass to intr handlers */
+
+inthand_t
+ IDTVEC(fastintr0), IDTVEC(fastintr1),
+ IDTVEC(fastintr2), IDTVEC(fastintr3),
+ IDTVEC(fastintr4), IDTVEC(fastintr5),
+ IDTVEC(fastintr6), IDTVEC(fastintr7),
+ IDTVEC(fastintr8), IDTVEC(fastintr9),
+ IDTVEC(fastintr10), IDTVEC(fastintr11),
+ IDTVEC(fastintr12), IDTVEC(fastintr13),
+ IDTVEC(fastintr14), IDTVEC(fastintr15);
+inthand_t
+ IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3),
+ IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7),
+ IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11),
+ IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15);
+
+/* these functions ONLY exist in an SMP/APIC_IO kernel: */
+inthand_t
+ IDTVEC(fastintr16), IDTVEC(fastintr17),
+ IDTVEC(fastintr18), IDTVEC(fastintr19),
+ IDTVEC(fastintr20), IDTVEC(fastintr21),
+ IDTVEC(fastintr22), IDTVEC(fastintr23);
+inthand_t
+ IDTVEC(intr16), IDTVEC(intr17), IDTVEC(intr18), IDTVEC(intr19),
+ IDTVEC(intr20), IDTVEC(intr21), IDTVEC(intr22), IDTVEC(intr23);
+#define XINVLTLB_OFFSET 32
+inthand_t
+ Xinvltlb;
+
+struct isa_device;
+
+void isa_defaultirq __P((void));
+int isa_irq_pending __P((struct isa_device *dvp));
+/* this function ONLY exists in an SMP/APIC_IO kernel: */
+int icu_irq_pending __P((struct isa_device *dvp));
+int isa_nmi __P((int cd));
+void update_intrname __P((int intr, int device_id));
+int icu_setup __P((int intr, inthand2_t *func, void *arg,
+ u_int *maskptr, int flags));
+int icu_unset __P((int intr, inthand2_t *handler));
+int update_intr_masks __P((void));
+void register_imask __P((struct isa_device *dvp, u_int mask));
+
+#endif /* KERNEL */
+
+#endif /* !_I386_ISA_INTR_MACHDEP_H_ */
diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c
index a54f7bb..ccadc08 100644
--- a/sys/amd64/isa/isa.c
+++ b/sys/amd64/isa/isa.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.87 1997/05/29 05:56:12 fsmp Exp $
+ * $Id: isa.c,v 1.88 1997/05/31 09:27:31 peter Exp $
*/
/*
@@ -47,8 +47,6 @@
* isa_dmastart()
*/
-#include "opt_auto_eoi.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
@@ -65,6 +63,7 @@
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/isa.h>
#include <i386/isa/icu.h>
#include <i386/isa/ic/i8237.h>
@@ -72,14 +71,6 @@
#include <sys/interrupt.h>
-#ifdef APIC_IO
-/*
- * This is to accommodate "mixed-mode" programming for
- * motherboards that don't connect the 8254 to the IO APIC.
- */
-#define AUTO_EOI_1
-#endif
-
/*
** Register definitions for DMA controller 1 (channels 0..3):
*/
@@ -96,40 +87,6 @@
#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
-u_long *intr_countp[ICU_LEN];
-inthand2_t *intr_handler[ICU_LEN];
-u_int intr_mask[ICU_LEN];
-u_int* intr_mptr[ICU_LEN];
-int intr_unit[ICU_LEN];
-
-static inthand_t *fastintr[ICU_LEN] = {
- &IDTVEC(fastintr0), &IDTVEC(fastintr1),
- &IDTVEC(fastintr2), &IDTVEC(fastintr3),
- &IDTVEC(fastintr4), &IDTVEC(fastintr5),
- &IDTVEC(fastintr6), &IDTVEC(fastintr7),
- &IDTVEC(fastintr8), &IDTVEC(fastintr9),
- &IDTVEC(fastintr10), &IDTVEC(fastintr11),
- &IDTVEC(fastintr12), &IDTVEC(fastintr13),
- &IDTVEC(fastintr14), &IDTVEC(fastintr15)
-#if defined(APIC_IO)
- , &IDTVEC(fastintr16), &IDTVEC(fastintr17),
- &IDTVEC(fastintr18), &IDTVEC(fastintr19),
- &IDTVEC(fastintr20), &IDTVEC(fastintr21),
- &IDTVEC(fastintr22), &IDTVEC(fastintr23)
-#endif /* APIC_IO */
-};
-
-static inthand_t *slowintr[ICU_LEN] = {
- &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
- &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
- &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
- &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
-#if defined(APIC_IO)
- , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
- &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23)
-#endif /* APIC_IO */
-};
-
static void config_isadev __P((struct isa_device *isdp, u_int *mp));
static void config_isadev_c __P((struct isa_device *isdp, u_int *mp,
int reconfig));
@@ -139,8 +96,6 @@ static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp,
static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp,
u_int checkbits));
static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan));
-static inthand2_t isa_strayintr;
-static void register_imask __P((struct isa_device *dvp, u_int mask));
/*
* print a conflict message
@@ -615,44 +570,6 @@ config_isadev_c(isdp, mp, reconfig)
}
}
-/*
- * Fill in default interrupt table (in case of spuruious interrupt
- * during configuration of kernel, setup interrupt control unit
- */
-void
-isa_defaultirq()
-{
- int i;
-
- /* icu vectors */
- for (i = 0; i < ICU_LEN; i++)
- icu_unset(i, (inthand2_t *)NULL);
-
- /* initialize 8259's */
- outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
- outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
- outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
-#ifdef AUTO_EOI_1
- outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
-#else
- outb(IO_ICU1+1, 1); /* 8086 mode */
-#endif
- outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
- outb(IO_ICU1, 0x0a); /* default to IRR on read */
- outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
-
- outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
- outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */
- outb(IO_ICU2+1,2); /* my slave id is 2 */
-#ifdef AUTO_EOI_2
- outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
-#else
- outb(IO_ICU2+1,1); /* 8086 mode */
-#endif
- outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
- outb(IO_ICU2, 0x0a); /* default to IRR on read */
-}
-
static caddr_t dma_bouncebuf[8];
static u_int dma_bouncebufsize[8];
static u_int8_t dma_bounced = 0;
@@ -956,70 +873,6 @@ isa_dmarangecheck(caddr_t va, u_int length, int chan) {
return (0);
}
-#define NMI_PARITY (1 << 7)
-#define NMI_IOCHAN (1 << 6)
-#define ENMI_WATCHDOG (1 << 7)
-#define ENMI_BUSTIMER (1 << 6)
-#define ENMI_IOSTATUS (1 << 5)
-
-/*
- * Handle a NMI, possibly a machine check.
- * return true to panic system, false to ignore.
- */
-int
-isa_nmi(cd)
- int cd;
-{
- int isa_port = inb(0x61);
- int eisa_port = inb(0x461);
- if(isa_port & NMI_PARITY) {
- panic("RAM parity error, likely hardware failure.");
- } else if(isa_port & NMI_IOCHAN) {
- panic("I/O channel check, likely hardware failure.");
- } else if(eisa_port & ENMI_WATCHDOG) {
- panic("EISA watchdog timer expired, likely hardware failure.");
- } else if(eisa_port & ENMI_BUSTIMER) {
- panic("EISA bus timeout, likely hardware failure.");
- } else if(eisa_port & ENMI_IOSTATUS) {
- panic("EISA I/O port status error.");
- } else {
- printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
- return(0);
- }
-}
-
-/*
- * Caught a stray interrupt, notify
- */
-static void
-isa_strayintr(d)
- int d;
-{
-
- /* DON'T BOTHER FOR NOW! */
- /* for some reason, we get bursts of intr #7, even if not enabled! */
- /*
- * Well the reason you got bursts of intr #7 is because someone
- * raised an interrupt line and dropped it before the 8259 could
- * prioritize it. This is documented in the intel data book. This
- * means you have BAD hardware! I have changed this so that only
- * the first 5 get logged, then it quits logging them, and puts
- * out a special message. rgrimes 3/25/1993
- */
- /*
- * XXX TODO print a different message for #7 if it is for a
- * glitch. Glitches can be distinguished from real #7's by
- * testing that the in-service bit is _not_ set. The test
- * must be done before sending an EOI so it can't be done if
- * we are using AUTO_EOI_1.
- */
- if (intrcnt[NR_DEVICES + d] <= 5)
- log(LOG_ERR, "stray irq %d\n", d);
- if (intrcnt[NR_DEVICES + d] == 5)
- log(LOG_CRIT,
- "too many stray irq %d's; not logging any more\n", d);
-}
-
/*
* Find the highest priority enabled display device. Since we can't
* distinguish display devices from ttys, depend on display devices
@@ -1067,210 +920,3 @@ struct isa_device *find_isadev(table, driverp, unit)
return (table);
}
-/*
- * Return nonzero if a (masked) irq is pending for a given device.
- */
-#if defined(APIC_IO)
-
-int
-isa_irq_pending(dvp)
- struct isa_device *dvp;
-{
- /* read APIC IRR containing the 16 ISA INTerrupts */
- return ((lapic__irr1 & 0x00ffffff)
- & (u_int32_t)dvp->id_irq) ? 1 : 0;
-}
-
-/*
- * an 8259 specific routine,
- * for use by boot probes in certain device drivers.
- */
-int
-icu_irq_pending(dvp)
- struct isa_device *dvp;
-{
- unsigned id_irq;
- id_irq = dvp->id_irq;
- if (id_irq & 0xff)
- return (inb(IO_ICU1) & id_irq);
- return (inb(IO_ICU2) & (id_irq >> 8));
-}
-
-#else /* APIC_IO */
-
-int
-isa_irq_pending(dvp)
- struct isa_device *dvp;
-{
- unsigned id_irq;
- id_irq = dvp->id_irq;
- if (id_irq & 0xff)
- return (inb(IO_ICU1) & id_irq);
- return (inb(IO_ICU2) & (id_irq >> 8));
-}
-
-#endif /* APIC_IO */
-
-int
-update_intr_masks(void)
-{
- int intr, n=0;
- u_int mask,*maskptr;
-
- for (intr=0; intr < ICU_LEN; intr ++) {
-#if defined(APIC_IO)
- /* no 8259 SLAVE to ignore */
-#else
- if (intr==2) continue; /* ignore 8259 SLAVE output */
-#endif /* APIC_IO */
- maskptr = intr_mptr[intr];
- if (!maskptr) continue;
- *maskptr |= 1 << intr;
- mask = *maskptr;
- if (mask != intr_mask[intr]) {
-#if 0
- printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
- intr, intr_mask[intr], mask, maskptr);
-#endif
- intr_mask[intr]=mask;
- n++;
- }
-
- }
- return (n);
-}
-
-/*
- * The find_device_id function is only required because of the way the
- * device names are currently stored for reporting in systat or vmstat.
- * In fact, those programs should be modified to use the sysctl interface
- * to obtain a list of driver names by traversing intreclist_head[irq].
- */
-
-static int
-find_device_id(int irq)
-{
- char buf[16];
- char *cp;
- int free_id, id;
-
- sprintf(buf, "pci irq%d", irq);
- cp = intrnames;
- /* default to 0, which corresponds to clk0 */
- free_id = 0;
-
- for (id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- return (id);
- if (free_id == 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0');
- }
-#if 0
- if (free_id == 0) {
- /*
- * All pci irq counters are in use, perhaps because config
- * is old so there aren't any. Abuse the clk0 counter.
- */
- printf("\tcounting shared irq%d as clk0 irq\n", irq);
- }
-#endif
- return (free_id);
-}
-
-void
-update_intrname(int intr, int device_id)
-{
- char *cp;
- int id;
-
- if (device_id == -1)
- device_id = find_device_id(intr);
-
- if ((u_int)device_id >= NR_DEVICES)
- return;
-
- intr_countp[intr] = &intrcnt[device_id];
-
- for (cp = intrnames, id = 0; id <= device_id; id++)
- while (*cp++ != '\0')
- ;
- if (cp > eintrnames)
- return;
- if (intr < 10) {
- cp[-3] = intr + '0';
- cp[-2] = ' ';
- } else if (intr < 20) {
- cp[-3] = '1';
- cp[-2] = intr - 10 + '0';
- } else {
- cp[-3] = '2';
- cp[-2] = intr - 20 + '0';
- }
-}
-
-int
-icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
-{
- u_long ef;
- u_int mask = (maskptr ? *maskptr : 0);
-
-#if defined(APIC_IO)
- if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
-#else
- if ((u_int)intr >= ICU_LEN || intr == 2)
-#endif /* APIC_IO */
- if (intr_handler[intr] != isa_strayintr)
- return (EBUSY);
-
- ef = read_eflags();
- disable_intr();
- intr_handler[intr] = handler;
- intr_mptr[intr] = maskptr;
- intr_mask[intr] = mask | (1 << intr);
- intr_unit[intr] = arg;
- setidt(ICU_OFFSET + intr,
- flags & RI_FAST ? fastintr[intr] : slowintr[intr],
- SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
- INTREN(1 << intr);
- write_eflags(ef);
- return (0);
-}
-
-static void
-register_imask(dvp, mask)
- struct isa_device *dvp;
- u_int mask;
-{
- if (dvp->id_alive && dvp->id_irq) {
- int intr;
-
- intr = ffs(dvp->id_irq) - 1;
- intr_mask[intr] = mask | (1 <<intr);
- }
- (void) update_intr_masks();
-}
-
-int
-icu_unset(intr, handler)
- int intr;
- inthand2_t *handler;
-{
- u_long ef;
-
- if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
- return (EINVAL);
-
- INTRDIS(1 << intr);
- ef = read_eflags();
- disable_intr();
- intr_countp[intr] = &intrcnt[NR_DEVICES + intr];
- intr_handler[intr] = isa_strayintr;
- intr_mptr[intr] = NULL;
- intr_mask[intr] = HWI_MASK | SWI_MASK;
- intr_unit[intr] = intr;
- setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- write_eflags(ef);
- return (0);
-}
diff --git a/sys/amd64/isa/nmi.c b/sys/amd64/isa/nmi.c
new file mode 100644
index 0000000..40acb8e
--- /dev/null
+++ b/sys/amd64/isa/nmi.c
@@ -0,0 +1,418 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
+ * $Id: isa.c,v 1.85 1997/05/26 14:42:24 se Exp $
+ */
+
+#include "opt_auto_eoi.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <machine/ipl.h>
+#include <machine/md_var.h>
+#include <machine/segments.h>
+#if defined(APIC_IO)
+#include <machine/smp.h>
+#include <machine/apic.h>
+#endif /* APIC_IO */
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/isa.h>
+#include <i386/isa/icu.h>
+#include <i386/isa/ic/i8237.h>
+#include "vector.h"
+
+#include <i386/isa/intr_machdep.h>
+#include <sys/interrupt.h>
+
+#ifdef APIC_IO
+/*
+ * This is to accommodate "mixed-mode" programming for
+ * motherboards that don't connect the 8254 to the IO APIC.
+ */
+#define AUTO_EOI_1
+#endif
+
+u_long *intr_countp[ICU_LEN];
+inthand2_t *intr_handler[ICU_LEN];
+u_int intr_mask[ICU_LEN];
+u_int* intr_mptr[ICU_LEN];
+int intr_unit[ICU_LEN];
+
+static inthand_t *fastintr[ICU_LEN] = {
+ &IDTVEC(fastintr0), &IDTVEC(fastintr1),
+ &IDTVEC(fastintr2), &IDTVEC(fastintr3),
+ &IDTVEC(fastintr4), &IDTVEC(fastintr5),
+ &IDTVEC(fastintr6), &IDTVEC(fastintr7),
+ &IDTVEC(fastintr8), &IDTVEC(fastintr9),
+ &IDTVEC(fastintr10), &IDTVEC(fastintr11),
+ &IDTVEC(fastintr12), &IDTVEC(fastintr13),
+ &IDTVEC(fastintr14), &IDTVEC(fastintr15)
+#if defined(APIC_IO)
+ , &IDTVEC(fastintr16), &IDTVEC(fastintr17),
+ &IDTVEC(fastintr18), &IDTVEC(fastintr19),
+ &IDTVEC(fastintr20), &IDTVEC(fastintr21),
+ &IDTVEC(fastintr22), &IDTVEC(fastintr23)
+#endif /* APIC_IO */
+};
+
+static inthand_t *slowintr[ICU_LEN] = {
+ &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
+ &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
+ &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
+ &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
+#if defined(APIC_IO)
+ , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
+ &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23)
+#endif /* APIC_IO */
+};
+
+static inthand2_t isa_strayintr;
+
+#define NMI_PARITY (1 << 7)
+#define NMI_IOCHAN (1 << 6)
+#define ENMI_WATCHDOG (1 << 7)
+#define ENMI_BUSTIMER (1 << 6)
+#define ENMI_IOSTATUS (1 << 5)
+
+/*
+ * Handle a NMI, possibly a machine check.
+ * return true to panic system, false to ignore.
+ */
+int
+isa_nmi(cd)
+ int cd;
+{
+ int isa_port = inb(0x61);
+ int eisa_port = inb(0x461);
+ if(isa_port & NMI_PARITY) {
+ panic("RAM parity error, likely hardware failure.");
+ } else if(isa_port & NMI_IOCHAN) {
+ panic("I/O channel check, likely hardware failure.");
+ } else if(eisa_port & ENMI_WATCHDOG) {
+ panic("EISA watchdog timer expired, likely hardware failure.");
+ } else if(eisa_port & ENMI_BUSTIMER) {
+ panic("EISA bus timeout, likely hardware failure.");
+ } else if(eisa_port & ENMI_IOSTATUS) {
+ panic("EISA I/O port status error.");
+ } else {
+ printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
+ return(0);
+ }
+}
+
+/*
+ * Fill in default interrupt table (in case of spuruious interrupt
+ * during configuration of kernel, setup interrupt control unit
+ */
+void
+isa_defaultirq()
+{
+ int i;
+
+ /* icu vectors */
+ for (i = 0; i < ICU_LEN; i++)
+ icu_unset(i, (inthand2_t *)NULL);
+
+ /* initialize 8259's */
+ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
+ outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
+#ifdef AUTO_EOI_1
+ outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU1+1, 1); /* 8086 mode */
+#endif
+ outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU1, 0x0a); /* default to IRR on read */
+ outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
+
+ outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */
+ outb(IO_ICU2+1,2); /* my slave id is 2 */
+#ifdef AUTO_EOI_2
+ outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU2+1,1); /* 8086 mode */
+#endif
+ outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU2, 0x0a); /* default to IRR on read */
+}
+
+/*
+ * Caught a stray interrupt, notify
+ */
+static void
+isa_strayintr(d)
+ int d;
+{
+
+ /* DON'T BOTHER FOR NOW! */
+ /* for some reason, we get bursts of intr #7, even if not enabled! */
+ /*
+ * Well the reason you got bursts of intr #7 is because someone
+ * raised an interrupt line and dropped it before the 8259 could
+ * prioritize it. This is documented in the intel data book. This
+ * means you have BAD hardware! I have changed this so that only
+ * the first 5 get logged, then it quits logging them, and puts
+ * out a special message. rgrimes 3/25/1993
+ */
+ /*
+ * XXX TODO print a different message for #7 if it is for a
+ * glitch. Glitches can be distinguished from real #7's by
+ * testing that the in-service bit is _not_ set. The test
+ * must be done before sending an EOI so it can't be done if
+ * we are using AUTO_EOI_1.
+ */
+ if (intrcnt[NR_DEVICES + d] <= 5)
+ log(LOG_ERR, "stray irq %d\n", d);
+ if (intrcnt[NR_DEVICES + d] == 5)
+ log(LOG_CRIT,
+ "too many stray irq %d's; not logging any more\n", d);
+}
+
+/*
+ * Return nonzero if a (masked) irq is pending for a given device.
+ */
+#if defined(APIC_IO)
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ /* read APIC IRR containing the 16 ISA INTerrupts */
+ return ((lapic__irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+}
+
+/*
+ * an 8259 specific routine,
+ * for use by boot probes in certain device drivers.
+ */
+int
+icu_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#else /* APIC_IO */
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#endif /* APIC_IO */
+
+int
+update_intr_masks(void)
+{
+ int intr, n=0;
+ u_int mask,*maskptr;
+
+ for (intr=0; intr < ICU_LEN; intr ++) {
+#if defined(APIC_IO)
+ /* no 8259 SLAVE to ignore */
+#else
+ if (intr==2) continue; /* ignore 8259 SLAVE output */
+#endif /* APIC_IO */
+ maskptr = intr_mptr[intr];
+ if (!maskptr) continue;
+ *maskptr |= 1 << intr;
+ mask = *maskptr;
+ if (mask != intr_mask[intr]) {
+#if 0
+ printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
+ intr, intr_mask[intr], mask, maskptr);
+#endif
+ intr_mask[intr]=mask;
+ n++;
+ }
+
+ }
+ return (n);
+}
+
+/*
+ * The find_device_id function is only required because of the way the
+ * device names are currently stored for reporting in systat or vmstat.
+ * In fact, those programs should be modified to use the sysctl interface
+ * to obtain a list of driver names by traversing intreclist_head[irq].
+ */
+static int
+find_device_id(int irq)
+{
+ char buf[16];
+ char *cp;
+ int free_id, id;
+
+ sprintf(buf, "pci irq%d", irq);
+ cp = intrnames;
+ /* default to 0, which corresponds to clk0 */
+ free_id = 0;
+
+ for (id = 0; id < NR_DEVICES; id++) {
+ if (strcmp(cp, buf) == 0)
+ return (id);
+ if (free_id == 0 && strcmp(cp, "pci irqnn") == 0)
+ free_id = id;
+ while (*cp++ != '\0');
+ }
+#if 0
+ if (free_id == 0) {
+ /*
+ * All pci irq counters are in use, perhaps because config
+ * is old so there aren't any. Abuse the clk0 counter.
+ */
+ printf("\tcounting shared irq%d as clk0 irq\n", irq);
+ }
+#endif
+ return (free_id);
+}
+
+void
+update_intrname(int intr, int device_id)
+{
+ char *cp;
+ int id;
+
+ if (device_id == -1)
+ device_id = find_device_id(intr);
+
+ if ((u_int)device_id >= NR_DEVICES)
+ return;
+
+ intr_countp[intr] = &intrcnt[device_id];
+
+ for (cp = intrnames, id = 0; id <= device_id; id++)
+ while (*cp++ != '\0')
+ ;
+ if (cp > eintrnames)
+ return;
+ if (intr < 10) {
+ cp[-3] = intr + '0';
+ cp[-2] = ' ';
+ } else if (intr < 20) {
+ cp[-3] = '1';
+ cp[-2] = intr - 10 + '0';
+ } else {
+ cp[-3] = '2';
+ cp[-2] = intr - 20 + '0';
+ }
+}
+
+
+int
+icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
+{
+ u_long ef;
+ u_int mask = (maskptr ? *maskptr : 0);
+
+#if defined(APIC_IO)
+ if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
+#else
+ if ((u_int)intr >= ICU_LEN || intr == 2)
+#endif /* APIC_IO */
+ if (intr_handler[intr] != isa_strayintr)
+ return (EBUSY);
+
+ ef = read_eflags();
+ disable_intr();
+ intr_handler[intr] = handler;
+ intr_mptr[intr] = maskptr;
+ intr_mask[intr] = mask | (1 << intr);
+ intr_unit[intr] = (int) arg;
+ setidt(ICU_OFFSET + intr,
+ flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ INTREN(1 << intr);
+ write_eflags(ef);
+ return (0);
+}
+
+void
+register_imask(dvp, mask)
+ struct isa_device *dvp;
+ u_int mask;
+{
+ if (dvp->id_alive && dvp->id_irq) {
+ int intr;
+
+ intr = ffs(dvp->id_irq) - 1;
+ intr_mask[intr] = mask | (1 <<intr);
+ }
+ (void) update_intr_masks();
+}
+
+int
+icu_unset(intr, handler)
+ int intr;
+ inthand2_t *handler;
+{
+ u_long ef;
+
+ if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
+ return (EINVAL);
+
+ INTRDIS(1 << intr);
+ ef = read_eflags();
+ disable_intr();
+ intr_countp[intr] = &intrcnt[NR_DEVICES + intr];
+ intr_handler[intr] = isa_strayintr;
+ intr_mptr[intr] = NULL;
+ intr_mask[intr] = HWI_MASK | SWI_MASK;
+ intr_unit[intr] = intr;
+ setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+ write_eflags(ef);
+ return (0);
+}
diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c
index d364f4f..aca74fa 100644
--- a/sys/amd64/isa/npx.c
+++ b/sys/amd64/isa/npx.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)npx.c 7.2 (Berkeley) 5/12/91
- * $Id: npx.c,v 1.43 1997/05/07 19:58:13 peter Exp $
+ * $Id: npx.c,v 1.44 1997/05/31 09:27:31 peter Exp $
*/
#include "npx.h"
@@ -69,6 +69,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/isa.h>
/*
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index f917fc0..f9d9342 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.163 1997/05/31 18:01:38 peter Exp $
+# $Id: files.i386,v 1.164 1997/06/01 20:25:55 bde Exp $
#
aic7xxx_asm optional ahc device-driver \
dependency "$S/dev/aic7xxx/*.[chyl]" \
@@ -126,6 +126,7 @@ i386/isa/if_ze.c optional ze device-driver
i386/isa/if_zp.c optional zp device-driver
i386/isa/ipl_funcs.c standard \
compile-with "${CC} -c ${CFLAGS} ${PROF:S/^$/-fomit-frame-pointer/} $<"
+i386/isa/intr_machdep.c standard
i386/isa/isa.c optional isa device-driver
i386/isa/istallion.c optional stli device-driver
i386/isa/joy.c optional joy device-driver
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index f917fc0..f9d9342 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.163 1997/05/31 18:01:38 peter Exp $
+# $Id: files.i386,v 1.164 1997/06/01 20:25:55 bde Exp $
#
aic7xxx_asm optional ahc device-driver \
dependency "$S/dev/aic7xxx/*.[chyl]" \
@@ -126,6 +126,7 @@ i386/isa/if_ze.c optional ze device-driver
i386/isa/if_zp.c optional zp device-driver
i386/isa/ipl_funcs.c standard \
compile-with "${CC} -c ${CFLAGS} ${PROF:S/^$/-fomit-frame-pointer/} $<"
+i386/isa/intr_machdep.c standard
i386/isa/isa.c optional isa device-driver
i386/isa/istallion.c optional stli device-driver
i386/isa/joy.c optional joy device-driver
diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c
index 30b17d8..474a1a9 100644
--- a/sys/i386/i386/identcpu.c
+++ b/sys/i386/i386/identcpu.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
- * $Id: identcpu.c,v 1.21 1997/05/23 06:22:47 charnier Exp $
+ * $Id: identcpu.c,v 1.22 1997/05/31 08:45:23 kato Exp $
*/
#include "opt_cpu.h"
@@ -56,7 +56,7 @@
#include <machine/sysarch.h>
#include <machine/md_var.h>
-#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
/* XXX - should be in header file */
void i486_bzero __P((void *buf, size_t len));
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 8a9a8d3..186541c 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.244 1997/05/26 09:23:29 fsmp Exp $
+ * $Id: machdep.c,v 1.245 1997/05/26 18:40:45 fsmp Exp $
*/
#include "npx.h"
@@ -117,6 +117,7 @@
#endif
#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/rtc.h>
#include <machine/random.h>
diff --git a/sys/i386/i386/mem.c b/sys/i386/i386/mem.c
index ae8e95c..c6eb954 100644
--- a/sys/i386/i386/mem.c
+++ b/sys/i386/i386/mem.c
@@ -38,7 +38,7 @@
*
* from: Utah $Hdr: mem.c 1.13 89/10/08$
* from: @(#)mem.c 7.2 (Berkeley) 5/9/91
- * $Id: mem.c,v 1.43 1997/05/07 20:02:37 peter Exp $
+ * $Id: mem.c,v 1.44 1997/05/07 20:32:41 peter Exp $
*/
/*
@@ -65,6 +65,7 @@
#ifdef PERFMON
#include <machine/perfmon.h>
#endif
+#include <i386/isa/intr_machdep.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index d508788..f73c4f2 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.96 1997/05/29 05:04:30 peter Exp $
+ * $Id: trap.c,v 1.97 1997/05/31 09:27:29 peter Exp $
*/
/*
@@ -76,7 +76,7 @@
#include <machine/psl.h>
#include <machine/reg.h>
#include <machine/trap.h>
-#include <machine/../isa/isa_device.h>
+#include <machine/../isa/intr_machdep.h>
#include <machine/smp.h>
#ifdef POWERFAIL_NMI
diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c
index 13e66f5..4ae5c36 100644
--- a/sys/i386/i386/tsc.c
+++ b/sys/i386/i386/tsc.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.85 1997/05/29 05:00:35 peter Exp $
+ * $Id: clock.c,v 1.86 1997/05/31 09:27:30 peter Exp $
*/
/*
@@ -67,7 +67,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
-#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c
index 13e66f5..4ae5c36 100644
--- a/sys/i386/isa/clock.c
+++ b/sys/i386/isa/clock.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.85 1997/05/29 05:00:35 peter Exp $
+ * $Id: clock.c,v 1.86 1997/05/31 09:27:30 peter Exp $
*/
/*
@@ -67,7 +67,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
-#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
diff --git a/sys/i386/isa/intr_machdep.c b/sys/i386/isa/intr_machdep.c
new file mode 100644
index 0000000..40acb8e
--- /dev/null
+++ b/sys/i386/isa/intr_machdep.c
@@ -0,0 +1,418 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
+ * $Id: isa.c,v 1.85 1997/05/26 14:42:24 se Exp $
+ */
+
+#include "opt_auto_eoi.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <machine/ipl.h>
+#include <machine/md_var.h>
+#include <machine/segments.h>
+#if defined(APIC_IO)
+#include <machine/smp.h>
+#include <machine/apic.h>
+#endif /* APIC_IO */
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/isa.h>
+#include <i386/isa/icu.h>
+#include <i386/isa/ic/i8237.h>
+#include "vector.h"
+
+#include <i386/isa/intr_machdep.h>
+#include <sys/interrupt.h>
+
+#ifdef APIC_IO
+/*
+ * This is to accommodate "mixed-mode" programming for
+ * motherboards that don't connect the 8254 to the IO APIC.
+ */
+#define AUTO_EOI_1
+#endif
+
+u_long *intr_countp[ICU_LEN];
+inthand2_t *intr_handler[ICU_LEN];
+u_int intr_mask[ICU_LEN];
+u_int* intr_mptr[ICU_LEN];
+int intr_unit[ICU_LEN];
+
+static inthand_t *fastintr[ICU_LEN] = {
+ &IDTVEC(fastintr0), &IDTVEC(fastintr1),
+ &IDTVEC(fastintr2), &IDTVEC(fastintr3),
+ &IDTVEC(fastintr4), &IDTVEC(fastintr5),
+ &IDTVEC(fastintr6), &IDTVEC(fastintr7),
+ &IDTVEC(fastintr8), &IDTVEC(fastintr9),
+ &IDTVEC(fastintr10), &IDTVEC(fastintr11),
+ &IDTVEC(fastintr12), &IDTVEC(fastintr13),
+ &IDTVEC(fastintr14), &IDTVEC(fastintr15)
+#if defined(APIC_IO)
+ , &IDTVEC(fastintr16), &IDTVEC(fastintr17),
+ &IDTVEC(fastintr18), &IDTVEC(fastintr19),
+ &IDTVEC(fastintr20), &IDTVEC(fastintr21),
+ &IDTVEC(fastintr22), &IDTVEC(fastintr23)
+#endif /* APIC_IO */
+};
+
+static inthand_t *slowintr[ICU_LEN] = {
+ &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
+ &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
+ &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
+ &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
+#if defined(APIC_IO)
+ , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
+ &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23)
+#endif /* APIC_IO */
+};
+
+static inthand2_t isa_strayintr;
+
+#define NMI_PARITY (1 << 7)
+#define NMI_IOCHAN (1 << 6)
+#define ENMI_WATCHDOG (1 << 7)
+#define ENMI_BUSTIMER (1 << 6)
+#define ENMI_IOSTATUS (1 << 5)
+
+/*
+ * Handle a NMI, possibly a machine check.
+ * return true to panic system, false to ignore.
+ */
+int
+isa_nmi(cd)
+ int cd;
+{
+ int isa_port = inb(0x61);
+ int eisa_port = inb(0x461);
+ if(isa_port & NMI_PARITY) {
+ panic("RAM parity error, likely hardware failure.");
+ } else if(isa_port & NMI_IOCHAN) {
+ panic("I/O channel check, likely hardware failure.");
+ } else if(eisa_port & ENMI_WATCHDOG) {
+ panic("EISA watchdog timer expired, likely hardware failure.");
+ } else if(eisa_port & ENMI_BUSTIMER) {
+ panic("EISA bus timeout, likely hardware failure.");
+ } else if(eisa_port & ENMI_IOSTATUS) {
+ panic("EISA I/O port status error.");
+ } else {
+ printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
+ return(0);
+ }
+}
+
+/*
+ * Fill in default interrupt table (in case of spuruious interrupt
+ * during configuration of kernel, setup interrupt control unit
+ */
+void
+isa_defaultirq()
+{
+ int i;
+
+ /* icu vectors */
+ for (i = 0; i < ICU_LEN; i++)
+ icu_unset(i, (inthand2_t *)NULL);
+
+ /* initialize 8259's */
+ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
+ outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
+#ifdef AUTO_EOI_1
+ outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU1+1, 1); /* 8086 mode */
+#endif
+ outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU1, 0x0a); /* default to IRR on read */
+ outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
+
+ outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */
+ outb(IO_ICU2+1,2); /* my slave id is 2 */
+#ifdef AUTO_EOI_2
+ outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU2+1,1); /* 8086 mode */
+#endif
+ outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU2, 0x0a); /* default to IRR on read */
+}
+
+/*
+ * Caught a stray interrupt, notify
+ */
+static void
+isa_strayintr(d)
+ int d;
+{
+
+ /* DON'T BOTHER FOR NOW! */
+ /* for some reason, we get bursts of intr #7, even if not enabled! */
+ /*
+ * Well the reason you got bursts of intr #7 is because someone
+ * raised an interrupt line and dropped it before the 8259 could
+ * prioritize it. This is documented in the intel data book. This
+ * means you have BAD hardware! I have changed this so that only
+ * the first 5 get logged, then it quits logging them, and puts
+ * out a special message. rgrimes 3/25/1993
+ */
+ /*
+ * XXX TODO print a different message for #7 if it is for a
+ * glitch. Glitches can be distinguished from real #7's by
+ * testing that the in-service bit is _not_ set. The test
+ * must be done before sending an EOI so it can't be done if
+ * we are using AUTO_EOI_1.
+ */
+ if (intrcnt[NR_DEVICES + d] <= 5)
+ log(LOG_ERR, "stray irq %d\n", d);
+ if (intrcnt[NR_DEVICES + d] == 5)
+ log(LOG_CRIT,
+ "too many stray irq %d's; not logging any more\n", d);
+}
+
+/*
+ * Return nonzero if a (masked) irq is pending for a given device.
+ */
+#if defined(APIC_IO)
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ /* read APIC IRR containing the 16 ISA INTerrupts */
+ return ((lapic__irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+}
+
+/*
+ * an 8259 specific routine,
+ * for use by boot probes in certain device drivers.
+ */
+int
+icu_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#else /* APIC_IO */
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#endif /* APIC_IO */
+
+int
+update_intr_masks(void)
+{
+ int intr, n=0;
+ u_int mask,*maskptr;
+
+ for (intr=0; intr < ICU_LEN; intr ++) {
+#if defined(APIC_IO)
+ /* no 8259 SLAVE to ignore */
+#else
+ if (intr==2) continue; /* ignore 8259 SLAVE output */
+#endif /* APIC_IO */
+ maskptr = intr_mptr[intr];
+ if (!maskptr) continue;
+ *maskptr |= 1 << intr;
+ mask = *maskptr;
+ if (mask != intr_mask[intr]) {
+#if 0
+ printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
+ intr, intr_mask[intr], mask, maskptr);
+#endif
+ intr_mask[intr]=mask;
+ n++;
+ }
+
+ }
+ return (n);
+}
+
+/*
+ * The find_device_id function is only required because of the way the
+ * device names are currently stored for reporting in systat or vmstat.
+ * In fact, those programs should be modified to use the sysctl interface
+ * to obtain a list of driver names by traversing intreclist_head[irq].
+ */
+static int
+find_device_id(int irq)
+{
+ char buf[16];
+ char *cp;
+ int free_id, id;
+
+ sprintf(buf, "pci irq%d", irq);
+ cp = intrnames;
+ /* default to 0, which corresponds to clk0 */
+ free_id = 0;
+
+ for (id = 0; id < NR_DEVICES; id++) {
+ if (strcmp(cp, buf) == 0)
+ return (id);
+ if (free_id == 0 && strcmp(cp, "pci irqnn") == 0)
+ free_id = id;
+ while (*cp++ != '\0');
+ }
+#if 0
+ if (free_id == 0) {
+ /*
+ * All pci irq counters are in use, perhaps because config
+ * is old so there aren't any. Abuse the clk0 counter.
+ */
+ printf("\tcounting shared irq%d as clk0 irq\n", irq);
+ }
+#endif
+ return (free_id);
+}
+
+void
+update_intrname(int intr, int device_id)
+{
+ char *cp;
+ int id;
+
+ if (device_id == -1)
+ device_id = find_device_id(intr);
+
+ if ((u_int)device_id >= NR_DEVICES)
+ return;
+
+ intr_countp[intr] = &intrcnt[device_id];
+
+ for (cp = intrnames, id = 0; id <= device_id; id++)
+ while (*cp++ != '\0')
+ ;
+ if (cp > eintrnames)
+ return;
+ if (intr < 10) {
+ cp[-3] = intr + '0';
+ cp[-2] = ' ';
+ } else if (intr < 20) {
+ cp[-3] = '1';
+ cp[-2] = intr - 10 + '0';
+ } else {
+ cp[-3] = '2';
+ cp[-2] = intr - 20 + '0';
+ }
+}
+
+
+int
+icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
+{
+ u_long ef;
+ u_int mask = (maskptr ? *maskptr : 0);
+
+#if defined(APIC_IO)
+ if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
+#else
+ if ((u_int)intr >= ICU_LEN || intr == 2)
+#endif /* APIC_IO */
+ if (intr_handler[intr] != isa_strayintr)
+ return (EBUSY);
+
+ ef = read_eflags();
+ disable_intr();
+ intr_handler[intr] = handler;
+ intr_mptr[intr] = maskptr;
+ intr_mask[intr] = mask | (1 << intr);
+ intr_unit[intr] = (int) arg;
+ setidt(ICU_OFFSET + intr,
+ flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ INTREN(1 << intr);
+ write_eflags(ef);
+ return (0);
+}
+
+void
+register_imask(dvp, mask)
+ struct isa_device *dvp;
+ u_int mask;
+{
+ if (dvp->id_alive && dvp->id_irq) {
+ int intr;
+
+ intr = ffs(dvp->id_irq) - 1;
+ intr_mask[intr] = mask | (1 <<intr);
+ }
+ (void) update_intr_masks();
+}
+
+int
+icu_unset(intr, handler)
+ int intr;
+ inthand2_t *handler;
+{
+ u_long ef;
+
+ if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
+ return (EINVAL);
+
+ INTRDIS(1 << intr);
+ ef = read_eflags();
+ disable_intr();
+ intr_countp[intr] = &intrcnt[NR_DEVICES + intr];
+ intr_handler[intr] = isa_strayintr;
+ intr_mptr[intr] = NULL;
+ intr_mask[intr] = HWI_MASK | SWI_MASK;
+ intr_unit[intr] = intr;
+ setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+ write_eflags(ef);
+ return (0);
+}
diff --git a/sys/i386/isa/intr_machdep.h b/sys/i386/isa/intr_machdep.h
new file mode 100644
index 0000000..a9a512e
--- /dev/null
+++ b/sys/i386/isa/intr_machdep.h
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
+ * $Id: isa_device.h,v 1.39 1997/04/27 21:18:58 fsmp Exp $
+ */
+
+#ifndef _I386_ISA_INTR_MACHDEP_H_
+#define _I386_ISA_INTR_MACHDEP_H_
+
+/*
+ * Low level interrupt code.
+ */
+
+#ifdef KERNEL
+
+/*
+ * Type of the first (asm) part of an interrupt handler.
+ */
+typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
+
+#define IDTVEC(name) __CONCAT(X,name)
+
+extern char eintrnames[]; /* end of intrnames[] */
+extern u_long intrcnt[]; /* counts for for each device and stray */
+extern char intrnames[]; /* string table containing device names */
+extern u_long *intr_countp[]; /* pointers into intrcnt[] */
+extern inthand2_t *intr_handler[]; /* C entry points of intr handlers */
+extern u_int intr_mask[]; /* sets of intrs masked during handling of 1 */
+extern int intr_unit[]; /* cookies to pass to intr handlers */
+
+inthand_t
+ IDTVEC(fastintr0), IDTVEC(fastintr1),
+ IDTVEC(fastintr2), IDTVEC(fastintr3),
+ IDTVEC(fastintr4), IDTVEC(fastintr5),
+ IDTVEC(fastintr6), IDTVEC(fastintr7),
+ IDTVEC(fastintr8), IDTVEC(fastintr9),
+ IDTVEC(fastintr10), IDTVEC(fastintr11),
+ IDTVEC(fastintr12), IDTVEC(fastintr13),
+ IDTVEC(fastintr14), IDTVEC(fastintr15);
+inthand_t
+ IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3),
+ IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7),
+ IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11),
+ IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15);
+
+/* these functions ONLY exist in an SMP/APIC_IO kernel: */
+inthand_t
+ IDTVEC(fastintr16), IDTVEC(fastintr17),
+ IDTVEC(fastintr18), IDTVEC(fastintr19),
+ IDTVEC(fastintr20), IDTVEC(fastintr21),
+ IDTVEC(fastintr22), IDTVEC(fastintr23);
+inthand_t
+ IDTVEC(intr16), IDTVEC(intr17), IDTVEC(intr18), IDTVEC(intr19),
+ IDTVEC(intr20), IDTVEC(intr21), IDTVEC(intr22), IDTVEC(intr23);
+#define XINVLTLB_OFFSET 32
+inthand_t
+ Xinvltlb;
+
+struct isa_device;
+
+void isa_defaultirq __P((void));
+int isa_irq_pending __P((struct isa_device *dvp));
+/* this function ONLY exists in an SMP/APIC_IO kernel: */
+int icu_irq_pending __P((struct isa_device *dvp));
+int isa_nmi __P((int cd));
+void update_intrname __P((int intr, int device_id));
+int icu_setup __P((int intr, inthand2_t *func, void *arg,
+ u_int *maskptr, int flags));
+int icu_unset __P((int intr, inthand2_t *handler));
+int update_intr_masks __P((void));
+void register_imask __P((struct isa_device *dvp, u_int mask));
+
+#endif /* KERNEL */
+
+#endif /* !_I386_ISA_INTR_MACHDEP_H_ */
diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c
index a54f7bb..ccadc08 100644
--- a/sys/i386/isa/isa.c
+++ b/sys/i386/isa/isa.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.87 1997/05/29 05:56:12 fsmp Exp $
+ * $Id: isa.c,v 1.88 1997/05/31 09:27:31 peter Exp $
*/
/*
@@ -47,8 +47,6 @@
* isa_dmastart()
*/
-#include "opt_auto_eoi.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
@@ -65,6 +63,7 @@
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/isa.h>
#include <i386/isa/icu.h>
#include <i386/isa/ic/i8237.h>
@@ -72,14 +71,6 @@
#include <sys/interrupt.h>
-#ifdef APIC_IO
-/*
- * This is to accommodate "mixed-mode" programming for
- * motherboards that don't connect the 8254 to the IO APIC.
- */
-#define AUTO_EOI_1
-#endif
-
/*
** Register definitions for DMA controller 1 (channels 0..3):
*/
@@ -96,40 +87,6 @@
#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
-u_long *intr_countp[ICU_LEN];
-inthand2_t *intr_handler[ICU_LEN];
-u_int intr_mask[ICU_LEN];
-u_int* intr_mptr[ICU_LEN];
-int intr_unit[ICU_LEN];
-
-static inthand_t *fastintr[ICU_LEN] = {
- &IDTVEC(fastintr0), &IDTVEC(fastintr1),
- &IDTVEC(fastintr2), &IDTVEC(fastintr3),
- &IDTVEC(fastintr4), &IDTVEC(fastintr5),
- &IDTVEC(fastintr6), &IDTVEC(fastintr7),
- &IDTVEC(fastintr8), &IDTVEC(fastintr9),
- &IDTVEC(fastintr10), &IDTVEC(fastintr11),
- &IDTVEC(fastintr12), &IDTVEC(fastintr13),
- &IDTVEC(fastintr14), &IDTVEC(fastintr15)
-#if defined(APIC_IO)
- , &IDTVEC(fastintr16), &IDTVEC(fastintr17),
- &IDTVEC(fastintr18), &IDTVEC(fastintr19),
- &IDTVEC(fastintr20), &IDTVEC(fastintr21),
- &IDTVEC(fastintr22), &IDTVEC(fastintr23)
-#endif /* APIC_IO */
-};
-
-static inthand_t *slowintr[ICU_LEN] = {
- &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
- &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
- &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
- &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
-#if defined(APIC_IO)
- , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
- &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23)
-#endif /* APIC_IO */
-};
-
static void config_isadev __P((struct isa_device *isdp, u_int *mp));
static void config_isadev_c __P((struct isa_device *isdp, u_int *mp,
int reconfig));
@@ -139,8 +96,6 @@ static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp,
static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp,
u_int checkbits));
static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan));
-static inthand2_t isa_strayintr;
-static void register_imask __P((struct isa_device *dvp, u_int mask));
/*
* print a conflict message
@@ -615,44 +570,6 @@ config_isadev_c(isdp, mp, reconfig)
}
}
-/*
- * Fill in default interrupt table (in case of spuruious interrupt
- * during configuration of kernel, setup interrupt control unit
- */
-void
-isa_defaultirq()
-{
- int i;
-
- /* icu vectors */
- for (i = 0; i < ICU_LEN; i++)
- icu_unset(i, (inthand2_t *)NULL);
-
- /* initialize 8259's */
- outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
- outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
- outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
-#ifdef AUTO_EOI_1
- outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
-#else
- outb(IO_ICU1+1, 1); /* 8086 mode */
-#endif
- outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
- outb(IO_ICU1, 0x0a); /* default to IRR on read */
- outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
-
- outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
- outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */
- outb(IO_ICU2+1,2); /* my slave id is 2 */
-#ifdef AUTO_EOI_2
- outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
-#else
- outb(IO_ICU2+1,1); /* 8086 mode */
-#endif
- outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
- outb(IO_ICU2, 0x0a); /* default to IRR on read */
-}
-
static caddr_t dma_bouncebuf[8];
static u_int dma_bouncebufsize[8];
static u_int8_t dma_bounced = 0;
@@ -956,70 +873,6 @@ isa_dmarangecheck(caddr_t va, u_int length, int chan) {
return (0);
}
-#define NMI_PARITY (1 << 7)
-#define NMI_IOCHAN (1 << 6)
-#define ENMI_WATCHDOG (1 << 7)
-#define ENMI_BUSTIMER (1 << 6)
-#define ENMI_IOSTATUS (1 << 5)
-
-/*
- * Handle a NMI, possibly a machine check.
- * return true to panic system, false to ignore.
- */
-int
-isa_nmi(cd)
- int cd;
-{
- int isa_port = inb(0x61);
- int eisa_port = inb(0x461);
- if(isa_port & NMI_PARITY) {
- panic("RAM parity error, likely hardware failure.");
- } else if(isa_port & NMI_IOCHAN) {
- panic("I/O channel check, likely hardware failure.");
- } else if(eisa_port & ENMI_WATCHDOG) {
- panic("EISA watchdog timer expired, likely hardware failure.");
- } else if(eisa_port & ENMI_BUSTIMER) {
- panic("EISA bus timeout, likely hardware failure.");
- } else if(eisa_port & ENMI_IOSTATUS) {
- panic("EISA I/O port status error.");
- } else {
- printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
- return(0);
- }
-}
-
-/*
- * Caught a stray interrupt, notify
- */
-static void
-isa_strayintr(d)
- int d;
-{
-
- /* DON'T BOTHER FOR NOW! */
- /* for some reason, we get bursts of intr #7, even if not enabled! */
- /*
- * Well the reason you got bursts of intr #7 is because someone
- * raised an interrupt line and dropped it before the 8259 could
- * prioritize it. This is documented in the intel data book. This
- * means you have BAD hardware! I have changed this so that only
- * the first 5 get logged, then it quits logging them, and puts
- * out a special message. rgrimes 3/25/1993
- */
- /*
- * XXX TODO print a different message for #7 if it is for a
- * glitch. Glitches can be distinguished from real #7's by
- * testing that the in-service bit is _not_ set. The test
- * must be done before sending an EOI so it can't be done if
- * we are using AUTO_EOI_1.
- */
- if (intrcnt[NR_DEVICES + d] <= 5)
- log(LOG_ERR, "stray irq %d\n", d);
- if (intrcnt[NR_DEVICES + d] == 5)
- log(LOG_CRIT,
- "too many stray irq %d's; not logging any more\n", d);
-}
-
/*
* Find the highest priority enabled display device. Since we can't
* distinguish display devices from ttys, depend on display devices
@@ -1067,210 +920,3 @@ struct isa_device *find_isadev(table, driverp, unit)
return (table);
}
-/*
- * Return nonzero if a (masked) irq is pending for a given device.
- */
-#if defined(APIC_IO)
-
-int
-isa_irq_pending(dvp)
- struct isa_device *dvp;
-{
- /* read APIC IRR containing the 16 ISA INTerrupts */
- return ((lapic__irr1 & 0x00ffffff)
- & (u_int32_t)dvp->id_irq) ? 1 : 0;
-}
-
-/*
- * an 8259 specific routine,
- * for use by boot probes in certain device drivers.
- */
-int
-icu_irq_pending(dvp)
- struct isa_device *dvp;
-{
- unsigned id_irq;
- id_irq = dvp->id_irq;
- if (id_irq & 0xff)
- return (inb(IO_ICU1) & id_irq);
- return (inb(IO_ICU2) & (id_irq >> 8));
-}
-
-#else /* APIC_IO */
-
-int
-isa_irq_pending(dvp)
- struct isa_device *dvp;
-{
- unsigned id_irq;
- id_irq = dvp->id_irq;
- if (id_irq & 0xff)
- return (inb(IO_ICU1) & id_irq);
- return (inb(IO_ICU2) & (id_irq >> 8));
-}
-
-#endif /* APIC_IO */
-
-int
-update_intr_masks(void)
-{
- int intr, n=0;
- u_int mask,*maskptr;
-
- for (intr=0; intr < ICU_LEN; intr ++) {
-#if defined(APIC_IO)
- /* no 8259 SLAVE to ignore */
-#else
- if (intr==2) continue; /* ignore 8259 SLAVE output */
-#endif /* APIC_IO */
- maskptr = intr_mptr[intr];
- if (!maskptr) continue;
- *maskptr |= 1 << intr;
- mask = *maskptr;
- if (mask != intr_mask[intr]) {
-#if 0
- printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
- intr, intr_mask[intr], mask, maskptr);
-#endif
- intr_mask[intr]=mask;
- n++;
- }
-
- }
- return (n);
-}
-
-/*
- * The find_device_id function is only required because of the way the
- * device names are currently stored for reporting in systat or vmstat.
- * In fact, those programs should be modified to use the sysctl interface
- * to obtain a list of driver names by traversing intreclist_head[irq].
- */
-
-static int
-find_device_id(int irq)
-{
- char buf[16];
- char *cp;
- int free_id, id;
-
- sprintf(buf, "pci irq%d", irq);
- cp = intrnames;
- /* default to 0, which corresponds to clk0 */
- free_id = 0;
-
- for (id = 0; id < NR_DEVICES; id++) {
- if (strcmp(cp, buf) == 0)
- return (id);
- if (free_id == 0 && strcmp(cp, "pci irqnn") == 0)
- free_id = id;
- while (*cp++ != '\0');
- }
-#if 0
- if (free_id == 0) {
- /*
- * All pci irq counters are in use, perhaps because config
- * is old so there aren't any. Abuse the clk0 counter.
- */
- printf("\tcounting shared irq%d as clk0 irq\n", irq);
- }
-#endif
- return (free_id);
-}
-
-void
-update_intrname(int intr, int device_id)
-{
- char *cp;
- int id;
-
- if (device_id == -1)
- device_id = find_device_id(intr);
-
- if ((u_int)device_id >= NR_DEVICES)
- return;
-
- intr_countp[intr] = &intrcnt[device_id];
-
- for (cp = intrnames, id = 0; id <= device_id; id++)
- while (*cp++ != '\0')
- ;
- if (cp > eintrnames)
- return;
- if (intr < 10) {
- cp[-3] = intr + '0';
- cp[-2] = ' ';
- } else if (intr < 20) {
- cp[-3] = '1';
- cp[-2] = intr - 10 + '0';
- } else {
- cp[-3] = '2';
- cp[-2] = intr - 20 + '0';
- }
-}
-
-int
-icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
-{
- u_long ef;
- u_int mask = (maskptr ? *maskptr : 0);
-
-#if defined(APIC_IO)
- if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
-#else
- if ((u_int)intr >= ICU_LEN || intr == 2)
-#endif /* APIC_IO */
- if (intr_handler[intr] != isa_strayintr)
- return (EBUSY);
-
- ef = read_eflags();
- disable_intr();
- intr_handler[intr] = handler;
- intr_mptr[intr] = maskptr;
- intr_mask[intr] = mask | (1 << intr);
- intr_unit[intr] = arg;
- setidt(ICU_OFFSET + intr,
- flags & RI_FAST ? fastintr[intr] : slowintr[intr],
- SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
- INTREN(1 << intr);
- write_eflags(ef);
- return (0);
-}
-
-static void
-register_imask(dvp, mask)
- struct isa_device *dvp;
- u_int mask;
-{
- if (dvp->id_alive && dvp->id_irq) {
- int intr;
-
- intr = ffs(dvp->id_irq) - 1;
- intr_mask[intr] = mask | (1 <<intr);
- }
- (void) update_intr_masks();
-}
-
-int
-icu_unset(intr, handler)
- int intr;
- inthand2_t *handler;
-{
- u_long ef;
-
- if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
- return (EINVAL);
-
- INTRDIS(1 << intr);
- ef = read_eflags();
- disable_intr();
- intr_countp[intr] = &intrcnt[NR_DEVICES + intr];
- intr_handler[intr] = isa_strayintr;
- intr_mptr[intr] = NULL;
- intr_mask[intr] = HWI_MASK | SWI_MASK;
- intr_unit[intr] = intr;
- setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- write_eflags(ef);
- return (0);
-}
diff --git a/sys/i386/isa/isa_device.h b/sys/i386/isa/isa_device.h
index dad1f4d..bf7c7a9 100644
--- a/sys/i386/isa/isa_device.h
+++ b/sys/i386/isa/isa_device.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
- * $Id: isa_device.h,v 1.40 1997/05/26 14:42:24 se Exp $
+ * $Id: isa_device.h,v 1.41 1997/05/31 09:07:36 peter Exp $
*/
#ifndef _I386_ISA_ISA_DEVICE_H_
@@ -41,13 +41,6 @@
* ISA Bus Autoconfiguration
*/
-#define IDTVEC(name) __CONCAT(X,name)
-
-/*
- * Type of the first (asm) part of an interrupt handler.
- */
-typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
-
/*
* Per device structure.
*
@@ -106,14 +99,6 @@ struct isa_driver {
#ifdef KERNEL
-extern char eintrnames[]; /* end of intrnames[] */
-extern u_long intrcnt[]; /* counts for for each device and stray */
-extern char intrnames[]; /* string table containing device names */
-extern u_long *intr_countp[]; /* pointers into intrcnt[] */
-extern inthand2_t *intr_handler[]; /* C entry points of intr handlers */
-extern u_int intr_mask[]; /* sets of intrs masked during handling of 1 */
-extern int intr_unit[]; /* cookies to pass to intr handlers */
-
extern struct isa_device isa_biotab_fdc[];
extern struct isa_device isa_biotab_wdc[];
extern struct isa_device isa_devtab_bio[];
@@ -121,34 +106,6 @@ extern struct isa_device isa_devtab_net[];
extern struct isa_device isa_devtab_null[];
extern struct isa_device isa_devtab_tty[];
-inthand_t
- IDTVEC(fastintr0), IDTVEC(fastintr1),
- IDTVEC(fastintr2), IDTVEC(fastintr3),
- IDTVEC(fastintr4), IDTVEC(fastintr5),
- IDTVEC(fastintr6), IDTVEC(fastintr7),
- IDTVEC(fastintr8), IDTVEC(fastintr9),
- IDTVEC(fastintr10), IDTVEC(fastintr11),
- IDTVEC(fastintr12), IDTVEC(fastintr13),
- IDTVEC(fastintr14), IDTVEC(fastintr15);
-inthand_t
- IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3),
- IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7),
- IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11),
- IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15);
-
-/* these functions ONLY exist in an SMP/APIC_IO kernel: */
-inthand_t
- IDTVEC(fastintr16), IDTVEC(fastintr17),
- IDTVEC(fastintr18), IDTVEC(fastintr19),
- IDTVEC(fastintr20), IDTVEC(fastintr21),
- IDTVEC(fastintr22), IDTVEC(fastintr23);
-inthand_t
- IDTVEC(intr16), IDTVEC(intr17), IDTVEC(intr18), IDTVEC(intr19),
- IDTVEC(intr20), IDTVEC(intr21), IDTVEC(intr22), IDTVEC(intr23);
-#define XINVLTLB_OFFSET 32
-inthand_t
- Xinvltlb;
-
struct isa_device *
find_display __P((void));
struct isa_device *
@@ -156,23 +113,13 @@ struct isa_device *
int unit));
int haveseen_isadev __P((struct isa_device *dvp, u_int checkbits));
void isa_configure __P((void));
-void isa_defaultirq __P((void));
void isa_dmacascade __P((int chan));
void isa_dmadone __P((int flags, caddr_t addr, int nbytes, int chan));
void isa_dmainit __P((int chan, u_int bouncebufsize));
void isa_dmastart __P((int flags, caddr_t addr, u_int nbytes, int chan));
int isa_dma_acquire __P((int chan));
void isa_dma_release __P((int chan));
-int isa_irq_pending __P((struct isa_device *dvp));
-/* this function ONLY exists in an SMP/APIC_IO kernel: */
-int icu_irq_pending __P((struct isa_device *dvp));
-int isa_nmi __P((int cd));
void reconfig_isadev __P((struct isa_device *isdp, u_int *mp));
-void update_intrname __P((int intr, int device_id));
-int icu_setup __P((int intr, inthand2_t *func, void *arg,
- u_int *maskptr, int flags));
-int icu_unset __P((int intr, inthand2_t *handler));
-int update_intr_masks __P((void));
#endif /* KERNEL */
diff --git a/sys/i386/isa/nmi.c b/sys/i386/isa/nmi.c
new file mode 100644
index 0000000..40acb8e
--- /dev/null
+++ b/sys/i386/isa/nmi.c
@@ -0,0 +1,418 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
+ * $Id: isa.c,v 1.85 1997/05/26 14:42:24 se Exp $
+ */
+
+#include "opt_auto_eoi.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <machine/ipl.h>
+#include <machine/md_var.h>
+#include <machine/segments.h>
+#if defined(APIC_IO)
+#include <machine/smp.h>
+#include <machine/apic.h>
+#endif /* APIC_IO */
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/isa.h>
+#include <i386/isa/icu.h>
+#include <i386/isa/ic/i8237.h>
+#include "vector.h"
+
+#include <i386/isa/intr_machdep.h>
+#include <sys/interrupt.h>
+
+#ifdef APIC_IO
+/*
+ * This is to accommodate "mixed-mode" programming for
+ * motherboards that don't connect the 8254 to the IO APIC.
+ */
+#define AUTO_EOI_1
+#endif
+
+u_long *intr_countp[ICU_LEN];
+inthand2_t *intr_handler[ICU_LEN];
+u_int intr_mask[ICU_LEN];
+u_int* intr_mptr[ICU_LEN];
+int intr_unit[ICU_LEN];
+
+static inthand_t *fastintr[ICU_LEN] = {
+ &IDTVEC(fastintr0), &IDTVEC(fastintr1),
+ &IDTVEC(fastintr2), &IDTVEC(fastintr3),
+ &IDTVEC(fastintr4), &IDTVEC(fastintr5),
+ &IDTVEC(fastintr6), &IDTVEC(fastintr7),
+ &IDTVEC(fastintr8), &IDTVEC(fastintr9),
+ &IDTVEC(fastintr10), &IDTVEC(fastintr11),
+ &IDTVEC(fastintr12), &IDTVEC(fastintr13),
+ &IDTVEC(fastintr14), &IDTVEC(fastintr15)
+#if defined(APIC_IO)
+ , &IDTVEC(fastintr16), &IDTVEC(fastintr17),
+ &IDTVEC(fastintr18), &IDTVEC(fastintr19),
+ &IDTVEC(fastintr20), &IDTVEC(fastintr21),
+ &IDTVEC(fastintr22), &IDTVEC(fastintr23)
+#endif /* APIC_IO */
+};
+
+static inthand_t *slowintr[ICU_LEN] = {
+ &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
+ &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
+ &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
+ &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
+#if defined(APIC_IO)
+ , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
+ &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23)
+#endif /* APIC_IO */
+};
+
+static inthand2_t isa_strayintr;
+
+#define NMI_PARITY (1 << 7)
+#define NMI_IOCHAN (1 << 6)
+#define ENMI_WATCHDOG (1 << 7)
+#define ENMI_BUSTIMER (1 << 6)
+#define ENMI_IOSTATUS (1 << 5)
+
+/*
+ * Handle a NMI, possibly a machine check.
+ * return true to panic system, false to ignore.
+ */
+int
+isa_nmi(cd)
+ int cd;
+{
+ int isa_port = inb(0x61);
+ int eisa_port = inb(0x461);
+ if(isa_port & NMI_PARITY) {
+ panic("RAM parity error, likely hardware failure.");
+ } else if(isa_port & NMI_IOCHAN) {
+ panic("I/O channel check, likely hardware failure.");
+ } else if(eisa_port & ENMI_WATCHDOG) {
+ panic("EISA watchdog timer expired, likely hardware failure.");
+ } else if(eisa_port & ENMI_BUSTIMER) {
+ panic("EISA bus timeout, likely hardware failure.");
+ } else if(eisa_port & ENMI_IOSTATUS) {
+ panic("EISA I/O port status error.");
+ } else {
+ printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
+ return(0);
+ }
+}
+
+/*
+ * Fill in default interrupt table (in case of spuruious interrupt
+ * during configuration of kernel, setup interrupt control unit
+ */
+void
+isa_defaultirq()
+{
+ int i;
+
+ /* icu vectors */
+ for (i = 0; i < ICU_LEN; i++)
+ icu_unset(i, (inthand2_t *)NULL);
+
+ /* initialize 8259's */
+ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
+ outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
+#ifdef AUTO_EOI_1
+ outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU1+1, 1); /* 8086 mode */
+#endif
+ outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU1, 0x0a); /* default to IRR on read */
+ outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
+
+ outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
+ outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */
+ outb(IO_ICU2+1,2); /* my slave id is 2 */
+#ifdef AUTO_EOI_2
+ outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU2+1,1); /* 8086 mode */
+#endif
+ outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU2, 0x0a); /* default to IRR on read */
+}
+
+/*
+ * Caught a stray interrupt, notify
+ */
+static void
+isa_strayintr(d)
+ int d;
+{
+
+ /* DON'T BOTHER FOR NOW! */
+ /* for some reason, we get bursts of intr #7, even if not enabled! */
+ /*
+ * Well the reason you got bursts of intr #7 is because someone
+ * raised an interrupt line and dropped it before the 8259 could
+ * prioritize it. This is documented in the intel data book. This
+ * means you have BAD hardware! I have changed this so that only
+ * the first 5 get logged, then it quits logging them, and puts
+ * out a special message. rgrimes 3/25/1993
+ */
+ /*
+ * XXX TODO print a different message for #7 if it is for a
+ * glitch. Glitches can be distinguished from real #7's by
+ * testing that the in-service bit is _not_ set. The test
+ * must be done before sending an EOI so it can't be done if
+ * we are using AUTO_EOI_1.
+ */
+ if (intrcnt[NR_DEVICES + d] <= 5)
+ log(LOG_ERR, "stray irq %d\n", d);
+ if (intrcnt[NR_DEVICES + d] == 5)
+ log(LOG_CRIT,
+ "too many stray irq %d's; not logging any more\n", d);
+}
+
+/*
+ * Return nonzero if a (masked) irq is pending for a given device.
+ */
+#if defined(APIC_IO)
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ /* read APIC IRR containing the 16 ISA INTerrupts */
+ return ((lapic__irr1 & 0x00ffffff)
+ & (u_int32_t)dvp->id_irq) ? 1 : 0;
+}
+
+/*
+ * an 8259 specific routine,
+ * for use by boot probes in certain device drivers.
+ */
+int
+icu_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#else /* APIC_IO */
+
+int
+isa_irq_pending(dvp)
+ struct isa_device *dvp;
+{
+ unsigned id_irq;
+ id_irq = dvp->id_irq;
+ if (id_irq & 0xff)
+ return (inb(IO_ICU1) & id_irq);
+ return (inb(IO_ICU2) & (id_irq >> 8));
+}
+
+#endif /* APIC_IO */
+
+int
+update_intr_masks(void)
+{
+ int intr, n=0;
+ u_int mask,*maskptr;
+
+ for (intr=0; intr < ICU_LEN; intr ++) {
+#if defined(APIC_IO)
+ /* no 8259 SLAVE to ignore */
+#else
+ if (intr==2) continue; /* ignore 8259 SLAVE output */
+#endif /* APIC_IO */
+ maskptr = intr_mptr[intr];
+ if (!maskptr) continue;
+ *maskptr |= 1 << intr;
+ mask = *maskptr;
+ if (mask != intr_mask[intr]) {
+#if 0
+ printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
+ intr, intr_mask[intr], mask, maskptr);
+#endif
+ intr_mask[intr]=mask;
+ n++;
+ }
+
+ }
+ return (n);
+}
+
+/*
+ * The find_device_id function is only required because of the way the
+ * device names are currently stored for reporting in systat or vmstat.
+ * In fact, those programs should be modified to use the sysctl interface
+ * to obtain a list of driver names by traversing intreclist_head[irq].
+ */
+static int
+find_device_id(int irq)
+{
+ char buf[16];
+ char *cp;
+ int free_id, id;
+
+ sprintf(buf, "pci irq%d", irq);
+ cp = intrnames;
+ /* default to 0, which corresponds to clk0 */
+ free_id = 0;
+
+ for (id = 0; id < NR_DEVICES; id++) {
+ if (strcmp(cp, buf) == 0)
+ return (id);
+ if (free_id == 0 && strcmp(cp, "pci irqnn") == 0)
+ free_id = id;
+ while (*cp++ != '\0');
+ }
+#if 0
+ if (free_id == 0) {
+ /*
+ * All pci irq counters are in use, perhaps because config
+ * is old so there aren't any. Abuse the clk0 counter.
+ */
+ printf("\tcounting shared irq%d as clk0 irq\n", irq);
+ }
+#endif
+ return (free_id);
+}
+
+void
+update_intrname(int intr, int device_id)
+{
+ char *cp;
+ int id;
+
+ if (device_id == -1)
+ device_id = find_device_id(intr);
+
+ if ((u_int)device_id >= NR_DEVICES)
+ return;
+
+ intr_countp[intr] = &intrcnt[device_id];
+
+ for (cp = intrnames, id = 0; id <= device_id; id++)
+ while (*cp++ != '\0')
+ ;
+ if (cp > eintrnames)
+ return;
+ if (intr < 10) {
+ cp[-3] = intr + '0';
+ cp[-2] = ' ';
+ } else if (intr < 20) {
+ cp[-3] = '1';
+ cp[-2] = intr - 10 + '0';
+ } else {
+ cp[-3] = '2';
+ cp[-2] = intr - 20 + '0';
+ }
+}
+
+
+int
+icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
+{
+ u_long ef;
+ u_int mask = (maskptr ? *maskptr : 0);
+
+#if defined(APIC_IO)
+ if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
+#else
+ if ((u_int)intr >= ICU_LEN || intr == 2)
+#endif /* APIC_IO */
+ if (intr_handler[intr] != isa_strayintr)
+ return (EBUSY);
+
+ ef = read_eflags();
+ disable_intr();
+ intr_handler[intr] = handler;
+ intr_mptr[intr] = maskptr;
+ intr_mask[intr] = mask | (1 << intr);
+ intr_unit[intr] = (int) arg;
+ setidt(ICU_OFFSET + intr,
+ flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ INTREN(1 << intr);
+ write_eflags(ef);
+ return (0);
+}
+
+void
+register_imask(dvp, mask)
+ struct isa_device *dvp;
+ u_int mask;
+{
+ if (dvp->id_alive && dvp->id_irq) {
+ int intr;
+
+ intr = ffs(dvp->id_irq) - 1;
+ intr_mask[intr] = mask | (1 <<intr);
+ }
+ (void) update_intr_masks();
+}
+
+int
+icu_unset(intr, handler)
+ int intr;
+ inthand2_t *handler;
+{
+ u_long ef;
+
+ if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
+ return (EINVAL);
+
+ INTRDIS(1 << intr);
+ ef = read_eflags();
+ disable_intr();
+ intr_countp[intr] = &intrcnt[NR_DEVICES + intr];
+ intr_handler[intr] = isa_strayintr;
+ intr_mptr[intr] = NULL;
+ intr_mask[intr] = HWI_MASK | SWI_MASK;
+ intr_unit[intr] = intr;
+ setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+ write_eflags(ef);
+ return (0);
+}
diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c
index d364f4f..aca74fa 100644
--- a/sys/i386/isa/npx.c
+++ b/sys/i386/isa/npx.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)npx.c 7.2 (Berkeley) 5/12/91
- * $Id: npx.c,v 1.43 1997/05/07 19:58:13 peter Exp $
+ * $Id: npx.c,v 1.44 1997/05/31 09:27:31 peter Exp $
*/
#include "npx.h"
@@ -69,6 +69,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/isa.h>
/*
diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c
index 13e66f5..4ae5c36 100644
--- a/sys/isa/atrtc.c
+++ b/sys/isa/atrtc.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.85 1997/05/29 05:00:35 peter Exp $
+ * $Id: clock.c,v 1.86 1997/05/31 09:27:30 peter Exp $
*/
/*
@@ -67,7 +67,7 @@
#include <i386/isa/icu.h>
#include <i386/isa/isa.h>
-#include <i386/isa/isa_device.h>
+#include <i386/isa/intr_machdep.h>
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 3f7feaf..6e258ab 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: kern_intr.c,v 1.3 1997/05/31 09:30:39 peter Exp $
+ * $Id: kern_intr.c,v 1.4 1997/06/01 16:05:13 peter Exp $
*
*/
@@ -37,8 +37,8 @@
#endif /* RESOURCE_CHECK */
#include <i386/isa/icu.h>
-#include <i386/isa/isa_device.h>
-#include <sys/interrupt.h> /* XXX needs inthand2_t from isa_device.h */
+#include <i386/isa/intr_machdep.h>
+#include <sys/interrupt.h>
#include <machine/ipl.h>
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index d508788..f73c4f2 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.96 1997/05/29 05:04:30 peter Exp $
+ * $Id: trap.c,v 1.97 1997/05/31 09:27:29 peter Exp $
*/
/*
@@ -76,7 +76,7 @@
#include <machine/psl.h>
#include <machine/reg.h>
#include <machine/trap.h>
-#include <machine/../isa/isa_device.h>
+#include <machine/../isa/intr_machdep.h>
#include <machine/smp.h>
#ifdef POWERFAIL_NMI
diff --git a/sys/net/ppp_tty.c b/sys/net/ppp_tty.c
index f0a0408..87f6840d 100644
--- a/sys/net/ppp_tty.c
+++ b/sys/net/ppp_tty.c
@@ -70,7 +70,7 @@
* Paul Mackerras (paulus@cs.anu.edu.au).
*/
-/* $Id: ppp_tty.c,v 1.16 1997/05/31 09:49:35 peter Exp $ */
+/* $Id: ppp_tty.c,v 1.17 1997/05/31 10:13:46 peter Exp $ */
/* from Id: ppp_tty.c,v 1.3 1995/08/16 01:36:40 paulus Exp */
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
@@ -96,7 +96,7 @@
#define KERNEL
#ifdef i386 /* fiddle with the spl locking */
-# include <i386/isa/isa_device.h>
+# include <i386/isa/intr_machdep.h>
#endif
#include <net/if.h>
OpenPOWER on IntegriCloud