int __init pciauto_bus_scan()

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