diff options
author | imp <imp@FreeBSD.org> | 2002-04-24 15:30:11 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2002-04-24 15:30:11 +0000 |
commit | 85bb92b6154d72f77704d9066f6794a559bba1b7 (patch) | |
tree | a7851f3ef82f8654f5f4bb7737d19185167aab8e /sys/amd64/pci/pci_cfgreg.c | |
parent | 17b84c592bd7264c71c39aab4e7ab8d03a11175b (diff) | |
download | FreeBSD-src-85bb92b6154d72f77704d9066f6794a559bba1b7.zip FreeBSD-src-85bb92b6154d72f77704d9066f6794a559bba1b7.tar.gz |
o Work around bugs in the powerof2 macro: It thinks that 0 is a power of
2, but that's not the case. This fixes the case where there were slots
in the PIR table that had no bits set, but we assumed they did and used
strange results as a result.
o Map invalid INTLINE registers to 255 in pci_cfgreg.c. This should allow
us to remove the bogus checks in MI code for non-255 values.
I put these changes out for review a while ago, but no one responded
to them, so into current they go.
This should help us work better on machines that don't route
interrupts in the traditional way.
MFC After: 4286 millifortnights
Diffstat (limited to 'sys/amd64/pci/pci_cfgreg.c')
-rw-r--r-- | sys/amd64/pci/pci_cfgreg.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c index 825d9b7..27c8912 100644 --- a/sys/amd64/pci/pci_cfgreg.c +++ b/sys/amd64/pci/pci_cfgreg.c @@ -178,6 +178,7 @@ pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes) u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes) { + uint32_t line, pin; #ifdef APIC_IO /* * If we are using the APIC, the contents of the intline register will probably @@ -186,7 +187,6 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes) * attempts to read them and translate to our private vector numbers. */ if ((reg == PCIR_INTLINE) && (bytes == 1)) { - int pin, line; pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1); line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1); @@ -217,6 +217,18 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes) } return(line); } +#else + /* + * Some BIOS writers seem to want to ignore the spec and put + * 0 in the intline rather than 255 to indicate none. The rest of + * the code uses 255 as an invalid IRQ. + */ + if (reg == PCIR_INTLINE && bytes == 1) { + line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1); + pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1); + if (pin != 0 && (line == 0 || line >= 128)) + return (255); + } #endif /* APIC_IO */ return(pci_do_cfgregread(bus, slot, func, reg, bytes)); } @@ -307,9 +319,11 @@ static int pci_cfgintr_unique(struct PIR_entry *pe, int pin) { int irq; + uint32_t irqmask; - if (powerof2(pe->pe_intpin[pin - 1].irqs)) { - irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1; + irqmask = pe->pe_intpin[pin - 1].irqs; + if (irqmask != 0 && powerof2(irqmask)) { + irq = ffs(irqmask) - 1; PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq)); return(irq); } @@ -344,7 +358,7 @@ pci_cfgintr_linked(struct PIR_entry *pe, int pin) continue; /* link destination mapped to a unique interrupt? */ - if (powerof2(pi->irqs)) { + if (pi->irqs != 0 && powerof2(pi->irqs)) { irq = ffs(pi->irqs) - 1; PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n", pi->link, irq)); @@ -394,14 +408,6 @@ pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int (pci_get_slot(*childp) == device) && (pci_get_intpin(*childp) == matchpin)) { irq = pci_get_irq(*childp); - /* - * Some BIOS writers seem to want to ignore the spec and put - * 0 in the intline rather than 255 to indicate none. Once - * we've found one that matches, we break because there can - * be no others (which is why test looks a little odd). - */ - if (irq == 0) - irq = 255; if (irq != 255) PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n", pe->pe_intpin[pin - 1].link, irq, |