diff options
author | jhb <jhb@FreeBSD.org> | 2005-04-14 18:25:09 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-04-14 18:25:09 +0000 |
commit | d6a800e5926c0c3aff8d4e1edea3220c21ec2d2e (patch) | |
tree | f9b55d2f089ae96090fda21e2173847e4459669b /sys | |
parent | d3ad4828d61536a544fb3011197e8c19433449e3 (diff) | |
download | FreeBSD-src-d6a800e5926c0c3aff8d4e1edea3220c21ec2d2e.zip FreeBSD-src-d6a800e5926c0c3aff8d4e1edea3220c21ec2d2e.tar.gz |
Trust the settings programmed by the BIOS over what the $PIR says.
Specifically, if the BIOS has programmed an IRQ for a device that doesn't
match the list of valid IRQs for the link, use it anyway as some BIOSes
don't correctly list the valid IRQs in the $PIR. Also, allow the user
to specify an IRQ that $PIR claims is invalid as an override, but emit a
warning in that case.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/i386/pci/pci_pir.c | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c index 89e8356..faeb0a7 100644 --- a/sys/i386/pci/pci_pir.c +++ b/sys/i386/pci/pci_pir.c @@ -324,22 +324,50 @@ pci_pir_initial_irqs(struct PIR_entry *entry, struct PIR_intpin *intpin, pin = intpin - entry->pe_intpin; pci_link = pci_pir_find_link(intpin->link); irq = pci_pir_search_irq(entry->pe_bus, entry->pe_device, pin); - if (irq == PCI_INVALID_IRQ) + if (irq == PCI_INVALID_IRQ || irq == pci_link->pl_irq) return; - if (pci_pir_valid_irq(pci_link, irq)) { - if (pci_link->pl_irq == PCI_INVALID_IRQ) { - pci_link->pl_irq = irq; - pci_link->pl_routed = 1; - } else if (pci_link->pl_irq != irq) + + /* + * If we don't have an IRQ for this link yet, then we trust the + * BIOS, even if it seems invalid from the $PIR entries. + */ + if (pci_link->pl_irq == PCI_INVALID_IRQ) { + if (!pci_pir_valid_irq(pci_link, irq)) printf( - "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n", + "$PIR: Using invalid BIOS IRQ %d from %d.%d.INT%c is for link %#x\n", irq, entry->pe_bus, entry->pe_device, pin + 'A', - pci_link->pl_id, pci_link->pl_irq); - } else + pci_link->pl_id); + pci_link->pl_irq = irq; + pci_link->pl_routed = 1; + return; + } + + /* + * We have an IRQ and it doesn't match the current IRQ for this + * link. If the new IRQ is invalid, then warn about it and ignore + * it. If the old IRQ is invalid and the new IRQ is valid, then + * prefer the new IRQ instead. If both IRQs are valid, then just + * use the first one. Note that if we ever get into this situation + * we are having to guess which setting the BIOS actually routed. + * Perhaps we should just give up instead. + */ + if (!pci_pir_valid_irq(pci_link, irq)) { printf( "$PIR: BIOS IRQ %d for %d.%d.INT%c is not valid for link %#x\n", irq, entry->pe_bus, entry->pe_device, pin + 'A', pci_link->pl_id); + } else if (!pci_pir_valid_irq(pci_link, pci_link->pl_irq)) { + printf( +"$PIR: Preferring valid BIOS IRQ %d from %d.%d.INT%c for link %#x to IRQ %d\n", + irq, entry->pe_bus, entry->pe_device, pin + 'A', + pci_link->pl_id, pci_link->pl_irq); + pci_link->pl_irq = irq; + pci_link->pl_routed = 1; + } else + printf( + "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n", + irq, entry->pe_bus, entry->pe_device, pin + 'A', + pci_link->pl_id, pci_link->pl_irq); } /* @@ -386,9 +414,9 @@ pci_pir_parse(void) } /* - * Allow the user to override the IRQ for a given link device as - * long as the override is valid or is 255 or 0 to clear a preset - * IRQ. + * Allow the user to override the IRQ for a given link device. We + * allow invalid IRQs to be specified but warn about them. An IRQ + * of 255 or 0 clears any preset IRQ. */ i = 0; TAILQ_FOREACH(pci_link, &pci_links, pl_links) { @@ -398,12 +426,14 @@ pci_pir_parse(void) continue; if (irq == 0) irq = PCI_INVALID_IRQ; - if (irq == PCI_INVALID_IRQ || - pci_pir_valid_irq(pci_link, irq)) { - pci_link->pl_routed = 0; - pci_link->pl_irq = irq; - i = 1; - } + if (irq != PCI_INVALID_IRQ && + !pci_pir_valid_irq(pci_link, irq) && bootverbose) + printf( + "$PIR: Warning, IRQ %d for link %#x is not listed as valid\n", + irq, pci_link->pl_id); + pci_link->pl_routed = 0; + pci_link->pl_irq = irq; + i = 1; } if (bootverbose && i) { printf("$PIR: Links after tunable overrides:\n"); |