]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
MdeModulePkg/PciBus: Do not enable MemWriteAndInvalidate bit for PCIE
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
index f7aea4fd80c8423723e4c3db7bf54f5442f1bdfd..6f3d1bebc6c298fbba88bffa660fff1b0f81fdd0 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   PCI emumeration support functions implementation for PCI Bus module.\r
 \r
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2018, 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
@@ -17,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
@@ -164,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
@@ -324,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
@@ -516,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
@@ -586,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
@@ -1163,9 +1254,11 @@ DetermineDeviceAttribute (
     PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
 \r
     //\r
-    // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
-    //\r
-    PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+    // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL\r
+    // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.\r
+    if (!PciIoDevice->IsPciExp) {\r
+      PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+    }\r
   }\r
 \r
   FastB2BSupport = TRUE;\r
@@ -1250,7 +1343,6 @@ UpdatePciInfo (
 {\r
   EFI_STATUS                        Status;\r
   UINTN                             BarIndex;\r
-  UINTN                             BarEndIndex;\r
   BOOLEAN                           SetFlag;\r
   VOID                              *Configuration;\r
   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
@@ -1258,7 +1350,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
@@ -1266,7 +1358,7 @@ UpdatePciInfo (
     Status = gBS->LocateProtocol (\r
                     &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
                     NULL,\r
-                    (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+                    (VOID **) &gIncompatiblePciDeviceSupport\r
                     );\r
   }\r
   if (Status == EFI_SUCCESS) {\r
@@ -1274,15 +1366,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
@@ -1304,23 +1396,19 @@ UpdatePciInfo (
       break;\r
     }\r
 \r
-    BarIndex    = (UINTN) Ptr->AddrTranslationOffset;\r
-    BarEndIndex = BarIndex;\r
-\r
-    //\r
-    // Update all the bars in the device\r
-    //\r
-    if (BarIndex == PCI_BAR_ALL) {\r
-      BarIndex    = 0;\r
-      BarEndIndex = PCI_MAX_BAR - 1;\r
-    }\r
-\r
-    if (BarIndex > PCI_MAX_BAR) {\r
-      Ptr++;\r
-      continue;\r
-    }\r
+    for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {\r
+      if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&\r
+          (Ptr->AddrTranslationOffset != MAX_UINT8) &&\r
+          (Ptr->AddrTranslationOffset != BarIndex)\r
+          ) {\r
+        //\r
+        // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).\r
+        // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.\r
+        // Comparing against MAX_UINT8 is to keep backward compatibility.\r
+        //\r
+        continue;\r
+      }\r
 \r
-    for (; BarIndex <= BarEndIndex; BarIndex++) {\r
       SetFlag = FALSE;\r
       switch (Ptr->ResType) {\r
       case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
@@ -1330,6 +1418,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
@@ -1354,7 +1474,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
@@ -1370,6 +1490,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
@@ -1388,15 +1510,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
@@ -1415,15 +1537,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
@@ -1674,6 +1796,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
@@ -1706,7 +1829,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