diff options
author | dfr <dfr@FreeBSD.org> | 1997-06-02 08:19:06 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1997-06-02 08:19:06 +0000 |
commit | 6ba14cc686e7f472a6937088de33f356556bf759 (patch) | |
tree | c7c4bcee2063b32a59ec0918ff2f82386e367571 /sys/i386/isa/isa.c | |
parent | 33ddef35e6191fb2cd19ec096f2d855851331a45 (diff) | |
download | FreeBSD-src-6ba14cc686e7f472a6937088de33f356556bf759.zip FreeBSD-src-6ba14cc686e7f472a6937088de33f356556bf759.tar.gz |
Move interrupt handling code from isa.c to a new file. This should make
isa.c (slightly) more portable and will make my life developing the really
portable version much easier.
Reviewed by: peter, fsmp
Diffstat (limited to 'sys/i386/isa/isa.c')
-rw-r--r-- | sys/i386/isa/isa.c | 358 |
1 files changed, 2 insertions, 356 deletions
diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c index a54f7bb..ccadc08 100644 --- a/sys/i386/isa/isa.c +++ b/sys/i386/isa/isa.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.87 1997/05/29 05:56:12 fsmp Exp $ + * $Id: isa.c,v 1.88 1997/05/31 09:27:31 peter Exp $ */ /* @@ -47,8 +47,6 @@ * isa_dmastart() */ -#include "opt_auto_eoi.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> @@ -65,6 +63,7 @@ #include <vm/vm_param.h> #include <vm/pmap.h> #include <i386/isa/isa_device.h> +#include <i386/isa/intr_machdep.h> #include <i386/isa/isa.h> #include <i386/isa/icu.h> #include <i386/isa/ic/i8237.h> @@ -72,14 +71,6 @@ #include <sys/interrupt.h> -#ifdef APIC_IO -/* - * This is to accommodate "mixed-mode" programming for - * motherboards that don't connect the 8254 to the IO APIC. - */ -#define AUTO_EOI_1 -#endif - /* ** Register definitions for DMA controller 1 (channels 0..3): */ @@ -96,40 +87,6 @@ #define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ #define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ -u_long *intr_countp[ICU_LEN]; -inthand2_t *intr_handler[ICU_LEN]; -u_int intr_mask[ICU_LEN]; -u_int* intr_mptr[ICU_LEN]; -int intr_unit[ICU_LEN]; - -static inthand_t *fastintr[ICU_LEN] = { - &IDTVEC(fastintr0), &IDTVEC(fastintr1), - &IDTVEC(fastintr2), &IDTVEC(fastintr3), - &IDTVEC(fastintr4), &IDTVEC(fastintr5), - &IDTVEC(fastintr6), &IDTVEC(fastintr7), - &IDTVEC(fastintr8), &IDTVEC(fastintr9), - &IDTVEC(fastintr10), &IDTVEC(fastintr11), - &IDTVEC(fastintr12), &IDTVEC(fastintr13), - &IDTVEC(fastintr14), &IDTVEC(fastintr15) -#if defined(APIC_IO) - , &IDTVEC(fastintr16), &IDTVEC(fastintr17), - &IDTVEC(fastintr18), &IDTVEC(fastintr19), - &IDTVEC(fastintr20), &IDTVEC(fastintr21), - &IDTVEC(fastintr22), &IDTVEC(fastintr23) -#endif /* APIC_IO */ -}; - -static inthand_t *slowintr[ICU_LEN] = { - &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), - &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), - &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), - &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) -#if defined(APIC_IO) - , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19), - &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23) -#endif /* APIC_IO */ -}; - static void config_isadev __P((struct isa_device *isdp, u_int *mp)); static void config_isadev_c __P((struct isa_device *isdp, u_int *mp, int reconfig)); @@ -139,8 +96,6 @@ static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp, static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp, u_int checkbits)); static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan)); -static inthand2_t isa_strayintr; -static void register_imask __P((struct isa_device *dvp, u_int mask)); /* * print a conflict message @@ -615,44 +570,6 @@ config_isadev_c(isdp, mp, reconfig) } } -/* - * Fill in default interrupt table (in case of spuruious interrupt - * during configuration of kernel, setup interrupt control unit - */ -void -isa_defaultirq() -{ - int i; - - /* icu vectors */ - for (i = 0; i < ICU_LEN; i++) - icu_unset(i, (inthand2_t *)NULL); - - /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ - outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */ - outb(IO_ICU1+1, 1<<2); /* slave on line 2 */ -#ifdef AUTO_EOI_1 - outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */ -#else - outb(IO_ICU1+1, 1); /* 8086 mode */ -#endif - outb(IO_ICU1+1, 0xff); /* leave interrupts masked */ - outb(IO_ICU1, 0x0a); /* default to IRR on read */ - outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ - - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ - outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */ - outb(IO_ICU2+1,2); /* my slave id is 2 */ -#ifdef AUTO_EOI_2 - outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */ -#else - outb(IO_ICU2+1,1); /* 8086 mode */ -#endif - outb(IO_ICU2+1, 0xff); /* leave interrupts masked */ - outb(IO_ICU2, 0x0a); /* default to IRR on read */ -} - static caddr_t dma_bouncebuf[8]; static u_int dma_bouncebufsize[8]; static u_int8_t dma_bounced = 0; @@ -956,70 +873,6 @@ isa_dmarangecheck(caddr_t va, u_int length, int chan) { return (0); } -#define NMI_PARITY (1 << 7) -#define NMI_IOCHAN (1 << 6) -#define ENMI_WATCHDOG (1 << 7) -#define ENMI_BUSTIMER (1 << 6) -#define ENMI_IOSTATUS (1 << 5) - -/* - * Handle a NMI, possibly a machine check. - * return true to panic system, false to ignore. - */ -int -isa_nmi(cd) - int cd; -{ - int isa_port = inb(0x61); - int eisa_port = inb(0x461); - if(isa_port & NMI_PARITY) { - panic("RAM parity error, likely hardware failure."); - } else if(isa_port & NMI_IOCHAN) { - panic("I/O channel check, likely hardware failure."); - } else if(eisa_port & ENMI_WATCHDOG) { - panic("EISA watchdog timer expired, likely hardware failure."); - } else if(eisa_port & ENMI_BUSTIMER) { - panic("EISA bus timeout, likely hardware failure."); - } else if(eisa_port & ENMI_IOSTATUS) { - panic("EISA I/O port status error."); - } else { - printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port); - return(0); - } -} - -/* - * Caught a stray interrupt, notify - */ -static void -isa_strayintr(d) - int d; -{ - - /* DON'T BOTHER FOR NOW! */ - /* for some reason, we get bursts of intr #7, even if not enabled! */ - /* - * Well the reason you got bursts of intr #7 is because someone - * raised an interrupt line and dropped it before the 8259 could - * prioritize it. This is documented in the intel data book. This - * means you have BAD hardware! I have changed this so that only - * the first 5 get logged, then it quits logging them, and puts - * out a special message. rgrimes 3/25/1993 - */ - /* - * XXX TODO print a different message for #7 if it is for a - * glitch. Glitches can be distinguished from real #7's by - * testing that the in-service bit is _not_ set. The test - * must be done before sending an EOI so it can't be done if - * we are using AUTO_EOI_1. - */ - if (intrcnt[NR_DEVICES + d] <= 5) - log(LOG_ERR, "stray irq %d\n", d); - if (intrcnt[NR_DEVICES + d] == 5) - log(LOG_CRIT, - "too many stray irq %d's; not logging any more\n", d); -} - /* * Find the highest priority enabled display device. Since we can't * distinguish display devices from ttys, depend on display devices @@ -1067,210 +920,3 @@ struct isa_device *find_isadev(table, driverp, unit) return (table); } -/* - * Return nonzero if a (masked) irq is pending for a given device. - */ -#if defined(APIC_IO) - -int -isa_irq_pending(dvp) - struct isa_device *dvp; -{ - /* read APIC IRR containing the 16 ISA INTerrupts */ - return ((lapic__irr1 & 0x00ffffff) - & (u_int32_t)dvp->id_irq) ? 1 : 0; -} - -/* - * an 8259 specific routine, - * for use by boot probes in certain device drivers. - */ -int -icu_irq_pending(dvp) - struct isa_device *dvp; -{ - unsigned id_irq; - id_irq = dvp->id_irq; - if (id_irq & 0xff) - return (inb(IO_ICU1) & id_irq); - return (inb(IO_ICU2) & (id_irq >> 8)); -} - -#else /* APIC_IO */ - -int -isa_irq_pending(dvp) - struct isa_device *dvp; -{ - unsigned id_irq; - id_irq = dvp->id_irq; - if (id_irq & 0xff) - return (inb(IO_ICU1) & id_irq); - return (inb(IO_ICU2) & (id_irq >> 8)); -} - -#endif /* APIC_IO */ - -int -update_intr_masks(void) -{ - int intr, n=0; - u_int mask,*maskptr; - - for (intr=0; intr < ICU_LEN; intr ++) { -#if defined(APIC_IO) - /* no 8259 SLAVE to ignore */ -#else - if (intr==2) continue; /* ignore 8259 SLAVE output */ -#endif /* APIC_IO */ - maskptr = intr_mptr[intr]; - if (!maskptr) continue; - *maskptr |= 1 << intr; - mask = *maskptr; - if (mask != intr_mask[intr]) { -#if 0 - printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n", - intr, intr_mask[intr], mask, maskptr); -#endif - intr_mask[intr]=mask; - n++; - } - - } - return (n); -} - -/* - * The find_device_id function is only required because of the way the - * device names are currently stored for reporting in systat or vmstat. - * In fact, those programs should be modified to use the sysctl interface - * to obtain a list of driver names by traversing intreclist_head[irq]. - */ - -static int -find_device_id(int irq) -{ - char buf[16]; - char *cp; - int free_id, id; - - sprintf(buf, "pci irq%d", irq); - cp = intrnames; - /* default to 0, which corresponds to clk0 */ - free_id = 0; - - for (id = 0; id < NR_DEVICES; id++) { - if (strcmp(cp, buf) == 0) - return (id); - if (free_id == 0 && strcmp(cp, "pci irqnn") == 0) - free_id = id; - while (*cp++ != '\0'); - } -#if 0 - if (free_id == 0) { - /* - * All pci irq counters are in use, perhaps because config - * is old so there aren't any. Abuse the clk0 counter. - */ - printf("\tcounting shared irq%d as clk0 irq\n", irq); - } -#endif - return (free_id); -} - -void -update_intrname(int intr, int device_id) -{ - char *cp; - int id; - - if (device_id == -1) - device_id = find_device_id(intr); - - if ((u_int)device_id >= NR_DEVICES) - return; - - intr_countp[intr] = &intrcnt[device_id]; - - for (cp = intrnames, id = 0; id <= device_id; id++) - while (*cp++ != '\0') - ; - if (cp > eintrnames) - return; - if (intr < 10) { - cp[-3] = intr + '0'; - cp[-2] = ' '; - } else if (intr < 20) { - cp[-3] = '1'; - cp[-2] = intr - 10 + '0'; - } else { - cp[-3] = '2'; - cp[-2] = intr - 20 + '0'; - } -} - -int -icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) -{ - u_long ef; - u_int mask = (maskptr ? *maskptr : 0); - -#if defined(APIC_IO) - if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */ -#else - if ((u_int)intr >= ICU_LEN || intr == 2) -#endif /* APIC_IO */ - if (intr_handler[intr] != isa_strayintr) - return (EBUSY); - - ef = read_eflags(); - disable_intr(); - intr_handler[intr] = handler; - intr_mptr[intr] = maskptr; - intr_mask[intr] = mask | (1 << intr); - intr_unit[intr] = arg; - setidt(ICU_OFFSET + intr, - flags & RI_FAST ? fastintr[intr] : slowintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - INTREN(1 << intr); - write_eflags(ef); - return (0); -} - -static void -register_imask(dvp, mask) - struct isa_device *dvp; - u_int mask; -{ - if (dvp->id_alive && dvp->id_irq) { - int intr; - - intr = ffs(dvp->id_irq) - 1; - intr_mask[intr] = mask | (1 <<intr); - } - (void) update_intr_masks(); -} - -int -icu_unset(intr, handler) - int intr; - inthand2_t *handler; -{ - u_long ef; - - if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr]) - return (EINVAL); - - INTRDIS(1 << intr); - ef = read_eflags(); - disable_intr(); - intr_countp[intr] = &intrcnt[NR_DEVICES + intr]; - intr_handler[intr] = isa_strayintr; - intr_mptr[intr] = NULL; - intr_mask[intr] = HWI_MASK | SWI_MASK; - intr_unit[intr] = intr; - setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - write_eflags(ef); - return (0); -} |