+
+/**
+ * Detect the type of downstream bridge.
+ *
+ * This function is a heuristic to detect which type of bus is downstream
+ * of a PCI-to-PCI bridge. This functions by looking for various capability
+ * blocks to figure out the type of downstream bridge. PCI-X, PCI-E, and
+ * Hypertransport all seem to have appropriate capabilities.
+ *
+ * When only a PCI-Express capability is found the type is examined to see
+ * which type of bridge we have.
+ *
+ * @param dev Pointer to the device structure of the bridge.
+ * @return Appropriate bridge operations.
+ */
+static struct device_operations *get_pci_bridge_ops(device_t dev)
+{
+ unsigned int pos;
+
+#if CONFIG_PCIX_PLUGIN_SUPPORT == 1
+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (pos) {
+ printk(BIOS_DEBUG, "%s subordinate bus PCI-X\n", dev_path(dev));
+ return &default_pcix_ops_bus;
+ }
+#endif
+#if CONFIG_AGP_PLUGIN_SUPPORT == 1
+ /* How do I detect a PCI to AGP bridge? */
+#endif
+#if CONFIG_HYPERTRANSPORT_PLUGIN_SUPPORT == 1
+ pos = 0;
+ while ((pos = pci_find_next_capability(dev, PCI_CAP_ID_HT, pos))) {
+ u16 flags;
+ flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
+ if ((flags >> 13) == 1) {
+ /* Host or Secondary Interface */
+ printk(BIOS_DEBUG, "%s subordinate bus HT\n",
+ dev_path(dev));
+ return &default_ht_ops_bus;
+ }
+ }
+#endif
+#if CONFIG_PCIEXP_PLUGIN_SUPPORT == 1
+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIE);
+ if (pos) {
+ u16 flags;
+ flags = pci_read_config16(dev, pos + PCI_EXP_FLAGS);
+ switch ((flags & PCI_EXP_FLAGS_TYPE) >> 4) {
+ case PCI_EXP_TYPE_ROOT_PORT:
+ case PCI_EXP_TYPE_UPSTREAM:
+ case PCI_EXP_TYPE_DOWNSTREAM:
+ printk(BIOS_DEBUG, "%s subordinate bus PCI Express\n",
+ dev_path(dev));
+ return &default_pciexp_ops_bus;
+ case PCI_EXP_TYPE_PCI_BRIDGE:
+ printk(BIOS_DEBUG, "%s subordinate PCI\n",
+ dev_path(dev));
+ return &default_pci_ops_bus;
+ default:
+ break;
+ }
+ }
+#endif
+ return &default_pci_ops_bus;
+}
+
+/**
+ * Set up PCI device operation.
+ *
+ * Check if it already has a driver. If not, use find_device_operations(),
+ * or set to a default based on type.
+ *
+ * @param dev Pointer to the device whose pci_ops you want to set.
+ * @see pci_drivers
+ */