+/**
+ * @brief Scan a PCI bus.
+ *
+ * Determine the existence of a given PCI device.
+ *
+ * @param bus pointer to the bus structure
+ * @param devfn to look at
+ *
+ * @return The device structure for hte device (if found)
+ * or the NULL if no device is found.
+ */
+device_t pci_probe_dev(device_t dev, struct bus *bus, unsigned devfn)
+{
+ uint32_t id, class;
+ uint8_t hdr_type;
+
+ /* Detect if a device is present */
+ if (!dev) {
+ struct device dummy;
+ dummy.bus = bus;
+ dummy.path.type = DEVICE_PATH_PCI;
+ dummy.path.u.pci.devfn = devfn;
+ id = pci_read_config32(&dummy, PCI_VENDOR_ID);
+ /* Have we found somthing?
+ * Some broken boards return 0 if a slot is empty.
+ */
+ if ( (id == 0xffffffff) || (id == 0x00000000) ||
+ (id == 0x0000ffff) || (id == 0xffff0000))
+ {
+ printk_spew("PCI: devfn 0x%x, bad id 0x%x\n", devfn, id);
+ return NULL;
+ }
+ dev = alloc_dev(bus, &dummy.path);
+ }
+ else {
+ /* Enable/disable the device. Once we have
+ * found the device specific operations this
+ * operations we will disable the device with
+ * those as well.
+ *
+ * This is geared toward devices that have subfunctions
+ * that do not show up by default.
+ *
+ * If a device is a stuff option on the motherboard
+ * it may be absent and enable_dev must cope.
+ *
+ */
+ /* Run the magice enable sequence for the device */
+ if (dev->chip_ops && dev->chip_ops->enable_dev) {
+ dev->chip_ops->enable_dev(dev);
+ }
+ /* Now read the vendor and device id */
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+
+
+ /* If the device does not have a pci id disable it.
+ * Possibly this is because we have already disabled
+ * the device. But this also handles optional devices
+ * that may not always show up.
+ */
+ /* If the chain is fully enumerated quit */
+ if ( (id == 0xffffffff) || (id == 0x00000000) ||
+ (id == 0x0000ffff) || (id == 0xffff0000))
+ {
+ if (dev->enabled) {
+ printk_info("Disabling static device: %s\n",
+ dev_path(dev));
+ dev->enabled = 0;
+ }
+ return dev;
+ }
+ }
+ /* Read the rest of the pci configuration information */
+ hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
+ class = pci_read_config32(dev, PCI_CLASS_REVISION);
+
+ /* Store the interesting information in the device structure */
+ dev->vendor = id & 0xffff;
+ dev->device = (id >> 16) & 0xffff;
+ dev->hdr_type = hdr_type;
+ /* class code, the upper 3 bytes of PCI_CLASS_REVISION */
+ dev->class = class >> 8;
+
+
+ /* Architectural/System devices always need to
+ * be bus masters.
+ */
+ if ((dev->class >> 16) == PCI_BASE_CLASS_SYSTEM) {
+ dev->command |= PCI_COMMAND_MASTER;
+ }
+ /* Look at the vendor and device id, or at least the
+ * header type and class and figure out which set of
+ * configuration methods to use. Unless we already
+ * have some pci ops.
+ */
+ set_pci_ops(dev);
+
+ /* Now run the magic enable/disable sequence for the device */
+ if (dev->ops && dev->ops->enable) {
+ dev->ops->enable(dev);
+ }
+
+
+ /* Display the device and error if we don't have some pci operations
+ * for it.
+ */
+ printk_debug("%s [%04x/%04x] %s%s\n",
+ dev_path(dev),
+ dev->vendor, dev->device,
+ dev->enabled?"enabled": "disabled",
+ dev->ops?"" : " No operations"
+ );
+
+ return dev;
+}
+
+/**
+ * @brief Scan a PCI bus.
+ *
+ * Determine the existence of devices and bridges on a PCI bus. If there are
+ * bridges on the bus, recursively scan the buses behind the bridges.
+ *
+ * This function is the default scan_bus() method for the root device
+ * 'dev_root'.
+ *