From 9ae3fdcb02b3815e163d7b983ba77a8b3aaf6e1c Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 16 May 2011 14:06:27 +0000 Subject: [PATCH] * Move redirection entry configuration into a separate function and allow to specify the delivery mode. * Use that function from ioapic_configure_io_interrupt() and use it when configuring NMI sources to actually set the entries to NMI. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41531 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/arch/x86/ioapic.cpp | 117 +++++++++++++++----------- 1 file changed, 70 insertions(+), 47 deletions(-) diff --git a/src/system/kernel/arch/x86/ioapic.cpp b/src/system/kernel/arch/x86/ioapic.cpp index 973abe4c06..35ce465962 100644 --- a/src/system/kernel/arch/x86/ioapic.cpp +++ b/src/system/kernel/arch/x86/ioapic.cpp @@ -192,6 +192,35 @@ ioapic_write_64(struct ioapic& ioapic, uint8 registerSelect, uint64 value, } +static void +ioapic_configure_pin(struct ioapic& ioapic, uint8 pin, uint8 vector, + uint8 triggerPolarity, uint8 deliveryMode) +{ + uint64 entry = ioapic_read_64(ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2); + entry &= ~((1 << IO_APIC_TRIGGER_MODE_SHIFT) + | (1 << IO_APIC_PIN_POLARITY_SHIFT) + | (IO_APIC_INTERRUPT_VECTOR_MASK << IO_APIC_INTERRUPT_VECTOR_SHIFT)) + | (IO_APIC_DELIVERY_MODE_MASK << IO_APIC_DELIVERY_MODE_SHIFT); + + if (triggerPolarity & B_LEVEL_TRIGGERED) { + entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT); + ioapic.level_triggered_mask |= ((uint64)1 << pin); + } else { + entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT); + ioapic.level_triggered_mask &= ~((uint64)1 << pin); + } + + if (triggerPolarity & B_LOW_ACTIVE_POLARITY) + entry |= (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT); + else + entry |= (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT); + + entry |= (uint64)deliveryMode << IO_APIC_DELIVERY_MODE_SHIFT; + entry |= (vector + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT; + ioapic_write_64(ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2, entry, true); +} + + static bool ioapic_is_spurious_interrupt(int32 gsi) { @@ -273,26 +302,8 @@ ioapic_configure_io_interrupt(int32 gsi, uint32 config) TRACE(("ioapic_configure_io_interrupt: gsi %ld -> io-apic %u pin %u; " "config 0x%08lx\n", gsi, ioapic->number, pin, config)); - uint64 entry = ioapic_read_64(*ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2); - entry &= ~((1 << IO_APIC_TRIGGER_MODE_SHIFT) - | (1 << IO_APIC_PIN_POLARITY_SHIFT) - | (IO_APIC_INTERRUPT_VECTOR_MASK << IO_APIC_INTERRUPT_VECTOR_SHIFT)); - - if (config & B_LEVEL_TRIGGERED) { - entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT); - ioapic->level_triggered_mask |= ((uint64)1 << pin); - } else { - entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT); - ioapic->level_triggered_mask &= ~((uint64)1 << pin); - } - - if (config & B_LOW_ACTIVE_POLARITY) - entry |= (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT); - else - entry |= (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT); - - entry |= (gsi + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT; - ioapic_write_64(*ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2, entry, true); + ioapic_configure_pin(*ioapic, pin, gsi, config, + IO_APIC_DELIVERY_MODE_FIXED); } @@ -450,6 +461,40 @@ acpi_enumerate_ioapics(acpi_table_madt* madt) } +static inline uint32 +acpi_madt_convert_inti_flags(uint16 flags) +{ + uint32 config = 0; + switch (flags & ACPI_MADT_POLARITY_MASK) { + case ACPI_MADT_POLARITY_ACTIVE_LOW: + config = B_LOW_ACTIVE_POLARITY; + break; + default: + dprintf("invalid polarity in inti flags\n"); + // fall through and assume active high + case ACPI_MADT_POLARITY_ACTIVE_HIGH: + case ACPI_MADT_POLARITY_CONFORMS: + config = B_HIGH_ACTIVE_POLARITY; + break; + } + + switch (flags & ACPI_MADT_TRIGGER_MASK) { + case ACPI_MADT_TRIGGER_LEVEL: + config |= B_LEVEL_TRIGGERED; + break; + default: + dprintf("invalid trigger mode in source override\n"); + // fall through and assume edge triggered + case ACPI_MADT_TRIGGER_CONFORMS: + case ACPI_MADT_TRIGGER_EDGE: + config |= B_EDGE_TRIGGERED; + break; + } + + return config; +} + + static void acpi_configure_source_overrides(acpi_table_madt* madt) { @@ -482,33 +527,7 @@ acpi_configure_source_overrides(acpi_table_madt* madt) } // configure non-standard polarity/trigger modes - uint32 config = 0; - switch (info->IntiFlags & ACPI_MADT_POLARITY_MASK) { - case ACPI_MADT_POLARITY_ACTIVE_LOW: - config = B_LOW_ACTIVE_POLARITY; - break; - default: - dprintf("invalid polarity in source override\n"); - // fall through and assume active high - case ACPI_MADT_POLARITY_ACTIVE_HIGH: - case ACPI_MADT_POLARITY_CONFORMS: - config = B_HIGH_ACTIVE_POLARITY; - break; - } - - switch (info->IntiFlags & ACPI_MADT_TRIGGER_MASK) { - case ACPI_MADT_TRIGGER_LEVEL: - config |= B_LEVEL_TRIGGERED; - break; - default: - dprintf("invalid trigger mode in source override\n"); - // fall through and assume edge triggered - case ACPI_MADT_TRIGGER_CONFORMS: - case ACPI_MADT_TRIGGER_EDGE: - config |= B_EDGE_TRIGGERED; - break; - } - + uint32 config = acpi_madt_convert_inti_flags(info->IntiFlags); ioapic_configure_io_interrupt(info->GlobalIrq, config); break; } @@ -529,6 +548,10 @@ acpi_configure_source_overrides(acpi_table_madt* madt) uint8 pin = info->GlobalIrq - ioapic->global_interrupt_base; ioapic->nmi_mask |= (uint64)1 << pin; + + uint32 config = acpi_madt_convert_inti_flags(info->IntiFlags); + ioapic_configure_pin(*ioapic, pin, info->GlobalIrq, config, + IO_APIC_DELIVERY_MODE_NMI); break; }