]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
OvmfPkg: PciHostBridgeDxe: look for all root buses
[mirror_edk2.git] / OvmfPkg / PciHostBridgeDxe / PciHostBridge.c
index 7dda75f0d3ea03c2fefb3aba1cc385052271bb3b..348664438d4a2ace26211e5a9c4b7a9ae2faa204 100644 (file)
@@ -43,14 +43,6 @@ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
   }\r
 };\r
 \r
-//\r
-// Hard code: Root Bridge's resource aperture\r
-//\r
-\r
-PCI_ROOT_BRIDGE_RESOURCE_APERTURE  mResAperture[1] = {\r
-  {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}\r
-};\r
-\r
 EFI_HANDLE mDriverImageHandle;\r
 \r
 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {\r
@@ -80,8 +72,15 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
 \r
   param[in]  RootBusNumber     The bus number of the root bus (root bridge) to\r
                                create.\r
-                               RootBusNumber is expected to fall into the valid\r
-                               offset range of mResAperture.\r
+\r
+  param[in]  MaxSubBusNumber   The inclusive maximum bus number that can be\r
+                               assigned to any subordinate bus found behind any\r
+                               PCI bridge hanging off this root bus.\r
+\r
+                               The caller is repsonsible for ensuring that\r
+                               RootBusNumber <= MaxSubBusNumber. If\r
+                               RootBusNumber equals MaxSubBusNumber, then the\r
+                               root bus has no room for subordinate buses.\r
 \r
   param[in]  HostBridgeHandle  The EFI_HANDLE corresponding to the host bridge\r
                                that is the parent of the root bridge to create.\r
@@ -108,12 +107,16 @@ STATIC
 EFI_STATUS\r
 InitRootBridge (\r
   IN  UINT8                    RootBusNumber,\r
+  IN  UINT8                    MaxSubBusNumber,\r
   IN  EFI_HANDLE               HostBridgeHandle,\r
   OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus\r
   )\r
 {\r
-  PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
-  EFI_STATUS               Status;\r
+  PCI_ROOT_BRIDGE_INSTANCE          *PrivateData;\r
+  PCI_ROOT_BRIDGE_RESOURCE_APERTURE ResAperture;\r
+  EFI_STATUS                        Status;\r
+\r
+  ASSERT (RootBusNumber <= MaxSubBusNumber);\r
 \r
   PrivateData = AllocateZeroPool (sizeof *PrivateData);\r
   if (PrivateData == NULL) {\r
@@ -126,13 +129,18 @@ InitRootBridge (
     sizeof mRootBridgeDevicePathTemplate);\r
   PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;\r
 \r
+  ResAperture.BusBase  = RootBusNumber;\r
+  ResAperture.BusLimit = MaxSubBusNumber;\r
+  ResAperture.MemBase  = BASE_2GB;\r
+  ResAperture.MemLimit = BASE_4GB - 1;\r
+  ResAperture.IoBase   = 0;\r
+  ResAperture.IoLimit  = MAX_UINT16;\r
   //\r
   // The function call below allocates no resources and performs no actions\r
   // that have to be rolled back on later failure. It always succeeds.\r
   //\r
   Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,\r
-             EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,\r
-             &mResAperture[RootBusNumber]);\r
+             EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM, &ResAperture);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,\r
@@ -143,6 +151,9 @@ InitRootBridge (
     goto FreePrivateData;\r
   }\r
 \r
+  DEBUG ((EFI_D_INFO,\r
+    "%a: installed root bus %d, with room for %d subordinate bus(es)\n",\r
+    __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));\r
   *RootBus = PrivateData;\r
   return EFI_SUCCESS;\r
 \r
@@ -196,6 +207,7 @@ InitializePciHostBridge (
   )\r
 {\r
   EFI_STATUS                  Status;\r
+  UINTN                       LastRootBridgeNumber;\r
   UINTN                       RootBridgeNumber;\r
   PCI_HOST_BRIDGE_INSTANCE    *HostBridge;\r
   PCI_ROOT_BRIDGE_INSTANCE    *RootBus;\r
@@ -224,20 +236,55 @@ InitializePciHostBridge (
     goto FreeHostBridge;\r
   }\r
 \r
-  for (RootBridgeNumber = 0;\r
-       RootBridgeNumber < 1;\r
+  //\r
+  // The "main" root bus is always there.\r
+  //\r
+  LastRootBridgeNumber = 0;\r
+\r
+  //\r
+  // Scan all other root buses. If function 0 of any device on a bus returns a\r
+  // VendorId register value different from all-bits-one, then that bus is\r
+  // alive.\r
+  //\r
+  for (RootBridgeNumber = 1;\r
+       RootBridgeNumber < 256;\r
        ++RootBridgeNumber) {\r
-    Status = InitRootBridge (\r
-               (UINT8)RootBridgeNumber,\r
-               HostBridge->HostBridgeHandle,\r
-               &RootBus\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      goto RollbackProtocols;\r
+    UINTN Device;\r
+\r
+    for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) {\r
+      if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,\r
+                       PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {\r
+        break;\r
+      }\r
+    }\r
+    if (Device <= MAX_PCI_DEVICE_NUMBER) {\r
+      //\r
+      // Found the next root bus. We can now install the *previous* one,\r
+      // because now we know how big a bus number range *that* one has, for any\r
+      // subordinate buses that might exist behind PCI bridges hanging off it.\r
+      //\r
+      Status = InitRootBridge ((UINT8)LastRootBridgeNumber,\r
+                 (UINT8)(RootBridgeNumber - 1), HostBridge->HostBridgeHandle,\r
+                 &RootBus);\r
+      if (EFI_ERROR (Status)) {\r
+        goto RollbackProtocols;\r
+      }\r
+      InsertTailList (&HostBridge->Head, &RootBus->Link);\r
+      LastRootBridgeNumber = RootBridgeNumber;\r
     }\r
-    InsertTailList (&HostBridge->Head, &RootBus->Link);\r
   }\r
 \r
+  //\r
+  // Install the last root bus (which might be the only, ie. main, root bus, if\r
+  // we've found no extra root buses).\r
+  //\r
+  Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255,\r
+             HostBridge->HostBridgeHandle, &RootBus);\r
+  if (EFI_ERROR (Status)) {\r
+    goto RollbackProtocols;\r
+  }\r
+  InsertTailList (&HostBridge->Head, &RootBus->Link);\r
+\r
   return EFI_SUCCESS;\r
 \r
 RollbackProtocols:\r