summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1999-04-21 07:26:30 +0000
committerpeter <peter@FreeBSD.org>1999-04-21 07:26:30 +0000
commitfa628c268c2d531552037f05699c06959d9618e6 (patch)
tree139882de7181a80226508d0a7c0f4695f2639ae0
parent47b96f90c086096cb12e76442461d4da895e207b (diff)
downloadFreeBSD-src-fa628c268c2d531552037f05699c06959d9618e6.zip
FreeBSD-src-fa628c268c2d531552037f05699c06959d9618e6.tar.gz
Stage 1 of a cleanup of the i386 interrupt registration mechanism.
Interrupts under the new scheme are managed by the i386 nexus with the awareness of the resource manager. There is further room for optimizing the interfaces still. All the users of register_intr()/intr_create() should be gone, with the exception of pcic and i386/isa/clock.c.
-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