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