]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: PciHostBridgeDxe: look for all root buses
authorLaszlo Ersek <lersek@redhat.com>
Tue, 14 Jul 2015 12:02:29 +0000 (12:02 +0000)
committerlersek <lersek@Edk2>
Tue, 14 Jul 2015 12:02:29 +0000 (12:02 +0000)
In this patch we assume that root bus number 0 is always there (same as
before), and scan the rest of the extra root buses, up to and including
255. When an extra root bus is found, we install the PCI root bridge IO
protocol for the previous root bus (which might be bus 0 or just the
previous extra root bus).

The root bridge protocol created thus will report the available bus number
range

  [own bus number, next extra root bus number - 1]

The LHS of this interval will be used for the root bus's own number, and
the rest of the interval (which might encompass 0 additional elements too)
can be used by the PCI bus driver to assign subordinate bus numbers from.

(Subordinate buses are provided by PCI bridges that hang off the root bus
in question.)

For MMIO and IO space allocation, all the root buses share the original
[0x8000_0000, 0xFFFF_FFFF] and [0x0, 0xFFFF] ranges, respectively.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17962 6f19259b-4bc3-4df7-8a09-765794883524

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