diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index eda2cfdba5..e389d02e6e 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -650,16 +650,6 @@ ioapic_init(kernel_args* args) // aren't different routings based on it this is non-fatal } - IRQRoutingTable table; - status = read_irq_routing_table(acpiModule, &table, - sIOAPICMaxRedirectionEntry + 1); - if (status != B_OK) { - dprintf("reading IRQ routing table failed, not configuring ioapic.\n"); - acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC); - // revert to PIC interrupt model just in case - return; - } - sLevelTriggeredInterrupts = 0; sIOAPICMaxRedirectionEntry = ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT) @@ -667,8 +657,19 @@ ioapic_init(kernel_args* args) TRACE(("ioapic has %lu entries\n", sIOAPICMaxRedirectionEntry + 1)); - status = enable_irq_routing(acpiModule, table, + IRQRoutingTable table; + status = prepare_irq_routing(acpiModule, table, sIOAPICMaxRedirectionEntry + 1); + if (status != B_OK) { + dprintf("IRQ routing preparation failed, not configuring ioapic.\n"); + acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC); + // revert to PIC interrupt model just in case + return; + } + + print_irq_routing_table(&table); + + status = enable_irq_routing(acpiModule, table); if (status != B_OK) { panic("failed to enable IRQ routing"); // if it failed early on it might still work in PIC mode @@ -709,8 +710,6 @@ ioapic_init(kernel_args* args) ioapic_write_64(IO_APIC_REDIRECTION_TABLE + 2 * i, entry); } - print_irq_routing_table(&table); - // configure io apic interrupts from PCI routing table for (int i = 0; i < table.Count(); i++) { irq_routing_entry& entry = table.ElementAt(i); diff --git a/src/system/kernel/arch/x86/irq_routing_table.cpp b/src/system/kernel/arch/x86/irq_routing_table.cpp index 3b616a8ce4..ff66b059ce 100644 --- a/src/system/kernel/arch/x86/irq_routing_table.cpp +++ b/src/system/kernel/arch/x86/irq_routing_table.cpp @@ -163,8 +163,8 @@ fill_pci_info_for_entry(pci_module_info* pci, irq_routing_entry& entry) static status_t -configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, - uint32 maxIRQCount) +choose_link_device_configurations(acpi_module_info* acpi, + IRQRoutingTable& routingTable, uint32 maxIRQCount) { /* Before configuring the link devices we have to take a few things into @@ -275,21 +275,16 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, irq_descriptor& chosenDescriptor = link->possible_irqs.ElementAt(bestIRQIndex); if (chosenDescriptor.irq >= maxIRQCount) { - panic("chosen irq %u is not addressable (max %lu)", + dprintf("chosen irq %u is not addressable (max %lu)\n", chosenDescriptor.irq, maxIRQCount); return B_ERROR; } irqUsage[chosenDescriptor.irq] += link->used_by.Count(); - status_t status = set_current_irq(acpi, link->handle, chosenDescriptor); - if (status != B_OK) { - panic("failed to set irq on link device"); - return status; - } - for (int j = 0; j < link->used_by.Count(); j++) { irq_routing_entry* irqEntry = link->used_by.ElementAt(j); + irqEntry->needs_configuration = j == 0; // only configure once irqEntry->irq = chosenDescriptor.irq; irqEntry->polarity = chosenDescriptor.polarity; irqEntry->trigger_mode = chosenDescriptor.trigger_mode; @@ -302,6 +297,32 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, } +static status_t +configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable) +{ + for (int i = 0; i < routingTable.Count(); i++) { + irq_routing_entry& irqEntry = routingTable.ElementAt(i); + if (!irqEntry.needs_configuration) + continue; + + irq_descriptor configuration; + configuration.irq = irqEntry.irq; + configuration.polarity = irqEntry.polarity; + configuration.trigger_mode = irqEntry.trigger_mode; + + status_t status = set_current_irq(acpi, irqEntry.source, configuration); + if (status != B_OK) { + panic("failed to set irq on link device"); + return status; + } + + irqEntry.needs_configuration = false; + } + + return B_OK; +} + + static status_t evaluate_integer(acpi_module_info* acpi, acpi_handle handle, const char* method, uint64& value) @@ -368,8 +389,8 @@ handle_routing_table_entry(acpi_module_info* acpi, pci_module_info* pci, } if (noSource) { - // fill in the GSI and config; link based entries will be resolved at - // link configuration time + // fill in the GSI and config + irqEntry.needs_configuration = false; irqEntry.irq = irqEntry.source_index; irqEntry.polarity = B_LOW_ACTIVE_POLARITY; irqEntry.trigger_mode = B_LEVEL_TRIGGERED; @@ -382,7 +403,7 @@ handle_routing_table_entry(acpi_module_info* acpi, pci_module_info* pci, static status_t read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, acpi_handle device, const pci_address& parentAddress, - IRQRoutingTable* table, bool rootBridge, uint32 maxIRQCount) + IRQRoutingTable& table, bool rootBridge, uint32 maxIRQCount) { acpi_data buffer; buffer.pointer = NULL; @@ -440,7 +461,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, return B_ERROR; } - table->PushBack(irqEntry); + table.PushBack(irqEntry); } acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable @@ -483,8 +504,8 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, } -status_t -read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table, +static status_t +read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table, uint32 maxIRQCount) { char rootPciName[255]; @@ -526,16 +547,28 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table, if (status != B_OK) return status; - return table->Count() > 0 ? B_OK : B_ERROR; + return table.Count() > 0 ? B_OK : B_ERROR; } status_t -enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable, +prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable, uint32 maxIRQCount) +{ + status_t status = read_irq_routing_table(acpi, routingTable, maxIRQCount); + if (status != B_OK) + return status; + + // resolve desired configuration of link devices + return choose_link_device_configurations(acpi, routingTable, maxIRQCount); +} + + +status_t +enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable) { // configure the link devices; also resolves GSIs for link based entries - status_t status = configure_link_devices(acpi, routingTable, maxIRQCount); + status_t status = configure_link_devices(acpi, routingTable); if (status != B_OK) { panic("failed to configure link devices"); return status; diff --git a/src/system/kernel/arch/x86/irq_routing_table.h b/src/system/kernel/arch/x86/irq_routing_table.h index 01cf7975bd..96d52436d0 100644 --- a/src/system/kernel/arch/x86/irq_routing_table.h +++ b/src/system/kernel/arch/x86/irq_routing_table.h @@ -19,6 +19,7 @@ struct irq_routing_entry { acpi_handle source; uint32 source_index; + bool needs_configuration; // PCI bus_manager connection uint8 pci_bus; @@ -71,10 +72,10 @@ void print_irq_descriptor(irq_descriptor* descriptor); void print_irq_routing_table(IRQRoutingTable* table); -status_t read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table, +status_t prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& table, uint32 maxIRQCount); status_t enable_irq_routing(acpi_module_info* acpi, - IRQRoutingTable& routingTable, uint32 maxIRQCount); + IRQRoutingTable& routingTable); status_t read_current_irq(acpi_module_info* acpi, acpi_handle device, irq_descriptor& descriptor);