in lib/pci-auto.c [223:316]
int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
{
int sub_bus, pci_devfn, pci_class, cmdstat, found_multi=0;
unsigned short vid;
unsigned char header_type;
struct pci_dev *dev = &pciauto_dev;
pciauto_dev.bus = &pciauto_bus;
pciauto_dev.sysdata = pci_ctrl;
pciauto_bus.ops = pci_ctrl->ops;
/*
* Fetch our I/O and memory space upper boundaries used
* to allocated base addresses on this pci_controller.
*/
if (current_bus == pci_ctrl->first_busno)
{
pciauto_upper_iospc = pci_ctrl->io_resource.end + 1;
pciauto_upper_memspc = pci_ctrl->mem_resources[0].end + 1;
}
sub_bus = current_bus;
for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++)
{
/* Skip our host bridge */
if ((current_bus == pci_ctrl->first_busno) && (pci_devfn == 0))
continue;
if (PCI_FUNC(pci_devfn) && !found_multi)
continue;
pciauto_bus.number = current_bus;
pciauto_dev.devfn = pci_devfn;
/* If config space read fails from this device, move on */
if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type))
continue;
if (!PCI_FUNC(pci_devfn))
found_multi = header_type & 0x80;
pci_read_config_word(dev, PCI_VENDOR_ID, &vid);
if (vid == 0xffff || vid == 0x0000) {
found_multi = 0;
continue;
}
pci_read_config_dword(dev, PCI_CLASS_REVISION, &pci_class);
if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
int iosave, memsave;
pr_debug("PCI Autoconfig: Found P2P bridge, device %d\n",
PCI_SLOT(pci_devfn));
/* Allocate PCI I/O and/or memory space */
pciauto_setup_bars(dev, PCI_BASE_ADDRESS_1);
pciauto_prescan_setup_bridge(dev, current_bus, sub_bus,
&iosave, &memsave);
sub_bus = pciauto_bus_scan(pci_ctrl, sub_bus+1);
pciauto_postscan_setup_bridge(dev, current_bus, sub_bus,
&iosave, &memsave);
pciauto_bus.number = current_bus;
continue;
}
/*
* Found a peripheral, enable some standard
* settings
*/
pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
pci_write_config_dword(dev, PCI_COMMAND,
cmdstat |
PCI_COMMAND_IO |
PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
/* Allocate PCI I/O and/or memory space */
pr_debug("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
pciauto_setup_bars(dev, PCI_BASE_ADDRESS_5);
pciauto_setup_irq(pci_ctrl, dev, pci_devfn);
}
return sub_bus;
}