]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
MdeModulePkg: Clean ACPI 2.0 characters in UEFI spec
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciRootBridgeIo.c
index dbb415ac2d6e12764c33ffa6af4e78bf68ca8c78..dc06c16dc038d2f397547ce8af2d87e492a09750 100644 (file)
@@ -2,7 +2,7 @@
 \r
   PCI Root Bridge Io Protocol code.\r
 \r
-Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 1999 - 2017, 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
@@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "PciRootBridge.h"\r
 #include "PciHostResource.h"\r
 \r
+extern EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;\r
+\r
 #define NO_MAPPING  (VOID *) (UINTN) -1\r
 \r
 //\r
@@ -59,20 +61,19 @@ UINT8 mOutStride[] = {
   Construct the Pci Root Bridge instance.\r
 \r
   @param Bridge            The root bridge instance.\r
-  @param HostBridgeHandle  Handle to the HostBridge.\r
 \r
   @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created\r
           or NULL if creation fails.\r
 **/\r
 PCI_ROOT_BRIDGE_INSTANCE *\r
 CreateRootBridge (\r
-  IN PCI_ROOT_BRIDGE       *Bridge,\r
-  IN EFI_HANDLE            HostBridgeHandle\r
+  IN PCI_ROOT_BRIDGE       *Bridge\r
   )\r
 {\r
   PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
   PCI_RESOURCE_TYPE        Index;\r
   CHAR16                   *DevicePathStr;\r
+  PCI_ROOT_BRIDGE_APERTURE *Aperture;\r
 \r
   DevicePathStr = NULL;\r
 \r
@@ -120,32 +121,37 @@ CreateRootBridge (
     }\r
   }\r
 \r
-  if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
-    //\r
-    // If this bit is set, then the PCI Root Bridge does not\r
-    // support separate windows for Non-prefetchable and Prefetchable\r
-    // memory.\r
-    //\r
-    ASSERT (Bridge->PMem.Base > Bridge->PMem.Limit);\r
-    ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit);\r
-    if ((Bridge->PMem.Base <= Bridge->PMem.Limit) ||\r
-        (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit)\r
-        ) {\r
-      return NULL;\r
+  //\r
+  // Ignore AllocationAttributes when resources were already assigned.\r
+  //\r
+  if (!Bridge->ResourceAssigned) {\r
+    if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
+      //\r
+      // If this bit is set, then the PCI Root Bridge does not\r
+      // support separate windows for Non-prefetchable and Prefetchable\r
+      // memory.\r
+      //\r
+      ASSERT (Bridge->PMem.Base > Bridge->PMem.Limit);\r
+      ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit);\r
+      if ((Bridge->PMem.Base <= Bridge->PMem.Limit) ||\r
+          (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit)\r
+          ) {\r
+        return NULL;\r
+      }\r
     }\r
-  }\r
 \r
-  if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
-    //\r
-    // If this bit is not set, then the PCI Root Bridge does not support\r
-    // 64 bit memory windows.\r
-    //\r
-    ASSERT (Bridge->MemAbove4G.Base > Bridge->MemAbove4G.Limit);\r
-    ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit);\r
-    if ((Bridge->MemAbove4G.Base <= Bridge->MemAbove4G.Limit) ||\r
-        (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit)\r
-        ) {\r
-      return NULL;\r
+    if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
+      //\r
+      // If this bit is not set, then the PCI Root Bridge does not support\r
+      // 64 bit memory windows.\r
+      //\r
+      ASSERT (Bridge->MemAbove4G.Base > Bridge->MemAbove4G.Limit);\r
+      ASSERT (Bridge->PMemAbove4G.Base > Bridge->PMemAbove4G.Limit);\r
+      if ((Bridge->MemAbove4G.Base <= Bridge->MemAbove4G.Limit) ||\r
+          (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit)\r
+          ) {\r
+        return NULL;\r
+      }\r
     }\r
   }\r
 \r
@@ -174,14 +180,43 @@ CreateRootBridge (
   CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
 \r
   for (Index = TypeIo; Index < TypeMax; Index++) {\r
-    RootBridge->ResAllocNode[Index].Type   = Index;\r
-    RootBridge->ResAllocNode[Index].Base   = 0;\r
-    RootBridge->ResAllocNode[Index].Length = 0;\r
-    RootBridge->ResAllocNode[Index].Status = ResNone;\r
+    switch (Index) {\r
+    case TypeBus:\r
+      Aperture = &RootBridge->Bus;\r
+      break;\r
+    case TypeIo:\r
+      Aperture = &RootBridge->Io;\r
+      break;\r
+    case TypeMem32:\r
+      Aperture = &RootBridge->Mem;\r
+      break;\r
+    case TypeMem64:\r
+      Aperture = &RootBridge->MemAbove4G;\r
+      break;\r
+    case TypePMem32:\r
+      Aperture = &RootBridge->PMem;\r
+      break;\r
+    case TypePMem64:\r
+      Aperture = &RootBridge->PMemAbove4G;\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      Aperture = NULL;\r
+      break;\r
+    }\r
+    RootBridge->ResAllocNode[Index].Type     = Index;\r
+    if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) {\r
+      RootBridge->ResAllocNode[Index].Base   = Aperture->Base;\r
+      RootBridge->ResAllocNode[Index].Length = Aperture->Limit - Aperture->Base + 1;\r
+      RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
+    } else {\r
+      RootBridge->ResAllocNode[Index].Base   = 0;\r
+      RootBridge->ResAllocNode[Index].Length = 0;\r
+      RootBridge->ResAllocNode[Index].Status = ResNone;\r
+    }\r
   }\r
 \r
   RootBridge->RootBridgeIo.SegmentNumber  = Bridge->Segment;\r
