summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/alpha/isa/isa.c6
-rw-r--r--sys/alpha/pci/pcibus.c37
-rw-r--r--sys/amd64/amd64/legacy.c13
-rw-r--r--sys/amd64/amd64/nexus.c13
-rw-r--r--sys/amd64/amd64/tsc.c28
-rw-r--r--sys/amd64/isa/clock.c28
-rw-r--r--sys/amd64/isa/intr_machdep.c468
-rw-r--r--sys/amd64/isa/intr_machdep.h19
-rw-r--r--sys/amd64/isa/isa_dma.c3
-rw-r--r--sys/amd64/isa/nmi.c468
-rw-r--r--sys/cam/cam_xpt.c4
-rw-r--r--sys/dev/ata/ata-all.c61
-rw-r--r--sys/i386/i386/legacy.c13
-rw-r--r--sys/i386/i386/nexus.c13
-rw-r--r--sys/i386/i386/tsc.c28
-rw-r--r--sys/i386/include/types.h3
-rw-r--r--sys/i386/isa/clock.c28
-rw-r--r--sys/i386/isa/intr_machdep.c468
-rw-r--r--sys/i386/isa/intr_machdep.h19
-rw-r--r--sys/i386/isa/ipl_funcs.c10
-rw-r--r--sys/i386/isa/isa_device.h4
-rw-r--r--sys/i386/isa/isa_dma.c3
-rw-r--r--sys/i386/isa/nmi.c468
-rw-r--r--sys/i386/isa/random_machdep.c3
-rw-r--r--sys/isa/atrtc.c28
-rw-r--r--sys/isa/isavar.h6
-rw-r--r--sys/kern/kern_intr.c406
-rw-r--r--sys/kern/kern_random.c3
-rw-r--r--sys/pci/intpm.c12
-rw-r--r--sys/sys/interrupt.h23
-rw-r--r--sys/sys/systm.h5
31 files changed, 1888 insertions, 803 deletions
diff --git a/sys/alpha/isa/isa.c b/sys/alpha/isa/isa.c
index 5b6b54e..db1104c 100644
--- a/sys/alpha/isa/isa.c
+++ b/sys/alpha/isa/isa.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: isa.c,v 1.9 1999/01/23 16:53:27 dfr Exp $
+ * $Id: isa.c,v 1.10 1999/04/16 21:21:37 peter Exp $
*/
#include <sys/param.h>
@@ -202,7 +202,7 @@ isa_intr_disable(int irq)
splx(s);
}
-int
+intrmask_t
isa_irq_pending(void)
{
u_char irr1;
@@ -213,7 +213,7 @@ isa_irq_pending(void)
return ((irr2 << 8) | irr1);
}
-int
+intrmask_t
isa_irq_mask(void)
{
u_char irr1;
diff --git a/sys/alpha/pci/pcibus.c b/sys/alpha/pci/pcibus.c
index f6cde88..f0c0eb2 100644
--- a/sys/alpha/pci/pcibus.c
+++ b/sys/alpha/pci/pcibus.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: pcibus.c,v 1.9 1999/04/16 21:21:39 peter Exp $
+ * $Id: pcibus.c,v 1.10 1999/04/19 08:55:11 dfr Exp $
*
*/
@@ -131,41 +131,6 @@ pci_cvt_to_bwx(vm_offset_t sparse)
return NULL;
}
-#if 0
-
-/*
- * These can disappear when I update the pci code to use the new
- * device framework.
- */
-struct intrec *
-intr_create(void *dev_instance, int irq, inthand2_t handler, void *arg,
- intrmask_t *maskptr, int flags)
-{
- struct resource *res;
- device_t pcib = chipset.intrdev;
- int zero = 0;
- void *cookie;
-
- res = BUS_ALLOC_RESOURCE(pcib, NULL, SYS_RES_IRQ, &zero,
- irq, irq, 1, RF_SHAREABLE | RF_ACTIVE);
- if (BUS_SETUP_INTR(pcib, pcib, res, (driver_intr_t *)handler, arg, &cookie))
- return 0;
-
- return (struct intrec *)cookie;
-}
-
-int
-intr_connect(struct intrec *idesc)
-{
- /*
- * intr_create has already connected it (doesn't matter for the
- * only consumer of this interface (pci).
- */
- return 0;
-}
-
-#endif
-
void
alpha_platform_assign_pciintr(pcicfgregs *cfg)
{
diff --git a/sys/amd64/amd64/legacy.c b/sys/amd64/amd64/legacy.c
index 0cf03f0..cfb7b03 100644
--- a/sys/amd64/amd64/legacy.c
+++ b/sys/amd64/amd64/legacy.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: nexus.c,v 1.2 1999/04/18 14:30:55 kato Exp $
+ * $Id: nexus.c,v 1.3 1999/04/19 08:04:19 peter Exp $
*/
/*
@@ -305,6 +305,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
intrmask_t *mask;
driver_t *driver;
int error, icflags;
+ char name[32];
if (child)
device_printf(child, "interrupting at irq %d\n",
@@ -348,11 +349,11 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
if (error)
return (error);
- *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg,
+ snprintf(name, sizeof(name), "%s%d", device_get_name(child),
+ device_get_unit(child));
+ *cookiep = inthand_add(name, irq->r_start, ihand, arg,
mask, icflags);
- if (*cookiep)
- error = intr_connect(*cookiep);
- else
+ if (*cookiep == NULL)
error = EINVAL; /* XXX ??? */
return (error);
@@ -361,7 +362,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
- return (intr_destroy(ih));
+ return (inthand_remove(ih));
}
static devclass_t pcib_devclass;
diff --git a/sys/amd64/amd64/nexus.c b/sys/amd64/amd64/nexus.c
index 0cf03f0..cfb7b03 100644
--- a/sys/amd64/amd64/nexus.c
+++ b/sys/amd64/amd64/nexus.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: nexus.c,v 1.2 1999/04/18 14:30:55 kato Exp $
+ * $Id: nexus.c,v 1.3 1999/04/19 08:04:19 peter Exp $
*/
/*
@@ -305,6 +305,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
intrmask_t *mask;
driver_t *driver;
int error, icflags;
+ char name[32];
if (child)
device_printf(child, "interrupting at irq %d\n",
@@ -348,11 +349,11 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
if (error)
return (error);
- *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg,
+ snprintf(name, sizeof(name), "%s%d", device_get_name(child),
+ device_get_unit(child));
+ *cookiep = inthand_add(name, irq->r_start, ihand, arg,
mask, icflags);
- if (*cookiep)
- error = intr_connect(*cookiep);
- else
+ if (*cookiep == NULL)
error = EINVAL; /* XXX ??? */
return (error);
@@ -361,7 +362,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
- return (intr_destroy(ih));
+ return (inthand_remove(ih));
}
static devclass_t pcib_devclass;
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c
index d9bca71..3daaf94 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.128 1998/10/23 10:46:20 phk Exp $
+ * $Id: clock.c,v 1.129 1998/12/14 13:30:29 mckay Exp $
*/
/*
@@ -86,7 +86,7 @@
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
-#include <sys/interrupt.h>
+#include <i386/isa/intr_machdep.h>
#ifdef SMP
#define disable_intr() CLOCK_DISABLE_INTR()
@@ -948,6 +948,7 @@ cpu_initclocks()
int diag;
#ifdef APIC_IO
int apic_8254_trial;
+ intrec *clkdesc;
#endif /* APIC_IO */
if (statclock_disable) {
@@ -982,16 +983,14 @@ cpu_initclocks()
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
}
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
#else /* APIC_IO */
- register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
+ INTR_EXCL);
INTREN(IRQ0);
#endif /* APIC_IO */
@@ -1012,9 +1011,8 @@ cpu_initclocks()
panic("APIC RTC != 8");
#endif /* APIC_IO */
- register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
- /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
- /* unit */ 0);
+ inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
+ INTR_EXCL);
#ifdef APIC_IO
INTREN(APIC_IRQ8);
@@ -1038,17 +1036,15 @@ cpu_initclocks()
* Workaround: Limited variant of mixed mode.
*/
INTRDIS(1 << apic_8254_intr);
- unregister_intr(apic_8254_intr,
- /* XXX */ (inthand2_t *) clkintr);
+ inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
"8254 is not connected to IO APIC int pin %d\n",
apic_8254_intr);
apic_8254_intr = 0;
setup_8254_mixed_mode();
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index d9bca71..3daaf94 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.128 1998/10/23 10:46:20 phk Exp $
+ * $Id: clock.c,v 1.129 1998/12/14 13:30:29 mckay Exp $
*/
/*
@@ -86,7 +86,7 @@
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
-#include <sys/interrupt.h>
+#include <i386/isa/intr_machdep.h>
#ifdef SMP
#define disable_intr() CLOCK_DISABLE_INTR()
@@ -948,6 +948,7 @@ cpu_initclocks()
int diag;
#ifdef APIC_IO
int apic_8254_trial;
+ intrec *clkdesc;
#endif /* APIC_IO */
if (statclock_disable) {
@@ -982,16 +983,14 @@ cpu_initclocks()
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
}
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
#else /* APIC_IO */
- register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
+ INTR_EXCL);
INTREN(IRQ0);
#endif /* APIC_IO */
@@ -1012,9 +1011,8 @@ cpu_initclocks()
panic("APIC RTC != 8");
#endif /* APIC_IO */
- register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
- /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
- /* unit */ 0);
+ inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
+ INTR_EXCL);
#ifdef APIC_IO
INTREN(APIC_IRQ8);
@@ -1038,17 +1036,15 @@ cpu_initclocks()
* Workaround: Limited variant of mixed mode.
*/
INTRDIS(1 << apic_8254_intr);
- unregister_intr(apic_8254_intr,
- /* XXX */ (inthand2_t *) clkintr);
+ inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
"8254 is not connected to IO APIC int pin %d\n",
apic_8254_intr);
apic_8254_intr = 0;
setup_8254_mixed_mode();
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c
index 4f7c1e9..256c617 100644
--- a/sys/amd64/isa/intr_machdep.c
+++ b/sys/amd64/isa/intr_machdep.c
@@ -34,7 +34,13 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $
+ * $Id: intr_machdep.c,v 1.18 1999/04/16 21:22:22 peter Exp $
+ */
+/*
+ * This file contains an aggregated module marked:
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * All rights reserved.
+ * See the notice for details.
*/
#include "opt_auto_eoi.h"
@@ -45,9 +51,14 @@
#endif
#include <sys/systm.h>
#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <sys/interrupt.h>
#include <machine/ipl.h>
#include <machine/md_var.h>
#include <machine/segments.h>
+#include <sys/bus.h>
+
#if defined(APIC_IO)
#include <machine/smp.h>
#include <machine/smptests.h> /** FAST_HI */
@@ -62,6 +73,7 @@
#endif
#include <i386/isa/icu.h>
+#include <isa/isavar.h>
#include <i386/isa/intr_machdep.h>
#include <sys/interrupt.h>
#ifdef APIC_IO
@@ -300,7 +312,8 @@ update_intr_masks(void)
if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */
#endif /* APIC_IO */
maskptr = intr_mptr[intr];
- if (!maskptr) continue;
+ if (!maskptr)
+ continue;
*maskptr |= 1 << intr;
mask = *maskptr;
if (mask != intr_mask[intr]) {
@@ -316,48 +329,11 @@ update_intr_masks(void)
return (n);
}
-static const char *
-isa_get_nameunit(int id)
-{
- static char buf[32];
- struct isa_device *dp;
-
- if (id == -1)
- return ("pci"); /* XXX may also be eisa */
- if (id == 0)
- return ("clk0"); /* XXX may also be sloppy driver */
- if (id == 1)
- return ("rtc0");
-#if 0
- for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_cam; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_net; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_null; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
-#endif
- return "???";
-
-found_device:
- snprintf(buf, sizeof(buf), "%s%d", dp->id_driver->name, dp->id_unit);
- return (buf);
-}
-
-void
-update_intrname(int intr, int device_id)
+static void
+update_intrname(int intr, char *name)
{
char buf[32];
char *cp;
- const char *name;
int name_index, off, strayintr;
/*
@@ -371,7 +347,8 @@ update_intrname(int intr, int device_id)
strayintr) + 1;
}
- name = isa_get_nameunit(device_id);
+ if (name == NULL)
+ name = "???";
if (snprintf(buf, sizeof(buf), "%s irq%d", name, intr) >= sizeof(buf))
goto use_bitbucket;
@@ -516,3 +493,410 @@ icu_unset(intr, handler)
write_eflags(ef);
return (0);
}
+
+/* The following notice applies beyond this point in the file */
+
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $Id: kern_intr.c,v 1.21 1998/11/10 09:16:29 peter Exp $
+ *
+ */
+
+typedef struct intrec {
+ intrmask_t mask;
+ inthand2_t *handler;
+ void *argument;
+ struct intrec *next;
+ char *name;
+ int intr;
+ intrmask_t *maskptr;
+ int flags;
+} intrec;
+
+static intrec *intreclist_head[ICU_LEN];
+
+typedef struct isarec {
+ int id_unit;
+ ointhand2_t *id_handler;
+} isarec;
+
+static isarec *isareclist[ICU_LEN];
+
+/*
+ * The interrupt multiplexer calls each of the handlers in turn,
+ * and applies the associated interrupt mask to "cpl", which is
+ * defined as a ".long" in /sys/i386/isa/ipl.s
+ */
+
+static void
+intr_mux(void *arg)
+{
+ intrec *p = arg;
+ int oldspl;
+
+ while (p != NULL) {
+ oldspl = splq(p->mask);
+ p->handler(p->argument);
+ splx(oldspl);
+ p = p->next;
+ }
+}
+
+static void
+isa_intr_wrap(void *cookie)
+{
+ isarec *irec = (isarec *)cookie;
+
+ irec->id_handler(irec->id_unit);
+}
+
+static intrec*
+find_idesc(unsigned *maskptr, int irq)
+{
+ intrec *p = intreclist_head[irq];
+
+ while (p && p->maskptr != maskptr)
+ p = p->next;
+
+ return (p);
+}
+
+static intrec**
+find_pred(intrec *idesc, int irq)
+{
+ intrec **pp = &intreclist_head[irq];
+ intrec *p = *pp;
+
+ while (p != idesc) {
+ if (p == NULL)
+ return (NULL);
+ pp = &p->next;
+ p = *pp;
+ }
+ return (pp);
+}
+
+/*
+ * Both the low level handler and the shared interrupt multiplexer
+ * block out further interrupts as set in the handlers "mask", while
+ * the handler is running. In fact *maskptr should be used for this
+ * purpose, but since this requires one more pointer dereference on
+ * each interrupt, we rather bother update "mask" whenever *maskptr
+ * changes. The function "update_masks" should be called **after**
+ * all manipulation of the linked list of interrupt handlers hung
+ * off of intrdec_head[irq] is complete, since the chain of handlers
+ * will both determine the *maskptr values and the instances of mask
+ * that are fixed. This function should be called with the irq for
+ * which a new handler has been add blocked, since the masks may not
+ * yet know about the use of this irq for a device of a certain class.
+ */
+
+static void
+update_mux_masks(void)
+{
+ int irq;
+ for (irq = 0; irq < ICU_LEN; irq++) {
+ intrec *idesc = intreclist_head[irq];
+ while (idesc != NULL) {
+ if (idesc->maskptr != NULL) {
+ /* our copy of *maskptr may be stale, refresh */
+ idesc->mask = *idesc->maskptr;
+ }
+ idesc = idesc->next;
+ }
+ }
+}
+
+static void
+update_masks(intrmask_t *maskptr, int irq)
+{
+ intrmask_t mask = 1 << irq;
+
+ if (maskptr == NULL)
+ return;
+
+ if (find_idesc(maskptr, irq) == NULL) {
+ /* no reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) == 0)
+ return;
+ /* the irq was included in the classes mask, remove it */
+ INTRUNMASK(*maskptr, mask);
+ } else {
+ /* a reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) != 0)
+ return;
+ /* put the irq into the classes mask */
+ INTRMASK(*maskptr, mask);
+ }
+ /* we need to update all values in the intr_mask[irq] array */
+ update_intr_masks();
+ /* update mask in chains of the interrupt multiplex handler as well */
+ update_mux_masks();
+}
+
+/*
+ * Add interrupt handler to linked list hung off of intreclist_head[irq]
+ * and install shared interrupt multiplex handler, if necessary
+ */
+
+static int
+add_intrdesc(intrec *idesc)
+{
+ int irq = idesc->intr;
+
+ intrec *head = intreclist_head[irq];
+
+ if (head == NULL) {
+ /* first handler for this irq, just install it */
+ if (icu_setup(irq, idesc->handler, idesc->argument,
+ idesc->maskptr, idesc->flags) != 0)
+ return (-1);
+
+ update_intrname(irq, idesc->name);
+ /* keep reference */
+ intreclist_head[irq] = idesc;
+ } else {
+ if ((idesc->flags & INTR_EXCL) != 0
+ || (head->flags & INTR_EXCL) != 0) {
+ /*
+ * can't append new handler, if either list head or
+ * new handler do not allow interrupts to be shared
+ */
+ if (bootverbose)
+ printf("\tdevice combination doesn't support "
+ "shared irq%d\n", irq);
+ return (-1);
+ }
+ if (head->next == NULL) {
+ /*
+ * second handler for this irq, replace device driver's
+ * handler by shared interrupt multiplexer function
+ */
+ icu_unset(irq, head->handler);
+ if (icu_setup(irq, intr_mux, head, 0, 0) != 0)
+ return (-1);
+ if (bootverbose)
+ printf("\tusing shared irq%d.\n", irq);
+ update_intrname(irq, "mux");
+ }
+ /* just append to the end of the chain */
+ while (head->next != NULL)
+ head = head->next;
+ head->next = idesc;
+ }
+ update_masks(idesc->maskptr, irq);
+ return (0);
+}
+
+/*
+ * Create and activate an interrupt handler descriptor data structure.
+ *
+ * The dev_instance pointer is required for resource management, and will
+ * only be passed through to resource_claim().
+ *
+ * There will be functions that derive a driver and unit name from a
+ * dev_instance variable, and those functions will be used to maintain the
+ * interrupt counter label array referenced by systat and vmstat to report
+ * device interrupt rates (->update_intrlabels).
+ *
+ * Add the interrupt handler descriptor data structure created by an
+ * earlier call of create_intr() to the linked list for its irq and
+ * adjust the interrupt masks if necessary.
+ */
+
+intrec *
+inthand_add(const char *name, int irq, inthand2_t handler, void *arg,
+ intrmask_t *maskptr, int flags)
+{
+ intrec *idesc;
+ int errcode = -1;
+ intrmask_t oldspl;
+
+ if (ICU_LEN > 8 * sizeof *maskptr) {
+ printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n",
+ ICU_LEN, 8 * sizeof *maskptr);
+ return (NULL);
+ }
+ if ((unsigned)irq >= ICU_LEN) {
+ printf("create_intr: requested irq%d too high, limit is %d\n",
+ irq, ICU_LEN -1);
+ return (NULL);
+ }
+
+ idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK);
+ if (idesc == NULL)
+ return NULL;
+ bzero(idesc, sizeof *idesc);
+
+ if (name == NULL)
+ name = "???";
+ idesc->name = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
+ if (idesc->name == NULL) {
+ free(idesc, M_DEVBUF);
+ return NULL;
+ }
+ strcpy(idesc->name, name);
+
+ idesc->handler = handler;
+ idesc->argument = arg;
+ idesc->maskptr = maskptr;
+ idesc->intr = irq;
+ idesc->flags = flags;
+
+ /* block this irq */
+ oldspl = splq(1 << irq);
+
+ /* add irq to class selected by maskptr */
+ errcode = add_intrdesc(idesc);
+ splx(oldspl);
+
+ if (errcode != 0) {
+ if (bootverbose)
+ printf("\tintr_connect(irq%d) failed, result=%d\n",
+ irq, errcode);
+ free(idesc->name, M_DEVBUF);
+ free(idesc, M_DEVBUF);
+ idesc = NULL;
+ }
+
+ return (idesc);
+}
+
+/*
+ * Deactivate and remove the interrupt handler descriptor data connected
+ * created by an earlier call of intr_connect() from the linked list and
+ * adjust theinterrupt masks if necessary.
+ *
+ * Return the memory held by the interrupt handler descriptor data structure
+ * to the system. Make sure, the handler is not actively used anymore, before.
+ */
+
+int
+inthand_remove(intrec *idesc)
+{
+ intrec **hook, *head;
+ int irq;
+ int errcode = 0;
+ intrmask_t oldspl;
+
+ if (idesc == NULL)
+ return (-1);
+
+ irq = idesc->intr;
+
+ /* find pointer that keeps the reference to this interrupt descriptor */
+ hook = find_pred(idesc, irq);
+ if (hook == NULL)
+ return (-1);
+
+ /* make copy of original list head, the line after may overwrite it */
+ head = intreclist_head[irq];
+
+ /* unlink: make predecessor point to idesc->next instead of to idesc */
+ *hook = idesc->next;
+
+ /* now check whether the element we removed was the list head */
+ if (idesc == head) {
+
+ oldspl = splq(1 << irq);
+
+ /* we want to remove the list head, which was known to intr_mux */
+ icu_unset(irq, intr_mux);
+
+ /* check whether the new list head is the only element on list */
+ head = intreclist_head[irq];
+ if (head != NULL) {
+ if (head->next != NULL) {
+ /* install the multiplex handler with new list head as argument */
+ errcode = icu_setup(irq, intr_mux, head, 0, 0);
+ if (errcode == 0)
+ update_intrname(irq, NULL);
+ } else {
+ /* install the one remaining handler for this irq */
+ errcode = icu_setup(irq, head->handler,
+ head->argument,
+ head->maskptr, head->flags);
+ if (errcode == 0)
+ update_intrname(irq, head->name);
+ }
+ }
+ splx(oldspl);
+ }
+ update_masks(idesc->maskptr, irq);
+
+ free(idesc, M_DEVBUF);
+ return (0);
+}
+
+/*
+ * Emulate the register_intr() call previously defined as low level function.
+ * That function (now icu_setup()) may no longer be directly called, since
+ * a conflict between an ISA and PCI interrupt might go by unnocticed, else.
+ */
+
+int
+register_intr(int intr, int device_id, u_int flags,
+ ointhand2_t handler, u_int *maskptr, int unit)
+{
+ intrec *idesc;
+ isarec *irec;
+
+ irec = malloc(sizeof *irec, M_DEVBUF, M_WAITOK);
+ if (irec == NULL)
+ return NULL;
+ bzero(irec, sizeof *irec);
+ irec->id_unit = device_id;
+ irec->id_handler = handler;
+
+ flags |= INTR_EXCL;
+ idesc = inthand_add("old", intr, isa_intr_wrap, irec, maskptr, flags);
+ if (idesc == NULL) {
+ free(irec, M_DEVBUF);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Emulate the old unregister_intr() low level function.
+ * Make sure there is just one interrupt, that it was
+ * registered as non-shared, and that the handlers match.
+ */
+
+int
+unregister_intr(int intr, ointhand2_t handler)
+{
+ intrec *p = intreclist_head[intr];
+
+ if (p != NULL && (p->flags & INTR_EXCL) != 0 &&
+ p->handler == isa_intr_wrap && isareclist[intr] != NULL &&
+ isareclist[intr]->id_handler == handler) {
+ free(isareclist[intr], M_DEVBUF);
+ isareclist[intr] = NULL;
+ return (inthand_remove(p));
+ }
+ return (EINVAL);
+}
diff --git a/sys/amd64/isa/intr_machdep.h b/sys/amd64/isa/intr_machdep.h
index 7cdce87..1d49d1d 100644
--- a/sys/amd64/isa/intr_machdep.h
+++ b/sys/amd64/isa/intr_machdep.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
- * $Id: intr_machdep.h,v 1.12 1998/05/31 10:53:54 bde Exp $
+ * $Id: intr_machdep.h,v 1.13 1998/06/18 15:32:06 bde Exp $
*/
#ifndef _I386_ISA_INTR_MACHDEP_H_
@@ -190,15 +190,28 @@ inthand_t
struct isa_device;
void isa_defaultirq __P((void));
-intrmask_t isa_irq_pending __P((void));
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));
+intrmask_t splq __P((intrmask_t mask));
+
+/* XXX currently dev_instance must be set to the ISA device_id or -1 for PCI */
+#define INTR_FAST 0x00000001 /* fast interrupt handler */
+#define INTR_EXCL 0x00010000 /* excl. intr, default is shared */
+
+struct intrec *inthand_add(const char *name, int irq, inthand2_t handler,
+ void *arg, intrmask_t *maskptr, int flags);
+
+int inthand_remove(struct intrec *idesc);
+
+int register_intr __P((int intr, int device_id, u_int flags,
+ ointhand2_t *handler, u_int *maskptr, int unit));
+int unregister_intr(int intr, ointhand2_t handler);
+
#endif /* LOCORE */
#endif /* KERNEL */
diff --git a/sys/amd64/isa/isa_dma.c b/sys/amd64/isa/isa_dma.c
index abea7f8..bbc09fd 100644
--- a/sys/amd64/isa/isa_dma.c
+++ b/sys/amd64/isa/isa_dma.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.117 1998/11/29 15:42:40 phk Exp $
+ * $Id: isa_dma.c,v 1.1 1999/04/16 21:22:24 peter Exp $
*/
/*
@@ -60,7 +60,6 @@
#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/ic/i8237.h>
diff --git a/sys/amd64/isa/nmi.c b/sys/amd64/isa/nmi.c
index 4f7c1e9..256c617 100644
--- a/sys/amd64/isa/nmi.c
+++ b/sys/amd64/isa/nmi.c
@@ -34,7 +34,13 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $
+ * $Id: intr_machdep.c,v 1.18 1999/04/16 21:22:22 peter Exp $
+ */
+/*
+ * This file contains an aggregated module marked:
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * All rights reserved.
+ * See the notice for details.
*/
#include "opt_auto_eoi.h"
@@ -45,9 +51,14 @@
#endif
#include <sys/systm.h>
#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <sys/interrupt.h>
#include <machine/ipl.h>
#include <machine/md_var.h>
#include <machine/segments.h>
+#include <sys/bus.h>
+
#if defined(APIC_IO)
#include <machine/smp.h>
#include <machine/smptests.h> /** FAST_HI */
@@ -62,6 +73,7 @@
#endif
#include <i386/isa/icu.h>
+#include <isa/isavar.h>
#include <i386/isa/intr_machdep.h>
#include <sys/interrupt.h>
#ifdef APIC_IO
@@ -300,7 +312,8 @@ update_intr_masks(void)
if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */
#endif /* APIC_IO */
maskptr = intr_mptr[intr];
- if (!maskptr) continue;
+ if (!maskptr)
+ continue;
*maskptr |= 1 << intr;
mask = *maskptr;
if (mask != intr_mask[intr]) {
@@ -316,48 +329,11 @@ update_intr_masks(void)
return (n);
}
-static const char *
-isa_get_nameunit(int id)
-{
- static char buf[32];
- struct isa_device *dp;
-
- if (id == -1)
- return ("pci"); /* XXX may also be eisa */
- if (id == 0)
- return ("clk0"); /* XXX may also be sloppy driver */
- if (id == 1)
- return ("rtc0");
-#if 0
- for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_cam; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_net; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_null; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
-#endif
- return "???";
-
-found_device:
- snprintf(buf, sizeof(buf), "%s%d", dp->id_driver->name, dp->id_unit);
- return (buf);
-}
-
-void
-update_intrname(int intr, int device_id)
+static void
+update_intrname(int intr, char *name)
{
char buf[32];
char *cp;
- const char *name;
int name_index, off, strayintr;
/*
@@ -371,7 +347,8 @@ update_intrname(int intr, int device_id)
strayintr) + 1;
}
- name = isa_get_nameunit(device_id);
+ if (name == NULL)
+ name = "???";
if (snprintf(buf, sizeof(buf), "%s irq%d", name, intr) >= sizeof(buf))
goto use_bitbucket;
@@ -516,3 +493,410 @@ icu_unset(intr, handler)
write_eflags(ef);
return (0);
}
+
+/* The following notice applies beyond this point in the file */
+
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $Id: kern_intr.c,v 1.21 1998/11/10 09:16:29 peter Exp $
+ *
+ */
+
+typedef struct intrec {
+ intrmask_t mask;
+ inthand2_t *handler;
+ void *argument;
+ struct intrec *next;
+ char *name;
+ int intr;
+ intrmask_t *maskptr;
+ int flags;
+} intrec;
+
+static intrec *intreclist_head[ICU_LEN];
+
+typedef struct isarec {
+ int id_unit;
+ ointhand2_t *id_handler;
+} isarec;
+
+static isarec *isareclist[ICU_LEN];
+
+/*
+ * The interrupt multiplexer calls each of the handlers in turn,
+ * and applies the associated interrupt mask to "cpl", which is
+ * defined as a ".long" in /sys/i386/isa/ipl.s
+ */
+
+static void
+intr_mux(void *arg)
+{
+ intrec *p = arg;
+ int oldspl;
+
+ while (p != NULL) {
+ oldspl = splq(p->mask);
+ p->handler(p->argument);
+ splx(oldspl);
+ p = p->next;
+ }
+}
+
+static void
+isa_intr_wrap(void *cookie)
+{
+ isarec *irec = (isarec *)cookie;
+
+ irec->id_handler(irec->id_unit);
+}
+
+static intrec*
+find_idesc(unsigned *maskptr, int irq)
+{
+ intrec *p = intreclist_head[irq];
+
+ while (p && p->maskptr != maskptr)
+ p = p->next;
+
+ return (p);
+}
+
+static intrec**
+find_pred(intrec *idesc, int irq)
+{
+ intrec **pp = &intreclist_head[irq];
+ intrec *p = *pp;
+
+ while (p != idesc) {
+ if (p == NULL)
+ return (NULL);
+ pp = &p->next;
+ p = *pp;
+ }
+ return (pp);
+}
+
+/*
+ * Both the low level handler and the shared interrupt multiplexer
+ * block out further interrupts as set in the handlers "mask", while
+ * the handler is running. In fact *maskptr should be used for this
+ * purpose, but since this requires one more pointer dereference on
+ * each interrupt, we rather bother update "mask" whenever *maskptr
+ * changes. The function "update_masks" should be called **after**
+ * all manipulation of the linked list of interrupt handlers hung
+ * off of intrdec_head[irq] is complete, since the chain of handlers
+ * will both determine the *maskptr values and the instances of mask
+ * that are fixed. This function should be called with the irq for
+ * which a new handler has been add blocked, since the masks may not
+ * yet know about the use of this irq for a device of a certain class.
+ */
+
+static void
+update_mux_masks(void)
+{
+ int irq;
+ for (irq = 0; irq < ICU_LEN; irq++) {
+ intrec *idesc = intreclist_head[irq];
+ while (idesc != NULL) {
+ if (idesc->maskptr != NULL) {
+ /* our copy of *maskptr may be stale, refresh */
+ idesc->mask = *idesc->maskptr;
+ }
+ idesc = idesc->next;
+ }
+ }
+}
+
+static void
+update_masks(intrmask_t *maskptr, int irq)
+{
+ intrmask_t mask = 1 << irq;
+
+ if (maskptr == NULL)
+ return;
+
+ if (find_idesc(maskptr, irq) == NULL) {
+ /* no reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) == 0)
+ return;
+ /* the irq was included in the classes mask, remove it */
+ INTRUNMASK(*maskptr, mask);
+ } else {
+ /* a reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) != 0)
+ return;
+ /* put the irq into the classes mask */
+ INTRMASK(*maskptr, mask);
+ }
+ /* we need to update all values in the intr_mask[irq] array */
+ update_intr_masks();
+ /* update mask in chains of the interrupt multiplex handler as well */
+ update_mux_masks();
+}
+
+/*
+ * Add interrupt handler to linked list hung off of intreclist_head[irq]
+ * and install shared interrupt multiplex handler, if necessary
+ */
+
+static int
+add_intrdesc(intrec *idesc)
+{
+ int irq = idesc->intr;
+
+ intrec *head = intreclist_head[irq];
+
+ if (head == NULL) {
+ /* first handler for this irq, just install it */
+ if (icu_setup(irq, idesc->handler, idesc->argument,
+ idesc->maskptr, idesc->flags) != 0)
+ return (-1);
+
+ update_intrname(irq, idesc->name);
+ /* keep reference */
+ intreclist_head[irq] = idesc;
+ } else {
+ if ((idesc->flags & INTR_EXCL) != 0
+ || (head->flags & INTR_EXCL) != 0) {
+ /*
+ * can't append new handler, if either list head or
+ * new handler do not allow interrupts to be shared
+ */
+ if (bootverbose)
+ printf("\tdevice combination doesn't support "
+ "shared irq%d\n", irq);
+ return (-1);
+ }
+ if (head->next == NULL) {
+ /*
+ * second handler for this irq, replace device driver's
+ * handler by shared interrupt multiplexer function
+ */
+ icu_unset(irq, head->handler);
+ if (icu_setup(irq, intr_mux, head, 0, 0) != 0)
+ return (-1);
+ if (bootverbose)
+ printf("\tusing shared irq%d.\n", irq);
+ update_intrname(irq, "mux");
+ }
+ /* just append to the end of the chain */
+ while (head->next != NULL)
+ head = head->next;
+ head->next = idesc;
+ }
+ update_masks(idesc->maskptr, irq);
+ return (0);
+}
+
+/*
+ * Create and activate an interrupt handler descriptor data structure.
+ *
+ * The dev_instance pointer is required for resource management, and will
+ * only be passed through to resource_claim().
+ *
+ * There will be functions that derive a driver and unit name from a
+ * dev_instance variable, and those functions will be used to maintain the
+ * interrupt counter label array referenced by systat and vmstat to report
+ * device interrupt rates (->update_intrlabels).
+ *
+ * Add the interrupt handler descriptor data structure created by an
+ * earlier call of create_intr() to the linked list for its irq and
+ * adjust the interrupt masks if necessary.
+ */
+
+intrec *
+inthand_add(const char *name, int irq, inthand2_t handler, void *arg,
+ intrmask_t *maskptr, int flags)
+{
+ intrec *idesc;
+ int errcode = -1;
+ intrmask_t oldspl;
+
+ if (ICU_LEN > 8 * sizeof *maskptr) {
+ printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n",
+ ICU_LEN, 8 * sizeof *maskptr);
+ return (NULL);
+ }
+ if ((unsigned)irq >= ICU_LEN) {
+ printf("create_intr: requested irq%d too high, limit is %d\n",
+ irq, ICU_LEN -1);
+ return (NULL);
+ }
+
+ idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK);
+ if (idesc == NULL)
+ return NULL;
+ bzero(idesc, sizeof *idesc);
+
+ if (name == NULL)
+ name = "???";
+ idesc->name = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
+ if (idesc->name == NULL) {
+ free(idesc, M_DEVBUF);
+ return NULL;
+ }
+ strcpy(idesc->name, name);
+
+ idesc->handler = handler;
+ idesc->argument = arg;
+ idesc->maskptr = maskptr;
+ idesc->intr = irq;
+ idesc->flags = flags;
+
+ /* block this irq */
+ oldspl = splq(1 << irq);
+
+ /* add irq to class selected by maskptr */
+ errcode = add_intrdesc(idesc);
+ splx(oldspl);
+
+ if (errcode != 0) {
+ if (bootverbose)
+ printf("\tintr_connect(irq%d) failed, result=%d\n",
+ irq, errcode);
+ free(idesc->name, M_DEVBUF);
+ free(idesc, M_DEVBUF);
+ idesc = NULL;
+ }
+
+ return (idesc);
+}
+
+/*
+ * Deactivate and remove the interrupt handler descriptor data connected
+ * created by an earlier call of intr_connect() from the linked list and
+ * adjust theinterrupt masks if necessary.
+ *
+ * Return the memory held by the interrupt handler descriptor data structure
+ * to the system. Make sure, the handler is not actively used anymore, before.
+ */
+
+int
+inthand_remove(intrec *idesc)
+{
+ intrec **hook, *head;
+ int irq;
+ int errcode = 0;
+ intrmask_t oldspl;
+
+ if (idesc == NULL)
+ return (-1);
+
+ irq = idesc->intr;
+
+ /* find pointer that keeps the reference to this interrupt descriptor */
+ hook = find_pred(idesc, irq);
+ if (hook == NULL)
+ return (-1);
+
+ /* make copy of original list head, the line after may overwrite it */
+ head = intreclist_head[irq];
+
+ /* unlink: make predecessor point to idesc->next instead of to idesc */
+ *hook = idesc->next;
+
+ /* now check whether the element we removed was the list head */
+ if (idesc == head) {
+
+ oldspl = splq(1 << irq);
+
+ /* we want to remove the list head, which was known to intr_mux */
+ icu_unset(irq, intr_mux);
+
+ /* check whether the new list head is the only element on list */
+ head = intreclist_head[irq];
+ if (head != NULL) {
+ if (head->next != NULL) {
+ /* install the multiplex handler with new list head as argument */
+ errcode = icu_setup(irq, intr_mux, head, 0, 0);
+ if (errcode == 0)
+ update_intrname(irq, NULL);
+ } else {
+ /* install the one remaining handler for this irq */
+ errcode = icu_setup(irq, head->handler,
+ head->argument,
+ head->maskptr, head->flags);
+ if (errcode == 0)
+ update_intrname(irq, head->name);
+ }
+ }
+ splx(oldspl);
+ }
+ update_masks(idesc->maskptr, irq);
+
+ free(idesc, M_DEVBUF);
+ return (0);
+}
+
+/*
+ * Emulate the register_intr() call previously defined as low level function.
+ * That function (now icu_setup()) may no longer be directly called, since
+ * a conflict between an ISA and PCI interrupt might go by unnocticed, else.
+ */
+
+int
+register_intr(int intr, int device_id, u_int flags,
+ ointhand2_t handler, u_int *maskptr, int unit)
+{
+ intrec *idesc;
+ isarec *irec;
+
+ irec = malloc(sizeof *irec, M_DEVBUF, M_WAITOK);
+ if (irec == NULL)
+ return NULL;
+ bzero(irec, sizeof *irec);
+ irec->id_unit = device_id;
+ irec->id_handler = handler;
+
+ flags |= INTR_EXCL;
+ idesc = inthand_add("old", intr, isa_intr_wrap, irec, maskptr, flags);
+ if (idesc == NULL) {
+ free(irec, M_DEVBUF);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Emulate the old unregister_intr() low level function.
+ * Make sure there is just one interrupt, that it was
+ * registered as non-shared, and that the handlers match.
+ */
+
+int
+unregister_intr(int intr, ointhand2_t handler)
+{
+ intrec *p = intreclist_head[intr];
+
+ if (p != NULL && (p->flags & INTR_EXCL) != 0 &&
+ p->handler == isa_intr_wrap && isareclist[intr] != NULL &&
+ isareclist[intr]->id_handler == handler) {
+ free(isareclist[intr], M_DEVBUF);
+ isareclist[intr] = NULL;
+ return (inthand_remove(p));
+ }
+ return (EINVAL);
+}
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 52428e0..3ed8344 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cam_xpt.c,v 1.51 1999/04/17 08:36:03 peter Exp $
+ * $Id: cam_xpt.c,v 1.52 1999/04/19 21:26:08 gibbs Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -63,8 +63,6 @@
#include "opt_cam.h"
#include "opt_scsi.h"
-extern void (*ihandlers[32]) __P((void));
-
/* Datastructures internal to the xpt layer */
/*
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index f9683b9..f57e1f5 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -25,7 +25,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: ata-all.c,v 1.7 1999/04/16 21:21:52 peter Exp $
+ * $Id: ata-all.c,v 1.8 1999/04/18 20:48:15 sos Exp $
*/
#include "ata.h"
@@ -52,6 +52,7 @@
#include <machine/clock.h>
#ifdef __i386__
#include <machine/smp.h>
+#include <i386/isa/intr_machdep.h>
#endif
#include <pci/pcivar.h>
#include <pci/pcireg.h>
@@ -70,10 +71,10 @@
/* prototypes */
#if NPCI > 0
-static void promise_intr(int32_t);
+static void promise_intr(void *);
#endif
static int32_t ata_probe(int32_t, int32_t, int32_t, device_t, int32_t *);
-static void ataintr(int32_t);
+static void ataintr(void *);
/*
* Ought to be handled by the devclass.
@@ -132,8 +133,9 @@ ata_isaattach(device_t dev)
{
struct resource *port;
struct resource *irq;
- int rid, unit;
void *ih;
+ int rid;
+ struct ata_softc *softc;
/* Allocate the port range and interrupt */
rid = 0;
@@ -147,14 +149,8 @@ ata_isaattach(device_t dev)
bus_release_resource(dev, SYS_RES_IOPORT, 0, port);
return (ENOMEM);
}
-
- /*
- * The interrupt code could be changed to take the ata_softc as
- * its argument directly.
- */
- unit = *(int *) device_get_softc(dev);
- return bus_setup_intr(dev, irq, (driver_intr_t *) ataintr,
- (void*)(uintptr_t) unit, &ih);
+ softc = device_get_softc(dev);
+ return bus_setup_intr(dev, irq, ataintr, softc, &ih);
}
static device_method_t ata_isa_methods[] = {
@@ -232,6 +228,7 @@ static int
ata_pciattach(device_t dev)
{
int unit = device_get_unit(dev);
+ struct ata_softc *softc;
u_int32_t type;
u_int8_t class, subclass;
u_int32_t cmd;
@@ -310,12 +307,14 @@ ata_pciattach(device_t dev)
/* now probe the addresse found for "real" ATA/ATAPI hardware */
lun = 0;
if (ata_probe(iobase_1, altiobase_1, bmaddr_1, dev, &lun)) {
+ softc = atadevices[lun];
if (iobase_1 == IO_WD1)
#ifdef __i386__
- register_intr(irq1,(int)"",0,(inthand2_t *)ataintr,&bio_imask,lun);
+ inthand_add(device_get_nameunit(dev), irq1, ataintr, softc,
+ &bio_imask, INTR_EXCL);
#endif
#ifdef __alpha__
- alpha_platform_setup_ide_intr(0, ataintr, (void *)(intptr_t)lun);
+ alpha_platform_setup_ide_intr(0, ataintr, softc);
#endif
else {
struct resource *irq;
@@ -324,23 +323,23 @@ ata_pciattach(device_t dev)
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0,1,RF_ACTIVE);
if (sysctrl)
- bus_setup_intr(dev, irq, (driver_intr_t *)promise_intr,
- (void *)lun, &ih);
+ bus_setup_intr(dev, irq, promise_intr, softc, &ih);
else
- bus_setup_intr(dev, irq, (driver_intr_t *)ataintr,
- (void *)lun, &ih);
+ bus_setup_intr(dev, irq, ataintr, softc, &ih);
}
printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
lun, iobase_1, isa_apic_irq(irq1), unit);
}
lun = 1;
if (ata_probe(iobase_2, altiobase_2, bmaddr_2, dev, &lun)) {
+ softc = atadevices[lun];
if (iobase_2 == IO_WD2)
#ifdef __i386__
- register_intr(irq2,(int)"",0,(inthand2_t *)ataintr,&bio_imask,lun);
+ inthand_add(device_get_nameunit(dev), irq2, ataintr, softc,
+ &bio_imask, INTR_EXCL);
#endif
#ifdef __alpha__
- alpha_platform_setup_ide_intr(1, ataintr, (void *)(intptr_t)lun);
+ alpha_platform_setup_ide_intr(1, ataintr, softc);
#endif
else {
struct resource *irq;
@@ -349,8 +348,7 @@ ata_pciattach(device_t dev)
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0,1,RF_ACTIVE);
if (!sysctrl)
- bus_setup_intr(dev, irq, (driver_intr_t *)ataintr,
- (void *)lun, &ih);
+ bus_setup_intr(dev, irq, ataintr, softc, &ih);
}
printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
lun, iobase_2, isa_apic_irq(irq2), unit);
@@ -375,16 +373,16 @@ static driver_t ata_pci_driver = {
DRIVER_MODULE(ata, pci, ata_pci_driver, ata_devclass, 0, 0);
static void
-promise_intr(int32_t unit)
+promise_intr(void *data)
{
- struct ata_softc *scp = atadevices[unit];
+ struct ata_softc *scp = (struct ata_softc *)data;
int32_t channel = inl((pci_read_config(scp->dev, 0x20, 4) & 0xfffc) + 0x1c);
if (channel & 0x00000400)
- ataintr(unit);
+ ataintr(data);
if (channel & 0x00004000)
- ataintr(unit+1);
+ ataintr(atadevices[scp->unit + 1]);
}
#endif
@@ -548,20 +546,17 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr,
}
static void
-ataintr(int32_t unit)
+ataintr(void *data)
{
struct ata_softc *scp;
struct atapi_request *atapi_request;
struct buf *ata_request;
u_int8_t status;
static int32_t intr_count = 0;
+ int unit;
- if (unit < 0 || unit > atanlun) {
- printf("ataintr: unit %d unusable\n", unit);
- return;
- }
-
- scp = atadevices[unit];
+ scp = (struct ata_softc *)data;
+ unit = scp->unit;
/* find & call the responsible driver to process this interrupt */
switch (scp->active) {
diff --git a/sys/i386/i386/legacy.c b/sys/i386/i386/legacy.c
index 0cf03f0..cfb7b03 100644
--- a/sys/i386/i386/legacy.c
+++ b/sys/i386/i386/legacy.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: nexus.c,v 1.2 1999/04/18 14:30:55 kato Exp $
+ * $Id: nexus.c,v 1.3 1999/04/19 08:04:19 peter Exp $
*/
/*
@@ -305,6 +305,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
intrmask_t *mask;
driver_t *driver;
int error, icflags;
+ char name[32];
if (child)
device_printf(child, "interrupting at irq %d\n",
@@ -348,11 +349,11 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
if (error)
return (error);
- *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg,
+ snprintf(name, sizeof(name), "%s%d", device_get_name(child),
+ device_get_unit(child));
+ *cookiep = inthand_add(name, irq->r_start, ihand, arg,
mask, icflags);
- if (*cookiep)
- error = intr_connect(*cookiep);
- else
+ if (*cookiep == NULL)
error = EINVAL; /* XXX ??? */
return (error);
@@ -361,7 +362,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
- return (intr_destroy(ih));
+ return (inthand_remove(ih));
}
static devclass_t pcib_devclass;
diff --git a/sys/i386/i386/nexus.c b/sys/i386/i386/nexus.c
index 0cf03f0..cfb7b03 100644
--- a/sys/i386/i386/nexus.c
+++ b/sys/i386/i386/nexus.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: nexus.c,v 1.2 1999/04/18 14:30:55 kato Exp $
+ * $Id: nexus.c,v 1.3 1999/04/19 08:04:19 peter Exp $
*/
/*
@@ -305,6 +305,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
intrmask_t *mask;
driver_t *driver;
int error, icflags;
+ char name[32];
if (child)
device_printf(child, "interrupting at irq %d\n",
@@ -348,11 +349,11 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
if (error)
return (error);
- *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg,
+ snprintf(name, sizeof(name), "%s%d", device_get_name(child),
+ device_get_unit(child));
+ *cookiep = inthand_add(name, irq->r_start, ihand, arg,
mask, icflags);
- if (*cookiep)
- error = intr_connect(*cookiep);
- else
+ if (*cookiep == NULL)
error = EINVAL; /* XXX ??? */
return (error);
@@ -361,7 +362,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
- return (intr_destroy(ih));
+ return (inthand_remove(ih));
}
static devclass_t pcib_devclass;
diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c
index d9bca71..3daaf94 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.128 1998/10/23 10:46:20 phk Exp $
+ * $Id: clock.c,v 1.129 1998/12/14 13:30:29 mckay Exp $
*/
/*
@@ -86,7 +86,7 @@
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
-#include <sys/interrupt.h>
+#include <i386/isa/intr_machdep.h>
#ifdef SMP
#define disable_intr() CLOCK_DISABLE_INTR()
@@ -948,6 +948,7 @@ cpu_initclocks()
int diag;
#ifdef APIC_IO
int apic_8254_trial;
+ intrec *clkdesc;
#endif /* APIC_IO */
if (statclock_disable) {
@@ -982,16 +983,14 @@ cpu_initclocks()
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
}
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
#else /* APIC_IO */
- register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
+ INTR_EXCL);
INTREN(IRQ0);
#endif /* APIC_IO */
@@ -1012,9 +1011,8 @@ cpu_initclocks()
panic("APIC RTC != 8");
#endif /* APIC_IO */
- register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
- /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
- /* unit */ 0);
+ inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
+ INTR_EXCL);
#ifdef APIC_IO
INTREN(APIC_IRQ8);
@@ -1038,17 +1036,15 @@ cpu_initclocks()
* Workaround: Limited variant of mixed mode.
*/
INTRDIS(1 << apic_8254_intr);
- unregister_intr(apic_8254_intr,
- /* XXX */ (inthand2_t *) clkintr);
+ inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
"8254 is not connected to IO APIC int pin %d\n",
apic_8254_intr);
apic_8254_intr = 0;
setup_8254_mixed_mode();
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
diff --git a/sys/i386/include/types.h b/sys/i386/include/types.h
index f28d633..c7eec31 100644
--- a/sys/i386/include/types.h
+++ b/sys/i386/include/types.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)types.h 8.3 (Berkeley) 1/5/94
- * $Id: types.h,v 1.15 1998/07/14 05:09:43 bde Exp $
+ * $Id: types.h,v 1.16 1998/12/19 00:02:29 dt Exp $
*/
#ifndef _MACHINE_TYPES_H_
@@ -65,5 +65,6 @@ typedef __uint32_t intrmask_t;
/* Interrupt handler function type. */
typedef void inthand2_t __P((void *_cookie));
+typedef void ointhand2_t __P((int _device_id));
#endif /* !_MACHINE_TYPES_H_ */
diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c
index d9bca71..3daaf94 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.128 1998/10/23 10:46:20 phk Exp $
+ * $Id: clock.c,v 1.129 1998/12/14 13:30:29 mckay Exp $
*/
/*
@@ -86,7 +86,7 @@
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
-#include <sys/interrupt.h>
+#include <i386/isa/intr_machdep.h>
#ifdef SMP
#define disable_intr() CLOCK_DISABLE_INTR()
@@ -948,6 +948,7 @@ cpu_initclocks()
int diag;
#ifdef APIC_IO
int apic_8254_trial;
+ intrec *clkdesc;
#endif /* APIC_IO */
if (statclock_disable) {
@@ -982,16 +983,14 @@ cpu_initclocks()
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
}
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
#else /* APIC_IO */
- register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
+ INTR_EXCL);
INTREN(IRQ0);
#endif /* APIC_IO */
@@ -1012,9 +1011,8 @@ cpu_initclocks()
panic("APIC RTC != 8");
#endif /* APIC_IO */
- register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
- /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
- /* unit */ 0);
+ inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
+ INTR_EXCL);
#ifdef APIC_IO
INTREN(APIC_IRQ8);
@@ -1038,17 +1036,15 @@ cpu_initclocks()
* Workaround: Limited variant of mixed mode.
*/
INTRDIS(1 << apic_8254_intr);
- unregister_intr(apic_8254_intr,
- /* XXX */ (inthand2_t *) clkintr);
+ inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
"8254 is not connected to IO APIC int pin %d\n",
apic_8254_intr);
apic_8254_intr = 0;
setup_8254_mixed_mode();
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
diff --git a/sys/i386/isa/intr_machdep.c b/sys/i386/isa/intr_machdep.c
index 4f7c1e9..256c617 100644
--- a/sys/i386/isa/intr_machdep.c
+++ b/sys/i386/isa/intr_machdep.c
@@ -34,7 +34,13 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $
+ * $Id: intr_machdep.c,v 1.18 1999/04/16 21:22:22 peter Exp $
+ */
+/*
+ * This file contains an aggregated module marked:
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * All rights reserved.
+ * See the notice for details.
*/
#include "opt_auto_eoi.h"
@@ -45,9 +51,14 @@
#endif
#include <sys/systm.h>
#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <sys/interrupt.h>
#include <machine/ipl.h>
#include <machine/md_var.h>
#include <machine/segments.h>
+#include <sys/bus.h>
+
#if defined(APIC_IO)
#include <machine/smp.h>
#include <machine/smptests.h> /** FAST_HI */
@@ -62,6 +73,7 @@
#endif
#include <i386/isa/icu.h>
+#include <isa/isavar.h>
#include <i386/isa/intr_machdep.h>
#include <sys/interrupt.h>
#ifdef APIC_IO
@@ -300,7 +312,8 @@ update_intr_masks(void)
if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */
#endif /* APIC_IO */
maskptr = intr_mptr[intr];
- if (!maskptr) continue;
+ if (!maskptr)
+ continue;
*maskptr |= 1 << intr;
mask = *maskptr;
if (mask != intr_mask[intr]) {
@@ -316,48 +329,11 @@ update_intr_masks(void)
return (n);
}
-static const char *
-isa_get_nameunit(int id)
-{
- static char buf[32];
- struct isa_device *dp;
-
- if (id == -1)
- return ("pci"); /* XXX may also be eisa */
- if (id == 0)
- return ("clk0"); /* XXX may also be sloppy driver */
- if (id == 1)
- return ("rtc0");
-#if 0
- for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_cam; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_net; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_null; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
-#endif
- return "???";
-
-found_device:
- snprintf(buf, sizeof(buf), "%s%d", dp->id_driver->name, dp->id_unit);
- return (buf);
-}
-
-void
-update_intrname(int intr, int device_id)
+static void
+update_intrname(int intr, char *name)
{
char buf[32];
char *cp;
- const char *name;
int name_index, off, strayintr;
/*
@@ -371,7 +347,8 @@ update_intrname(int intr, int device_id)
strayintr) + 1;
}
- name = isa_get_nameunit(device_id);
+ if (name == NULL)
+ name = "???";
if (snprintf(buf, sizeof(buf), "%s irq%d", name, intr) >= sizeof(buf))
goto use_bitbucket;
@@ -516,3 +493,410 @@ icu_unset(intr, handler)
write_eflags(ef);
return (0);
}
+
+/* The following notice applies beyond this point in the file */
+
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $Id: kern_intr.c,v 1.21 1998/11/10 09:16:29 peter Exp $
+ *
+ */
+
+typedef struct intrec {
+ intrmask_t mask;
+ inthand2_t *handler;
+ void *argument;
+ struct intrec *next;
+ char *name;
+ int intr;
+ intrmask_t *maskptr;
+ int flags;
+} intrec;
+
+static intrec *intreclist_head[ICU_LEN];
+
+typedef struct isarec {
+ int id_unit;
+ ointhand2_t *id_handler;
+} isarec;
+
+static isarec *isareclist[ICU_LEN];
+
+/*
+ * The interrupt multiplexer calls each of the handlers in turn,
+ * and applies the associated interrupt mask to "cpl", which is
+ * defined as a ".long" in /sys/i386/isa/ipl.s
+ */
+
+static void
+intr_mux(void *arg)
+{
+ intrec *p = arg;
+ int oldspl;
+
+ while (p != NULL) {
+ oldspl = splq(p->mask);
+ p->handler(p->argument);
+ splx(oldspl);
+ p = p->next;
+ }
+}
+
+static void
+isa_intr_wrap(void *cookie)
+{
+ isarec *irec = (isarec *)cookie;
+
+ irec->id_handler(irec->id_unit);
+}
+
+static intrec*
+find_idesc(unsigned *maskptr, int irq)
+{
+ intrec *p = intreclist_head[irq];
+
+ while (p && p->maskptr != maskptr)
+ p = p->next;
+
+ return (p);
+}
+
+static intrec**
+find_pred(intrec *idesc, int irq)
+{
+ intrec **pp = &intreclist_head[irq];
+ intrec *p = *pp;
+
+ while (p != idesc) {
+ if (p == NULL)
+ return (NULL);
+ pp = &p->next;
+ p = *pp;
+ }
+ return (pp);
+}
+
+/*
+ * Both the low level handler and the shared interrupt multiplexer
+ * block out further interrupts as set in the handlers "mask", while
+ * the handler is running. In fact *maskptr should be used for this
+ * purpose, but since this requires one more pointer dereference on
+ * each interrupt, we rather bother update "mask" whenever *maskptr
+ * changes. The function "update_masks" should be called **after**
+ * all manipulation of the linked list of interrupt handlers hung
+ * off of intrdec_head[irq] is complete, since the chain of handlers
+ * will both determine the *maskptr values and the instances of mask
+ * that are fixed. This function should be called with the irq for
+ * which a new handler has been add blocked, since the masks may not
+ * yet know about the use of this irq for a device of a certain class.
+ */
+
+static void
+update_mux_masks(void)
+{
+ int irq;
+ for (irq = 0; irq < ICU_LEN; irq++) {
+ intrec *idesc = intreclist_head[irq];
+ while (idesc != NULL) {
+ if (idesc->maskptr != NULL) {
+ /* our copy of *maskptr may be stale, refresh */
+ idesc->mask = *idesc->maskptr;
+ }
+ idesc = idesc->next;
+ }
+ }
+}
+
+static void
+update_masks(intrmask_t *maskptr, int irq)
+{
+ intrmask_t mask = 1 << irq;
+
+ if (maskptr == NULL)
+ return;
+
+ if (find_idesc(maskptr, irq) == NULL) {
+ /* no reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) == 0)
+ return;
+ /* the irq was included in the classes mask, remove it */
+ INTRUNMASK(*maskptr, mask);
+ } else {
+ /* a reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) != 0)
+ return;
+ /* put the irq into the classes mask */
+ INTRMASK(*maskptr, mask);
+ }
+ /* we need to update all values in the intr_mask[irq] array */
+ update_intr_masks();
+ /* update mask in chains of the interrupt multiplex handler as well */
+ update_mux_masks();
+}
+
+/*
+ * Add interrupt handler to linked list hung off of intreclist_head[irq]
+ * and install shared interrupt multiplex handler, if necessary
+ */
+
+static int
+add_intrdesc(intrec *idesc)
+{
+ int irq = idesc->intr;
+
+ intrec *head = intreclist_head[irq];
+
+ if (head == NULL) {
+ /* first handler for this irq, just install it */
+ if (icu_setup(irq, idesc->handler, idesc->argument,
+ idesc->maskptr, idesc->flags) != 0)
+ return (-1);
+
+ update_intrname(irq, idesc->name);
+ /* keep reference */
+ intreclist_head[irq] = idesc;
+ } else {
+ if ((idesc->flags & INTR_EXCL) != 0
+ || (head->flags & INTR_EXCL) != 0) {
+ /*
+ * can't append new handler, if either list head or
+ * new handler do not allow interrupts to be shared
+ */
+ if (bootverbose)
+ printf("\tdevice combination doesn't support "
+ "shared irq%d\n", irq);
+ return (-1);
+ }
+ if (head->next == NULL) {
+ /*
+ * second handler for this irq, replace device driver's
+ * handler by shared interrupt multiplexer function
+ */
+ icu_unset(irq, head->handler);
+ if (icu_setup(irq, intr_mux, head, 0, 0) != 0)
+ return (-1);
+ if (bootverbose)
+ printf("\tusing shared irq%d.\n", irq);
+ update_intrname(irq, "mux");
+ }
+ /* just append to the end of the chain */
+ while (head->next != NULL)
+ head = head->next;
+ head->next = idesc;
+ }
+ update_masks(idesc->maskptr, irq);
+ return (0);
+}
+
+/*
+ * Create and activate an interrupt handler descriptor data structure.
+ *
+ * The dev_instance pointer is required for resource management, and will
+ * only be passed through to resource_claim().
+ *
+ * There will be functions that derive a driver and unit name from a
+ * dev_instance variable, and those functions will be used to maintain the
+ * interrupt counter label array referenced by systat and vmstat to report
+ * device interrupt rates (->update_intrlabels).
+ *
+ * Add the interrupt handler descriptor data structure created by an
+ * earlier call of create_intr() to the linked list for its irq and
+ * adjust the interrupt masks if necessary.
+ */
+
+intrec *
+inthand_add(const char *name, int irq, inthand2_t handler, void *arg,
+ intrmask_t *maskptr, int flags)
+{
+ intrec *idesc;
+ int errcode = -1;
+ intrmask_t oldspl;
+
+ if (ICU_LEN > 8 * sizeof *maskptr) {
+ printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n",
+ ICU_LEN, 8 * sizeof *maskptr);
+ return (NULL);
+ }
+ if ((unsigned)irq >= ICU_LEN) {
+ printf("create_intr: requested irq%d too high, limit is %d\n",
+ irq, ICU_LEN -1);
+ return (NULL);
+ }
+
+ idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK);
+ if (idesc == NULL)
+ return NULL;
+ bzero(idesc, sizeof *idesc);
+
+ if (name == NULL)
+ name = "???";
+ idesc->name = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
+ if (idesc->name == NULL) {
+ free(idesc, M_DEVBUF);
+ return NULL;
+ }
+ strcpy(idesc->name, name);
+
+ idesc->handler = handler;
+ idesc->argument = arg;
+ idesc->maskptr = maskptr;
+ idesc->intr = irq;
+ idesc->flags = flags;
+
+ /* block this irq */
+ oldspl = splq(1 << irq);
+
+ /* add irq to class selected by maskptr */
+ errcode = add_intrdesc(idesc);
+ splx(oldspl);
+
+ if (errcode != 0) {
+ if (bootverbose)
+ printf("\tintr_connect(irq%d) failed, result=%d\n",
+ irq, errcode);
+ free(idesc->name, M_DEVBUF);
+ free(idesc, M_DEVBUF);
+ idesc = NULL;
+ }
+
+ return (idesc);
+}
+
+/*
+ * Deactivate and remove the interrupt handler descriptor data connected
+ * created by an earlier call of intr_connect() from the linked list and
+ * adjust theinterrupt masks if necessary.
+ *
+ * Return the memory held by the interrupt handler descriptor data structure
+ * to the system. Make sure, the handler is not actively used anymore, before.
+ */
+
+int
+inthand_remove(intrec *idesc)
+{
+ intrec **hook, *head;
+ int irq;
+ int errcode = 0;
+ intrmask_t oldspl;
+
+ if (idesc == NULL)
+ return (-1);
+
+ irq = idesc->intr;
+
+ /* find pointer that keeps the reference to this interrupt descriptor */
+ hook = find_pred(idesc, irq);
+ if (hook == NULL)
+ return (-1);
+
+ /* make copy of original list head, the line after may overwrite it */
+ head = intreclist_head[irq];
+
+ /* unlink: make predecessor point to idesc->next instead of to idesc */
+ *hook = idesc->next;
+
+ /* now check whether the element we removed was the list head */
+ if (idesc == head) {
+
+ oldspl = splq(1 << irq);
+
+ /* we want to remove the list head, which was known to intr_mux */
+ icu_unset(irq, intr_mux);
+
+ /* check whether the new list head is the only element on list */
+ head = intreclist_head[irq];
+ if (head != NULL) {
+ if (head->next != NULL) {
+ /* install the multiplex handler with new list head as argument */
+ errcode = icu_setup(irq, intr_mux, head, 0, 0);
+ if (errcode == 0)
+ update_intrname(irq, NULL);
+ } else {
+ /* install the one remaining handler for this irq */
+ errcode = icu_setup(irq, head->handler,
+ head->argument,
+ head->maskptr, head->flags);
+ if (errcode == 0)
+ update_intrname(irq, head->name);
+ }
+ }
+ splx(oldspl);
+ }
+ update_masks(idesc->maskptr, irq);
+
+ free(idesc, M_DEVBUF);
+ return (0);
+}
+
+/*
+ * Emulate the register_intr() call previously defined as low level function.
+ * That function (now icu_setup()) may no longer be directly called, since
+ * a conflict between an ISA and PCI interrupt might go by unnocticed, else.
+ */
+
+int
+register_intr(int intr, int device_id, u_int flags,
+ ointhand2_t handler, u_int *maskptr, int unit)
+{
+ intrec *idesc;
+ isarec *irec;
+
+ irec = malloc(sizeof *irec, M_DEVBUF, M_WAITOK);
+ if (irec == NULL)
+ return NULL;
+ bzero(irec, sizeof *irec);
+ irec->id_unit = device_id;
+ irec->id_handler = handler;
+
+ flags |= INTR_EXCL;
+ idesc = inthand_add("old", intr, isa_intr_wrap, irec, maskptr, flags);
+ if (idesc == NULL) {
+ free(irec, M_DEVBUF);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Emulate the old unregister_intr() low level function.
+ * Make sure there is just one interrupt, that it was
+ * registered as non-shared, and that the handlers match.
+ */
+
+int
+unregister_intr(int intr, ointhand2_t handler)
+{
+ intrec *p = intreclist_head[intr];
+
+ if (p != NULL && (p->flags & INTR_EXCL) != 0 &&
+ p->handler == isa_intr_wrap && isareclist[intr] != NULL &&
+ isareclist[intr]->id_handler == handler) {
+ free(isareclist[intr], M_DEVBUF);
+ isareclist[intr] = NULL;
+ return (inthand_remove(p));
+ }
+ return (EINVAL);
+}
diff --git a/sys/i386/isa/intr_machdep.h b/sys/i386/isa/intr_machdep.h
index 7cdce87..1d49d1d 100644
--- a/sys/i386/isa/intr_machdep.h
+++ b/sys/i386/isa/intr_machdep.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
- * $Id: intr_machdep.h,v 1.12 1998/05/31 10:53:54 bde Exp $
+ * $Id: intr_machdep.h,v 1.13 1998/06/18 15:32:06 bde Exp $
*/
#ifndef _I386_ISA_INTR_MACHDEP_H_
@@ -190,15 +190,28 @@ inthand_t
struct isa_device;
void isa_defaultirq __P((void));
-intrmask_t isa_irq_pending __P((void));
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));
+intrmask_t splq __P((intrmask_t mask));
+
+/* XXX currently dev_instance must be set to the ISA device_id or -1 for PCI */
+#define INTR_FAST 0x00000001 /* fast interrupt handler */
+#define INTR_EXCL 0x00010000 /* excl. intr, default is shared */
+
+struct intrec *inthand_add(const char *name, int irq, inthand2_t handler,
+ void *arg, intrmask_t *maskptr, int flags);
+
+int inthand_remove(struct intrec *idesc);
+
+int register_intr __P((int intr, int device_id, u_int flags,
+ ointhand2_t *handler, u_int *maskptr, int unit));
+int unregister_intr(int intr, ointhand2_t handler);
+
#endif /* LOCORE */
#endif /* KERNEL */
diff --git a/sys/i386/isa/ipl_funcs.c b/sys/i386/isa/ipl_funcs.c
index aeba4ac..c73fc22 100644
--- a/sys/i386/isa/ipl_funcs.c
+++ b/sys/i386/isa/ipl_funcs.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ipl_funcs.c,v 1.14 1998/12/07 21:58:22 archie Exp $
+ * $Id: ipl_funcs.c,v 1.15 1999/03/05 23:39:02 gibbs Exp $
*/
#include <sys/types.h>
@@ -105,6 +105,14 @@ splx(unsigned ipl)
splz();
}
+intrmask_t
+splq(intrmask_t mask)
+{
+ intrmask_t tmp = cpl;
+ cpl |= mask;
+ return (tmp);
+}
+
#else /* !SMP */
#include <machine/smp.h>
diff --git a/sys/i386/isa/isa_device.h b/sys/i386/isa/isa_device.h
index 8a8615f..92a3d14 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.58 1999/04/16 21:22:23 peter Exp $
+ * $Id: isa_device.h,v 1.59 1999/04/19 20:16:22 peter Exp $
*/
#ifndef _I386_ISA_ISA_DEVICE_H_
@@ -45,8 +45,6 @@
* ISA Bus Autoconfiguration
*/
-typedef void ointhand2_t __P((int unit));
-
/*
* Per device structure.
*
diff --git a/sys/i386/isa/isa_dma.c b/sys/i386/isa/isa_dma.c
index abea7f8..bbc09fd 100644
--- a/sys/i386/isa/isa_dma.c
+++ b/sys/i386/isa/isa_dma.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.117 1998/11/29 15:42:40 phk Exp $
+ * $Id: isa_dma.c,v 1.1 1999/04/16 21:22:24 peter Exp $
*/
/*
@@ -60,7 +60,6 @@
#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/ic/i8237.h>
diff --git a/sys/i386/isa/nmi.c b/sys/i386/isa/nmi.c
index 4f7c1e9..256c617 100644
--- a/sys/i386/isa/nmi.c
+++ b/sys/i386/isa/nmi.c
@@ -34,7 +34,13 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $
+ * $Id: intr_machdep.c,v 1.18 1999/04/16 21:22:22 peter Exp $
+ */
+/*
+ * This file contains an aggregated module marked:
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * All rights reserved.
+ * See the notice for details.
*/
#include "opt_auto_eoi.h"
@@ -45,9 +51,14 @@
#endif
#include <sys/systm.h>
#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <sys/interrupt.h>
#include <machine/ipl.h>
#include <machine/md_var.h>
#include <machine/segments.h>
+#include <sys/bus.h>
+
#if defined(APIC_IO)
#include <machine/smp.h>
#include <machine/smptests.h> /** FAST_HI */
@@ -62,6 +73,7 @@
#endif
#include <i386/isa/icu.h>
+#include <isa/isavar.h>
#include <i386/isa/intr_machdep.h>
#include <sys/interrupt.h>
#ifdef APIC_IO
@@ -300,7 +312,8 @@ update_intr_masks(void)
if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */
#endif /* APIC_IO */
maskptr = intr_mptr[intr];
- if (!maskptr) continue;
+ if (!maskptr)
+ continue;
*maskptr |= 1 << intr;
mask = *maskptr;
if (mask != intr_mask[intr]) {
@@ -316,48 +329,11 @@ update_intr_masks(void)
return (n);
}
-static const char *
-isa_get_nameunit(int id)
-{
- static char buf[32];
- struct isa_device *dp;
-
- if (id == -1)
- return ("pci"); /* XXX may also be eisa */
- if (id == 0)
- return ("clk0"); /* XXX may also be sloppy driver */
- if (id == 1)
- return ("rtc0");
-#if 0
- for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_cam; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_net; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_null; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
- for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++)
- if (dp->id_id == id)
- goto found_device;
-#endif
- return "???";
-
-found_device:
- snprintf(buf, sizeof(buf), "%s%d", dp->id_driver->name, dp->id_unit);
- return (buf);
-}
-
-void
-update_intrname(int intr, int device_id)
+static void
+update_intrname(int intr, char *name)
{
char buf[32];
char *cp;
- const char *name;
int name_index, off, strayintr;
/*
@@ -371,7 +347,8 @@ update_intrname(int intr, int device_id)
strayintr) + 1;
}
- name = isa_get_nameunit(device_id);
+ if (name == NULL)
+ name = "???";
if (snprintf(buf, sizeof(buf), "%s irq%d", name, intr) >= sizeof(buf))
goto use_bitbucket;
@@ -516,3 +493,410 @@ icu_unset(intr, handler)
write_eflags(ef);
return (0);
}
+
+/* The following notice applies beyond this point in the file */
+
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $Id: kern_intr.c,v 1.21 1998/11/10 09:16:29 peter Exp $
+ *
+ */
+
+typedef struct intrec {
+ intrmask_t mask;
+ inthand2_t *handler;
+ void *argument;
+ struct intrec *next;
+ char *name;
+ int intr;
+ intrmask_t *maskptr;
+ int flags;
+} intrec;
+
+static intrec *intreclist_head[ICU_LEN];
+
+typedef struct isarec {
+ int id_unit;
+ ointhand2_t *id_handler;
+} isarec;
+
+static isarec *isareclist[ICU_LEN];
+
+/*
+ * The interrupt multiplexer calls each of the handlers in turn,
+ * and applies the associated interrupt mask to "cpl", which is
+ * defined as a ".long" in /sys/i386/isa/ipl.s
+ */
+
+static void
+intr_mux(void *arg)
+{
+ intrec *p = arg;
+ int oldspl;
+
+ while (p != NULL) {
+ oldspl = splq(p->mask);
+ p->handler(p->argument);
+ splx(oldspl);
+ p = p->next;
+ }
+}
+
+static void
+isa_intr_wrap(void *cookie)
+{
+ isarec *irec = (isarec *)cookie;
+
+ irec->id_handler(irec->id_unit);
+}
+
+static intrec*
+find_idesc(unsigned *maskptr, int irq)
+{
+ intrec *p = intreclist_head[irq];
+
+ while (p && p->maskptr != maskptr)
+ p = p->next;
+
+ return (p);
+}
+
+static intrec**
+find_pred(intrec *idesc, int irq)
+{
+ intrec **pp = &intreclist_head[irq];
+ intrec *p = *pp;
+
+ while (p != idesc) {
+ if (p == NULL)
+ return (NULL);
+ pp = &p->next;
+ p = *pp;
+ }
+ return (pp);
+}
+
+/*
+ * Both the low level handler and the shared interrupt multiplexer
+ * block out further interrupts as set in the handlers "mask", while
+ * the handler is running. In fact *maskptr should be used for this
+ * purpose, but since this requires one more pointer dereference on
+ * each interrupt, we rather bother update "mask" whenever *maskptr
+ * changes. The function "update_masks" should be called **after**
+ * all manipulation of the linked list of interrupt handlers hung
+ * off of intrdec_head[irq] is complete, since the chain of handlers
+ * will both determine the *maskptr values and the instances of mask
+ * that are fixed. This function should be called with the irq for
+ * which a new handler has been add blocked, since the masks may not
+ * yet know about the use of this irq for a device of a certain class.
+ */
+
+static void
+update_mux_masks(void)
+{
+ int irq;
+ for (irq = 0; irq < ICU_LEN; irq++) {
+ intrec *idesc = intreclist_head[irq];
+ while (idesc != NULL) {
+ if (idesc->maskptr != NULL) {
+ /* our copy of *maskptr may be stale, refresh */
+ idesc->mask = *idesc->maskptr;
+ }
+ idesc = idesc->next;
+ }
+ }
+}
+
+static void
+update_masks(intrmask_t *maskptr, int irq)
+{
+ intrmask_t mask = 1 << irq;
+
+ if (maskptr == NULL)
+ return;
+
+ if (find_idesc(maskptr, irq) == NULL) {
+ /* no reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) == 0)
+ return;
+ /* the irq was included in the classes mask, remove it */
+ INTRUNMASK(*maskptr, mask);
+ } else {
+ /* a reference to this maskptr was found in this irq's chain */
+ if ((*maskptr & mask) != 0)
+ return;
+ /* put the irq into the classes mask */
+ INTRMASK(*maskptr, mask);
+ }
+ /* we need to update all values in the intr_mask[irq] array */
+ update_intr_masks();
+ /* update mask in chains of the interrupt multiplex handler as well */
+ update_mux_masks();
+}
+
+/*
+ * Add interrupt handler to linked list hung off of intreclist_head[irq]
+ * and install shared interrupt multiplex handler, if necessary
+ */
+
+static int
+add_intrdesc(intrec *idesc)
+{
+ int irq = idesc->intr;
+
+ intrec *head = intreclist_head[irq];
+
+ if (head == NULL) {
+ /* first handler for this irq, just install it */
+ if (icu_setup(irq, idesc->handler, idesc->argument,
+ idesc->maskptr, idesc->flags) != 0)
+ return (-1);
+
+ update_intrname(irq, idesc->name);
+ /* keep reference */
+ intreclist_head[irq] = idesc;
+ } else {
+ if ((idesc->flags & INTR_EXCL) != 0
+ || (head->flags & INTR_EXCL) != 0) {
+ /*
+ * can't append new handler, if either list head or
+ * new handler do not allow interrupts to be shared
+ */
+ if (bootverbose)
+ printf("\tdevice combination doesn't support "
+ "shared irq%d\n", irq);
+ return (-1);
+ }
+ if (head->next == NULL) {
+ /*
+ * second handler for this irq, replace device driver's
+ * handler by shared interrupt multiplexer function
+ */
+ icu_unset(irq, head->handler);
+ if (icu_setup(irq, intr_mux, head, 0, 0) != 0)
+ return (-1);
+ if (bootverbose)
+ printf("\tusing shared irq%d.\n", irq);
+ update_intrname(irq, "mux");
+ }
+ /* just append to the end of the chain */
+ while (head->next != NULL)
+ head = head->next;
+ head->next = idesc;
+ }
+ update_masks(idesc->maskptr, irq);
+ return (0);
+}
+
+/*
+ * Create and activate an interrupt handler descriptor data structure.
+ *
+ * The dev_instance pointer is required for resource management, and will
+ * only be passed through to resource_claim().
+ *
+ * There will be functions that derive a driver and unit name from a
+ * dev_instance variable, and those functions will be used to maintain the
+ * interrupt counter label array referenced by systat and vmstat to report
+ * device interrupt rates (->update_intrlabels).
+ *
+ * Add the interrupt handler descriptor data structure created by an
+ * earlier call of create_intr() to the linked list for its irq and
+ * adjust the interrupt masks if necessary.
+ */
+
+intrec *
+inthand_add(const char *name, int irq, inthand2_t handler, void *arg,
+ intrmask_t *maskptr, int flags)
+{
+ intrec *idesc;
+ int errcode = -1;
+ intrmask_t oldspl;
+
+ if (ICU_LEN > 8 * sizeof *maskptr) {
+ printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n",
+ ICU_LEN, 8 * sizeof *maskptr);
+ return (NULL);
+ }
+ if ((unsigned)irq >= ICU_LEN) {
+ printf("create_intr: requested irq%d too high, limit is %d\n",
+ irq, ICU_LEN -1);
+ return (NULL);
+ }
+
+ idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK);
+ if (idesc == NULL)
+ return NULL;
+ bzero(idesc, sizeof *idesc);
+
+ if (name == NULL)
+ name = "???";
+ idesc->name = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
+ if (idesc->name == NULL) {
+ free(idesc, M_DEVBUF);
+ return NULL;
+ }
+ strcpy(idesc->name, name);
+
+ idesc->handler = handler;
+ idesc->argument = arg;
+ idesc->maskptr = maskptr;
+ idesc->intr = irq;
+ idesc->flags = flags;
+
+ /* block this irq */
+ oldspl = splq(1 << irq);
+
+ /* add irq to class selected by maskptr */
+ errcode = add_intrdesc(idesc);
+ splx(oldspl);
+
+ if (errcode != 0) {
+ if (bootverbose)
+ printf("\tintr_connect(irq%d) failed, result=%d\n",
+ irq, errcode);
+ free(idesc->name, M_DEVBUF);
+ free(idesc, M_DEVBUF);
+ idesc = NULL;
+ }
+
+ return (idesc);
+}
+
+/*
+ * Deactivate and remove the interrupt handler descriptor data connected
+ * created by an earlier call of intr_connect() from the linked list and
+ * adjust theinterrupt masks if necessary.
+ *
+ * Return the memory held by the interrupt handler descriptor data structure
+ * to the system. Make sure, the handler is not actively used anymore, before.
+ */
+
+int
+inthand_remove(intrec *idesc)
+{
+ intrec **hook, *head;
+ int irq;
+ int errcode = 0;
+ intrmask_t oldspl;
+
+ if (idesc == NULL)
+ return (-1);
+
+ irq = idesc->intr;
+
+ /* find pointer that keeps the reference to this interrupt descriptor */
+ hook = find_pred(idesc, irq);
+ if (hook == NULL)
+ return (-1);
+
+ /* make copy of original list head, the line after may overwrite it */
+ head = intreclist_head[irq];
+
+ /* unlink: make predecessor point to idesc->next instead of to idesc */
+ *hook = idesc->next;
+
+ /* now check whether the element we removed was the list head */
+ if (idesc == head) {
+
+ oldspl = splq(1 << irq);
+
+ /* we want to remove the list head, which was known to intr_mux */
+ icu_unset(irq, intr_mux);
+
+ /* check whether the new list head is the only element on list */
+ head = intreclist_head[irq];
+ if (head != NULL) {
+ if (head->next != NULL) {
+ /* install the multiplex handler with new list head as argument */
+ errcode = icu_setup(irq, intr_mux, head, 0, 0);
+ if (errcode == 0)
+ update_intrname(irq, NULL);
+ } else {
+ /* install the one remaining handler for this irq */
+ errcode = icu_setup(irq, head->handler,
+ head->argument,
+ head->maskptr, head->flags);
+ if (errcode == 0)
+ update_intrname(irq, head->name);
+ }
+ }
+ splx(oldspl);
+ }
+ update_masks(idesc->maskptr, irq);
+
+ free(idesc, M_DEVBUF);
+ return (0);
+}
+
+/*
+ * Emulate the register_intr() call previously defined as low level function.
+ * That function (now icu_setup()) may no longer be directly called, since
+ * a conflict between an ISA and PCI interrupt might go by unnocticed, else.
+ */
+
+int
+register_intr(int intr, int device_id, u_int flags,
+ ointhand2_t handler, u_int *maskptr, int unit)
+{
+ intrec *idesc;
+ isarec *irec;
+
+ irec = malloc(sizeof *irec, M_DEVBUF, M_WAITOK);
+ if (irec == NULL)
+ return NULL;
+ bzero(irec, sizeof *irec);
+ irec->id_unit = device_id;
+ irec->id_handler = handler;
+
+ flags |= INTR_EXCL;
+ idesc = inthand_add("old", intr, isa_intr_wrap, irec, maskptr, flags);
+ if (idesc == NULL) {
+ free(irec, M_DEVBUF);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Emulate the old unregister_intr() low level function.
+ * Make sure there is just one interrupt, that it was
+ * registered as non-shared, and that the handlers match.
+ */
+
+int
+unregister_intr(int intr, ointhand2_t handler)
+{
+ intrec *p = intreclist_head[intr];
+
+ if (p != NULL && (p->flags & INTR_EXCL) != 0 &&
+ p->handler == isa_intr_wrap && isareclist[intr] != NULL &&
+ isareclist[intr]->id_handler == handler) {
+ free(isareclist[intr], M_DEVBUF);
+ isareclist[intr] = NULL;
+ return (inthand_remove(p));
+ }
+ return (EINVAL);
+}
diff --git a/sys/i386/isa/random_machdep.c b/sys/i386/isa/random_machdep.c
index d635668..fbb0f86 100644
--- a/sys/i386/isa/random_machdep.c
+++ b/sys/i386/isa/random_machdep.c
@@ -1,7 +1,7 @@
/*
* random_machdep.c -- A strong random number generator
*
- * $Id: random_machdep.c,v 1.28 1998/06/18 15:32:07 bde Exp $
+ * $Id: random_machdep.c,v 1.29 1998/06/21 11:33:32 bde Exp $
*
* Version 0.95, last modified 18-Oct-95
*
@@ -45,6 +45,7 @@
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/md5.h>
+#include <sys/bus.h>
#include <machine/random.h>
diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c
index d9bca71..3daaf94 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.128 1998/10/23 10:46:20 phk Exp $
+ * $Id: clock.c,v 1.129 1998/12/14 13:30:29 mckay Exp $
*/
/*
@@ -86,7 +86,7 @@
#include <i386/isa/rtc.h>
#include <i386/isa/timerreg.h>
-#include <sys/interrupt.h>
+#include <i386/isa/intr_machdep.h>
#ifdef SMP
#define disable_intr() CLOCK_DISABLE_INTR()
@@ -948,6 +948,7 @@ cpu_initclocks()
int diag;
#ifdef APIC_IO
int apic_8254_trial;
+ intrec *clkdesc;
#endif /* APIC_IO */
if (statclock_disable) {
@@ -982,16 +983,14 @@ cpu_initclocks()
panic("APIC_IO: Cannot route 8254 interrupt to CPU");
}
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
#else /* APIC_IO */
- register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
+ INTR_EXCL);
INTREN(IRQ0);
#endif /* APIC_IO */
@@ -1012,9 +1011,8 @@ cpu_initclocks()
panic("APIC RTC != 8");
#endif /* APIC_IO */
- register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
- /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
- /* unit */ 0);
+ inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
+ INTR_EXCL);
#ifdef APIC_IO
INTREN(APIC_IRQ8);
@@ -1038,17 +1036,15 @@ cpu_initclocks()
* Workaround: Limited variant of mixed mode.
*/
INTRDIS(1 << apic_8254_intr);
- unregister_intr(apic_8254_intr,
- /* XXX */ (inthand2_t *) clkintr);
+ inthand_remove(clkdesc);
printf("APIC_IO: Broken MP table detected: "
"8254 is not connected to IO APIC int pin %d\n",
apic_8254_intr);
apic_8254_intr = 0;
setup_8254_mixed_mode();
- register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
- /* XXX */ (inthand2_t *)clkintr, &clk_imask,
- /* unit */ 0);
+ inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
+ NULL, &clk_imask, INTR_EXCL);
INTREN(1 << apic_8254_intr);
}
diff --git a/sys/isa/isavar.h b/sys/isa/isavar.h
index 21447b6..f1eb25c 100644
--- a/sys/isa/isavar.h
+++ b/sys/isa/isavar.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: isavar.h,v 1.2 1998/11/15 18:25:17 dfr Exp $
+ * $Id: isavar.h,v 1.3 1999/04/16 21:22:34 peter Exp $
*/
#define ISA_NPORT_IVARS 2
@@ -53,8 +53,8 @@ enum isa_device_ivars {
ISA_IVAR_DRQ_1
};
-extern int isa_irq_pending(void);
-extern int isa_irq_mask(void);
+extern intrmask_t isa_irq_pending(void);
+extern intrmask_t isa_irq_mask(void);
/*
* Simplified accessors for isa devices
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 1d6756c..22565f7 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.20 1998/09/26 14:25:31 dfr Exp $
+ * $Id: kern_intr.c,v 1.21 1998/11/10 09:16:29 peter Exp $
*
*/
@@ -32,38 +32,11 @@
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/errno.h>
-#ifdef RESOURCE_CHECK
-#include <sys/drvresource.h>
-#endif /* RESOURCE_CHECK */
#include <machine/ipl.h>
-#ifdef __i386__
-#include <i386/isa/icu.h>
-#include <i386/isa/intr_machdep.h>
-#endif
-
#include <sys/interrupt.h>
-#include <stddef.h>
-
-#ifdef __i386__
-
-typedef struct intrec {
- intrmask_t mask;
- inthand2_t *handler;
- void *argument;
- struct intrec *next;
- void *devdata;
- int intr;
- intrmask_t *maskptr;
- int flags;
-} intrec;
-
-static intrec *intreclist_head[NHWI];
-
-#endif
-
struct swilist {
swihand_t *sl_handler;
struct swilist *sl_next;
@@ -71,383 +44,6 @@ struct swilist {
static struct swilist swilists[NSWI];
-#ifdef __i386__
-
-/*
- * The interrupt multiplexer calls each of the handlers in turn,
- * and applies the associated interrupt mask to "cpl", which is
- * defined as a ".long" in /sys/i386/isa/ipl.s
- */
-
-#ifndef SMP
-static __inline intrmask_t
-splq(intrmask_t mask)
-{
- intrmask_t tmp = cpl;
- cpl |= mask;
- return (tmp);
-}
-#endif /* SMP */
-
-static void
-intr_mux(void *arg)
-{
- intrec *p = arg;
-
- while (p != NULL) {
- int oldspl = splq(p->mask);
- p->handler(p->argument);
- splx(oldspl);
- p = p->next;
- }
-}
-
-static intrec*
-find_idesc(unsigned *maskptr, int irq)
-{
- intrec *p = intreclist_head[irq];
-
- while (p && p->maskptr != maskptr)
- p = p->next;
-
- return (p);
-}
-
-static intrec**
-find_pred(intrec *idesc, int irq)
-{
- intrec **pp = &intreclist_head[irq];
- intrec *p = *pp;
-
- while (p != idesc) {
- if (p == NULL)
- return (NULL);
- pp = &p->next;
- p = *pp;
- }
- return (pp);
-}
-
-/*
- * Both the low level handler and the shared interrupt multiplexer
- * block out further interrupts as set in the handlers "mask", while
- * the handler is running. In fact *maskptr should be used for this
- * purpose, but since this requires one more pointer dereference on
- * each interrupt, we rather bother update "mask" whenever *maskptr
- * changes. The function "update_masks" should be called **after**
- * all manipulation of the linked list of interrupt handlers hung
- * off of intrdec_head[irq] is complete, since the chain of handlers
- * will both determine the *maskptr values and the instances of mask
- * that are fixed. This function should be called with the irq for
- * which a new handler has been add blocked, since the masks may not
- * yet know about the use of this irq for a device of a certain class.
- */
-
-static void
-update_mux_masks(void)
-{
- int irq;
- for (irq = 0; irq < ICU_LEN; irq++) {
- intrec *idesc = intreclist_head[irq];
- while (idesc != NULL) {
- if (idesc->maskptr != NULL) {
- /* our copy of *maskptr may be stale, refresh */
- idesc->mask = *idesc->maskptr;
- }
- idesc = idesc->next;
- }
- }
-}
-
-static void
-update_masks(intrmask_t *maskptr, int irq)
-{
- intrmask_t mask = 1 << irq;
-
- if (maskptr == NULL)
- return;
-
- if (find_idesc(maskptr, irq) == NULL) {
- /* no reference to this maskptr was found in this irq's chain */
- if ((*maskptr & mask) == 0)
- return;
- /* the irq was included in the classes mask, remove it */
- INTRUNMASK(*maskptr, mask);
- } else {
- /* a reference to this maskptr was found in this irq's chain */
- if ((*maskptr & mask) != 0)
- return;
- /* put the irq into the classes mask */
- INTRMASK(*maskptr, mask);
- }
- /* we need to update all values in the intr_mask[irq] array */
- update_intr_masks();
- /* update mask in chains of the interrupt multiplex handler as well */
- update_mux_masks();
-}
-
-/*
- * Add interrupt handler to linked list hung off of intreclist_head[irq]
- * and install shared interrupt multiplex handler, if necessary
- */
-
-static int
-add_intrdesc(intrec *idesc)
-{
- int irq = idesc->intr;
-
- intrec *head = intreclist_head[irq];
-
- if (head == NULL) {
- /* first handler for this irq, just install it */
- if (icu_setup(irq, idesc->handler, idesc->argument,
- idesc->maskptr, idesc->flags) != 0)
- return (-1);
-
- update_intrname(irq, (intptr_t)idesc->devdata);
- /* keep reference */
- intreclist_head[irq] = idesc;
- } else {
- if ((idesc->flags & INTR_EXCL) != 0
- || (head->flags & INTR_EXCL) != 0) {
- /*
- * can't append new handler, if either list head or
- * new handler do not allow interrupts to be shared
- */
- if (bootverbose)
- printf("\tdevice combination doesn't support "
- "shared irq%d\n", irq);
- return (-1);
- }
- if (head->next == NULL) {
- /*
- * second handler for this irq, replace device driver's
- * handler by shared interrupt multiplexer function
- */
- icu_unset(irq, head->handler);
- if (icu_setup(irq, (inthand2_t*)intr_mux, head, 0, 0) != 0)
- return (-1);
- if (bootverbose)
- printf("\tusing shared irq%d.\n", irq);
- update_intrname(irq, -1);
- }
- /* just append to the end of the chain */
- while (head->next != NULL)
- head = head->next;
- head->next = idesc;
- }
- update_masks(idesc->maskptr, irq);
- return (0);
-}
-
-/*
- * Add the interrupt handler descriptor data structure created by an
- * earlier call of create_intr() to the linked list for its irq and
- * adjust the interrupt masks if necessary.
- *
- * This function effectively activates the handler.
- */
-
-int
-intr_connect(intrec *idesc)
-{
- int errcode = -1;
- int irq;
-
-#ifdef RESOURCE_CHECK
- int resflag;
-#endif /* RESOURCE_CHECK */
-
- if (idesc == NULL)
- return (-1);
-
- irq = idesc->intr;
-#ifdef RESOURCE_CHECK
- resflag = (idesc->flags & INTR_EXCL) ? RESF_NONE : RESF_SHARED;
- if (resource_claim(idesc->devdata, REST_INT, resflag, irq, irq) == 0)
-#endif /* RESOURCE_CHECK */
- {
- /* block this irq */
- intrmask_t oldspl = splq(1 << irq);
-
- /* add irq to class selected by maskptr */
- errcode = add_intrdesc(idesc);
- splx(oldspl);
- }
- if (errcode != 0 && bootverbose)
- printf("\tintr_connect(irq%d) failed, result=%d\n",
- irq, errcode);
-
- return (errcode);
-}
-
-/*
- * Remove the interrupt handler descriptor data connected created by an
- * earlier call of intr_connect() from the linked list and adjust the
- * interrupt masks if necessary.
- *
- * This function deactivates the handler.
- */
-
-int
-intr_disconnect(intrec *idesc)
-{
- intrec **hook, *head;
- int irq;
- int errcode = 0;
-
- if (idesc == NULL)
- return (-1);
-
- irq = idesc->intr;
-
- /* find pointer that keeps the reference to this interrupt descriptor */
- hook = find_pred(idesc, irq);
- if (hook == NULL)
- return (-1);
-
- /* make copy of original list head, the line after may overwrite it */
- head = intreclist_head[irq];
-
- /* unlink: make predecessor point to idesc->next instead of to idesc */
- *hook = idesc->next;
-
- /* now check whether the element we removed was the list head */
- if (idesc == head) {
- intrmask_t oldspl = splq(1 << irq);
-
- /* we want to remove the list head, which was known to intr_mux */
- icu_unset(irq, (inthand2_t*)intr_mux);
-
- /* check whether the new list head is the only element on list */
- head = intreclist_head[irq];
- if (head != NULL) {
- if (head->next != NULL) {
- /* install the multiplex handler with new list head as argument */
- errcode = icu_setup(irq, (inthand2_t*)intr_mux, head, 0, 0);
- if (errcode == 0)
- update_intrname(irq, -1);
- } else {
- /* install the one remaining handler for this irq */
- errcode = icu_setup(irq, head->handler,
- head->argument,
- head->maskptr, head->flags);
- if (errcode == 0)
- update_intrname(irq, (intptr_t)head->devdata);
- }
- }
- splx(oldspl);
- }
- update_masks(idesc->maskptr, irq);
-#ifdef RESOURCE_CHECK
- resource_free(idesc->devdata);
-#endif /* RESOURCE_CHECK */
- return (0);
-}
-
-/*
- * Create an interrupt handler descriptor data structure, which later can
- * be activated or deactivated at will by calls of [dis]connect(intrec*).
- *
- * The dev_instance pointer is required for resource management, and will
- * only be passed through to resource_claim().
- *
- * The interrupt handler takes an argument of type (void*), which is not
- * what is currently used for ISA devices. But since the unit number passed
- * to an ISA interrupt handler can be stored in a (void*) variable, this
- * causes no problems. Eventually all the ISA interrupt handlers should be
- * modified to accept the pointer to their private data, too, instead of
- * an integer index.
- *
- * There will be functions that derive a driver and unit name from a
- * dev_instance variable, and those functions will be used to maintain the
- * interrupt counter label array referenced by systat and vmstat to report
- * device interrupt rates (->update_intrlabels).
- */
-
-intrec *
-intr_create(void *dev_instance, int irq, inthand2_t handler, void *arg,
- intrmask_t *maskptr, int flags)
-{
- intrec *idesc;
-
- if (ICU_LEN > 8 * sizeof *maskptr) {
- printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n",
- ICU_LEN, 8 * sizeof *maskptr);
- return (NULL);
- }
- if ((unsigned)irq >= ICU_LEN) {
- printf("create_intr: requested irq%d too high, limit is %d\n",
- irq, ICU_LEN -1);
- return (NULL);
- }
-
- idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK);
- if (idesc) {
- idesc->next = NULL;
- bzero(idesc, sizeof *idesc);
-
- idesc->devdata = dev_instance;
- idesc->handler = handler;
- idesc->argument = arg;
- idesc->maskptr = maskptr;
- idesc->intr = irq;
- idesc->flags = flags;
- }
- return (idesc);
-}
-
-/*
- * Return the memory held by the interrupt handler descriptor data structure
- * to the system. Make sure, the handler is not actively used anymore, before.
- */
-
-int
-intr_destroy(intrec *rec)
-{
- if (intr_disconnect(rec) != 0)
- return (-1);
- free(rec, M_DEVBUF);
- return (0);
-}
-
-/*
- * Emulate the register_intr() call previously defined as low level function.
- * That function (now icu_setup()) may no longer be directly called, since
- * a conflict between an ISA and PCI interrupt might go by unnocticed, else.
- */
-
-int
-register_intr(int intr, int device_id, u_int flags,
- inthand2_t handler, u_int *maskptr, int unit)
-{
- /* XXX modify to include isa_device instead of device_id */
- intrec *idesc;
-
- flags |= INTR_EXCL;
- idesc = intr_create((void *)(intptr_t)device_id, intr, handler,
- (void*)(intptr_t)unit, maskptr, flags);
- return (intr_connect(idesc));
-}
-
-/*
- * Emulate the old unregister_intr() low level function.
- * Make sure there is just one interrupt, that it was
- * registered as non-shared, and that the handlers match.
- */
-
-int
-unregister_intr(int intr, inthand2_t handler)
-{
- intrec *p = intreclist_head[intr];
-
- if (p != NULL && (p->flags & INTR_EXCL) != 0 && p->handler == handler)
- return (intr_destroy(p));
- return (EINVAL);
-}
-
-#endif /* __i386__ */
-
void
register_swi(intr, handler)
int intr;
diff --git a/sys/kern/kern_random.c b/sys/kern/kern_random.c
index d635668..fbb0f86 100644
--- a/sys/kern/kern_random.c
+++ b/sys/kern/kern_random.c
@@ -1,7 +1,7 @@
/*
* random_machdep.c -- A strong random number generator
*
- * $Id: random_machdep.c,v 1.28 1998/06/18 15:32:07 bde Exp $
+ * $Id: random_machdep.c,v 1.29 1998/06/21 11:33:32 bde Exp $
*
* Version 0.95, last modified 18-Oct-95
*
@@ -45,6 +45,7 @@
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/md5.h>
+#include <sys/bus.h>
#include <machine/random.h>
diff --git a/sys/pci/intpm.c b/sys/pci/intpm.c
index 705e8c6..a07d752 100644
--- a/sys/pci/intpm.c
+++ b/sys/pci/intpm.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: intpm.c,v 1.3 1999/01/27 23:45:43 dillon Exp $
+ * $Id: intpm.c,v 1.4 1999/01/28 00:57:53 dillon Exp $
*/
#include "pci.h"
@@ -670,12 +670,10 @@ static int force_pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsign
#endif
/* Spec sheet claims that it use IRQ 9*/
int irq = 9;
- void *dev_instance = (void *)-1; /* XXX use cfg->devdata */
void *idesc;
- idesc = intr_create(dev_instance, irq, func, arg, maskptr, 0);
- error = intr_connect(idesc);
- if (error != 0)
+ idesc = inthand_add(NULL, irq, func, arg, maskptr, 0);
+ if (idesc == 0)
return 0;
#ifdef APIC_IO
nextpin = next_apic_irq(irq);
@@ -706,9 +704,7 @@ static int force_pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsign
nextpin = next_apic_irq(irq);
while (nextpin >= 0) {
- idesc = intr_create(dev_instance, nextpin, func, arg,
- maskptr, 0);
- error = intr_connect(idesc);
+ idesc = inthand_add(NULL, nextpin, func, arg, maskptr, 0);
if (error != 0)
return 0;
printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq);
diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h
index 5db9081..6c71703 100644
--- a/sys/sys/interrupt.h
+++ b/sys/sys/interrupt.h
@@ -23,35 +23,20 @@
* (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: interrupt.h,v 1.6 1997/07/09 18:08:15 ache Exp $
+ * $Id: interrupt.h,v 1.7 1998/08/11 15:08:13 bde Exp $
*/
-/* XXX currently dev_instance must be set to the ISA device_id or -1 for PCI */
-#define INTR_FAST 0x00000001 /* fast interrupt handler */
-#define INTR_EXCL 0x00010000 /* excl. intr, default is shared */
+#ifndef _SYS_INTERRUPT_H_
+#define _SYS_INTERRUPT_H_
typedef void swihand_t __P((void));
-struct intrec *intr_create(void *dev_instance, int irq, inthand2_t handler,
- void *arg, intrmask_t *maskptr, int flags);
-
-int intr_destroy(struct intrec *idesc);
-
-int intr_connect(struct intrec *idesc);
-int intr_disconnect(struct intrec *idesc);
-
void register_swi __P((int intr, swihand_t *handler));
void swi_dispatcher __P((int intr));
swihand_t swi_generic;
swihand_t swi_null;
void unregister_swi __P((int intr, swihand_t *handler));
-/* XXX emulate old interface for now ... */
-int register_intr __P((int intr, int device_id, u_int flags,
- inthand2_t *handler, u_int *maskptr, int unit));
-int unregister_intr(int intr, inthand2_t handler);
+extern swihand_t *ihandlers[];
-#ifdef NHWI
-/* XXX type change in middle; MI code uses only the top NSWI entries. */
-extern swihand_t *ihandlers[NHWI + NSWI];
#endif
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 99539f1..cb28195 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)systm.h 8.7 (Berkeley) 3/29/95
- * $Id: systm.h,v 1.86 1999/03/05 19:27:22 bde Exp $
+ * $Id: systm.h,v 1.87 1999/03/11 15:09:40 phk Exp $
*/
#ifndef _SYS_SYSTM_H_
@@ -220,9 +220,6 @@ intrmask_t splclock __P((void));
intrmask_t splhigh __P((void));
intrmask_t splimp __P((void));
intrmask_t splnet __P((void));
-#ifdef SMP
-intrmask_t splq __P((intrmask_t mask));
-#endif
intrmask_t splsoftcam __P((void));
intrmask_t splsoftcambio __P((void));
intrmask_t splsoftcamnet __P((void));
OpenPOWER on IntegriCloud