- Add a pci_cfgintr_valid() function to see if a given IRQ is a valid
IRQ for an entry in a PCIBIOS interrupt routing ($PIR) table. - Change pci_cfgintr() to except the current IRQ of a device as a fourth argument and to use that IRQ for the device if it is valid. - If an intpin entry in a $PIR entry has a link of 0, it means that that intpin isn't connected to anything that can trigger an interrupt. Thus, test the link against 0 to find invalid entries in the table instead of implicitly relying on the irqs field to be zero. In the machines I have looked at, intpin entries with a link of 0 often have the bits for all possible interrupts for PCI devices set.
This commit is contained in:
parent
d04c7d51be
commit
8ab96fd8d0
@ -50,6 +50,6 @@
|
||||
int pci_cfgregopen(void);
|
||||
u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
|
||||
void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);
|
||||
int pci_cfgintr(int bus, int device, int pin);
|
||||
int pci_cfgintr(int bus, int device, int pin, int oldirq);
|
||||
int pci_kill_pcibios(void);
|
||||
int pci_pcibios_active(void);
|
||||
|
@ -77,7 +77,8 @@ nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
|
||||
static int
|
||||
nexus_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin));
|
||||
return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin,
|
||||
pci_get_irq(dev)));
|
||||
}
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
@ -61,6 +61,7 @@ static int enable_pcibios = 0;
|
||||
|
||||
TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios);
|
||||
|
||||
static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
|
||||
static int pci_cfgintr_unique(struct PIR_entry *pe, int pin);
|
||||
static int pci_cfgintr_linked(struct PIR_entry *pe, int pin);
|
||||
static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
|
||||
@ -272,7 +273,7 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
|
||||
* anyway, due to the way PCI interrupts are assigned.
|
||||
*/
|
||||
int
|
||||
pci_cfgintr(int bus, int device, int pin)
|
||||
pci_cfgintr(int bus, int device, int pin, int oldirq)
|
||||
{
|
||||
struct PIR_entry *pe;
|
||||
int i, irq;
|
||||
@ -298,7 +299,20 @@ pci_cfgintr(int bus, int device, int pin)
|
||||
i++, pe++) {
|
||||
if ((bus != pe->pe_bus) || (device != pe->pe_device))
|
||||
continue;
|
||||
/*
|
||||
* A link of 0 means that this intpin is not connected to
|
||||
* any other device's interrupt pins and is not connected to
|
||||
* any of the Interrupt Router's interrupt pins, so we can't
|
||||
* route it.
|
||||
*/
|
||||
if (pe->pe_intpin[pin - 1].link == 0)
|
||||
continue;
|
||||
|
||||
if (pci_cfgintr_valid(pe, pin, oldirq)) {
|
||||
printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus,
|
||||
device, 'A' + pin - 1, oldirq);
|
||||
return (oldirq);
|
||||
}
|
||||
irq = pci_cfgintr_linked(pe, pin);
|
||||
if (irq == PCI_INVALID_IRQ)
|
||||
irq = pci_cfgintr_unique(pe, pin);
|
||||
@ -337,6 +351,24 @@ pci_cfgintr(int bus, int device, int pin)
|
||||
return(PCI_INVALID_IRQ);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if an existing IRQ setting is valid.
|
||||
*/
|
||||
static int
|
||||
pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq)
|
||||
{
|
||||
uint32_t irqmask;
|
||||
|
||||
if (!PCI_INTERRUPT_VALID(irq))
|
||||
return (0);
|
||||
irqmask = pe->pe_intpin[pin - 1].irqs;
|
||||
if (irqmask & (1 << irq)) {
|
||||
PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq));
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look to see if the routing table claims this pin is uniquely routed.
|
||||
*/
|
||||
|
@ -50,6 +50,6 @@
|
||||
int pci_cfgregopen(void);
|
||||
u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
|
||||
void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);
|
||||
int pci_cfgintr(int bus, int device, int pin);
|
||||
int pci_cfgintr(int bus, int device, int pin, int oldirq);
|
||||
int pci_kill_pcibios(void);
|
||||
int pci_pcibios_active(void);
|
||||
|
@ -77,7 +77,8 @@ nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
|
||||
static int
|
||||
nexus_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin));
|
||||
return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin,
|
||||
pci_get_irq(dev)));
|
||||
}
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
@ -61,6 +61,7 @@ static int enable_pcibios = 0;
|
||||
|
||||
TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios);
|
||||
|
||||
static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
|
||||
static int pci_cfgintr_unique(struct PIR_entry *pe, int pin);
|
||||
static int pci_cfgintr_linked(struct PIR_entry *pe, int pin);
|
||||
static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
|
||||
@ -272,7 +273,7 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
|
||||
* anyway, due to the way PCI interrupts are assigned.
|
||||
*/
|
||||
int
|
||||
pci_cfgintr(int bus, int device, int pin)
|
||||
pci_cfgintr(int bus, int device, int pin, int oldirq)
|
||||
{
|
||||
struct PIR_entry *pe;
|
||||
int i, irq;
|
||||
@ -298,7 +299,20 @@ pci_cfgintr(int bus, int device, int pin)
|
||||
i++, pe++) {
|
||||
if ((bus != pe->pe_bus) || (device != pe->pe_device))
|
||||
continue;
|
||||
/*
|
||||
* A link of 0 means that this intpin is not connected to
|
||||
* any other device's interrupt pins and is not connected to
|
||||
* any of the Interrupt Router's interrupt pins, so we can't
|
||||
* route it.
|
||||
*/
|
||||
if (pe->pe_intpin[pin - 1].link == 0)
|
||||
continue;
|
||||
|
||||
if (pci_cfgintr_valid(pe, pin, oldirq)) {
|
||||
printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus,
|
||||
device, 'A' + pin - 1, oldirq);
|
||||
return (oldirq);
|
||||
}
|
||||
irq = pci_cfgintr_linked(pe, pin);
|
||||
if (irq == PCI_INVALID_IRQ)
|
||||
irq = pci_cfgintr_unique(pe, pin);
|
||||
@ -337,6 +351,24 @@ pci_cfgintr(int bus, int device, int pin)
|
||||
return(PCI_INVALID_IRQ);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if an existing IRQ setting is valid.
|
||||
*/
|
||||
static int
|
||||
pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq)
|
||||
{
|
||||
uint32_t irqmask;
|
||||
|
||||
if (!PCI_INTERRUPT_VALID(irq))
|
||||
return (0);
|
||||
irqmask = pe->pe_intpin[pin - 1].irqs;
|
||||
if (irqmask & (1 << irq)) {
|
||||
PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq));
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look to see if the routing table claims this pin is uniquely routed.
|
||||
*/
|
||||
|
@ -61,6 +61,7 @@ static int enable_pcibios = 0;
|
||||
|
||||
TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios);
|
||||
|
||||
static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
|
||||
static int pci_cfgintr_unique(struct PIR_entry *pe, int pin);
|
||||
static int pci_cfgintr_linked(struct PIR_entry *pe, int pin);
|
||||
static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
|
||||
@ -272,7 +273,7 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
|
||||
* anyway, due to the way PCI interrupts are assigned.
|
||||
*/
|
||||
int
|
||||
pci_cfgintr(int bus, int device, int pin)
|
||||
pci_cfgintr(int bus, int device, int pin, int oldirq)
|
||||
{
|
||||
struct PIR_entry *pe;
|
||||
int i, irq;
|
||||
@ -298,7 +299,20 @@ pci_cfgintr(int bus, int device, int pin)
|
||||
i++, pe++) {
|
||||
if ((bus != pe->pe_bus) || (device != pe->pe_device))
|
||||
continue;
|
||||
/*
|
||||
* A link of 0 means that this intpin is not connected to
|
||||
* any other device's interrupt pins and is not connected to
|
||||
* any of the Interrupt Router's interrupt pins, so we can't
|
||||
* route it.
|
||||
*/
|
||||
if (pe->pe_intpin[pin - 1].link == 0)
|
||||
continue;
|
||||
|
||||
if (pci_cfgintr_valid(pe, pin, oldirq)) {
|
||||
printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus,
|
||||
device, 'A' + pin - 1, oldirq);
|
||||
return (oldirq);
|
||||
}
|
||||
irq = pci_cfgintr_linked(pe, pin);
|
||||
if (irq == PCI_INVALID_IRQ)
|
||||
irq = pci_cfgintr_unique(pe, pin);
|
||||
@ -337,6 +351,24 @@ pci_cfgintr(int bus, int device, int pin)
|
||||
return(PCI_INVALID_IRQ);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if an existing IRQ setting is valid.
|
||||
*/
|
||||
static int
|
||||
pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq)
|
||||
{
|
||||
uint32_t irqmask;
|
||||
|
||||
if (!PCI_INTERRUPT_VALID(irq))
|
||||
return (0);
|
||||
irqmask = pe->pe_intpin[pin - 1].irqs;
|
||||
if (irqmask & (1 << irq)) {
|
||||
PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq));
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look to see if the routing table claims this pin is uniquely routed.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user