- 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:
John Baldwin 2002-09-06 17:08:07 +00:00
parent d04c7d51be
commit 8ab96fd8d0
7 changed files with 105 additions and 7 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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.
*/

View File

@ -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);

View File

@ -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;

View File

@ -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.
*/

View File

@ -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.
*/