summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2004-07-08 01:42:49 +0000
committerpeter <peter@FreeBSD.org>2004-07-08 01:42:49 +0000
commite3e493024dec3bde4f375b5e9253880b423771c0 (patch)
tree9b1a3645cab9fdbceba7847d110ec6a26d3963e3 /sys/amd64
parentdd3c90cb130487da4a03fb9222df5e64c180e55f (diff)
downloadFreeBSD-src-e3e493024dec3bde4f375b5e9253880b423771c0.zip
FreeBSD-src-e3e493024dec3bde4f375b5e9253880b423771c0.tar.gz
MFi386: various io apic cleanups
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/io_apic.c169
-rw-r--r--sys/amd64/amd64/mptable.c25
-rw-r--r--sys/amd64/include/apicvar.h7
3 files changed, 147 insertions, 54 deletions
diff --git a/sys/amd64/amd64/io_apic.c b/sys/amd64/amd64/io_apic.c
index b734162..4b8568d 100644
--- a/sys/amd64/amd64/io_apic.c
+++ b/sys/amd64/amd64/io_apic.c
@@ -100,6 +100,7 @@ struct ioapic_intsrc {
u_int io_edgetrigger:1;
u_int io_masked:1;
int io_dest:5;
+ int io_bus:4;
};
struct ioapic {
@@ -115,6 +116,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);
@@ -163,6 +166,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)
{
@@ -299,10 +341,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);
@@ -365,32 +404,39 @@ ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
{
struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc;
struct ioapic *io = (struct ioapic *)isrc->is_pic;
+ int changed;
KASSERT(!(trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM),
("%s: Conforming trigger or polarity\n", __func__));
/*
- * For now we ignore any requests but do output any changes that
- * would be made to the console it bootverbose is enabled. The only
- * known causes of these messages so far is a bug in acpi(4) that
- * causes the ISA IRQs used for PCI interrupts in PIC mode to be
- * set to level/low when they aren't being used. There are possibly
- * legitimate requests, so at some point when the acpi(4) driver is
- * fixed this code can be changed to actually change the intpin as
- * requested.
+ * EISA interrupts always use active high polarity, so don't allow
+ * them to be set to active low.
+ *
+ * XXX: Should we write to the ELCR if the trigger mode changes for
+ * an EISA IRQ?
*/
- if (!bootverbose)
- return (0);
- if (intpin->io_edgetrigger != (trig == INTR_TRIGGER_EDGE))
- printf(
- "ioapic%u: Request to change trigger for pin %u to %s ignored\n",
- io->io_id, intpin->io_intpin, trig == INTR_TRIGGER_EDGE ?
- "edge" : "level");
- if (intpin->io_activehi != (pol == INTR_POLARITY_HIGH))
- printf(
- "ioapic%u: Request to change polarity for pin %u to %s ignored\n",
- io->io_id, intpin->io_intpin, pol == INTR_POLARITY_HIGH ?
- "high" : "low");
+ if (intpin->io_bus == APIC_BUS_EISA)
+ pol = INTR_POLARITY_HIGH;
+ changed = 0;
+ if (intpin->io_edgetrigger != (trig == INTR_TRIGGER_EDGE)) {
+ if (bootverbose)
+ printf("ioapic%u: Changing trigger for pin %u to %s\n",
+ io->io_id, intpin->io_intpin,
+ trig == INTR_TRIGGER_EDGE ? "edge" : "level");
+ intpin->io_edgetrigger = (trig == INTR_TRIGGER_EDGE);
+ changed++;
+ }
+ if (intpin->io_activehi != (pol == INTR_POLARITY_HIGH)) {
+ if (bootverbose)
+ printf("ioapic%u: Changing polarity for pin %u to %s\n",
+ io->io_id, intpin->io_intpin,
+ pol == INTR_POLARITY_HIGH ? "high" : "low");
+ intpin->io_activehi = (pol == INTR_POLARITY_HIGH);
+ changed++;
+ }
+ if (changed)
+ ioapic_program_intpin(intpin);
return (0);
}
@@ -491,44 +537,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);
@@ -583,6 +621,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;
@@ -590,8 +647,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;
@@ -610,8 +670,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;
@@ -630,10 +693,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/amd64/amd64/mptable.c b/sys/amd64/amd64/mptable.c
index 622aeaa..ac56bf1 100644
--- a/sys/amd64/amd64/mptable.c
+++ b/sys/amd64/amd64/mptable.c
@@ -639,14 +639,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:
@@ -944,7 +958,8 @@ mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin)
'A' + pin);
return (PCI_INVALID_IRQ);
}
- device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, 'A' + pin,
- args.vector);
+ if (bootverbose)
+ device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot,
+ 'A' + pin, args.vector);
return (args.vector);
}
diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h
index 30b9a8e..e6804d7 100644
--- a/sys/amd64/include/apicvar.h
+++ b/sys/amd64/include/apicvar.h
@@ -114,6 +114,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.
@@ -142,6 +148,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