]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
MdeModulePkg/SdMmcPciHcDxe: Do not map memory for non DMA transfer
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciPei / DmaMem.c
index 71d61138bcad1ad06c2e481fad1ddfbf760ee8b9..c4d93aea25708fe97a3fbcf90a9ac3e269e08409 100644 (file)
@@ -224,6 +224,134 @@ IoMmuFreeBuffer (
   return Status;\r
 }\r
 \r
+/**\r
+  Allocates aligned pages that are suitable for an OperationBusMasterCommonBuffer or\r
+  OperationBusMasterCommonBuffer64 mapping.\r
+\r
+  @param  Pages                 The number of pages to allocate.\r
+  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.\r
+  @param  HostAddress           A pointer to store the base system memory address of the\r
+                                allocated range.\r
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to\r
+                                access the hosts HostAddress.\r
+  @param  Mapping               A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were allocated.\r
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are\r
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+IoMmuAllocateAlignedBuffer (\r
+  IN UINTN                  Pages,\r
+  IN UINTN                  Alignment,\r
+  OUT VOID                  **HostAddress,\r
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,\r
+  OUT VOID                  **Mapping\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  VOID                  *Memory;\r
+  UINTN                 AlignedMemory;\r
+  UINTN                 AlignmentMask;\r
+  UINTN                 UnalignedPages;\r
+  UINTN                 RealPages;\r
+  UINTN                 NumberOfBytes;\r
+  EFI_PHYSICAL_ADDRESS  HostPhyAddress;\r
+\r
+  *HostAddress   = NULL;\r
+  *DeviceAddress = 0;\r
+  AlignmentMask  = Alignment - 1;\r
+\r
+  //\r
+  // Calculate the total number of pages since alignment is larger than page size.\r
+  //\r
+  RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
+\r
+  //\r
+  // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
+  //\r
+  ASSERT (RealPages > Pages);\r
+\r
+  if (mIoMmu != NULL) {\r
+    Status = mIoMmu->AllocateBuffer (\r
+                       mIoMmu,\r
+                       EfiBootServicesData,\r
+                       RealPages,\r
+                       HostAddress,\r
+                       0\r
+                       );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Memory         = *HostAddress;\r
+    AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
+    UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
+    if (UnalignedPages > 0) {\r
+      //\r
+      // Free first unaligned page(s).\r
+      //\r
+      Status = mIoMmu->FreeBuffer (\r
+                         mIoMmu,\r
+                         UnalignedPages,\r
+                         Memory);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+    Memory         = (VOID *)(UINTN)(AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
+    UnalignedPages = RealPages - Pages - UnalignedPages;\r
+    if (UnalignedPages > 0) {\r
+      //\r
+      // Free last unaligned page(s).\r
+      //\r
+      Status = mIoMmu->FreeBuffer (\r
+                         mIoMmu,\r
+                         UnalignedPages,\r
+                         Memory);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+    *HostAddress  = (VOID *) AlignedMemory;\r
+    NumberOfBytes = EFI_PAGES_TO_SIZE(Pages);\r
+    Status = mIoMmu->Map (\r
+                       mIoMmu,\r
+                       EdkiiIoMmuOperationBusMasterCommonBuffer,\r
+                       *HostAddress,\r
+                       &NumberOfBytes,\r
+                       DeviceAddress,\r
+                       Mapping\r
+                       );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    Status = mIoMmu->SetAttribute (\r
+                       mIoMmu,\r
+                       *Mapping,\r
+                       EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
+                       );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  } else {\r
+    Status = PeiServicesAllocatePages (\r
+               EfiBootServicesData,\r
+               RealPages,\r
+               &HostPhyAddress\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    *HostAddress = (VOID *)(((UINTN) HostPhyAddress + AlignmentMask) & ~AlignmentMask);\r
+    *DeviceAddress = ((UINTN) HostPhyAddress + AlignmentMask) & ~AlignmentMask;\r
+    *Mapping = NULL;\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Initialize IOMMU.\r
 **/\r