Provide an interrupt availability check callback instead of a maximum IRQ
number. This accounts for possible gaps in the IO-APIC GSI mappings. Since most of the time there will be only a single IO-APIC the extra overhead is relatively small. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41431 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d11e32a807
commit
eda743903e
@ -167,10 +167,17 @@ ioapic_write_64(struct ioapic& ioapic, uint8 registerSelect, uint64 value)
|
||||
|
||||
|
||||
static bool
|
||||
ioapic_is_spurious_interrupt(int32 num)
|
||||
ioapic_is_interrupt_available(int32 gsi)
|
||||
{
|
||||
return find_ioapic(gsi) != NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
ioapic_is_spurious_interrupt(int32 gsi)
|
||||
{
|
||||
// the spurious interrupt vector is initialized to the max value in smp
|
||||
return num == 0xff - ARCH_INTERRUPT_BASE;
|
||||
return gsi == 0xff - ARCH_INTERRUPT_BASE;
|
||||
}
|
||||
|
||||
|
||||
@ -507,15 +514,9 @@ ioapic_init(kernel_args* args)
|
||||
// aren't different routings based on it this is non-fatal
|
||||
}
|
||||
|
||||
// TODO: this isn't necessarily correct, as they may not be listed in order
|
||||
// of global interrupt base and there may even be gaps!
|
||||
struct ioapic* lastIOAPIC = &sIOAPICs;
|
||||
while (lastIOAPIC->next != NULL)
|
||||
lastIOAPIC = lastIOAPIC->next;
|
||||
|
||||
IRQRoutingTable table;
|
||||
status = prepare_irq_routing(acpiModule, table,
|
||||
lastIOAPIC->global_interrupt_last + 1);
|
||||
&ioapic_is_interrupt_available);
|
||||
if (status != B_OK) {
|
||||
dprintf("IRQ routing preparation failed, not configuring io-apics\n");
|
||||
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);
|
||||
|
@ -164,7 +164,8 @@ fill_pci_info_for_entry(pci_module_info* pci, irq_routing_entry& entry)
|
||||
|
||||
static status_t
|
||||
choose_link_device_configurations(acpi_module_info* acpi,
|
||||
IRQRoutingTable& routingTable, uint32 maxIRQCount)
|
||||
IRQRoutingTable& routingTable,
|
||||
interrupt_available_check_function checkFunction)
|
||||
{
|
||||
/*
|
||||
Before configuring the link devices we have to take a few things into
|
||||
@ -184,7 +185,7 @@ choose_link_device_configurations(acpi_module_info* acpi,
|
||||
*/
|
||||
|
||||
uint16 validForPCI = 0; // only applies to the ISA IRQs
|
||||
uint16 irqUsage[maxIRQCount];
|
||||
uint16 irqUsage[256];
|
||||
memset(irqUsage, 0, sizeof(irqUsage));
|
||||
|
||||
// find all unique link devices and resolve their possible IRQs
|
||||
@ -254,7 +255,7 @@ choose_link_device_configurations(acpi_module_info* acpi,
|
||||
uint16 bestIRQUsage = UINT16_MAX;
|
||||
for (int j = 0; j < link->possible_irqs.Count(); j++) {
|
||||
irq_descriptor& possibleIRQ = link->possible_irqs.ElementAt(j);
|
||||
if (possibleIRQ.irq >= maxIRQCount) {
|
||||
if (!checkFunction(possibleIRQ.irq)) {
|
||||
// we can't address this pin
|
||||
continue;
|
||||
}
|
||||
@ -274,9 +275,8 @@ choose_link_device_configurations(acpi_module_info* acpi,
|
||||
// pick that one and update the counts
|
||||
irq_descriptor& chosenDescriptor
|
||||
= link->possible_irqs.ElementAt(bestIRQIndex);
|
||||
if (chosenDescriptor.irq >= maxIRQCount) {
|
||||
dprintf("chosen irq %u is not addressable (max %lu)\n",
|
||||
chosenDescriptor.irq, maxIRQCount);
|
||||
if (!checkFunction(chosenDescriptor.irq)) {
|
||||
dprintf("chosen irq %u is not addressable\n", chosenDescriptor.irq);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@ -403,7 +403,8 @@ 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,
|
||||
interrupt_available_check_function checkFunction)
|
||||
{
|
||||
acpi_data buffer;
|
||||
buffer.pointer = NULL;
|
||||
@ -454,9 +455,8 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
||||
status = handle_routing_table_entry(acpi, pci, acpiTable, pciAddress,
|
||||
irqEntry);
|
||||
if (status == B_OK) {
|
||||
if (irqEntry.source == NULL && irqEntry.irq >= maxIRQCount) {
|
||||
dprintf("hardwired irq %u not addressable (max %lu)\n",
|
||||
irqEntry.irq, maxIRQCount);
|
||||
if (irqEntry.source == NULL && !checkFunction(irqEntry.irq)) {
|
||||
dprintf("hardwired irq %u not addressable\n", irqEntry.irq);
|
||||
free(buffer.pointer);
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -494,7 +494,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
||||
|
||||
TRACE("recursing down to child \"%s\"\n", childName);
|
||||
status = read_irq_routing_table_recursive(acpi, pci, childHandle,
|
||||
pciAddress, table, false, maxIRQCount);
|
||||
pciAddress, table, false, checkFunction);
|
||||
if (status != B_OK)
|
||||
break;
|
||||
}
|
||||
@ -506,7 +506,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
||||
|
||||
static status_t
|
||||
read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
|
||||
uint32 maxIRQCount)
|
||||
interrupt_available_check_function checkFunction)
|
||||
{
|
||||
char rootPciName[255];
|
||||
acpi_handle rootPciHandle;
|
||||
@ -540,7 +540,7 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
|
||||
}
|
||||
|
||||
status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle,
|
||||
rootPciAddress, table, true, maxIRQCount);
|
||||
rootPciAddress, table, true, checkFunction);
|
||||
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
|
||||
@ -553,14 +553,14 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
|
||||
|
||||
status_t
|
||||
prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
||||
uint32 maxIRQCount)
|
||||
interrupt_available_check_function checkFunction)
|
||||
{
|
||||
status_t status = read_irq_routing_table(acpi, routingTable, maxIRQCount);
|
||||
status_t status = read_irq_routing_table(acpi, routingTable, checkFunction);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
// resolve desired configuration of link devices
|
||||
return choose_link_device_configurations(acpi, routingTable, maxIRQCount);
|
||||
return choose_link_device_configurations(acpi, routingTable, checkFunction);
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,12 +68,15 @@ struct link_device {
|
||||
};
|
||||
|
||||
|
||||
typedef bool (*interrupt_available_check_function)(int32 globalSystemInterrupt);
|
||||
|
||||
|
||||
void print_irq_descriptor(const irq_descriptor& descriptor);
|
||||
void print_irq_routing_table(const IRQRoutingTable& table);
|
||||
|
||||
|
||||
status_t prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& table,
|
||||
uint32 maxIRQCount);
|
||||
interrupt_available_check_function checkFunction);
|
||||
status_t enable_irq_routing(acpi_module_info* acpi,
|
||||
IRQRoutingTable& routingTable);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user