]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
MdeModulePkg PciBusDxe: The PCI Bus Driver is updated to support multiple PCI bus...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumerator.c
index 189ce1360f37d03375f381f1699c0078ef970c13..42065738ed6194a17b19db597b51ab203f56b620 100644 (file)
@@ -158,10 +158,16 @@ PciRootBridgeEnumerator (
 {\r
   EFI_STATUS                        Status;\r
   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3;\r
   UINT8                             SubBusNumber;\r
   UINT8                             StartBusNumber;\r
   UINT8                             PaddedBusRange;\r
   EFI_HANDLE                        RootBridgeHandle;\r
+  UINT8                             Desc;\r
+  UINT64                            AddrLen;\r
+  UINT64                            AddrRangeMin;\r
 \r
   SubBusNumber    = 0;\r
   StartBusNumber  = 0;\r
@@ -191,11 +197,40 @@ PciRootBridgeEnumerator (
     return Status;\r
   }\r
 \r
+  if (Configuration == NULL || Configuration->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  RootBridgeDev->BusNumberRanges = Configuration;\r
+\r
+  //\r
+  // Sort the descriptors in ascending order\r
+  //\r
+  for (Configuration1 = Configuration; Configuration1->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration1++) {\r
+    Configuration2 = Configuration1;\r
+    for (Configuration3 = Configuration1 + 1; Configuration3->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration3++) {\r
+      if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) {\r
+        Configuration2 = Configuration3;\r
+      }\r
+    }\r
+    //\r
+    // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,\r
+    // so only need to swap these two fields.\r
+    //\r
+    if (Configuration2 != Configuration1) {\r
+      AddrRangeMin = Configuration1->AddrRangeMin;\r
+      Configuration1->AddrRangeMin = Configuration2->AddrRangeMin;\r
+      Configuration2->AddrRangeMin = AddrRangeMin;\r
+      \r
+      AddrLen = Configuration1->AddrLen;\r
+      Configuration1->AddrLen = Configuration2->AddrLen;\r
+      Configuration2->AddrLen = AddrLen;\r
+    }\r
+  }\r
+\r
   //\r
   // Get the bus number to start with\r
   //\r
   StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
-  PaddedBusRange  = (UINT8) (Configuration->AddrRangeMax);\r
 \r
   //\r
   // Initialize the subordinate bus number\r
@@ -215,7 +250,7 @@ PciRootBridgeEnumerator (
   //\r
   Status = PciScanBus (\r
             RootBridgeDev,\r
-            (UINT8) (Configuration->AddrRangeMin),\r
+            StartBusNumber,\r
             &SubBusNumber,\r
             &PaddedBusRange\r
             );\r
@@ -228,24 +263,45 @@ PciRootBridgeEnumerator (
   //\r
   // Assign max bus number scanned\r
   //\r
-  Configuration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
 \r
+  Status = PciAllocateBusNumber (RootBridgeDev, SubBusNumber, PaddedBusRange, &SubBusNumber);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }  \r
+\r
+  //\r
+  // Find the bus range which contains the higest bus number, then returns the number of buses\r
+  // that should be decoded.\r
+  //\r
+  while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBusNumber) {\r
+    Configuration++;\r
+  }\r
+  AddrLen = Configuration->AddrLen;\r
+  Configuration->AddrLen = SubBusNumber - Configuration->AddrRangeMin + 1;\r
+\r
+  //\r
+  // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.\r
+  //\r
+  Configuration++;\r
+  Desc = Configuration->Desc;\r
+  Configuration->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+  \r
   //\r
   // Set bus number\r
   //\r
   Status = PciResAlloc->SetBusNumbers (\r
                           PciResAlloc,\r
                           RootBridgeHandle,\r
-                          Configuration\r
+                          RootBridgeDev->BusNumberRanges\r
                           );\r
 \r
-  FreePool (Configuration);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
+  //\r
+  // Restore changed fields\r
+  //\r
+  Configuration->Desc = Desc;\r
+  (Configuration - 1)->AddrLen = AddrLen;\r
+  \r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -351,7 +407,11 @@ PciAssignBusNumber (
         //\r
         // Reserved one bus for cardbus bridge\r
         //\r
-        SecondBus = ++(*SubBusNumber);\r
+        Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+        SecondBus = *SubBusNumber;\r
 \r
         Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
 \r