summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/pci-pc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/pci-pc.c')
-rw-r--r--arch/i386/kernel/pci-pc.c77
1 files changed, 61 insertions, 16 deletions
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index 8ce187d3f..61d13af55 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -688,7 +688,7 @@ static struct irq_routing_table * __init pcibios_get_irq_routing_table(void)
struct irq_routing_table *rt;
int ret, map;
- if (pci_probe & PCI_NO_IRQ_SCAN)
+ if (!(pci_probe & PCI_BIOS_IRQ_SCAN))
return NULL;
pcibios_irq_page = __get_free_page(GFP_KERNEL);
if (!pcibios_irq_page)
@@ -868,7 +868,30 @@ static void __init pci_fixup_i450nx(struct pci_dev *d)
if (suba < subb)
pci_scan_bus(suba+1, pci_root->ops, NULL); /* Bus B */
}
- pci_probe |= PCI_NO_PEER_FIXUP;
+}
+
+static void __init pci_fixup_rcc(struct pci_dev *d)
+{
+ /*
+ * RCC host bridges -- Find and scan all secondary buses.
+ * Register 0x44 contains first, 0x45 last bus number routed there.
+ */
+ u8 busno;
+ pci_read_config_byte(d, 0x44, &busno);
+ printk("PCI: RCC host bridge: secondary bus %02x\n", busno);
+ pci_scan_bus(busno, pci_root->ops, NULL);
+}
+
+static void __init pci_fixup_compaq(struct pci_dev *d)
+{
+ /*
+ * Compaq host bridges -- Find and scan all secondary buses.
+ * This time registers 0xc8 and 0xc9.
+ */
+ u8 busno;
+ pci_read_config_byte(d, 0xc8, &busno);
+ printk("PCI: Compaq host bridge: secondary bus %02x\n", busno);
+ pci_scan_bus(busno, pci_root->ops, NULL);
}
static void __init pci_fixup_umc_ide(struct pci_dev *d)
@@ -905,6 +928,9 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_HE, pci_fixup_rcc },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_LE, pci_fixup_rcc },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
{ 0 }
@@ -919,6 +945,8 @@ extern int skip_ioapic_setup;
#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
#define PIRQ_VERSION 0x0100
+static struct irq_routing_table *pirq_table;
+
/*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
*/
@@ -974,7 +1002,6 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
*/
if (busmap[i] && pci_scan_bus(i, pci_root->ops, NULL))
printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i);
- pci_probe |= PCI_NO_PEER_FIXUP;
}
/*
@@ -982,7 +1009,7 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
* table, but unfortunately we have to know the interrupt router chip.
*/
-static char * __init pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *rt, int pin)
+static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *rt, int pin, int assign)
{
struct irq_info *q;
struct pci_dev *router;
@@ -1012,9 +1039,9 @@ static char * __init pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_
return NULL;
}
DBG(" -> PIRQ %02x, mask %04x", pirq, mask);
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+ if (!assign || (dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
newirq = 0;
- else for(newirq = 15; newirq && !(mask & (1 << newirq)); newirq--)
+ else for(newirq = 13; newirq && !(mask & (1 << newirq)); newirq--)
;
if (!(router = pci_find_slot(rt->rtr_bus, rt->rtr_devfn))) {
DBG(" -> router not found\n");
@@ -1068,7 +1095,7 @@ static void __init pcibios_fixup_irqs(void)
struct pci_dev *dev;
u8 pin;
- rtable = pcibios_find_irq_routing_table();
+ rtable = pirq_table = pcibios_find_irq_routing_table();
#ifdef CONFIG_PCI_BIOS
if (!rtable && pci_bios_present)
rtable = pcibios_get_irq_routing_table();
@@ -1106,7 +1133,7 @@ static void __init pcibios_fixup_irqs(void)
dev->irq = irq;
}
}
- rtable = NULL; /* Avoid IRQ assignment below */
+ pirq_table = NULL; /* Avoid automatic IRQ assignment */
}
#endif
/*
@@ -1114,10 +1141,10 @@ static void __init pcibios_fixup_irqs(void)
*/
if (dev->irq >= NR_IRQS)
dev->irq = 0;
- if (pin && !dev->irq && rtable && rtable->version) {
- char *msg = pcibios_lookup_irq(dev, rtable, pin);
+ if (pin && !dev->irq && pirq_table) {
+ char *msg = pcibios_lookup_irq(dev, pirq_table, pin, 0);
if (msg)
- printk("PCI: Assigned IRQ %d to device %s [%s]\n", dev->irq, dev->slot_name, msg);
+ printk("PCI: Found IRQ %d for device %s [%s]\n", dev->irq, dev->slot_name, msg);
}
}
@@ -1173,7 +1200,7 @@ void __init pcibios_init(void)
pci_scan_bus(0, ops, NULL);
pcibios_fixup_irqs();
- if (!(pci_probe & PCI_NO_PEER_FIXUP))
+ if (pci_probe & PCI_PEER_FIXUP)
pcibios_fixup_peer_bridges();
pcibios_resource_survey();
@@ -1199,8 +1226,8 @@ char * __init pcibios_setup(char *str)
} else if (!strcmp(str, "nosort")) {
pci_probe |= PCI_NO_SORT;
return NULL;
- } else if (!strcmp(str, "noirq")) {
- pci_probe |= PCI_NO_IRQ_SCAN;
+ } else if (!strcmp(str, "biosirq")) {
+ pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
}
#endif
@@ -1214,8 +1241,8 @@ char * __init pcibios_setup(char *str)
return NULL;
}
#endif
- else if (!strcmp(str, "nopeer")) {
- pci_probe |= PCI_NO_PEER_FIXUP;
+ else if (!strcmp(str, "peer")) {
+ pci_probe |= PCI_PEER_FIXUP;
return NULL;
} else if (!strcmp(str, "rom")) {
pci_probe |= PCI_ASSIGN_ROMS;
@@ -1223,3 +1250,21 @@ char * __init pcibios_setup(char *str)
}
return str;
}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+ int err;
+
+ if ((err = pcibios_enable_resources(dev)) < 0)
+ return err;
+ if (!dev->irq && pirq_table) {
+ u8 pin;
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin) {
+ char *msg = pcibios_lookup_irq(dev, pirq_table, pin, 1);
+ if (msg)
+ printk("PCI: Assigned IRQ %d to device %s [%s]\n", dev->irq, dev->slot_name, msg);
+ }
+ }
+ return 0;
+}