summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-06-23 15:29:20 +0000
committerjhb <jhb@FreeBSD.org>2004-06-23 15:29:20 +0000
commit22d8e1a72ee83a4d20da2cc201b27d2d2494eba5 (patch)
tree6cfd5687b02ab3781300ee19c0425154d9c94fa7
parent72f48d54670d08a6d096b8c79a51b3a90be61dc5 (diff)
downloadFreeBSD-src-22d8e1a72ee83a4d20da2cc201b27d2d2494eba5.zip
FreeBSD-src-22d8e1a72ee83a4d20da2cc201b27d2d2494eba5.tar.gz
Various cleanups in support of a future ioapic_config_intr() function:
- Allow ioapic_set_{nmi,smi,extint}() to be called multiple times on the same pin so long as the pin's mode is the same as the mode being requested. - Add a notion of bus type for the interrupt associated with interrupt pin. This is needed so that we can force all EISA interrupts to be active high in the forthcoming ioapic_config_intr(). - Fix a bug for EISA systems that didn't remap IRQs. This would have broken EISA systems that tried to disable mixed mode for IRQ 0.
-rw-r--r--sys/i386/i386/io_apic.c122
-rw-r--r--sys/i386/i386/mptable.c20
-rw-r--r--sys/i386/include/apicvar.h7
3 files changed, 117 insertions, 32 deletions
diff --git a/sys/i386/i386/io_apic.c b/sys/i386/i386/io_apic.c
index c1e3b07..c00bebf 100644
--- a/sys/i386/i386/io_apic.c
+++ b/sys/i386/i386/io_apic.c
@@ -99,6 +99,7 @@ struct ioapic_intsrc {
u_int io_edgetrigger:1;
u_int io_masked:1;
int io_dest:5;
+ int io_bus:4;
};
struct ioapic {
@@ -114,6 +115,8 @@ struct ioapic {
static u_int ioapic_read(volatile ioapic_t *apic, int reg);
static void ioapic_write(volatile ioapic_t *apic, int reg, u_int val);
+static const char *ioapic_bus_string(int bus_type);
+static void ioapic_print_vector(struct ioapic_intsrc *intpin);
static void ioapic_enable_source(struct intsrc *isrc);
static void ioapic_disable_source(struct intsrc *isrc);
static void ioapic_eoi_source(struct intsrc *isrc);
@@ -162,6 +165,45 @@ ioapic_write(volatile ioapic_t *apic, int reg, u_int val)
apic->iowin = val;
}
+static const char *
+ioapic_bus_string(int bus_type)
+{
+
+ switch (bus_type) {
+ case APIC_BUS_ISA:
+ return ("ISA");
+ case APIC_BUS_EISA:
+ return ("EISA");
+ case APIC_BUS_PCI:
+ return ("PCI");
+ default:
+ return ("unknown");
+ }
+}
+
+static void
+ioapic_print_vector(struct ioapic_intsrc *intpin)
+{
+
+ switch (intpin->io_vector) {
+ case VECTOR_DISABLED:
+ printf("disabled");
+ break;
+ case VECTOR_EXTINT:
+ printf("ExtINT");
+ break;
+ case VECTOR_NMI:
+ printf("NMI");
+ break;
+ case VECTOR_SMI:
+ printf("SMI");
+ break;
+ default:
+ printf("%s IRQ %u", ioapic_bus_string(intpin->io_bus),
+ intpin->io_vector);
+ }
+}
+
static void
ioapic_enable_source(struct intsrc *isrc)
{
@@ -298,10 +340,7 @@ ioapic_program_destination(struct ioapic_intsrc *intpin)
if (bootverbose) {
printf("ioapic%u: routing intpin %u (", io->io_id,
intpin->io_intpin);
- if (intpin->io_vector == VECTOR_EXTINT)
- printf("ExtINT");
- else
- printf("IRQ %u", intpin->io_vector);
+ ioapic_print_vector(intpin);
printf(") to cluster %u\n", intpin->io_dest);
}
ioapic_program_intpin(intpin);
@@ -490,44 +529,36 @@ ioapic_create(uintptr_t addr, int32_t apic_id, int intbase)
intpin->io_vector = intbase + i;
/*
- * Assume that pin 0 on the first IO APIC is an ExtINT pin by
- * default. Assume that intpins 1-15 are ISA interrupts and
- * use suitable defaults for those. Assume that all other
- * intpins are PCI interrupts. Enable the ExtINT pin if
- * mixed mode is available and active but mask all other pins.
+ * Assume that pin 0 on the first I/O APIC is an ExtINT pin
+ * and that pins 1-15 are ISA interrupts. Assume that all
+ * other pins are PCI interrupts.
*/
- if (intpin->io_vector == 0) {
- intpin->io_activehi = 1;
- intpin->io_edgetrigger = 1;
- intpin->io_vector = VECTOR_EXTINT;
- if (mixed_mode_enabled && mixed_mode_active)
- intpin->io_masked = 0;
- else
- intpin->io_masked = 1;
- } else if (intpin->io_vector < IOAPIC_ISA_INTS) {
+ if (intpin->io_vector == 0)
+ ioapic_set_extint(io, i);
+ else if (intpin->io_vector < IOAPIC_ISA_INTS) {
+ intpin->io_bus = APIC_BUS_ISA;
intpin->io_activehi = 1;
intpin->io_edgetrigger = 1;
intpin->io_masked = 1;
} else {
+ intpin->io_bus = APIC_BUS_PCI;
intpin->io_activehi = 0;
intpin->io_edgetrigger = 0;
intpin->io_masked = 1;
}
/*
- * Start off without a logical cluster destination until
- * the pin is enabled.
+ * Route interrupts to the BSP by default using physical
+ * addressing. Vectored interrupts get readdressed using
+ * logical IDs to CPU clusters when they are enabled.
*/
intpin->io_dest = DEST_NONE;
- if (bootverbose) {
+ if (bootverbose && intpin->io_vector != VECTOR_DISABLED) {
printf("ioapic%u: intpin %d -> ", io->io_id, i);
- if (intpin->io_vector == VECTOR_EXTINT)
- printf("ExtINT");
- else
- printf("irq %u", intpin->io_vector);
- printf(" (%s, active%s)\n", intpin->io_edgetrigger ?
- "edge" : "level", intpin->io_activehi ? "hi" :
- "lo");
+ ioapic_print_vector(intpin);
+ printf(" (%s, %s)\n", intpin->io_edgetrigger ?
+ "edge" : "level", intpin->io_activehi ? "high" :
+ "low");
}
value = ioapic_read(apic, IOAPIC_REDTBL_LO(i));
ioapic_write(apic, IOAPIC_REDTBL_LO(i), value | IOART_INTMSET);
@@ -582,6 +613,25 @@ ioapic_remap_vector(void *cookie, u_int pin, int vector)
}
int
+ioapic_set_bus(void *cookie, u_int pin, int bus_type)
+{
+ struct ioapic *io;
+
+ if (bus_type < 0 || bus_type > APIC_BUS_MAX)
+ return (EINVAL);
+ io = (struct ioapic *)cookie;
+ if (pin >= io->io_numintr)
+ return (EINVAL);
+ if (io->io_pins[pin].io_vector >= NUM_IO_INTS)
+ return (EINVAL);
+ io->io_pins[pin].io_bus = bus_type;
+ if (bootverbose)
+ printf("ioapic%u: intpin %d bus %s\n", io->io_id, pin,
+ ioapic_bus_string(bus_type));
+ return (0);
+}
+
+int
ioapic_set_nmi(void *cookie, u_int pin)
{
struct ioapic *io;
@@ -589,8 +639,11 @@ ioapic_set_nmi(void *cookie, u_int pin)
io = (struct ioapic *)cookie;
if (pin >= io->io_numintr)
return (EINVAL);
+ if (io->io_pins[pin].io_vector == VECTOR_NMI)
+ return (0);
if (io->io_pins[pin].io_vector >= NUM_IO_INTS)
return (EINVAL);
+ io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN;
io->io_pins[pin].io_vector = VECTOR_NMI;
io->io_pins[pin].io_masked = 0;
io->io_pins[pin].io_edgetrigger = 1;
@@ -609,8 +662,11 @@ ioapic_set_smi(void *cookie, u_int pin)
io = (struct ioapic *)cookie;
if (pin >= io->io_numintr)
return (EINVAL);
+ if (io->io_pins[pin].io_vector == VECTOR_SMI)
+ return (0);
if (io->io_pins[pin].io_vector >= NUM_IO_INTS)
return (EINVAL);
+ io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN;
io->io_pins[pin].io_vector = VECTOR_SMI;
io->io_pins[pin].io_masked = 0;
io->io_pins[pin].io_edgetrigger = 1;
@@ -629,10 +685,18 @@ ioapic_set_extint(void *cookie, u_int pin)
io = (struct ioapic *)cookie;
if (pin >= io->io_numintr)
return (EINVAL);
+ if (io->io_pins[pin].io_vector == VECTOR_EXTINT)
+ return (0);
if (io->io_pins[pin].io_vector >= NUM_IO_INTS)
return (EINVAL);
+ io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN;
io->io_pins[pin].io_vector = VECTOR_EXTINT;
- io->io_pins[pin].io_masked = 0;
+
+ /* Enable this pin if mixed mode is available and active. */
+ if (mixed_mode_enabled && mixed_mode_active)
+ io->io_pins[pin].io_masked = 0;
+ else
+ io->io_pins[pin].io_masked = 1;
io->io_pins[pin].io_edgetrigger = 1;
io->io_pins[pin].io_activehi = 1;
if (bootverbose)
diff --git a/sys/i386/i386/mptable.c b/sys/i386/i386/mptable.c
index 294e92f..262d336 100644
--- a/sys/i386/i386/mptable.c
+++ b/sys/i386/i386/mptable.c
@@ -646,14 +646,28 @@ mptable_parse_io_int(int_entry_ptr intr)
pin = intr->dst_apic_int;
switch (intr->int_type) {
case INTENTRY_TYPE_INT:
- if (busses[intr->src_bus_id].bus_type == NOBUS)
+ switch (busses[intr->src_bus_id].bus_type) {
+ case NOBUS:
panic("interrupt from missing bus");
- if (busses[intr->src_bus_id].bus_type == ISA &&
- intr->src_bus_irq != pin) {
+ case ISA:
+ case EISA:
+ if (busses[intr->src_bus_id].bus_type == ISA)
+ ioapic_set_bus(ioapic, pin, APIC_BUS_ISA);
+ else
+ ioapic_set_bus(ioapic, pin, APIC_BUS_EISA);
+ if (intr->src_bus_irq == pin)
+ break;
ioapic_remap_vector(ioapic, pin, intr->src_bus_irq);
if (ioapic_get_vector(ioapic, intr->src_bus_irq) ==
intr->src_bus_irq)
ioapic_disable_pin(ioapic, intr->src_bus_irq);
+ break;
+ case PCI:
+ ioapic_set_bus(ioapic, pin, APIC_BUS_PCI);
+ break;
+ default:
+ ioapic_set_bus(ioapic, pin, APIC_BUS_UNKNOWN);
+ break;
}
break;
case INTENTRY_TYPE_NMI:
diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h
index 7bdcc7f..cc46fda 100644
--- a/sys/i386/include/apicvar.h
+++ b/sys/i386/include/apicvar.h
@@ -113,6 +113,12 @@
#define APIC_IPI_DEST_ALL -2
#define APIC_IPI_DEST_OTHERS -3
+#define APIC_BUS_UNKNOWN -1
+#define APIC_BUS_ISA 0
+#define APIC_BUS_EISA 1
+#define APIC_BUS_PCI 2
+#define APIC_BUS_MAX APIC_BUS_PCI
+
/*
* An APIC enumerator is a psuedo bus driver that enumerates APIC's including
* CPU's and I/O APIC's.
@@ -141,6 +147,7 @@ int ioapic_get_vector(void *cookie, u_int pin);
int ioapic_next_logical_cluster(void);
void ioapic_register(void *cookie);
int ioapic_remap_vector(void *cookie, u_int pin, int vector);
+int ioapic_set_bus(void *cookie, u_int pin, int bus_type);
int ioapic_set_extint(void *cookie, u_int pin);
int ioapic_set_nmi(void *cookie, u_int pin);
int ioapic_set_polarity(void *cookie, u_int pin, enum intr_polarity pol);
OpenPOWER on IntegriCloud