]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
MdeModulePkg/PciBus: Fix a bug PPB MEM32 BAR isn't restored sometimes
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
index e93134613b488aad1b8c4fa5069500760769d562..70e45040e2efb2777f3386c59f0a620e06302d91 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
-  PCI resouces support functions implemntation for PCI Bus module.\r
+  PCI resources support functions implementation for PCI Bus module.\r
 \r
-Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<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
@@ -134,11 +134,11 @@ InsertResourceNode (
 \r
 /**\r
   This routine is used to merge two different resource trees in need of\r
-  resoure degradation.\r
+  resource degradation.\r
 \r
   For example, if an upstream PPB doesn't support,\r
   prefetchable memory decoding, the PCI bus driver will choose to call this function\r
-  to merge prefectchable memory resource list into normal memory list.\r
+  to merge prefetchable memory resource list into normal memory list.\r
 \r
   If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
   type.\r
@@ -335,7 +335,7 @@ CalculateApertureIo16 (
   This function is used to calculate the resource aperture\r
   for a given bridge device.\r
 \r
-  @param Bridge      PCI resouce node for given bridge device.\r
+  @param Bridge      PCI resource node for given bridge device.\r
 \r
 **/\r
 VOID\r
@@ -343,14 +343,9 @@ CalculateResourceAperture (
   IN PCI_RESOURCE_NODE    *Bridge\r
   )\r
 {\r
-  UINT64            Aperture;\r
+  UINT64            Aperture[2];\r
   LIST_ENTRY        *CurrentLink;\r
   PCI_RESOURCE_NODE *Node;\r
-  UINT64            PaddingAperture;\r
-  UINT64            Offset;\r
-\r
-  Aperture        = 0;\r
-  PaddingAperture = 0;\r
 \r
   if (Bridge == NULL) {\r
     return ;\r
@@ -362,6 +357,8 @@ CalculateResourceAperture (
     return ;\r
   }\r
 \r
+  Aperture[PciResUsageTypical] = 0;\r
+  Aperture[PciResUsagePadding] = 0;\r
   //\r
   // Assume the bridge is aligned\r
   //\r
@@ -369,58 +366,42 @@ CalculateResourceAperture (
       ; !IsNull (&Bridge->ChildList, CurrentLink)\r
       ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)\r
       ) {\r
-\r
     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-    if (Node->ResourceUsage == PciResUsagePadding) {\r
-      ASSERT (PaddingAperture == 0);\r
-      PaddingAperture = Node->Length;\r
-      continue;\r
-    }\r
 \r
     //\r
-    // Apply padding resource if available\r
+    // It's possible for a bridge to contain multiple padding resource\r
+    // nodes due to DegradeResource().\r
     //\r
-    Offset = Aperture & (Node->Alignment);\r
-\r
-    if (Offset != 0) {\r
-\r
-      Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
-\r
-    }\r
-\r
+    ASSERT ((Node->ResourceUsage == PciResUsageTypical) ||\r
+            (Node->ResourceUsage == PciResUsagePadding));\r
+    ASSERT (Node->ResourceUsage < ARRAY_SIZE (Aperture));\r
     //\r
     // Recode current aperture as a offset\r
-    // this offset will be used in future real allocation\r
+    // Apply padding resource to meet alignment requirement\r
+    // Node offset will be used in future real allocation\r
     //\r
-    Node->Offset = Aperture;\r
+    Node->Offset = ALIGN_VALUE (Aperture[Node->ResourceUsage], Node->Alignment + 1);\r
 \r
     //\r
-    // Increment aperture by the length of node\r
+    // Record the total aperture.\r
     //\r
-    Aperture += Node->Length;\r
+    Aperture[Node->ResourceUsage] = Node->Offset + Node->Length;\r
   }\r
 \r
   //\r
-  // At last, adjust the aperture with the bridge's\r
-  // alignment\r
+  // Adjust the aperture with the bridge's alignment\r
   //\r
-  Offset = Aperture & (Bridge->Alignment);\r
-  if (Offset != 0) {\r
-    Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
-  }\r
+  Aperture[PciResUsageTypical] = ALIGN_VALUE (Aperture[PciResUsageTypical], Bridge->Alignment + 1);\r
+  Aperture[PciResUsagePadding] = ALIGN_VALUE (Aperture[PciResUsagePadding], Bridge->Alignment + 1);\r
 \r
   //\r
-  // If the bridge has already padded the resource and the\r
-  // amount of padded resource is larger, then keep the\r
-  // padded resource\r
+  // Hotplug controller needs padding resources.\r
+  // Use the larger one between the padding resource and actual occupied resource.\r
   //\r
-  if (Bridge->Length < Aperture) {\r
-    Bridge->Length = Aperture;\r
-  }\r
+  Bridge->Length = MAX (Aperture[PciResUsageTypical], Aperture[PciResUsagePadding]);\r
 \r
   //\r
-  // Adjust the bridge's alignment to the first child's alignment\r
-  // if the bridge has at least one child\r
+  // Adjust the bridge's alignment to the MAX (first) alignment of all children.\r
   //\r
   CurrentLink = Bridge->ChildList.ForwardLink;\r
   if (CurrentLink != &Bridge->ChildList) {\r
@@ -429,16 +410,10 @@ CalculateResourceAperture (
       Bridge->Alignment = Node->Alignment;\r
     }\r
   }\r
-\r
-  //\r
-  // Hotplug controller needs padding resources.\r
-  // Use the larger one between the padding resource and actual occupied resource.\r
-  //\r
-  Bridge->Length = MAX (Bridge->Length, PaddingAperture);\r
 }\r
 \r
 /**\r
-  Get IO/Memory resource infor for given PCI device.\r
+  Get IO/Memory resource info for given PCI device.\r
 \r
   @param PciDev     Pci device instance.\r
   @param IoNode     Resource info node for IO .\r
@@ -471,13 +446,14 @@ GetResourceFromDevice (
     switch ((PciDev->PciBar)[Index].BarType) {\r
 \r
     case PciBarTypeMem32:\r
+    case PciBarTypeOpRom:\r
 \r
       Node = CreateResourceNode (\r
               PciDev,\r
               (PciDev->PciBar)[Index].Length,\r
               (PciDev->PciBar)[Index].Alignment,\r
               Index,\r
-              PciBarTypeMem32,\r
+              (PciDev->PciBar)[Index].BarType,\r
               PciResUsageTypical\r
               );\r
 \r
@@ -856,7 +832,7 @@ CreateResourceMap (
                        );\r
 \r
       //\r
-      // Recursively create resouce map on this bridge\r
+      // Recursively create resource map on this bridge\r
       //\r
       CreateResourceMap (\r
         Temp,\r
@@ -1141,7 +1117,7 @@ DegradeResource (
         PMem64Node,\r
         TRUE\r
         );\r
-    } \r
+    }\r
 \r
     //\r
     // if both PMEM64 and PMEM32 requests from child devices, which can not be satisfied\r
@@ -1219,10 +1195,10 @@ BridgeSupportResourceDecode (
   This function is used to program the resource allocated\r
   for each resource node under specified bridge.\r
 \r
-  @param Base     Base address of resource to be progammed.\r
+  @param Base     Base address of resource to be programmed.\r
   @param Bridge   PCI resource node for the bridge device.\r
 \r
-  @retval EFI_SUCCESS            Successfully to program all resouces\r
+  @retval EFI_SUCCESS            Successfully to program all resources\r
                                  on given PCI bridge device.\r
   @retval EFI_OUT_OF_RESOURCES   Base is all one.\r
 \r
@@ -1281,8 +1257,8 @@ ProgramResource (
 /**\r
   Program Bar register for PCI device.\r
 \r
-  @param Base  Base address for PCI device resource to be progammed.\r
-  @param Node  Point to resoure node structure.\r
+  @param Base  Base address for PCI device resource to be programmed.\r
+  @param Node  Point to resource node structure.\r
 \r
 **/\r
 VOID\r
@@ -1332,7 +1308,13 @@ ProgramBar (
                  1,\r
                  &Address\r
                  );\r
+  //\r
+  // Continue to the case PciBarTypeOpRom to set the BaseAddress.\r
+  // PciBarTypeOpRom is a virtual BAR only in root bridge, to capture\r
+  // the MEM32 resource requirement for Option ROM shadow.\r
+  //\r
 \r
+  case PciBarTypeOpRom:\r
     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
 \r
     break;\r
@@ -1372,8 +1354,8 @@ ProgramBar (
 /**\r
   Program IOV VF Bar register for PCI device.\r
 \r
-  @param Base  Base address for PCI device resource to be progammed.\r
-  @param Node  Point to resoure node structure.\r
+  @param Base  Base address for PCI device resource to be programmed.\r
+  @param Node  Point to resource node structure.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1456,10 +1438,10 @@ ProgramVfBar (
 }\r
 \r
 /**\r
-  Program PCI-PCI bridge apperture.\r
+  Program PCI-PCI bridge aperture.\r
 \r
   @param Base  Base address for resource.\r
-  @param Node  Point to resoure node structure.\r
+  @param Node  Point to resource node structure.\r
 \r
 **/\r
 VOID\r
@@ -1475,7 +1457,7 @@ ProgramPpbApperture (
   Address = 0;\r
   //\r
   // If no device resource of this PPB, return anyway\r
-  // Apperture is set default in the initialization code\r
+  // Aperture is set default in the initialization code\r
   //\r
   if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
     //\r
@@ -1667,45 +1649,64 @@ ProgramPpbApperture (
 /**\r
   Program parent bridge for Option Rom.\r
 \r
-  @param PciDevice      Pci deivce instance.\r
-  @param OptionRomBase  Base address for Optiona Rom.\r
+  @param PciDevice      Pci device instance.\r
+  @param OptionRomBase  Base address for Option Rom.\r
   @param Enable         Enable or disable PCI memory.\r
 \r
 **/\r
 VOID\r
-ProgrameUpstreamBridgeForRom (\r
+ProgramUpstreamBridgeForRom (\r
   IN PCI_IO_DEVICE   *PciDevice,\r
   IN UINT32          OptionRomBase,\r
   IN BOOLEAN         Enable\r
   )\r
 {\r
-  PCI_IO_DEVICE     *Parent;\r
-  PCI_RESOURCE_NODE Node;\r
+  PCI_IO_DEVICE       *Parent;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT16              Base;\r
+  UINT16              Limit;\r
   //\r
   // For root bridge, just return.\r
   //\r
   Parent = PciDevice->Parent;\r
-  ZeroMem (&Node, sizeof (Node));\r
   while (Parent != NULL) {\r
     if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
       break;\r
     }\r
 \r
-    Node.PciDev     = Parent;\r
-    Node.Length     = PciDevice->RomSize;\r
-    Node.Alignment  = 0;\r
-    Node.Bar        = PPB_MEM32_RANGE;\r
-    Node.ResType    = PciBarTypeMem32;\r
-    Node.Offset     = 0;\r
+    PciIo = &Parent->PciIo;\r
 \r
     //\r
-    // Program PPB to only open a single <= 16MB apperture\r
+    // Program PPB to only open a single <= 16MB aperture\r
     //\r
     if (Enable) {\r
-      ProgramPpbApperture (OptionRomBase, &Node);\r
+      //\r
+      // Only cover MMIO for Option ROM.\r
+      //\r
+      Base  = (UINT16) (OptionRomBase >> 16);\r
+      Limit = (UINT16) ((OptionRomBase + PciDevice->RomSize - 1) >> 16);\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);\r
+\r
       PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
     } else {\r
-      InitializePpb (Parent);\r
+      //\r
+      // Cover 32bit MMIO for devices below the bridge.\r
+      //\r
+      if (Parent->PciBar[PPB_MEM32_RANGE].Length == 0) {\r
+        //\r
+        // When devices under the bridge contains Option ROM and doesn't require 32bit MMIO.\r
+        //\r
+        Base  = (UINT16) gAllOne;\r
+        Limit = (UINT16) gAllZero;\r
+      } else {\r
+        Base  = (UINT16) ((UINT32) Parent->PciBar[PPB_MEM32_RANGE].BaseAddress >> 16);\r
+        Limit = (UINT16) ((UINT32) (Parent->PciBar[PPB_MEM32_RANGE].BaseAddress\r
+                                    + Parent->PciBar[PPB_MEM32_RANGE].Length - 1) >> 16);\r
+      }\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);\r
+\r
       PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
     }\r
 \r
@@ -1757,7 +1758,7 @@ InitializeResourcePool (
 }\r
 \r
 /**\r
-  Destory given resource tree.\r
+  Destroy given resource tree.\r
 \r
   @param Bridge  PCI resource root node of resource tree.\r
 \r
@@ -1814,7 +1815,7 @@ ResourcePaddingForCardBusBridge (
 \r
   //\r
   // Memory Base/Limit Register 0\r
-  // Bar 1 denodes memory range 0\r
+  // Bar 1 decodes memory range 0\r
   //\r
   Node = CreateResourceNode (\r
            PciDev,\r
@@ -1832,7 +1833,7 @@ ResourcePaddingForCardBusBridge (
 \r
   //\r
   // Memory Base/Limit Register 1\r
-  // Bar 2 denodes memory range1\r
+  // Bar 2 decodes memory range1\r
   //\r
   Node = CreateResourceNode (\r
            PciDev,\r
@@ -1850,7 +1851,7 @@ ResourcePaddingForCardBusBridge (
 \r
   //\r
   // Io Base/Limit\r
-  // Bar 3 denodes io range 0\r
+  // Bar 3 decodes io range 0\r
   //\r
   Node = CreateResourceNode (\r
            PciDev,\r
@@ -1868,7 +1869,7 @@ ResourcePaddingForCardBusBridge (
 \r
   //\r
   // Io Base/Limit\r
-  // Bar 4 denodes io range 0\r
+  // Bar 4 decodes io range 0\r
   //\r
   Node = CreateResourceNode (\r
            PciDev,\r
@@ -1972,7 +1973,7 @@ ProgramP2C (
 \r
     } else {\r
       //\r
-      // Set pre-fetchable bit\r
+      // Set prefetchable bit\r
       //\r
       PciIo->Pci.Read (\r
                    PciIo,\r
@@ -2042,7 +2043,7 @@ ProgramP2C (
     } else {\r
 \r
       //\r
-      // Set pre-fetchable bit\r
+      // Set prefetchable bit\r
       //\r
       PciIo->Pci.Read (\r
                    PciIo,\r
@@ -2175,7 +2176,7 @@ ApplyResourcePadding (
       if (Ptr->AddrSpaceGranularity == 32) {\r
 \r
         //\r
-        // prefechable\r
+        // prefetchable\r
         //\r
         if (Ptr->SpecificFlag == 0x6) {\r
           if (Ptr->AddrLen != 0) {\r
@@ -2198,7 +2199,7 @@ ApplyResourcePadding (
         }\r
 \r
         //\r
-        // Non-prefechable\r
+        // Non-prefetchable\r
         //\r
         if (Ptr->SpecificFlag == 0) {\r
           if (Ptr->AddrLen != 0) {\r
@@ -2224,7 +2225,7 @@ ApplyResourcePadding (
       if (Ptr->AddrSpaceGranularity == 64) {\r
 \r
         //\r
-        // prefechable\r
+        // prefetchable\r
         //\r
         if (Ptr->SpecificFlag == 0x6) {\r
           if (Ptr->AddrLen != 0) {\r
@@ -2247,7 +2248,7 @@ ApplyResourcePadding (
         }\r
 \r
         //\r
-        // Non-prefechable\r
+        // Non-prefetchable\r
         //\r
         if (Ptr->SpecificFlag == 0) {\r
           if (Ptr->AddrLen != 0) {\r