-  RootBridge->RootBridgeIo.ParentHandle   = HostBridgeHandle;\r
   RootBridge->RootBridgeIo.PollMem        = RootBridgeIoPollMem;\r
   RootBridge->RootBridgeIo.PollIo         = RootBridgeIoPollIo;\r
   RootBridge->RootBridgeIo.Mem.Read       = RootBridgeIoMemRead;\r
@@ -1039,11 +1074,36 @@ RootBridgeIoMap (
 \r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
+  if (mIoMmuProtocol != NULL) {\r
+    if (!RootBridge->DmaAbove4G) {\r
+      //\r
+      // Clear 64bit support\r
+      //\r
+      if (Operation > EfiPciOperationBusMasterCommonBuffer) {\r
+        Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64);\r
+      }\r
+    }\r
+    Status = mIoMmuProtocol->Map (\r
+                               mIoMmuProtocol,\r
+                               (EDKII_IOMMU_OPERATION) Operation,\r
+                               HostAddress,\r
+                               NumberOfBytes,\r
+                               DeviceAddress,\r
+                               Mapping\r
+                               );\r
+    return Status;\r
+  }\r
+\r
   PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
-  if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
+  if ((!RootBridge->DmaAbove4G ||\r
+       (Operation != EfiPciOperationBusMasterRead64 &&\r
+        Operation != EfiPciOperationBusMasterWrite64 &&\r
+        Operation != EfiPciOperationBusMasterCommonBuffer64)) &&\r
+      ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
+\r
     //\r
-    // If the root bridge can not handle performing DMA above 4GB but\r
-    // any part of the DMA transfer being mapped is above 4GB, then\r
+    // If the root bridge or the device cannot handle performing DMA above\r
+    // 4GB but any part of the DMA transfer being mapped is above 4GB, then\r
     // map the DMA transfer to a buffer below 4GB.\r
     //\r
 \r
@@ -1156,8 +1216,18 @@ RootBridgeIoUnmap (
   MAP_INFO                 *MapInfo;\r
   LIST_ENTRY               *Link;\r
   PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+  EFI_STATUS                Status;\r
+\r
+  if (mIoMmuProtocol != NULL) {\r
+    Status = mIoMmuProtocol->Unmap (\r
+                               mIoMmuProtocol,\r
+                               Mapping\r
+                               );\r
+    return Status;\r
+  }\r
 \r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
   //\r
   // See if the Map() operation associated with this Unmap() required a mapping\r
   // buffer. If a mapping buffer was not required, then this function simply\r
@@ -1274,8 +1344,27 @@ RootBridgeIoAllocateBuffer (
 \r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
+  if (mIoMmuProtocol != NULL) {\r
+    if (!RootBridge->DmaAbove4G) {\r
+      //\r
+      // Clear DUAL_ADDRESS_CYCLE\r
+      //\r
+      Attributes &= ~((UINT64) EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE);\r
+    }\r
+    Status = mIoMmuProtocol->AllocateBuffer (\r
+                               mIoMmuProtocol,\r
+                               Type,\r
+                               MemoryType,\r
+                               Pages,\r
+                               HostAddress,\r
+                               Attributes\r
+                               );\r
+    return Status;\r
+  }\r
+\r
   AllocateType = AllocateAnyPages;\r
-  if (!RootBridge->DmaAbove4G) {\r
+  if (!RootBridge->DmaAbove4G ||\r
+      (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {\r
     //\r
     // Limit allocations to memory below 4GB\r
     //\r
@@ -1317,6 +1406,17 @@ RootBridgeIoFreeBuffer (
   OUT VOID                             *HostAddress\r
   )\r
 {\r
+  EFI_STATUS                Status;\r
+\r
+  if (mIoMmuProtocol != NULL) {\r
+    Status = mIoMmuProtocol->FreeBuffer (\r
+                               mIoMmuProtocol,\r
+                               Pages,\r
+                               HostAddress\r
+                               );\r
+    return Status;\r
+  }\r
+\r
   return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
 }\r
 \r
@@ -1460,20 +1560,19 @@ RootBridgeIoSetAttributes (
 \r
 /**\r
   Retrieves the current resource settings of this PCI root bridge in the form\r
-  of a set of ACPI 2.0 resource descriptors.\r
+  of a set of ACPI resource descriptors.\r
 \r
   There are only two resource descriptor types from the ACPI Specification that\r
   may be used to describe the current resources allocated to a PCI root bridge.\r
-  These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),\r
-  and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space\r
-  Descriptor can describe memory, I/O, and bus number ranges for dynamic or\r
-  fixed resources. The configuration of a PCI root bridge is described with one\r
-  or more QWORD Address Space Descriptors followed by an End Tag.\r
+  These are the QWORD Address Space Descriptor, and the End Tag. The QWORD\r
+  Address Space Descriptor can describe memory, I/O, and bus number ranges for\r
+  dynamic or fixed resources. The configuration of a PCI root bridge is described\r
+  with one or more QWORD Address Space Descriptors followed by an End Tag.\r
 \r
   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
-  @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that\r
+  @param[out]  Resources   A pointer to the resource descriptors that\r
                            describe the current configuration of this PCI root\r
-                           bridge. The storage for the ACPI 2.0 resource\r
+                           bridge. The storage for the resource\r
                            descriptors is allocated by this function. The\r
                            caller must treat the return buffer as read-only\r
                            data, and the buffer must not be freed by the\r