patch-2.4.0-test9 linux/drivers/pci/pci.c
Next file: linux/drivers/pci/pci.ids
Previous file: linux/drivers/pci/names.c
Back to the patch index
Back to the overall index
- Lines: 227
- Date:
Wed Sep 20 13:34:06 2000
- Orig file:
v2.4.0-test8/linux/drivers/pci/pci.c
- Orig date:
Mon Jun 19 13:42:38 2000
diff -u --recursive --new-file v2.4.0-test8/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
@@ -657,134 +657,89 @@
return child;
}
-/*
- * A CardBus bridge is basically the same as a regular PCI bridge,
- * except we don't scan behind it because it will be changing.
- */
-static int __init pci_scan_cardbus(struct pci_bus *bus, struct pci_dev *dev, int busnr)
-{
- int i;
- unsigned short cr;
- unsigned int buses;
- struct pci_bus *child;
-
- /*
- * Insert it into the tree of buses.
- */
- DBG("Scanning CardBus bridge %s\n", dev->slot_name);
- child = pci_add_new_bus(bus, dev, ++busnr);
-
- for (i = 0; i < 4; i++)
- child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
-
- /*
- * Maybe we'll have another bus behind this one?
- */
- child->subordinate = ++busnr;
- sprintf(child->name, "PCI CardBus #%02x", child->number);
-
- /*
- * Clear all status bits and turn off memory,
- * I/O and master enables.
- */
- pci_read_config_word(dev, PCI_COMMAND, &cr);
- pci_write_config_word(dev, PCI_COMMAND, 0x0000);
- pci_write_config_word(dev, PCI_STATUS, 0xffff);
-
- /*
- * Read the existing primary/secondary/subordinate bus
- * number configuration to determine if the bridge
- * has already been configured by the system. If so,
- * do not modify the configuration, merely note it.
- */
- pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
- if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) {
- child->primary = buses & 0xFF;
- child->secondary = (buses >> 8) & 0xFF;
- child->subordinate = (buses >> 16) & 0xFF;
- child->number = child->secondary;
- if (child->subordinate > busnr)
- busnr = child->subordinate;
- } else {
- /*
- * Configure the bus numbers for this bridge:
- */
- buses &= 0xff000000;
- buses |=
- (((unsigned int)(child->primary) << 0) |
- ((unsigned int)(child->secondary) << 8) |
- ((unsigned int)(child->subordinate) << 16));
- pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
- }
- pci_write_config_word(dev, PCI_COMMAND, cr);
- return busnr;
-}
-
static unsigned int __init pci_do_scan_bus(struct pci_bus *bus);
/*
- * If it's a bridge, scan the bus behind it.
+ * If it's a bridge, configure it and scan the bus behind it.
+ * For CardBus bridges, we don't scan behind as the devices will
+ * be handled by the bridge driver itself.
+ *
+ * We need to process bridges in two passes -- first we scan those
+ * already configured by the BIOS and after we are done with all of
+ * them, we proceed to assigning numbers to the remaining buses in
+ * order to avoid overlaps between old and new bus numbers.
*/
-static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max)
+static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
{
unsigned int buses;
unsigned short cr;
struct pci_bus *child;
+ int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
- /*
- * Insert it into the tree of buses.
- */
- DBG("Scanning behind PCI bridge %s\n", dev->slot_name);
- child = pci_add_new_bus(bus, dev, ++max);
- sprintf(child->name, "PCI Bus #%02x", child->number);
-
- /*
- * Clear all status bits and turn off memory,
- * I/O and master enables.
- */
- pci_read_config_word(dev, PCI_COMMAND, &cr);
- pci_write_config_word(dev, PCI_COMMAND, 0x0000);
- pci_write_config_word(dev, PCI_STATUS, 0xffff);
-
- /*
- * Read the existing primary/secondary/subordinate bus
- * number configuration to determine if the PCI bridge
- * has already been configured by the system. If so,
- * do not modify the configuration, merely note it.
- */
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
- if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) {
- unsigned int cmax;
+ DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass);
+ if ((buses & 0xffffff) && !pcibios_assign_all_busses()) {
+ /*
+ * Bus already configured by firmware, process it in the first
+ * pass and just note the configuration.
+ */
+ if (pass)
+ return max;
+ child = pci_add_new_bus(bus, dev, 0);
child->primary = buses & 0xFF;
child->secondary = (buses >> 8) & 0xFF;
child->subordinate = (buses >> 16) & 0xFF;
child->number = child->secondary;
- cmax = pci_do_scan_bus(child);
- if (cmax > max) max = cmax;
+ if (!is_cardbus) {
+ unsigned int cmax = pci_do_scan_bus(child);
+ if (cmax > max) max = cmax;
+ } else {
+ int i;
+ for (i = 0; i < 4; i++)
+ child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ }
} else {
/*
- * Configure the bus numbers for this bridge:
+ * We need to assign a number to this bus which we always
+ * do in the second pass. We also keep all address decoders
+ * on the bridge disabled during scanning. FIXME: Why?
*/
- buses &= 0xff000000;
- buses |=
- (((unsigned int)(child->primary) << 0) |
- ((unsigned int)(child->secondary) << 8) |
- ((unsigned int)(child->subordinate) << 16));
- pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+ if (!pass)
+ return max;
+ pci_read_config_word(dev, PCI_COMMAND, &cr);
+ pci_write_config_word(dev, PCI_COMMAND, 0x0000);
+ pci_write_config_word(dev, PCI_STATUS, 0xffff);
+ child = pci_add_new_bus(bus, dev, ++max);
+ buses = (buses & 0xff000000)
+ | ((unsigned int)(child->primary) << 0)
+ | ((unsigned int)(child->secondary) << 8)
+ | ((unsigned int)(child->subordinate) << 16);
/*
- * Now we can scan all subordinate buses:
+ * We need to blast all three values with a single write.
*/
- max = pci_do_scan_bus(child);
+ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+ if (!is_cardbus) {
+ /* Now we can scan all subordinate buses... */
+ max = pci_do_scan_bus(child);
+ } else {
+ int i;
+ /*
+ * For CardBus bridges, we leave 4 bus numbers
+ * as cards with a PCI-to-PCI bridge can be
+ * inserted later.
+ */
+ max += 3;
+ for (i = 0; i < 4; i++)
+ child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ }
/*
- * Set the subordinate bus number to its real
- * value:
+ * Set the subordinate bus number to its real value.
*/
child->subordinate = max;
- buses = (buses & 0xff00ffff)
- | ((unsigned int)(child->subordinate) << 16);
- pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+ pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
+ pci_write_config_word(dev, PCI_COMMAND, cr);
}
- pci_write_config_word(dev, PCI_COMMAND, cr);
+ sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
return max;
}
@@ -933,7 +888,7 @@
static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
{
- unsigned int devfn, max;
+ unsigned int devfn, max, pass;
struct list_head *ln;
struct pci_dev *dev, dev0;
@@ -957,17 +912,12 @@
*/
DBG("Fixups for bus %02x\n", bus->number);
pcibios_fixup_bus(bus);
- for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
- dev = pci_dev_b(ln);
- switch (dev->class >> 8) {
- case PCI_CLASS_BRIDGE_PCI:
- max = pci_scan_bridge(bus, dev, max);
- break;
- case PCI_CLASS_BRIDGE_CARDBUS:
- max = pci_scan_cardbus(bus, dev, max);
- break;
+ for (pass=0; pass < 2; pass++)
+ for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+ dev = pci_dev_b(ln);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ max = pci_scan_bridge(bus, dev, max, pass);
}
- }
/*
* We've scanned the bus and so we know all about what's on
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)