summaryrefslogtreecommitdiffstats
path: root/sys/i386/acpica
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-01-26 19:34:24 +0000
committerjhb <jhb@FreeBSD.org>2004-01-26 19:34:24 +0000
commitfffdd26a90f14d4fd47f1690634668119cbe27b7 (patch)
treebefd833eafbea94fb180c7db5cd801d9ba719015 /sys/i386/acpica
parent217fb330c26cc6bc733ebc468bcfee39aa6860ea (diff)
downloadFreeBSD-src-fffdd26a90f14d4fd47f1690634668119cbe27b7.zip
FreeBSD-src-fffdd26a90f14d4fd47f1690634668119cbe27b7.tar.gz
- Call acpi_Startup() before parsing interrupt-related APIC resources so we
can look at the ACPI tables. If the startup fails, we panic and tell the user to try rebooting with ACPI disabled. Previously in this case we would try to use $PIR interrupt routing which only works for the atpic while using the apic to handle interrupts which would result in misrouted interrupts and a hang at boot time with no error message. - Read the SCI out of the FADT instead of hardcoding 9 when checking to see if an interrupt override entry is for the SCI. - Try to work around some BIOS brain damage for the SCI's programming by forcing the SCI to be level triggered and active low if it is routed to a non-ISA interrupt (greater than 15) or if it is identity mapped with edge trigger and active high polarity. This should fix some of the hangs with device apic and ACPI that some people see. Reviewed by: njl
Diffstat (limited to 'sys/i386/acpica')
-rw-r--r--sys/i386/acpica/madt.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/sys/i386/acpica/madt.c b/sys/i386/acpica/madt.c
index 01d7ccc..8116d2a 100644
--- a/sys/i386/acpica/madt.c
+++ b/sys/i386/acpica/madt.c
@@ -320,13 +320,22 @@ madt_setup_local(void)
}
/*
- * Run through the MP table enumerating I/O APICs.
+ * Enumerate I/O APICs and setup interrupt sources.
*/
static int
madt_setup_io(void)
{
int i;
+ /* Try to initialize ACPI so that we can access the FADT. */
+ i = acpi_Startup();
+ if (ACPI_FAILURE(i)) {
+ printf("MADT: ACPI Startup failed with %s\n",
+ AcpiFormatException(i));
+ printf("Try disabling either ACPI or apic support.\n");
+ panic("Using MADT but ACPI doesn't work");
+ }
+
/* First, we run through adding I/O APIC's. */
madt_walk_table(madt_parse_apics, NULL);
@@ -522,6 +531,7 @@ madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
{
void *new_ioapic, *old_ioapic;
u_int new_pin, old_pin;
+ int force_lo;
if (bootverbose)
printf("MADT: intr override: source %u, irq %u\n",
@@ -534,9 +544,27 @@ madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
return;
}
+ /*
+ * If the SCI is remapped to a non-ISA global interrupt,
+ * force it to level trigger and active-lo polarity.
+ * If the SCI is identity mapped but has edge trigger and
+ * active-hi polarity, also force it to use level/lo.
+ */
+ force_lo = 0;
+ if (intr->Source == AcpiGbl_FADT->SciInt)
+ if (intr->Interrupt > 15 || (intr->Interrupt == intr->Source &&
+ intr->TriggerMode == TRIGGER_EDGE &&
+ intr->Polarity == POLARITY_ACTIVE_HIGH))
+ force_lo = 1;
+
if (intr->Source != intr->Interrupt) {
- /* XXX: This assumes that the SCI uses IRQ 9. */
- if (intr->Interrupt > 15 && intr->Source == 9)
+ /*
+ * If the SCI is remapped to a non-ISA global interrupt,
+ * then override the vector we use to setup and allocate
+ * the interrupt.
+ */
+ if (intr->Interrupt > 15 &&
+ intr->Source == AcpiGbl_FADT->SciInt)
acpi_OverrideInterruptLevel(intr->Interrupt);
else
ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
@@ -548,10 +576,18 @@ madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
intr->Source)
ioapic_disable_pin(old_ioapic, old_pin);
}
- ioapic_set_triggermode(new_ioapic, new_pin,
- interrupt_trigger(intr->TriggerMode));
- ioapic_set_polarity(new_ioapic, new_pin,
- interrupt_polarity(intr->Polarity));
+ if (force_lo) {
+ printf(
+ "MADT: Forcing active-lo polarity and level trigger for IRQ %d\n",
+ intr->Source);
+ ioapic_set_polarity(new_ioapic, new_pin, 0);
+ ioapic_set_triggermode(new_ioapic, new_pin, 0);
+ } else {
+ ioapic_set_polarity(new_ioapic, new_pin,
+ interrupt_polarity(intr->Polarity));
+ ioapic_set_triggermode(new_ioapic, new_pin,
+ interrupt_trigger(intr->TriggerMode));
+ }
}
/*
OpenPOWER on IntegriCloud