]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
MdeModulePkg/PciBus: Accept Spec values as BarIndex and Alignment
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
index 9e7ac74eb70c331f56c57f035953435fce8b877f..ecda088814a3c846f17615876314f8036b2de2ca 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   PCI emumeration support functions implementation for PCI Bus module.\r
 \r
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -16,6 +17,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 extern CHAR16  *mBarTypeStr[];\r
 \r
+#define OLD_ALIGN   0xFFFFFFFFFFFFFFFFULL\r
+#define EVEN_ALIGN  0xFFFFFFFFFFFFFFFEULL\r
+#define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL\r
+#define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL\r
+\r
 /**\r
   This routine is used to check whether the pci device is present.\r
 \r
@@ -119,6 +125,14 @@ PciPciDeviceInfoCollector (
                  (UINT8) Device,\r
                  (UINT8) Func\r
                  );\r
+\r
+      if (EFI_ERROR (Status) && Func == 0) {\r
+        //\r
+        // go to next device if there is no Function 0\r
+        //\r
+        break;\r
+      }\r
+\r
       if (!EFI_ERROR (Status)) {\r
 \r
         //\r
@@ -155,6 +169,14 @@ PciPciDeviceInfoCollector (
             return Status;\r
           }\r
 \r
+          //\r
+          // Ensure secondary bus number is greater than the primary bus number to avoid\r
+          // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE\r
+          //\r
+          if (SecBus <= StartBusNumber) {\r
+            break;\r
+          }\r
+\r
           //\r
           // Get resource padding for PPB\r
           //\r
@@ -315,6 +337,81 @@ PciSearchDevice (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Dump the PPB padding resource information.\r
+\r
+  @param PciIoDevice     PCI IO instance.\r
+  @param ResourceType    The desired resource type to dump.\r
+                         PciBarTypeUnknown means to dump all types of resources.\r
+**/\r
+VOID\r
+DumpPpbPaddingResource (\r
+  IN PCI_IO_DEVICE                    *PciIoDevice,\r
+  IN PCI_BAR_TYPE                     ResourceType\r
+  )\r
+{\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+  PCI_BAR_TYPE                      Type;\r
+\r
+  if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
+    return;\r
+  }\r
+\r
+  if (ResourceType == PciBarTypeIo16 || ResourceType == PciBarTypeIo32) {\r
+    ResourceType = PciBarTypeIo;\r
+  }\r
+\r
+  for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {\r
+\r
+    Type = PciBarTypeUnknown;\r
+    if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
+      Type = PciBarTypeIo;\r
+    } else if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+\r
+      if (Descriptor->AddrSpaceGranularity == 32) {\r
+        //\r
+        // prefechable\r
+        //\r
+        if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {\r
+          Type = PciBarTypePMem32;\r
+        }\r
+\r
+        //\r
+        // Non-prefechable\r
+        //\r
+        if (Descriptor->SpecificFlag == 0) {\r
+          Type = PciBarTypeMem32;\r
+        }\r
+      }\r
+\r
+      if (Descriptor->AddrSpaceGranularity == 64) {\r
+        //\r
+        // prefechable\r
+        //\r
+        if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {\r
+          Type = PciBarTypePMem64;\r
+        }\r
+\r
+        //\r
+        // Non-prefechable\r
+        //\r
+        if (Descriptor->SpecificFlag == 0) {\r
+          Type = PciBarTypeMem64;\r
+        }\r
+      }\r
+    }\r
+\r
+    if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {\r
+      DEBUG ((\r
+        EFI_D_INFO,\r
+        "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",\r
+        mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen\r
+        ));\r
+    }\r
+  }\r
+\r
+}\r
+\r
 /**\r
   Dump the PCI BAR information.\r
 \r
@@ -507,14 +604,14 @@ GatherPpbInfo (
 \r
   //\r
   // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes\r
-  // PCI bridge supporting non-stardard I/O window alignment less than 4K.\r
+  // PCI bridge supporting non-standard I/O window alignment less than 4K.\r
   //\r
 \r
   PciIoDevice->BridgeIoAlignment = 0xFFF;\r
   if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {\r
     //\r
     // Check any bits of bit 3-1 of I/O Base Register are writable.\r
-    // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.\r
+    // if so, it is assumed non-standard I/O window alignment is supported by this bridge.\r
     // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.\r
     //\r
     Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));\r
@@ -577,7 +674,10 @@ GatherPpbInfo (
 \r
   GetResourcePaddingPpb (PciIoDevice);\r
 \r
-  DEBUG_CODE (DumpPciBars (PciIoDevice););\r
+  DEBUG_CODE (\r
+    DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);\r
+    DumpPciBars (PciIoDevice);\r
+  );\r
 \r
   return PciIoDevice;\r
 }\r
@@ -1240,8 +1340,8 @@ UpdatePciInfo (
   )\r
 {\r
   EFI_STATUS                        Status;\r
-  UINT                            BarIndex;\r
-  UINT                            BarEndIndex;\r
+  UINT64                            BarIndex;\r
+  UINT64                            BarEndIndex;\r
   BOOLEAN                           SetFlag;\r
   VOID                              *Configuration;\r
   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
@@ -1249,7 +1349,7 @@ UpdatePciInfo (
   Configuration = NULL;\r
   Status        = EFI_SUCCESS;\r
 \r
-  if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
+  if (gIncompatiblePciDeviceSupport == NULL) {\r
     //\r
     // It can only be supported after the Incompatible PCI Device\r
     // Support Protocol has been installed\r
@@ -1257,7 +1357,7 @@ UpdatePciInfo (
     Status = gBS->LocateProtocol (\r
                     &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
                     NULL,\r
-                    (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+                    (VOID **) &gIncompatiblePciDeviceSupport\r
                     );\r
   }\r
   if (Status == EFI_SUCCESS) {\r
@@ -1265,15 +1365,15 @@ UpdatePciInfo (
       // Check whether the device belongs to incompatible devices from protocol or not\r
       // If it is , then get its special requirement in the ACPI table\r
       //\r
-      Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
-                                                   gEfiIncompatiblePciDeviceSupport,\r
-                                                   PciIoDevice->Pci.Hdr.VendorId,\r
-                                                   PciIoDevice->Pci.Hdr.DeviceId,\r
-                                                   PciIoDevice->Pci.Hdr.RevisionID,\r
-                                                   PciIoDevice->Pci.Device.SubsystemVendorID,\r
-                                                   PciIoDevice->Pci.Device.SubsystemID,\r
-                                                   &Configuration\r
-                                                   );\r
+      Status = gIncompatiblePciDeviceSupport->CheckDevice (\r
+                                                gIncompatiblePciDeviceSupport,\r
+                                                PciIoDevice->Pci.Hdr.VendorId,\r
+                                                PciIoDevice->Pci.Hdr.DeviceId,\r
+                                                PciIoDevice->Pci.Hdr.RevisionID,\r
+                                                PciIoDevice->Pci.Device.SubsystemVendorID,\r
+                                                PciIoDevice->Pci.Device.SubsystemID,\r
+                                                &Configuration\r
+                                                );\r
 \r
   }\r
 \r
@@ -1295,18 +1395,19 @@ UpdatePciInfo (
       break;\r
     }\r
 \r
-    BarIndex    = (UINTN) Ptr->AddrTranslationOffset;\r
+    BarIndex    = Ptr->AddrTranslationOffset;\r
     BarEndIndex = BarIndex;\r
 \r
     //\r
     // Update all the bars in the device\r
+    // Compare against 0xFF is to keep backward compatibility.\r
     //\r
-    if (BarIndex == PCI_BAR_ALL) {\r
+    if ((BarIndex == MAX_UINT64) || (BarIndex == 0xFF)) {\r
       BarIndex    = 0;\r
       BarEndIndex = PCI_MAX_BAR - 1;\r
     }\r
 \r
-    if (BarIndex > PCI_MAX_BAR) {\r
+    if (BarIndex >= PCI_MAX_BAR) {\r
       Ptr++;\r
       continue;\r
     }\r
@@ -1321,6 +1422,38 @@ UpdatePciInfo (
         //\r
         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
           SetFlag = TRUE;\r
+\r
+          //\r
+          // Ignored if granularity is 0.\r
+          // Ignored if PCI BAR is I/O or 32-bit memory.\r
+          // If PCI BAR is 64-bit memory and granularity is 32, then\r
+          // the PCI BAR resource is allocated below 4GB.\r
+          // If PCI BAR is 64-bit memory and granularity is 64, then\r
+          // the PCI BAR resource is allocated above 4GB.\r
+          //\r
+          if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {\r
+            switch (Ptr->AddrSpaceGranularity) {\r
+            case 32:\r
+              PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
+            case 64:\r
+              PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;\r
+              break;\r
+            default:\r
+              break;\r
+            }\r
+          }\r
+\r
+          if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {\r
+            switch (Ptr->AddrSpaceGranularity) {\r
+            case 32:\r
+              PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
+            case 64:\r
+              PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;\r
+              break;\r
+            default:\r
+              break;\r
+            }\r
+          }\r
         }\r
         break;\r
 \r
@@ -1345,7 +1478,7 @@ UpdatePciInfo (
         //\r
         // Update the new length for the device\r
         //\r
-        if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
+        if (Ptr->AddrLen != 0) {\r
           PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
         }\r
       }\r
@@ -1361,6 +1494,8 @@ UpdatePciInfo (
 \r
 /**\r
   This routine will update the alignment with the new alignment.\r
+  Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep\r
+  backward compatibility.\r
 \r
   @param Alignment    Input Old alignment. Output updated alignment.\r
   @param NewAlignment New alignment.\r
@@ -1379,15 +1514,15 @@ SetNewAlign (
   // The new alignment is the same as the original,\r
   // so skip it\r
   //\r
-  if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
+  if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) {\r
     return ;\r
   }\r
   //\r
   // Check the validity of the parameter\r
   //\r
-   if (NewAlignment != PCI_BAR_EVEN_ALIGN  &&\r
-       NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
-       NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
+   if (NewAlignment != EVEN_ALIGN  &&\r
+       NewAlignment != SQUAD_ALIGN &&\r
+       NewAlignment != DQUAD_ALIGN ) {\r
     *Alignment = NewAlignment;\r
     return ;\r
   }\r
@@ -1406,15 +1541,15 @@ SetNewAlign (
   //\r
   // Adjust the alignment to even, quad or double quad boundary\r
   //\r
-  if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
+  if (NewAlignment == EVEN_ALIGN) {\r
     if ((OldAlignment & 0x01) != 0) {\r
       OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
     }\r
-  } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
+  } else if (NewAlignment == SQUAD_ALIGN) {\r
     if ((OldAlignment & 0x03) != 0) {\r
       OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
     }\r
-  } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
+  } else if (NewAlignment == DQUAD_ALIGN) {\r
     if ((OldAlignment & 0x07) != 0) {\r
       OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
     }\r
@@ -1665,6 +1800,7 @@ PciParseBar (
     return Offset + 4;\r
   }\r
 \r
+  PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;\r
   PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
   if ((Value & 0x01) != 0) {\r
     //\r
@@ -1697,7 +1833,6 @@ PciParseBar (
       PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
     }\r
 \r
-    PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;\r
     PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;\r
 \r
   } else {\r
@@ -1770,14 +1905,19 @@ PciParseBar (
           // some device implement MMIO bar with 0 length, need to treat it as no-bar\r
           //\r
           PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+          return Offset + 4;\r
         }\r
-        return Offset + 4;\r
       }\r
 \r
       //\r
       // Fix the length to support some spefic 64 bit BAR\r
       //\r
-      Value |= ((UINT32)(-1) << HighBitSet32 (Value));\r
+      if (Value == 0) {\r
+        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));\r
+        Value = (UINT32) -1;\r
+      } else {\r
+        Value |= ((UINT32)(-1) << HighBitSet32 (Value));\r
+      }\r
 \r
       //\r
       // Calculate the size of 64bit bar\r
@@ -2592,6 +2732,13 @@ ResetAllPpbBusNumber (
                  Func\r
                  );\r
 \r
+      if (EFI_ERROR (Status) && Func == 0) {\r
+        //\r
+        // go to next device if there is no Function 0\r
+        //\r
+        break;\r
+      }\r
+\r
       if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
 \r
         Register  = 0;\r