diff options
author | dg <dg@FreeBSD.org> | 1994-08-18 05:09:36 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1994-08-18 05:09:36 +0000 |
commit | 7b3218c89f6c5e1d72625d3be9db3a221ea7f330 (patch) | |
tree | 1abd0f0dcf193ac24dd552de50221c9fb30b3610 | |
parent | c87abe4536bb366a683e0f2b5fcaaa67d072ba75 (diff) | |
download | FreeBSD-src-7b3218c89f6c5e1d72625d3be9db3a221ea7f330.zip FreeBSD-src-7b3218c89f6c5e1d72625d3be9db3a221ea7f330.tar.gz |
Bruce Evans' dynamic interrupt support.
/usr/src/sys/i386/isa/clock.c:
o Garrett's statclock changes.
o Wire xxxintr, not Vclk.
o Wire using register_intr(), not setidt().
/usr/src/sys/i386/isa/icu.s:
o Garrett's statclock changes.
o Removed unused variable high_imask.
o Fake int 8 for rtc as well as int 0 for clk. Required for kernel
profiling with statclock, harmless otherwise.
/usr/src/sys/i386/isa/isa.c:
o Allow isdp->id_irq and other things in *isdp to be changed by
probes. Changing interrupts later requires direct calls to
register_intr() and unregister_intr() and more care.
ALLOW_CONFLICT_* is brought over from 1.1.5, except
ALLOW_CONFLICT_IRQ is not supported. IRQ conflict checking is
delayed until after probing so that drivers can change the IRQ
to a free one; real conflicts require more cooperation between
drivers to handle.
o Too many details to list.
o This file requires splitting and a lot more work.
/usr/src/sys/i386/isa/isa_device.h:
o Declare more things more completely.
/usr/src/sys/i386/isa/sio.c:
o Prepare to register interrupt handlers as fast.
/usr/src/sys/i386/isa/vector.s:
o Generate entry code for 16 fast interrupt handlers and 16 normal
interrupt handlers. Changed some constants to variables:
# $unit is now intr_unit[intr]. Type is int. Someday it should
be a cookie suitable for the handler (e.g., a struct com_s for
sio).
# $handler is now intr_handler[intr].
# intrcnt_actv[id_num] is now *intr_countp[intr]. The indirection
is required to get a contiguous range of counters for vmstat
and so that the drivers depend more in the driver than on the
interrupt number (drivers could take turns using an interrupt
and the counts would remain correct). There is a separate
counter for each device and for each stray interrupt. In
1.1.5, stray interrupt 7 clobbers the count for device 7 or
something worse if there is no device 7 :-(.
# mask is now intr_mask[intr] (was already indirect).
o Entry points are now _XintrI and _XfastintrI (I = intr = 0-15),
not _VdevU (U = unit).
o Removed BUILD_VECTORS stuff. There's a trace of it left for
the string table for vmstat but config now generates the
string in one piece because nothing more is required.
o Removed old handling of stray interrupts and older comments
about it.
Submitted by: Bruce Evans
-rw-r--r-- | sys/amd64/amd64/tsc.c | 12 | ||||
-rw-r--r-- | sys/amd64/isa/clock.c | 12 | ||||
-rw-r--r-- | sys/amd64/isa/isa.c | 358 | ||||
-rw-r--r-- | sys/amd64/isa/vector.S | 238 | ||||
-rw-r--r-- | sys/amd64/isa/vector.s | 238 | ||||
-rw-r--r-- | sys/dev/sio/sio.c | 3 | ||||
-rw-r--r-- | sys/i386/i386/tsc.c | 12 | ||||
-rw-r--r-- | sys/i386/isa/clock.c | 12 | ||||
-rw-r--r-- | sys/i386/isa/icu.s | 20 | ||||
-rw-r--r-- | sys/i386/isa/isa.c | 358 | ||||
-rw-r--r-- | sys/i386/isa/isa_device.h | 65 | ||||
-rw-r--r-- | sys/i386/isa/sio.c | 3 | ||||
-rw-r--r-- | sys/i386/isa/vector.s | 238 | ||||
-rw-r--r-- | sys/isa/atrtc.c | 12 | ||||
-rw-r--r-- | sys/isa/sio.c | 3 |
15 files changed, 856 insertions, 728 deletions
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 35f2e42..e3f3f21 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.13 1994/08/13 03:49:56 wollman Exp $ + * $Id: clock.c,v 1.14 1994/08/15 03:15:18 wollman Exp $ */ /* @@ -497,16 +497,14 @@ test_inittodr(time_t base) /* * Wire clock interrupt in. */ -#define V(s) __CONCAT(V, s) -extern void V(clk)(); -extern void V(rtc)(); - void enablertclock() { - setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, clkintr, + HWI_MASK | SWI_MASK, /* unit */ 0); INTREN(IRQ0); - setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, rtcintr, + SWI_CLOCK_MASK, /* unit */ 0); INTREN(IRQ8); outb(IO_RTC, RTC_STATUSB); outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR); diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 35f2e42..e3f3f21 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.13 1994/08/13 03:49:56 wollman Exp $ + * $Id: clock.c,v 1.14 1994/08/15 03:15:18 wollman Exp $ */ /* @@ -497,16 +497,14 @@ test_inittodr(time_t base) /* * Wire clock interrupt in. */ -#define V(s) __CONCAT(V, s) -extern void V(clk)(); -extern void V(rtc)(); - void enablertclock() { - setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, clkintr, + HWI_MASK | SWI_MASK, /* unit */ 0); INTREN(IRQ0); - setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, rtcintr, + SWI_CLOCK_MASK, /* unit */ 0); INTREN(IRQ8); outb(IO_RTC, RTC_STATUSB); outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR); diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c index 80be9a5..5b5878e 100644 --- a/sys/amd64/isa/isa.c +++ b/sys/amd64/isa/isa.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.19 1994/08/10 04:39:52 wollman Exp $ + * $Id: isa.c,v 1.20 1994/08/13 03:50:07 wollman Exp $ */ /* @@ -65,6 +65,7 @@ #include <i386/isa/icu.h> #include <i386/isa/ic/i8237.h> #include <i386/isa/ic/i8042.h> +#include "vector.h" /* ** Register definitions for DMA controller 1 (channels 0..3): @@ -82,20 +83,70 @@ #define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ #define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ -void config_isadev __P((struct isa_device *, u_int *)); +/* + * Bits to specify the type and amount of conflict checking. + */ +#define CC_ATTACH (1 << 0) +#define CC_DRQ (1 << 1) +#define CC_IOADDR (1 << 2) +#define CC_IRQ (1 << 3) +#define CC_MEMADDR (1 << 4) + +/* + * XXX these defines should be in a central place. + */ +#define read_eflags() ({u_long ef; \ + __asm("pushfl; popl %0" : "=a" (ef)); \ + ef; }) +#define write_eflags(ef) __asm("pushl %0; popfl" : : "a" ((u_long)(ef))) + +u_long *intr_countp[ICU_LEN]; +inthand2_t *intr_handler[ICU_LEN]; +u_int intr_mask[ICU_LEN]; +int intr_unit[ICU_LEN]; + +static inthand_t *fastintr[ICU_LEN] = { + &IDTVEC(fastintr0), &IDTVEC(fastintr1), + &IDTVEC(fastintr2), &IDTVEC(fastintr3), + &IDTVEC(fastintr4), &IDTVEC(fastintr5), + &IDTVEC(fastintr6), &IDTVEC(fastintr7), + &IDTVEC(fastintr8), &IDTVEC(fastintr9), + &IDTVEC(fastintr10), &IDTVEC(fastintr11), + &IDTVEC(fastintr12), &IDTVEC(fastintr13), + &IDTVEC(fastintr14), &IDTVEC(fastintr15) +}; + +static inthand_t *slowintr[ICU_LEN] = { + &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), + &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), + &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), + &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) +}; + +static void config_isadev __P((struct isa_device *isdp, u_int *mp)); +static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp, + int item, char const *whatnot, char const *reason, + char const *format)); +static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp, + u_int checkbits)); +static int haveseen_isadev __P((struct isa_device *dvp, u_int checkbits)); +static inthand2_t isa_strayintr; +static void register_imask __P((struct isa_device *dvp, u_int mask)); /* * print a conflict message */ -void -conflict(dvp, tmpdvp, item, reason, format) - struct isa_device *dvp, *tmpdvp; +static void +conflict(dvp, tmpdvp, item, whatnot, reason, format) + struct isa_device *dvp; + struct isa_device *tmpdvp; int item; - char *reason; - char *format; + char const *whatnot; + char const *reason; + char const *format; { - printf("%s%d not probed due to %s conflict with %s%d at ", - dvp->id_driver->name, dvp->id_unit, reason, + printf("%s%d not %sed due to %s conflict with %s%d at ", + dvp->id_driver->name, dvp->id_unit, whatnot, reason, tmpdvp->id_driver->name, tmpdvp->id_unit); printf(format, item); printf("\n"); @@ -105,9 +156,11 @@ conflict(dvp, tmpdvp, item, reason, format) * Check to see if things are alread in use, like IRQ's, I/O addresses * and Memory addresses. */ -int -haveseen(dvp, tmpdvp) - struct isa_device *dvp, *tmpdvp; +static int +haveseen(dvp, tmpdvp, checkbits) + struct isa_device *dvp; + struct isa_device *tmpdvp; + u_int checkbits; { int status = 0; @@ -115,17 +168,20 @@ haveseen(dvp, tmpdvp) * Only check against devices that have already been found */ if (tmpdvp->id_alive) { + char const *whatnot; + + whatnot = checkbits & CC_ATTACH ? "attach" : "probe"; /* * Check for I/O address conflict. We can only check the * starting address of the device against the range of the * device that has already been probed since we do not * know how many I/O addresses this device uses. */ - if (tmpdvp->id_alive != -1) { + if (checkbits & CC_IOADDR && tmpdvp->id_alive != -1) { if ((dvp->id_iobase >= tmpdvp->id_iobase) && (dvp->id_iobase <= (tmpdvp->id_iobase + tmpdvp->id_alive - 1))) { - conflict(dvp, tmpdvp, dvp->id_iobase, + conflict(dvp, tmpdvp, dvp->id_iobase, whatnot, "I/O address", "0x%x"); status = 1; } @@ -140,34 +196,32 @@ haveseen(dvp, tmpdvp) * since at that time we would know the full range. * XXX KERNBASE is a hack, we should have vaddr in the table! */ - if(tmpdvp->id_maddr) { - if((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && - (KERNBASE + dvp->id_maddr <= - (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { - conflict(dvp, tmpdvp, dvp->id_maddr, "maddr", - "0x%x"); + if (checkbits & CC_MEMADDR && tmpdvp->id_maddr) { + if ((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && + (KERNBASE + dvp->id_maddr <= + (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { + conflict(dvp, tmpdvp, (int)dvp->id_maddr, + whatnot, "maddr", "0x%x"); status = 1; } } -#ifndef COM_MULTIPORT /* * Check for IRQ conflicts. */ - if(tmpdvp->id_irq) { + if (checkbits & CC_IRQ && tmpdvp->id_irq) { if (tmpdvp->id_irq == dvp->id_irq) { conflict(dvp, tmpdvp, ffs(dvp->id_irq) - 1, - "irq", "%d"); + whatnot, "irq", "%d"); status = 1; } } -#endif /* * Check for DRQ conflicts. */ - if(tmpdvp->id_drq != -1) { + if (checkbits & CC_DRQ && tmpdvp->id_drq != -1) { if (tmpdvp->id_drq == dvp->id_drq) { - conflict(dvp, tmpdvp, dvp->id_drq, - "drq", "%d"); + conflict(dvp, tmpdvp, dvp->id_drq, whatnot, + "drq", "%d"); status = 1; } } @@ -179,25 +233,22 @@ haveseen(dvp, tmpdvp) * Search through all the isa_devtab_* tables looking for anything that * conflicts with the current device. */ -int -haveseen_isadev(dvp) +static int +haveseen_isadev(dvp, checkbits) struct isa_device *dvp; + u_int checkbits; { struct isa_device *tmpdvp; int status = 0; - for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } - for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } - for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } - for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } + for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); + for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); + for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); + for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); return(status); } @@ -208,26 +259,18 @@ void isa_configure() { struct isa_device *dvp; - enable_intr(); splhigh(); + enable_intr(); INTREN(IRQ_SLAVE); printf("Probing for devices on the ISA bus:\n"); - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,&tty_imask); - } - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,&bio_imask); - } - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,&net_imask); - } - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,(u_int *) NULL); - } + for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) + config_isadev(dvp, &tty_imask); + for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) + config_isadev(dvp, &bio_imask); + for (dvp = isa_devtab_net; dvp->id_driver; dvp++) + config_isadev(dvp, &net_imask); + for (dvp = isa_devtab_null; dvp->id_driver; dvp++) + config_isadev(dvp, (u_int *)NULL); bio_imask |= SWI_CLOCK_MASK; net_imask |= SWI_NET_MASK; tty_imask |= SWI_TTY_MASK; @@ -253,27 +296,54 @@ isa_configure() { printf("bio_imask %x tty_imask %x net_imask %x\n", bio_imask, tty_imask, net_imask); #endif + /* + * Finish initializing intr_mask[]. Note that the partly + * constructed masks aren't actually used since we're at splhigh. + * For fully dynamic initialization, register_intr() and + * unregister_intr() will have to adjust the masks for _all_ + * interrupts and for tty_imask, etc. + */ + for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) + register_imask(dvp, tty_imask); + for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) + register_imask(dvp, bio_imask); + for (dvp = isa_devtab_net; dvp->id_driver; dvp++) + register_imask(dvp, net_imask); + for (dvp = isa_devtab_null; dvp->id_driver; dvp++) + register_imask(dvp, SWI_CLOCK_MASK); splnone(); } /* * Configure an ISA device. */ -void +static void config_isadev(isdp, mp) struct isa_device *isdp; u_int *mp; { + u_int checkbits; + int id_alive; struct isa_driver *dp = isdp->id_driver; + checkbits = 0; +#ifndef ALLOW_CONFLICT_DRQ + checkbits |= CC_DRQ; +#endif +#ifndef ALLOW_CONFLICT_IOADDR + checkbits |= CC_IOADDR; +#endif +#ifndef ALLOW_CONFLICT_MEMADDR + checkbits |= CC_MEMADDR; +#endif + if (haveseen_isadev(isdp, checkbits)) + return; if (isdp->id_maddr) { - extern u_int atdevbase; - isdp->id_maddr -= 0xa0000; /* XXX should be a define */ isdp->id_maddr += atdevbase; } - isdp->id_alive = (*dp->probe)(isdp); - if (isdp->id_alive) { + id_alive = (*dp->probe)(isdp); + if (id_alive) { /* * Only print the I/O address range if id_alive != -1 * Right now this is a temporary fix just for the new @@ -282,21 +352,20 @@ config_isadev(isdp, mp) * Rod Grimes 04/26/94 */ printf("%s%d", dp->name, isdp->id_unit); - if (isdp->id_alive != -1) { + if (id_alive != -1) { printf(" at 0x%x", isdp->id_iobase); - if ((isdp->id_iobase + isdp->id_alive - 1) != + if ((isdp->id_iobase + id_alive - 1) != isdp->id_iobase) { printf("-0x%x", - isdp->id_iobase + - isdp->id_alive - 1); + isdp->id_iobase + id_alive - 1); } } - if(isdp->id_irq) + if (isdp->id_irq) printf(" irq %d", ffs(isdp->id_irq) - 1); if (isdp->id_drq != -1) printf(" drq %d", isdp->id_drq); if (isdp->id_maddr) - printf(" maddr 0x%x", kvtop(isdp->id_maddr)); + printf(" maddr 0x%lx", kvtop(isdp->id_maddr)); if (isdp->id_msize) printf(" msize %d", isdp->id_msize); if (isdp->id_flags) @@ -312,18 +381,25 @@ config_isadev(isdp, mp) } } } - + /* + * Check for conflicts again. The driver may have changed + * *dvp. We should weaken the early check since the + * driver may have been able to change *dvp to avoid + * conflicts if given a chance. We already skip the early + * check for IRQs and force a check for IRQs in the next + * group of checks. + */ + checkbits |= CC_IRQ; + if (haveseen_isadev(isdp, checkbits)) + return; + isdp->id_alive = id_alive; (*dp->attach)(isdp); - - if(isdp->id_irq) { - int intrno; - - intrno = ffs(isdp->id_irq)-1; - setidt(ICU_OFFSET+intrno, isdp->id_intr, - SDT_SYS386IGT, SEL_KPL); - if(mp) { - INTRMASK(*mp,isdp->id_irq); - } + if (isdp->id_irq) { + if (mp) + INTRMASK(*mp, isdp->id_irq); + register_intr(ffs(isdp->id_irq) - 1, isdp->id_id, + isdp->id_ri_flags, isdp->id_intr, + mp ? *mp : 0, isdp->id_unit); INTREN(isdp->id_irq); } } else { @@ -335,22 +411,6 @@ config_isadev(isdp, mp) } } -#define IDTVEC(name) __CONCAT(X,name) -/* default interrupt vector table entries */ -typedef void inthand_t(); -typedef void (*inthand_func_t)(); -extern inthand_t - IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3), - IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7), - IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11), - IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15); - -static inthand_func_t defvec[ICU_LEN] = { - &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), - &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), - &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), - &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) }; - /* * Fill in default interrupt table (in case of spuruious interrupt * during configuration of kernel, setup interrupt control unit @@ -362,7 +422,7 @@ isa_defaultirq() /* icu vectors */ for (i = 0; i < ICU_LEN; i++) - setidt(ICU_OFFSET + i, defvec[i], SDT_SYS386IGT, SEL_KPL); + unregister_intr(i, (inthand2_t *)NULL); /* initialize 8259's */ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ @@ -418,6 +478,9 @@ void isa_dmacascade(unsigned chan) } } +static int +isa_dmarangecheck(caddr_t va, unsigned length, unsigned chan); + /* * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment * problems by using a bounce buffer. @@ -520,7 +583,7 @@ void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) * Return true if special handling needed. */ -int +static int isa_dmarangecheck(caddr_t va, unsigned length, unsigned chan) { vm_offset_t phys, priorpage = 0, endva; u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); @@ -622,7 +685,7 @@ isa_nmi(cd) /* * Caught a stray interrupt, notify */ -void +static void isa_strayintr(d) int d; { @@ -637,13 +700,18 @@ isa_strayintr(d) * the first 5 get logged, then it quits logging them, and puts * out a special message. rgrimes 3/25/1993 */ - extern u_long intrcnt_stray; - - intrcnt_stray++; - if (intrcnt_stray <= 5) - log(LOG_ERR,"ISA strayintr %x\n", d); - if (intrcnt_stray == 5) - log(LOG_CRIT,"Too many ISA strayintr not logging any more\n"); + /* + * XXX TODO print a different message for #7 if it is for a + * glitch. Glitches can be distinguished from real #7's by + * testing that the in-service bit is _not_ set. The test + * must be done before sending an EOI so it can't be done if + * we are using AUTO_EOI_1. + */ + if (intrcnt[NR_DEVICES + d] <= 5) + log(LOG_ERR, "stray irq %d\n", d); + if (intrcnt[NR_DEVICES + d] == 5) + log(LOG_CRIT, + "too many stray irq %d's; not logging any more\n", d); } /* @@ -683,8 +751,84 @@ isa_irq_pending(dvp) { unsigned id_irq; - id_irq = (unsigned short) dvp->id_irq; /* XXX silly type in struct */ + id_irq = dvp->id_irq; if (id_irq & 0xff) return (inb(IO_ICU1) & id_irq); return (inb(IO_ICU2) & (id_irq >> 8)); } + +int +register_intr(intr, device_id, flags, handler, mask, unit) + int intr; + int device_id; + u_int flags; + inthand2_t *handler; + u_int mask; + int unit; +{ + char *cp; + u_long ef; + int id; + + if ((u_int)intr >= ICU_LEN || intr == 2 + || (u_int)device_id >= NR_DEVICES) + return (EINVAL); + if (intr_handler[intr] != isa_strayintr) + return (EBUSY); + ef = read_eflags(); + disable_intr(); + intr_countp[intr] = &intrcnt[device_id]; + intr_handler[intr] = handler; + intr_mask[intr] = mask | (1 << intr); + intr_unit[intr] = unit; + setidt(ICU_OFFSET + intr, + flags & RI_FAST ? fastintr[intr] : slowintr[intr], + SDT_SYS386IGT, SEL_KPL); + write_eflags(ef); + for (cp = intrnames, id = 0; id <= device_id; id++) + while (*cp++ != '\0') + ; + if (cp > eintrnames) + return (0); + if (intr < 10) { + cp[-3] = intr + '0'; + cp[-2] = ' '; + } else { + cp[-3] = '1'; + cp[-2] = intr - 10 + '0'; + } + return (0); +} + +static void +register_imask(dvp, mask) + struct isa_device *dvp; + u_int mask; +{ + if (dvp->id_alive && dvp->id_irq) { + int intr; + + intr = ffs(dvp->id_irq) - 1; + intr_mask[intr] = mask | (1 <<intr); + } +} + +int +unregister_intr(intr, handler) + int intr; + inthand2_t *handler; +{ + u_long ef; + + if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr]) + return (EINVAL); + ef = read_eflags(); + disable_intr(); + intr_countp[intr] = &intrcnt[NR_DEVICES + intr]; + intr_handler[intr] = isa_strayintr; + intr_mask[intr] = HWI_MASK | SWI_MASK; + intr_unit[intr] = intr; + setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL); + write_eflags(ef); + return (0); +} diff --git a/sys/amd64/isa/vector.S b/sys/amd64/isa/vector.S index 7135ae7..252bd95 100644 --- a/sys/amd64/isa/vector.S +++ b/sys/amd64/isa/vector.S @@ -1,6 +1,6 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.6 1994/01/10 23:15:09 ache Exp $ + * $Id: vector.s,v 1.7 1994/04/02 07:00:50 davidg Exp $ */ #include "i386/isa/icu.h" @@ -97,7 +97,10 @@ * loading segregs. */ -#define FAST_INTR(unit, irq_num, id_num, handler, enable_icus) \ +#define FAST_INTR(irq_num, enable_icus) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(fastintr/**/irq_num) ; \ pushl %eax ; /* save only call-used registers */ \ pushl %ecx ; \ pushl %edx ; \ @@ -107,12 +110,13 @@ movl %ax,%ds ; \ MAYBE_MOVW_AX_ES ; \ FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl $unit ; \ - call handler ; /* do the work ASAP */ \ + pushl _intr_unit + (irq_num) * 4 ; \ + call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ addl $4,%esp ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ - incl _intrcnt_actv + (id_num) * 4 ; \ + movl _intr_countp + (irq_num) * 4,%eax ; \ + incl (%eax) ; \ movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \ notl %eax ; \ andl _ipending,%eax ; \ @@ -147,7 +151,10 @@ MEXITCOUNT ; \ jmp _doreti -#define INTR(unit, irq_num, id_num, mask, handler, icu, enable_icus, reg, stray) \ +#define INTR(irq_num, icu, enable_icus, reg) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(intr/**/irq_num) ; \ pushl $0 ; /* dumby error code */ \ pushl $0 ; /* dumby trap type */ \ pushal ; \ @@ -167,15 +174,17 @@ testb $IRQ_BIT(irq_num),%reg ; \ jne 2f ; \ 1: ; \ +Xresume/**/irq_num: ; \ FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ - incl _intrcnt_actv + (id_num) * 4 ; \ + movl _intr_countp + (irq_num) * 4,%eax ; \ + incl (%eax) ; \ movl _cpl,%eax ; \ pushl %eax ; \ - pushl $unit ; \ - orl mask,%eax ; \ + pushl _intr_unit + (irq_num) * 4 ; \ + orl _intr_mask + (irq_num) * 4,%eax ; \ movl %eax,_cpl ; \ sti ; \ - call handler ; \ + call *_intr_handler + (irq_num) * 4 ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ @@ -189,9 +198,6 @@ ALIGN_TEXT ; \ 2: ; \ /* XXX skip mcounting here to avoid double count */ \ - movl $1b,%eax ; /* register resume address */ \ - /* XXX - someday do it at attach time */ \ - movl %eax,ihandlers + (irq_num) * 4 ; \ orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ popl %es ; \ popl %ds ; \ @@ -199,118 +205,48 @@ addl $4+4,%esp ; \ iret -/* - * vector.h has defined a macro 'BUILD_VECTORS' containing a big list of info - * about vectors, including a submacro 'BUILD_VECTOR' that operates on the - * info about each vector. We redefine 'BUILD_VECTOR' to expand the info - * in different ways. Here we expand it to a list of interrupt handlers. - * This order is of course unimportant. Elsewhere we expand it to inline - * linear search code for which the order is a little more important and - * concatenating the code with no holes is very important. - * - * XXX - now there is BUILD_FAST_VECTOR as well as BUILD_VECTOR. - * - * The info consists of the following items for each vector: - * - * name (identifier): name of the vector; used to build labels - * unit (expression): unit number to call the device driver with - * irq_num (number): number of the IRQ to handled (0-15) - * id_num (number): uniq numeric id for handler (assigned by config) - * mask (blank-ident): priority mask used - * handler (blank-ident): interrupt handler to call - * icu_num (number): (1 + irq_num / 8) converted for label building - * icu_enables (number): 1 for icu_num == 1, 1_AND_2 for icu_num == 2 - * reg (blank-ident): al for icu_num == 1, ah for icu_num == 2 - * - * 'irq_num' is converted in several ways at config time to get around - * limitations in cpp. The macros have blanks after commas iff they would - * not mess up identifiers and numbers. - */ - -#undef BUILD_FAST_VECTOR -#define BUILD_FAST_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .globl handler ; \ - .text ; \ - .globl _V/**/name ; \ - SUPERALIGN_TEXT ; \ -_V/**/name: ; \ - FAST_INTR(unit, irq_num,id_num, handler, ENABLE_ICU/**/icu_enables) - -#undef BUILD_VECTOR -#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .globl handler ; \ - .text ; \ - .globl _V/**/name ; \ - SUPERALIGN_TEXT ; \ -_V/**/name: ; \ - INTR(unit,irq_num, id_num, mask, handler, IO_ICU/**/icu_num, \ - ENABLE_ICU/**/icu_enables, reg,) - MCOUNT_LABEL(bintr) - BUILD_VECTORS - - /* hardware interrupt catcher (IDT 32 - 47) */ - .globl _isa_strayintr - -#define STRAYINTR(irq_num, icu_num, icu_enables, reg) \ -IDTVEC(intr/**/irq_num) ; \ - INTR(irq_num,irq_num,irq_num, _high_imask, _isa_strayintr, \ - IO_ICU/**/icu_num, ENABLE_ICU/**/icu_enables, reg,stray) - -/* - * XXX - the mask (1 << 2) == IRQ_SLAVE will be generated for IRQ 2, instead - * of the mask IRQ2 (defined as IRQ9 == (1 << 9)). But IRQ 2 "can't happen". - * In fact, all stray interrupts "can't happen" except for bugs. The - * "stray" IRQ 7 is documented behaviour of the 8259. It happens when there - * is a glitch on any of its interrupt inputs. Does it really interrupt when - * IRQ 7 is masked? - * - * XXX - unpend doesn't work for these, it sends them to the real handler. - * - * XXX - the race bug during initialization may be because I changed the - * order of switching from the stray to the real interrupt handler to before - * enabling interrupts. The old order looked unsafe but maybe it is OK with - * the stray interrupt handler installed. But these handlers only reduce - * the window of vulnerability - it is still open at the end of - * isa_configure(). - * - * XXX - many comments are stale. - */ - - STRAYINTR(0,1,1, al) - STRAYINTR(1,1,1, al) - STRAYINTR(2,1,1, al) - STRAYINTR(3,1,1, al) - STRAYINTR(4,1,1, al) - STRAYINTR(5,1,1, al) - STRAYINTR(6,1,1, al) - STRAYINTR(7,1,1, al) - STRAYINTR(8,2,1_AND_2, ah) - STRAYINTR(9,2,1_AND_2, ah) - STRAYINTR(10,2,1_AND_2, ah) - STRAYINTR(11,2,1_AND_2, ah) - STRAYINTR(12,2,1_AND_2, ah) - STRAYINTR(13,2,1_AND_2, ah) - STRAYINTR(14,2,1_AND_2, ah) - STRAYINTR(15,2,1_AND_2, ah) -#if 0 - INTRSTRAY(255, _highmask, 255) ; call _isa_strayintr ; INTREXIT2 -#endif + FAST_INTR(0, ENABLE_ICU1) + FAST_INTR(1, ENABLE_ICU1) + FAST_INTR(2, ENABLE_ICU1) + FAST_INTR(3, ENABLE_ICU1) + FAST_INTR(4, ENABLE_ICU1) + FAST_INTR(5, ENABLE_ICU1) + FAST_INTR(6, ENABLE_ICU1) + FAST_INTR(7, ENABLE_ICU1) + FAST_INTR(8, ENABLE_ICU1_AND_2) + FAST_INTR(9, ENABLE_ICU1_AND_2) + FAST_INTR(10, ENABLE_ICU1_AND_2) + FAST_INTR(11, ENABLE_ICU1_AND_2) + FAST_INTR(12, ENABLE_ICU1_AND_2) + FAST_INTR(13, ENABLE_ICU1_AND_2) + FAST_INTR(14, ENABLE_ICU1_AND_2) + FAST_INTR(15, ENABLE_ICU1_AND_2) + INTR(0, IO_ICU1, ENABLE_ICU1, al) + INTR(1, IO_ICU1, ENABLE_ICU1, al) + INTR(2, IO_ICU1, ENABLE_ICU1, al) + INTR(3, IO_ICU1, ENABLE_ICU1, al) + INTR(4, IO_ICU1, ENABLE_ICU1, al) + INTR(5, IO_ICU1, ENABLE_ICU1, al) + INTR(6, IO_ICU1, ENABLE_ICU1, al) + INTR(7, IO_ICU1, ENABLE_ICU1, al) + INTR(8, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(9, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(10, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(11, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(12, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(13, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(14, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(15, IO_ICU2, ENABLE_ICU1_AND_2, ah) MCOUNT_LABEL(eintr) -/* - * These are the interrupt counters, I moved them here from icu.s so that - * they are with the name table. rgrimes - * - * There are now lots of counters, this has been redone to work with - * Bruce Evans intr-0.1 code, which I modified some more to make it all - * work with vmstat. - */ .data ihandlers: /* addresses of interrupt handlers */ - .space NHWI*4 /* actually resumption addresses for HWI's */ + /* actually resumption addresses for HWI's */ + .long Xresume0, Xresume1, Xresume2, Xresume3 + .long Xresume4, Xresume5, Xresume6, Xresume7 + .long Xresume8, Xresume9, Xresume10, Xresume11 + .long Xresume12, Xresume13, Xresume14, Xresume15 .long swi_tty, swi_net, 0, 0, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, swi_clock, swi_ast imasks: /* masks for interrupt handlers */ @@ -318,43 +254,37 @@ imasks: /* masks for interrupt handlers */ .long SWI_TTY_MASK, SWI_NET_MASK, 0, 0, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK - .globl _intrcnt -_intrcnt: /* used by vmstat to calc size of table */ - .globl _intrcnt_bad7 -_intrcnt_bad7: .space 4 /* glitches on irq 7 */ - .globl _intrcnt_bad15 -_intrcnt_bad15: .space 4 /* glitches on irq 15 */ - .globl _intrcnt_stray -_intrcnt_stray: .space 4 /* total count of stray interrupts */ - .globl _intrcnt_actv -_intrcnt_actv: .space NR_REAL_INT_HANDLERS * 4 /* active interrupts */ - .globl _eintrcnt -_eintrcnt: /* used by vmstat to calc size of table */ - -/* - * Build the interrupt name table for vmstat - */ - -#undef BUILD_FAST_VECTOR -#define BUILD_FAST_VECTOR BUILD_VECTOR - -#undef BUILD_VECTOR -#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .ascii "name irq" ; \ - .asciz "irq_num" /* - * XXX - use the __STRING and __CONCAT macros from <sys/cdefs.h> to stringize - * and concatenate names above and elsewhere. Note that __CONCAT doesn't - * work when nested. + * Interrupt counters and names. The format of these and the label names + * must agree with what vmstat expects. The tables are indexed by device + * ids so that we don't have to move the names around as devices are + * attached. */ +#include "vector.h" + .globl _intrcnt, _eintrcnt +_intrcnt: + .space (NR_DEVICES + ICU_LEN) * 4 +_eintrcnt: - .text .globl _intrnames, _eintrnames _intrnames: - BUILD_VECTOR(bad,,7,,,,,,) - BUILD_VECTOR(bad,,15,,,,,,) - BUILD_VECTOR(stray,,,,,,,,) - BUILD_VECTORS - + .ascii DEVICE_NAMES + .asciz "stray irq0" + .asciz "stray irq1" + .asciz "stray irq2" + .asciz "stray irq3" + .asciz "stray irq4" + .asciz "stray irq5" + .asciz "stray irq6" + .asciz "stray irq7" + .asciz "stray irq8" + .asciz "stray irq9" + .asciz "stray irq10" + .asciz "stray irq11" + .asciz "stray irq12" + .asciz "stray irq13" + .asciz "stray irq14" + .asciz "stray irq15" _eintrnames: + + .text diff --git a/sys/amd64/isa/vector.s b/sys/amd64/isa/vector.s index 7135ae7..252bd95 100644 --- a/sys/amd64/isa/vector.s +++ b/sys/amd64/isa/vector.s @@ -1,6 +1,6 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.6 1994/01/10 23:15:09 ache Exp $ + * $Id: vector.s,v 1.7 1994/04/02 07:00:50 davidg Exp $ */ #include "i386/isa/icu.h" @@ -97,7 +97,10 @@ * loading segregs. */ -#define FAST_INTR(unit, irq_num, id_num, handler, enable_icus) \ +#define FAST_INTR(irq_num, enable_icus) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(fastintr/**/irq_num) ; \ pushl %eax ; /* save only call-used registers */ \ pushl %ecx ; \ pushl %edx ; \ @@ -107,12 +110,13 @@ movl %ax,%ds ; \ MAYBE_MOVW_AX_ES ; \ FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl $unit ; \ - call handler ; /* do the work ASAP */ \ + pushl _intr_unit + (irq_num) * 4 ; \ + call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ addl $4,%esp ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ - incl _intrcnt_actv + (id_num) * 4 ; \ + movl _intr_countp + (irq_num) * 4,%eax ; \ + incl (%eax) ; \ movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \ notl %eax ; \ andl _ipending,%eax ; \ @@ -147,7 +151,10 @@ MEXITCOUNT ; \ jmp _doreti -#define INTR(unit, irq_num, id_num, mask, handler, icu, enable_icus, reg, stray) \ +#define INTR(irq_num, icu, enable_icus, reg) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(intr/**/irq_num) ; \ pushl $0 ; /* dumby error code */ \ pushl $0 ; /* dumby trap type */ \ pushal ; \ @@ -167,15 +174,17 @@ testb $IRQ_BIT(irq_num),%reg ; \ jne 2f ; \ 1: ; \ +Xresume/**/irq_num: ; \ FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ - incl _intrcnt_actv + (id_num) * 4 ; \ + movl _intr_countp + (irq_num) * 4,%eax ; \ + incl (%eax) ; \ movl _cpl,%eax ; \ pushl %eax ; \ - pushl $unit ; \ - orl mask,%eax ; \ + pushl _intr_unit + (irq_num) * 4 ; \ + orl _intr_mask + (irq_num) * 4,%eax ; \ movl %eax,_cpl ; \ sti ; \ - call handler ; \ + call *_intr_handler + (irq_num) * 4 ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ @@ -189,9 +198,6 @@ ALIGN_TEXT ; \ 2: ; \ /* XXX skip mcounting here to avoid double count */ \ - movl $1b,%eax ; /* register resume address */ \ - /* XXX - someday do it at attach time */ \ - movl %eax,ihandlers + (irq_num) * 4 ; \ orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ popl %es ; \ popl %ds ; \ @@ -199,118 +205,48 @@ addl $4+4,%esp ; \ iret -/* - * vector.h has defined a macro 'BUILD_VECTORS' containing a big list of info - * about vectors, including a submacro 'BUILD_VECTOR' that operates on the - * info about each vector. We redefine 'BUILD_VECTOR' to expand the info - * in different ways. Here we expand it to a list of interrupt handlers. - * This order is of course unimportant. Elsewhere we expand it to inline - * linear search code for which the order is a little more important and - * concatenating the code with no holes is very important. - * - * XXX - now there is BUILD_FAST_VECTOR as well as BUILD_VECTOR. - * - * The info consists of the following items for each vector: - * - * name (identifier): name of the vector; used to build labels - * unit (expression): unit number to call the device driver with - * irq_num (number): number of the IRQ to handled (0-15) - * id_num (number): uniq numeric id for handler (assigned by config) - * mask (blank-ident): priority mask used - * handler (blank-ident): interrupt handler to call - * icu_num (number): (1 + irq_num / 8) converted for label building - * icu_enables (number): 1 for icu_num == 1, 1_AND_2 for icu_num == 2 - * reg (blank-ident): al for icu_num == 1, ah for icu_num == 2 - * - * 'irq_num' is converted in several ways at config time to get around - * limitations in cpp. The macros have blanks after commas iff they would - * not mess up identifiers and numbers. - */ - -#undef BUILD_FAST_VECTOR -#define BUILD_FAST_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .globl handler ; \ - .text ; \ - .globl _V/**/name ; \ - SUPERALIGN_TEXT ; \ -_V/**/name: ; \ - FAST_INTR(unit, irq_num,id_num, handler, ENABLE_ICU/**/icu_enables) - -#undef BUILD_VECTOR -#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .globl handler ; \ - .text ; \ - .globl _V/**/name ; \ - SUPERALIGN_TEXT ; \ -_V/**/name: ; \ - INTR(unit,irq_num, id_num, mask, handler, IO_ICU/**/icu_num, \ - ENABLE_ICU/**/icu_enables, reg,) - MCOUNT_LABEL(bintr) - BUILD_VECTORS - - /* hardware interrupt catcher (IDT 32 - 47) */ - .globl _isa_strayintr - -#define STRAYINTR(irq_num, icu_num, icu_enables, reg) \ -IDTVEC(intr/**/irq_num) ; \ - INTR(irq_num,irq_num,irq_num, _high_imask, _isa_strayintr, \ - IO_ICU/**/icu_num, ENABLE_ICU/**/icu_enables, reg,stray) - -/* - * XXX - the mask (1 << 2) == IRQ_SLAVE will be generated for IRQ 2, instead - * of the mask IRQ2 (defined as IRQ9 == (1 << 9)). But IRQ 2 "can't happen". - * In fact, all stray interrupts "can't happen" except for bugs. The - * "stray" IRQ 7 is documented behaviour of the 8259. It happens when there - * is a glitch on any of its interrupt inputs. Does it really interrupt when - * IRQ 7 is masked? - * - * XXX - unpend doesn't work for these, it sends them to the real handler. - * - * XXX - the race bug during initialization may be because I changed the - * order of switching from the stray to the real interrupt handler to before - * enabling interrupts. The old order looked unsafe but maybe it is OK with - * the stray interrupt handler installed. But these handlers only reduce - * the window of vulnerability - it is still open at the end of - * isa_configure(). - * - * XXX - many comments are stale. - */ - - STRAYINTR(0,1,1, al) - STRAYINTR(1,1,1, al) - STRAYINTR(2,1,1, al) - STRAYINTR(3,1,1, al) - STRAYINTR(4,1,1, al) - STRAYINTR(5,1,1, al) - STRAYINTR(6,1,1, al) - STRAYINTR(7,1,1, al) - STRAYINTR(8,2,1_AND_2, ah) - STRAYINTR(9,2,1_AND_2, ah) - STRAYINTR(10,2,1_AND_2, ah) - STRAYINTR(11,2,1_AND_2, ah) - STRAYINTR(12,2,1_AND_2, ah) - STRAYINTR(13,2,1_AND_2, ah) - STRAYINTR(14,2,1_AND_2, ah) - STRAYINTR(15,2,1_AND_2, ah) -#if 0 - INTRSTRAY(255, _highmask, 255) ; call _isa_strayintr ; INTREXIT2 -#endif + FAST_INTR(0, ENABLE_ICU1) + FAST_INTR(1, ENABLE_ICU1) + FAST_INTR(2, ENABLE_ICU1) + FAST_INTR(3, ENABLE_ICU1) + FAST_INTR(4, ENABLE_ICU1) + FAST_INTR(5, ENABLE_ICU1) + FAST_INTR(6, ENABLE_ICU1) + FAST_INTR(7, ENABLE_ICU1) + FAST_INTR(8, ENABLE_ICU1_AND_2) + FAST_INTR(9, ENABLE_ICU1_AND_2) + FAST_INTR(10, ENABLE_ICU1_AND_2) + FAST_INTR(11, ENABLE_ICU1_AND_2) + FAST_INTR(12, ENABLE_ICU1_AND_2) + FAST_INTR(13, ENABLE_ICU1_AND_2) + FAST_INTR(14, ENABLE_ICU1_AND_2) + FAST_INTR(15, ENABLE_ICU1_AND_2) + INTR(0, IO_ICU1, ENABLE_ICU1, al) + INTR(1, IO_ICU1, ENABLE_ICU1, al) + INTR(2, IO_ICU1, ENABLE_ICU1, al) + INTR(3, IO_ICU1, ENABLE_ICU1, al) + INTR(4, IO_ICU1, ENABLE_ICU1, al) + INTR(5, IO_ICU1, ENABLE_ICU1, al) + INTR(6, IO_ICU1, ENABLE_ICU1, al) + INTR(7, IO_ICU1, ENABLE_ICU1, al) + INTR(8, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(9, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(10, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(11, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(12, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(13, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(14, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(15, IO_ICU2, ENABLE_ICU1_AND_2, ah) MCOUNT_LABEL(eintr) -/* - * These are the interrupt counters, I moved them here from icu.s so that - * they are with the name table. rgrimes - * - * There are now lots of counters, this has been redone to work with - * Bruce Evans intr-0.1 code, which I modified some more to make it all - * work with vmstat. - */ .data ihandlers: /* addresses of interrupt handlers */ - .space NHWI*4 /* actually resumption addresses for HWI's */ + /* actually resumption addresses for HWI's */ + .long Xresume0, Xresume1, Xresume2, Xresume3 + .long Xresume4, Xresume5, Xresume6, Xresume7 + .long Xresume8, Xresume9, Xresume10, Xresume11 + .long Xresume12, Xresume13, Xresume14, Xresume15 .long swi_tty, swi_net, 0, 0, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, swi_clock, swi_ast imasks: /* masks for interrupt handlers */ @@ -318,43 +254,37 @@ imasks: /* masks for interrupt handlers */ .long SWI_TTY_MASK, SWI_NET_MASK, 0, 0, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK - .globl _intrcnt -_intrcnt: /* used by vmstat to calc size of table */ - .globl _intrcnt_bad7 -_intrcnt_bad7: .space 4 /* glitches on irq 7 */ - .globl _intrcnt_bad15 -_intrcnt_bad15: .space 4 /* glitches on irq 15 */ - .globl _intrcnt_stray -_intrcnt_stray: .space 4 /* total count of stray interrupts */ - .globl _intrcnt_actv -_intrcnt_actv: .space NR_REAL_INT_HANDLERS * 4 /* active interrupts */ - .globl _eintrcnt -_eintrcnt: /* used by vmstat to calc size of table */ - -/* - * Build the interrupt name table for vmstat - */ - -#undef BUILD_FAST_VECTOR -#define BUILD_FAST_VECTOR BUILD_VECTOR - -#undef BUILD_VECTOR -#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .ascii "name irq" ; \ - .asciz "irq_num" /* - * XXX - use the __STRING and __CONCAT macros from <sys/cdefs.h> to stringize - * and concatenate names above and elsewhere. Note that __CONCAT doesn't - * work when nested. + * Interrupt counters and names. The format of these and the label names + * must agree with what vmstat expects. The tables are indexed by device + * ids so that we don't have to move the names around as devices are + * attached. */ +#include "vector.h" + .globl _intrcnt, _eintrcnt +_intrcnt: + .space (NR_DEVICES + ICU_LEN) * 4 +_eintrcnt: - .text .globl _intrnames, _eintrnames _intrnames: - BUILD_VECTOR(bad,,7,,,,,,) - BUILD_VECTOR(bad,,15,,,,,,) - BUILD_VECTOR(stray,,,,,,,,) - BUILD_VECTORS - + .ascii DEVICE_NAMES + .asciz "stray irq0" + .asciz "stray irq1" + .asciz "stray irq2" + .asciz "stray irq3" + .asciz "stray irq4" + .asciz "stray irq5" + .asciz "stray irq6" + .asciz "stray irq7" + .asciz "stray irq8" + .asciz "stray irq9" + .asciz "stray irq10" + .asciz "stray irq11" + .asciz "stray irq12" + .asciz "stray irq13" + .asciz "stray irq14" + .asciz "stray irq15" _eintrnames: + + .text diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c index de95e90..d505c4d 100644 --- a/sys/dev/sio/sio.c +++ b/sys/dev/sio/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.47 1994/05/26 13:31:40 rgrimes Exp $ + * $Id: sio.c,v 1.48 1994/08/13 03:50:13 wollman Exp $ */ #include "sio.h" @@ -427,6 +427,7 @@ sioattach(isdp) int s; int unit; + isdp->id_ri_flags |= RI_FAST; iobase = isdp->id_iobase; unit = isdp->id_unit; s = spltty(); diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 35f2e42..e3f3f21 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.13 1994/08/13 03:49:56 wollman Exp $ + * $Id: clock.c,v 1.14 1994/08/15 03:15:18 wollman Exp $ */ /* @@ -497,16 +497,14 @@ test_inittodr(time_t base) /* * Wire clock interrupt in. */ -#define V(s) __CONCAT(V, s) -extern void V(clk)(); -extern void V(rtc)(); - void enablertclock() { - setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, clkintr, + HWI_MASK | SWI_MASK, /* unit */ 0); INTREN(IRQ0); - setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, rtcintr, + SWI_CLOCK_MASK, /* unit */ 0); INTREN(IRQ8); outb(IO_RTC, RTC_STATUSB); outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR); diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 35f2e42..e3f3f21 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.13 1994/08/13 03:49:56 wollman Exp $ + * $Id: clock.c,v 1.14 1994/08/15 03:15:18 wollman Exp $ */ /* @@ -497,16 +497,14 @@ test_inittodr(time_t base) /* * Wire clock interrupt in. */ -#define V(s) __CONCAT(V, s) -extern void V(clk)(); -extern void V(rtc)(); - void enablertclock() { - setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, clkintr, + HWI_MASK | SWI_MASK, /* unit */ 0); INTREN(IRQ0); - setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, rtcintr, + SWI_CLOCK_MASK, /* unit */ 0); INTREN(IRQ8); outb(IO_RTC, RTC_STATUSB); outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR); diff --git a/sys/i386/isa/icu.s b/sys/i386/isa/icu.s index 735eeda..4956ab8 100644 --- a/sys/i386/isa/icu.s +++ b/sys/i386/isa/icu.s @@ -36,7 +36,7 @@ * * @(#)icu.s 7.2 (Berkeley) 5/21/91 * - * $Id: icu.s,v 1.10 1994/08/13 03:50:01 wollman Exp $ + * $Id: icu.s,v 1.11 1994/08/15 03:15:19 wollman Exp $ */ /* @@ -57,7 +57,6 @@ _cpl: .long HWI_MASK | SWI_MASK /* current priority (all off) */ .globl _imen _imen: .long HWI_MASK /* interrupt mask enable (all h/w off) */ -_high_imask: .long HWI_MASK | SWI_MASK .globl _stat_imask _stat_imask: .long (1 << 8) .globl _tty_imask @@ -236,8 +235,8 @@ splz_swi: jmp splz_next /* - * Fake clock IRQ so that it appears to come from our caller and not from - * vec0, so that kernel profiling works. + * Fake clock interrupt(s) so that they appear to come from our caller instead + * of from here, so that system profiling works. * XXX do this more generally (for all vectors; look up the C entry point). * XXX frame bogusness stops us from just jumping to the C entry point. */ @@ -250,7 +249,17 @@ vec0: pushl %eax cli MEXITCOUNT - jmp _Vclk + jmp _Xintr0 /* XXX might need _Xfastintr0 */ + + ALIGN_TEXT +vec8: + popl %eax + pushfl + pushl $KCSEL + pushl %eax + cli + MEXITCOUNT + jmp _Xintr8 /* XXX might need _Xfastintr8 */ #define BUILD_VEC(irq_num) \ ALIGN_TEXT ; \ @@ -265,7 +274,6 @@ vec/**/irq_num: ; \ BUILD_VEC(5) BUILD_VEC(6) BUILD_VEC(7) - BUILD_VEC(8) BUILD_VEC(9) BUILD_VEC(10) BUILD_VEC(11) diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c index 80be9a5..5b5878e 100644 --- a/sys/i386/isa/isa.c +++ b/sys/i386/isa/isa.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.19 1994/08/10 04:39:52 wollman Exp $ + * $Id: isa.c,v 1.20 1994/08/13 03:50:07 wollman Exp $ */ /* @@ -65,6 +65,7 @@ #include <i386/isa/icu.h> #include <i386/isa/ic/i8237.h> #include <i386/isa/ic/i8042.h> +#include "vector.h" /* ** Register definitions for DMA controller 1 (channels 0..3): @@ -82,20 +83,70 @@ #define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ #define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ -void config_isadev __P((struct isa_device *, u_int *)); +/* + * Bits to specify the type and amount of conflict checking. + */ +#define CC_ATTACH (1 << 0) +#define CC_DRQ (1 << 1) +#define CC_IOADDR (1 << 2) +#define CC_IRQ (1 << 3) +#define CC_MEMADDR (1 << 4) + +/* + * XXX these defines should be in a central place. + */ +#define read_eflags() ({u_long ef; \ + __asm("pushfl; popl %0" : "=a" (ef)); \ + ef; }) +#define write_eflags(ef) __asm("pushl %0; popfl" : : "a" ((u_long)(ef))) + +u_long *intr_countp[ICU_LEN]; +inthand2_t *intr_handler[ICU_LEN]; +u_int intr_mask[ICU_LEN]; +int intr_unit[ICU_LEN]; + +static inthand_t *fastintr[ICU_LEN] = { + &IDTVEC(fastintr0), &IDTVEC(fastintr1), + &IDTVEC(fastintr2), &IDTVEC(fastintr3), + &IDTVEC(fastintr4), &IDTVEC(fastintr5), + &IDTVEC(fastintr6), &IDTVEC(fastintr7), + &IDTVEC(fastintr8), &IDTVEC(fastintr9), + &IDTVEC(fastintr10), &IDTVEC(fastintr11), + &IDTVEC(fastintr12), &IDTVEC(fastintr13), + &IDTVEC(fastintr14), &IDTVEC(fastintr15) +}; + +static inthand_t *slowintr[ICU_LEN] = { + &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), + &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), + &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), + &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) +}; + +static void config_isadev __P((struct isa_device *isdp, u_int *mp)); +static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp, + int item, char const *whatnot, char const *reason, + char const *format)); +static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp, + u_int checkbits)); +static int haveseen_isadev __P((struct isa_device *dvp, u_int checkbits)); +static inthand2_t isa_strayintr; +static void register_imask __P((struct isa_device *dvp, u_int mask)); /* * print a conflict message */ -void -conflict(dvp, tmpdvp, item, reason, format) - struct isa_device *dvp, *tmpdvp; +static void +conflict(dvp, tmpdvp, item, whatnot, reason, format) + struct isa_device *dvp; + struct isa_device *tmpdvp; int item; - char *reason; - char *format; + char const *whatnot; + char const *reason; + char const *format; { - printf("%s%d not probed due to %s conflict with %s%d at ", - dvp->id_driver->name, dvp->id_unit, reason, + printf("%s%d not %sed due to %s conflict with %s%d at ", + dvp->id_driver->name, dvp->id_unit, whatnot, reason, tmpdvp->id_driver->name, tmpdvp->id_unit); printf(format, item); printf("\n"); @@ -105,9 +156,11 @@ conflict(dvp, tmpdvp, item, reason, format) * Check to see if things are alread in use, like IRQ's, I/O addresses * and Memory addresses. */ -int -haveseen(dvp, tmpdvp) - struct isa_device *dvp, *tmpdvp; +static int +haveseen(dvp, tmpdvp, checkbits) + struct isa_device *dvp; + struct isa_device *tmpdvp; + u_int checkbits; { int status = 0; @@ -115,17 +168,20 @@ haveseen(dvp, tmpdvp) * Only check against devices that have already been found */ if (tmpdvp->id_alive) { + char const *whatnot; + + whatnot = checkbits & CC_ATTACH ? "attach" : "probe"; /* * Check for I/O address conflict. We can only check the * starting address of the device against the range of the * device that has already been probed since we do not * know how many I/O addresses this device uses. */ - if (tmpdvp->id_alive != -1) { + if (checkbits & CC_IOADDR && tmpdvp->id_alive != -1) { if ((dvp->id_iobase >= tmpdvp->id_iobase) && (dvp->id_iobase <= (tmpdvp->id_iobase + tmpdvp->id_alive - 1))) { - conflict(dvp, tmpdvp, dvp->id_iobase, + conflict(dvp, tmpdvp, dvp->id_iobase, whatnot, "I/O address", "0x%x"); status = 1; } @@ -140,34 +196,32 @@ haveseen(dvp, tmpdvp) * since at that time we would know the full range. * XXX KERNBASE is a hack, we should have vaddr in the table! */ - if(tmpdvp->id_maddr) { - if((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && - (KERNBASE + dvp->id_maddr <= - (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { - conflict(dvp, tmpdvp, dvp->id_maddr, "maddr", - "0x%x"); + if (checkbits & CC_MEMADDR && tmpdvp->id_maddr) { + if ((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && + (KERNBASE + dvp->id_maddr <= + (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { + conflict(dvp, tmpdvp, (int)dvp->id_maddr, + whatnot, "maddr", "0x%x"); status = 1; } } -#ifndef COM_MULTIPORT /* * Check for IRQ conflicts. */ - if(tmpdvp->id_irq) { + if (checkbits & CC_IRQ && tmpdvp->id_irq) { if (tmpdvp->id_irq == dvp->id_irq) { conflict(dvp, tmpdvp, ffs(dvp->id_irq) - 1, - "irq", "%d"); + whatnot, "irq", "%d"); status = 1; } } -#endif /* * Check for DRQ conflicts. */ - if(tmpdvp->id_drq != -1) { + if (checkbits & CC_DRQ && tmpdvp->id_drq != -1) { if (tmpdvp->id_drq == dvp->id_drq) { - conflict(dvp, tmpdvp, dvp->id_drq, - "drq", "%d"); + conflict(dvp, tmpdvp, dvp->id_drq, whatnot, + "drq", "%d"); status = 1; } } @@ -179,25 +233,22 @@ haveseen(dvp, tmpdvp) * Search through all the isa_devtab_* tables looking for anything that * conflicts with the current device. */ -int -haveseen_isadev(dvp) +static int +haveseen_isadev(dvp, checkbits) struct isa_device *dvp; + u_int checkbits; { struct isa_device *tmpdvp; int status = 0; - for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } - for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } - for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } - for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp); - } + for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); + for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); + for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); + for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) + status |= haveseen(dvp, tmpdvp, checkbits); return(status); } @@ -208,26 +259,18 @@ void isa_configure() { struct isa_device *dvp; - enable_intr(); splhigh(); + enable_intr(); INTREN(IRQ_SLAVE); printf("Probing for devices on the ISA bus:\n"); - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,&tty_imask); - } - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,&bio_imask); - } - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,&net_imask); - } - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) { - if (!haveseen_isadev(dvp)) - config_isadev(dvp,(u_int *) NULL); - } + for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) + config_isadev(dvp, &tty_imask); + for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) + config_isadev(dvp, &bio_imask); + for (dvp = isa_devtab_net; dvp->id_driver; dvp++) + config_isadev(dvp, &net_imask); + for (dvp = isa_devtab_null; dvp->id_driver; dvp++) + config_isadev(dvp, (u_int *)NULL); bio_imask |= SWI_CLOCK_MASK; net_imask |= SWI_NET_MASK; tty_imask |= SWI_TTY_MASK; @@ -253,27 +296,54 @@ isa_configure() { printf("bio_imask %x tty_imask %x net_imask %x\n", bio_imask, tty_imask, net_imask); #endif + /* + * Finish initializing intr_mask[]. Note that the partly + * constructed masks aren't actually used since we're at splhigh. + * For fully dynamic initialization, register_intr() and + * unregister_intr() will have to adjust the masks for _all_ + * interrupts and for tty_imask, etc. + */ + for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) + register_imask(dvp, tty_imask); + for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) + register_imask(dvp, bio_imask); + for (dvp = isa_devtab_net; dvp->id_driver; dvp++) + register_imask(dvp, net_imask); + for (dvp = isa_devtab_null; dvp->id_driver; dvp++) + register_imask(dvp, SWI_CLOCK_MASK); splnone(); } /* * Configure an ISA device. */ -void +static void config_isadev(isdp, mp) struct isa_device *isdp; u_int *mp; { + u_int checkbits; + int id_alive; struct isa_driver *dp = isdp->id_driver; + checkbits = 0; +#ifndef ALLOW_CONFLICT_DRQ + checkbits |= CC_DRQ; +#endif +#ifndef ALLOW_CONFLICT_IOADDR + checkbits |= CC_IOADDR; +#endif +#ifndef ALLOW_CONFLICT_MEMADDR + checkbits |= CC_MEMADDR; +#endif + if (haveseen_isadev(isdp, checkbits)) + return; if (isdp->id_maddr) { - extern u_int atdevbase; - isdp->id_maddr -= 0xa0000; /* XXX should be a define */ isdp->id_maddr += atdevbase; } - isdp->id_alive = (*dp->probe)(isdp); - if (isdp->id_alive) { + id_alive = (*dp->probe)(isdp); + if (id_alive) { /* * Only print the I/O address range if id_alive != -1 * Right now this is a temporary fix just for the new @@ -282,21 +352,20 @@ config_isadev(isdp, mp) * Rod Grimes 04/26/94 */ printf("%s%d", dp->name, isdp->id_unit); - if (isdp->id_alive != -1) { + if (id_alive != -1) { printf(" at 0x%x", isdp->id_iobase); - if ((isdp->id_iobase + isdp->id_alive - 1) != + if ((isdp->id_iobase + id_alive - 1) != isdp->id_iobase) { printf("-0x%x", - isdp->id_iobase + - isdp->id_alive - 1); + isdp->id_iobase + id_alive - 1); } } - if(isdp->id_irq) + if (isdp->id_irq) printf(" irq %d", ffs(isdp->id_irq) - 1); if (isdp->id_drq != -1) printf(" drq %d", isdp->id_drq); if (isdp->id_maddr) - printf(" maddr 0x%x", kvtop(isdp->id_maddr)); + printf(" maddr 0x%lx", kvtop(isdp->id_maddr)); if (isdp->id_msize) printf(" msize %d", isdp->id_msize); if (isdp->id_flags) @@ -312,18 +381,25 @@ config_isadev(isdp, mp) } } } - + /* + * Check for conflicts again. The driver may have changed + * *dvp. We should weaken the early check since the + * driver may have been able to change *dvp to avoid + * conflicts if given a chance. We already skip the early + * check for IRQs and force a check for IRQs in the next + * group of checks. + */ + checkbits |= CC_IRQ; + if (haveseen_isadev(isdp, checkbits)) + return; + isdp->id_alive = id_alive; (*dp->attach)(isdp); - - if(isdp->id_irq) { - int intrno; - - intrno = ffs(isdp->id_irq)-1; - setidt(ICU_OFFSET+intrno, isdp->id_intr, - SDT_SYS386IGT, SEL_KPL); - if(mp) { - INTRMASK(*mp,isdp->id_irq); - } + if (isdp->id_irq) { + if (mp) + INTRMASK(*mp, isdp->id_irq); + register_intr(ffs(isdp->id_irq) - 1, isdp->id_id, + isdp->id_ri_flags, isdp->id_intr, + mp ? *mp : 0, isdp->id_unit); INTREN(isdp->id_irq); } } else { @@ -335,22 +411,6 @@ config_isadev(isdp, mp) } } -#define IDTVEC(name) __CONCAT(X,name) -/* default interrupt vector table entries */ -typedef void inthand_t(); -typedef void (*inthand_func_t)(); -extern inthand_t - IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3), - IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7), - IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11), - IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15); - -static inthand_func_t defvec[ICU_LEN] = { - &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), - &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), - &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), - &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) }; - /* * Fill in default interrupt table (in case of spuruious interrupt * during configuration of kernel, setup interrupt control unit @@ -362,7 +422,7 @@ isa_defaultirq() /* icu vectors */ for (i = 0; i < ICU_LEN; i++) - setidt(ICU_OFFSET + i, defvec[i], SDT_SYS386IGT, SEL_KPL); + unregister_intr(i, (inthand2_t *)NULL); /* initialize 8259's */ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ @@ -418,6 +478,9 @@ void isa_dmacascade(unsigned chan) } } +static int +isa_dmarangecheck(caddr_t va, unsigned length, unsigned chan); + /* * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment * problems by using a bounce buffer. @@ -520,7 +583,7 @@ void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) * Return true if special handling needed. */ -int +static int isa_dmarangecheck(caddr_t va, unsigned length, unsigned chan) { vm_offset_t phys, priorpage = 0, endva; u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); @@ -622,7 +685,7 @@ isa_nmi(cd) /* * Caught a stray interrupt, notify */ -void +static void isa_strayintr(d) int d; { @@ -637,13 +700,18 @@ isa_strayintr(d) * the first 5 get logged, then it quits logging them, and puts * out a special message. rgrimes 3/25/1993 */ - extern u_long intrcnt_stray; - - intrcnt_stray++; - if (intrcnt_stray <= 5) - log(LOG_ERR,"ISA strayintr %x\n", d); - if (intrcnt_stray == 5) - log(LOG_CRIT,"Too many ISA strayintr not logging any more\n"); + /* + * XXX TODO print a different message for #7 if it is for a + * glitch. Glitches can be distinguished from real #7's by + * testing that the in-service bit is _not_ set. The test + * must be done before sending an EOI so it can't be done if + * we are using AUTO_EOI_1. + */ + if (intrcnt[NR_DEVICES + d] <= 5) + log(LOG_ERR, "stray irq %d\n", d); + if (intrcnt[NR_DEVICES + d] == 5) + log(LOG_CRIT, + "too many stray irq %d's; not logging any more\n", d); } /* @@ -683,8 +751,84 @@ isa_irq_pending(dvp) { unsigned id_irq; - id_irq = (unsigned short) dvp->id_irq; /* XXX silly type in struct */ + id_irq = dvp->id_irq; if (id_irq & 0xff) return (inb(IO_ICU1) & id_irq); return (inb(IO_ICU2) & (id_irq >> 8)); } + +int +register_intr(intr, device_id, flags, handler, mask, unit) + int intr; + int device_id; + u_int flags; + inthand2_t *handler; + u_int mask; + int unit; +{ + char *cp; + u_long ef; + int id; + + if ((u_int)intr >= ICU_LEN || intr == 2 + || (u_int)device_id >= NR_DEVICES) + return (EINVAL); + if (intr_handler[intr] != isa_strayintr) + return (EBUSY); + ef = read_eflags(); + disable_intr(); + intr_countp[intr] = &intrcnt[device_id]; + intr_handler[intr] = handler; + intr_mask[intr] = mask | (1 << intr); + intr_unit[intr] = unit; + setidt(ICU_OFFSET + intr, + flags & RI_FAST ? fastintr[intr] : slowintr[intr], + SDT_SYS386IGT, SEL_KPL); + write_eflags(ef); + for (cp = intrnames, id = 0; id <= device_id; id++) + while (*cp++ != '\0') + ; + if (cp > eintrnames) + return (0); + if (intr < 10) { + cp[-3] = intr + '0'; + cp[-2] = ' '; + } else { + cp[-3] = '1'; + cp[-2] = intr - 10 + '0'; + } + return (0); +} + +static void +register_imask(dvp, mask) + struct isa_device *dvp; + u_int mask; +{ + if (dvp->id_alive && dvp->id_irq) { + int intr; + + intr = ffs(dvp->id_irq) - 1; + intr_mask[intr] = mask | (1 <<intr); + } +} + +int +unregister_intr(intr, handler) + int intr; + inthand2_t *handler; +{ + u_long ef; + + if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr]) + return (EINVAL); + ef = read_eflags(); + disable_intr(); + intr_countp[intr] = &intrcnt[NR_DEVICES + intr]; + intr_handler[intr] = isa_strayintr; + intr_mask[intr] = HWI_MASK | SWI_MASK; + intr_unit[intr] = intr; + setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL); + write_eflags(ef); + return (0); +} diff --git a/sys/i386/isa/isa_device.h b/sys/i386/isa/isa_device.h index 16fac9a..47dd12d 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.4 1993/12/19 00:50:42 wollman Exp $ + * $Id: isa_device.h,v 1.5 1994/01/04 20:06:30 nate Exp $ */ #ifndef _I386_ISA_ISA_DEVICE_H_ @@ -41,21 +41,38 @@ * ISA Bus Autoconfiguration */ +#define IDTVEC(name) __CONCAT(X,name) + +/* + * Type of the first (asm) part of an interrupt handler. + */ +typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss)); + +/* + * Usual type of the second (C) part of an interrupt handler. Some bogus + * ones need the arg to be the interrupt frame (and not a copy of it, which + * is all that is possible in C). + */ +typedef void inthand2_t __P((int unit)); + /* * Per device structure. */ struct isa_device { + int id_id; /* device id */ struct isa_driver *id_driver; short id_iobase; /* base i/o address */ u_short id_irq; /* interrupt request */ short id_drq; /* DMA request */ caddr_t id_maddr; /* physical i/o memory address on bus (if any)*/ int id_msize; /* size of i/o memory */ - void (*id_intr)(); /* interrupt interface routine */ + inthand2_t *id_intr; /* interrupt interface routine */ int id_unit; /* unit number */ int id_flags; /* flags */ int id_scsiid; /* scsi id if needed */ int id_alive; /* device is present */ +#define RI_FAST 1 /* fast interrupt handler */ + u_int id_ri_flags; /* flags for register_intr() */ }; /* @@ -66,17 +83,49 @@ struct isa_device { * These are used at boot time by the configuration program. */ struct isa_driver { - int (*probe)(); /* test whether device is present */ - int (*attach)(); /* setup driver for a device */ + int (*probe) __P((struct isa_device *idp)); + /* test whether device is present */ + int (*attach) __P((struct isa_device *idp)); + /* setup driver for a device */ char *name; /* device name */ }; +extern char eintrnames[]; /* end of intrnames[] */ +extern u_long intrcnt[]; /* counts for for each device and stray */ +extern char intrnames[]; /* string table containing device names */ +u_long *intr_countp[]; /* indirectors into intrcnt[] */ +inthand2_t *intr_handler[]; /* C entry points of intr handlers */ +u_int intr_mask[]; /* sets of intrs masked during handling of 1 */ +int intr_unit[]; /* cookies to pass to intr handlers */ + extern struct isa_device isa_devtab_bio[], isa_devtab_tty[], isa_devtab_net[], isa_devtab_null[], isa_biotab_wdc[], isa_biotab_fdc[]; -extern struct isa_device *find_isadev(/* table, driver, unit*/); - -extern void isa_dmastart(int, caddr_t, unsigned, unsigned); -extern void isa_dmadone(int, caddr_t, int, int); +inthand_t + IDTVEC(fastintr0), IDTVEC(fastintr1), + IDTVEC(fastintr2), IDTVEC(fastintr3), + IDTVEC(fastintr4), IDTVEC(fastintr5), + IDTVEC(fastintr6), IDTVEC(fastintr7), + IDTVEC(fastintr8), IDTVEC(fastintr9), + IDTVEC(fastintr10), IDTVEC(fastintr11), + IDTVEC(fastintr12), IDTVEC(fastintr13), + IDTVEC(fastintr14), IDTVEC(fastintr15); +struct isa_device *find_isadev __P((struct isa_device *table, + struct isa_driver *driverp, int unit)); +inthand_t + IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3), + IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7), + IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11), + IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15); +void isa_configure __P((void)); +void isa_defaultirq __P((void)); +void isa_dmacascade __P((unsigned chan)); +void isa_dmadone __P((int, caddr_t, int, int)); +void isa_dmastart __P((int, caddr_t, unsigned, unsigned)); +int isa_irq_pending __P((struct isa_device *dvp)); +int isa_nmi __P((int cd)); +int register_intr __P((int intr, int device_id, u_int flags, + inthand2_t *handler, u_int mask, int unit)); +int unregister_intr __P((int intr, inthand2_t *handler)); #endif /* _I386_ISA_ISA_DEVICE_H_ */ diff --git a/sys/i386/isa/sio.c b/sys/i386/isa/sio.c index de95e90..d505c4d 100644 --- a/sys/i386/isa/sio.c +++ b/sys/i386/isa/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.47 1994/05/26 13:31:40 rgrimes Exp $ + * $Id: sio.c,v 1.48 1994/08/13 03:50:13 wollman Exp $ */ #include "sio.h" @@ -427,6 +427,7 @@ sioattach(isdp) int s; int unit; + isdp->id_ri_flags |= RI_FAST; iobase = isdp->id_iobase; unit = isdp->id_unit; s = spltty(); diff --git a/sys/i386/isa/vector.s b/sys/i386/isa/vector.s index 7135ae7..252bd95 100644 --- a/sys/i386/isa/vector.s +++ b/sys/i386/isa/vector.s @@ -1,6 +1,6 @@ /* * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.6 1994/01/10 23:15:09 ache Exp $ + * $Id: vector.s,v 1.7 1994/04/02 07:00:50 davidg Exp $ */ #include "i386/isa/icu.h" @@ -97,7 +97,10 @@ * loading segregs. */ -#define FAST_INTR(unit, irq_num, id_num, handler, enable_icus) \ +#define FAST_INTR(irq_num, enable_icus) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(fastintr/**/irq_num) ; \ pushl %eax ; /* save only call-used registers */ \ pushl %ecx ; \ pushl %edx ; \ @@ -107,12 +110,13 @@ movl %ax,%ds ; \ MAYBE_MOVW_AX_ES ; \ FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl $unit ; \ - call handler ; /* do the work ASAP */ \ + pushl _intr_unit + (irq_num) * 4 ; \ + call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ addl $4,%esp ; \ incl _cnt+V_INTR ; /* book-keeping can wait */ \ - incl _intrcnt_actv + (id_num) * 4 ; \ + movl _intr_countp + (irq_num) * 4,%eax ; \ + incl (%eax) ; \ movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \ notl %eax ; \ andl _ipending,%eax ; \ @@ -147,7 +151,10 @@ MEXITCOUNT ; \ jmp _doreti -#define INTR(unit, irq_num, id_num, mask, handler, icu, enable_icus, reg, stray) \ +#define INTR(irq_num, icu, enable_icus, reg) \ + .text ; \ + SUPERALIGN_TEXT ; \ +IDTVEC(intr/**/irq_num) ; \ pushl $0 ; /* dumby error code */ \ pushl $0 ; /* dumby trap type */ \ pushal ; \ @@ -167,15 +174,17 @@ testb $IRQ_BIT(irq_num),%reg ; \ jne 2f ; \ 1: ; \ +Xresume/**/irq_num: ; \ FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ - incl _intrcnt_actv + (id_num) * 4 ; \ + movl _intr_countp + (irq_num) * 4,%eax ; \ + incl (%eax) ; \ movl _cpl,%eax ; \ pushl %eax ; \ - pushl $unit ; \ - orl mask,%eax ; \ + pushl _intr_unit + (irq_num) * 4 ; \ + orl _intr_mask + (irq_num) * 4,%eax ; \ movl %eax,_cpl ; \ sti ; \ - call handler ; \ + call *_intr_handler + (irq_num) * 4 ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ @@ -189,9 +198,6 @@ ALIGN_TEXT ; \ 2: ; \ /* XXX skip mcounting here to avoid double count */ \ - movl $1b,%eax ; /* register resume address */ \ - /* XXX - someday do it at attach time */ \ - movl %eax,ihandlers + (irq_num) * 4 ; \ orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ popl %es ; \ popl %ds ; \ @@ -199,118 +205,48 @@ addl $4+4,%esp ; \ iret -/* - * vector.h has defined a macro 'BUILD_VECTORS' containing a big list of info - * about vectors, including a submacro 'BUILD_VECTOR' that operates on the - * info about each vector. We redefine 'BUILD_VECTOR' to expand the info - * in different ways. Here we expand it to a list of interrupt handlers. - * This order is of course unimportant. Elsewhere we expand it to inline - * linear search code for which the order is a little more important and - * concatenating the code with no holes is very important. - * - * XXX - now there is BUILD_FAST_VECTOR as well as BUILD_VECTOR. - * - * The info consists of the following items for each vector: - * - * name (identifier): name of the vector; used to build labels - * unit (expression): unit number to call the device driver with - * irq_num (number): number of the IRQ to handled (0-15) - * id_num (number): uniq numeric id for handler (assigned by config) - * mask (blank-ident): priority mask used - * handler (blank-ident): interrupt handler to call - * icu_num (number): (1 + irq_num / 8) converted for label building - * icu_enables (number): 1 for icu_num == 1, 1_AND_2 for icu_num == 2 - * reg (blank-ident): al for icu_num == 1, ah for icu_num == 2 - * - * 'irq_num' is converted in several ways at config time to get around - * limitations in cpp. The macros have blanks after commas iff they would - * not mess up identifiers and numbers. - */ - -#undef BUILD_FAST_VECTOR -#define BUILD_FAST_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .globl handler ; \ - .text ; \ - .globl _V/**/name ; \ - SUPERALIGN_TEXT ; \ -_V/**/name: ; \ - FAST_INTR(unit, irq_num,id_num, handler, ENABLE_ICU/**/icu_enables) - -#undef BUILD_VECTOR -#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .globl handler ; \ - .text ; \ - .globl _V/**/name ; \ - SUPERALIGN_TEXT ; \ -_V/**/name: ; \ - INTR(unit,irq_num, id_num, mask, handler, IO_ICU/**/icu_num, \ - ENABLE_ICU/**/icu_enables, reg,) - MCOUNT_LABEL(bintr) - BUILD_VECTORS - - /* hardware interrupt catcher (IDT 32 - 47) */ - .globl _isa_strayintr - -#define STRAYINTR(irq_num, icu_num, icu_enables, reg) \ -IDTVEC(intr/**/irq_num) ; \ - INTR(irq_num,irq_num,irq_num, _high_imask, _isa_strayintr, \ - IO_ICU/**/icu_num, ENABLE_ICU/**/icu_enables, reg,stray) - -/* - * XXX - the mask (1 << 2) == IRQ_SLAVE will be generated for IRQ 2, instead - * of the mask IRQ2 (defined as IRQ9 == (1 << 9)). But IRQ 2 "can't happen". - * In fact, all stray interrupts "can't happen" except for bugs. The - * "stray" IRQ 7 is documented behaviour of the 8259. It happens when there - * is a glitch on any of its interrupt inputs. Does it really interrupt when - * IRQ 7 is masked? - * - * XXX - unpend doesn't work for these, it sends them to the real handler. - * - * XXX - the race bug during initialization may be because I changed the - * order of switching from the stray to the real interrupt handler to before - * enabling interrupts. The old order looked unsafe but maybe it is OK with - * the stray interrupt handler installed. But these handlers only reduce - * the window of vulnerability - it is still open at the end of - * isa_configure(). - * - * XXX - many comments are stale. - */ - - STRAYINTR(0,1,1, al) - STRAYINTR(1,1,1, al) - STRAYINTR(2,1,1, al) - STRAYINTR(3,1,1, al) - STRAYINTR(4,1,1, al) - STRAYINTR(5,1,1, al) - STRAYINTR(6,1,1, al) - STRAYINTR(7,1,1, al) - STRAYINTR(8,2,1_AND_2, ah) - STRAYINTR(9,2,1_AND_2, ah) - STRAYINTR(10,2,1_AND_2, ah) - STRAYINTR(11,2,1_AND_2, ah) - STRAYINTR(12,2,1_AND_2, ah) - STRAYINTR(13,2,1_AND_2, ah) - STRAYINTR(14,2,1_AND_2, ah) - STRAYINTR(15,2,1_AND_2, ah) -#if 0 - INTRSTRAY(255, _highmask, 255) ; call _isa_strayintr ; INTREXIT2 -#endif + FAST_INTR(0, ENABLE_ICU1) + FAST_INTR(1, ENABLE_ICU1) + FAST_INTR(2, ENABLE_ICU1) + FAST_INTR(3, ENABLE_ICU1) + FAST_INTR(4, ENABLE_ICU1) + FAST_INTR(5, ENABLE_ICU1) + FAST_INTR(6, ENABLE_ICU1) + FAST_INTR(7, ENABLE_ICU1) + FAST_INTR(8, ENABLE_ICU1_AND_2) + FAST_INTR(9, ENABLE_ICU1_AND_2) + FAST_INTR(10, ENABLE_ICU1_AND_2) + FAST_INTR(11, ENABLE_ICU1_AND_2) + FAST_INTR(12, ENABLE_ICU1_AND_2) + FAST_INTR(13, ENABLE_ICU1_AND_2) + FAST_INTR(14, ENABLE_ICU1_AND_2) + FAST_INTR(15, ENABLE_ICU1_AND_2) + INTR(0, IO_ICU1, ENABLE_ICU1, al) + INTR(1, IO_ICU1, ENABLE_ICU1, al) + INTR(2, IO_ICU1, ENABLE_ICU1, al) + INTR(3, IO_ICU1, ENABLE_ICU1, al) + INTR(4, IO_ICU1, ENABLE_ICU1, al) + INTR(5, IO_ICU1, ENABLE_ICU1, al) + INTR(6, IO_ICU1, ENABLE_ICU1, al) + INTR(7, IO_ICU1, ENABLE_ICU1, al) + INTR(8, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(9, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(10, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(11, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(12, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(13, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(14, IO_ICU2, ENABLE_ICU1_AND_2, ah) + INTR(15, IO_ICU2, ENABLE_ICU1_AND_2, ah) MCOUNT_LABEL(eintr) -/* - * These are the interrupt counters, I moved them here from icu.s so that - * they are with the name table. rgrimes - * - * There are now lots of counters, this has been redone to work with - * Bruce Evans intr-0.1 code, which I modified some more to make it all - * work with vmstat. - */ .data ihandlers: /* addresses of interrupt handlers */ - .space NHWI*4 /* actually resumption addresses for HWI's */ + /* actually resumption addresses for HWI's */ + .long Xresume0, Xresume1, Xresume2, Xresume3 + .long Xresume4, Xresume5, Xresume6, Xresume7 + .long Xresume8, Xresume9, Xresume10, Xresume11 + .long Xresume12, Xresume13, Xresume14, Xresume15 .long swi_tty, swi_net, 0, 0, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, swi_clock, swi_ast imasks: /* masks for interrupt handlers */ @@ -318,43 +254,37 @@ imasks: /* masks for interrupt handlers */ .long SWI_TTY_MASK, SWI_NET_MASK, 0, 0, 0, 0, 0, 0 .long 0, 0, 0, 0, 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK - .globl _intrcnt -_intrcnt: /* used by vmstat to calc size of table */ - .globl _intrcnt_bad7 -_intrcnt_bad7: .space 4 /* glitches on irq 7 */ - .globl _intrcnt_bad15 -_intrcnt_bad15: .space 4 /* glitches on irq 15 */ - .globl _intrcnt_stray -_intrcnt_stray: .space 4 /* total count of stray interrupts */ - .globl _intrcnt_actv -_intrcnt_actv: .space NR_REAL_INT_HANDLERS * 4 /* active interrupts */ - .globl _eintrcnt -_eintrcnt: /* used by vmstat to calc size of table */ - -/* - * Build the interrupt name table for vmstat - */ - -#undef BUILD_FAST_VECTOR -#define BUILD_FAST_VECTOR BUILD_VECTOR - -#undef BUILD_VECTOR -#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \ - icu_num, icu_enables, reg) \ - .ascii "name irq" ; \ - .asciz "irq_num" /* - * XXX - use the __STRING and __CONCAT macros from <sys/cdefs.h> to stringize - * and concatenate names above and elsewhere. Note that __CONCAT doesn't - * work when nested. + * Interrupt counters and names. The format of these and the label names + * must agree with what vmstat expects. The tables are indexed by device + * ids so that we don't have to move the names around as devices are + * attached. */ +#include "vector.h" + .globl _intrcnt, _eintrcnt +_intrcnt: + .space (NR_DEVICES + ICU_LEN) * 4 +_eintrcnt: - .text .globl _intrnames, _eintrnames _intrnames: - BUILD_VECTOR(bad,,7,,,,,,) - BUILD_VECTOR(bad,,15,,,,,,) - BUILD_VECTOR(stray,,,,,,,,) - BUILD_VECTORS - + .ascii DEVICE_NAMES + .asciz "stray irq0" + .asciz "stray irq1" + .asciz "stray irq2" + .asciz "stray irq3" + .asciz "stray irq4" + .asciz "stray irq5" + .asciz "stray irq6" + .asciz "stray irq7" + .asciz "stray irq8" + .asciz "stray irq9" + .asciz "stray irq10" + .asciz "stray irq11" + .asciz "stray irq12" + .asciz "stray irq13" + .asciz "stray irq14" + .asciz "stray irq15" _eintrnames: + + .text diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index 35f2e42..e3f3f21 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.13 1994/08/13 03:49:56 wollman Exp $ + * $Id: clock.c,v 1.14 1994/08/15 03:15:18 wollman Exp $ */ /* @@ -497,16 +497,14 @@ test_inittodr(time_t base) /* * Wire clock interrupt in. */ -#define V(s) __CONCAT(V, s) -extern void V(clk)(); -extern void V(rtc)(); - void enablertclock() { - setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, clkintr, + HWI_MASK | SWI_MASK, /* unit */ 0); INTREN(IRQ0); - setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL); + register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, rtcintr, + SWI_CLOCK_MASK, /* unit */ 0); INTREN(IRQ8); outb(IO_RTC, RTC_STATUSB); outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR); diff --git a/sys/isa/sio.c b/sys/isa/sio.c index de95e90..d505c4d 100644 --- a/sys/isa/sio.c +++ b/sys/isa/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.47 1994/05/26 13:31:40 rgrimes Exp $ + * $Id: sio.c,v 1.48 1994/08/13 03:50:13 wollman Exp $ */ #include "sio.h" @@ -427,6 +427,7 @@ sioattach(isdp) int s; int unit; + isdp->id_ri_flags |= RI_FAST; iobase = isdp->id_iobase; unit = isdp->id_unit; s = spltty(); |