]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c
MdeModulePkg/UfsBlockIoPei: Support IoMmu
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsBlockIoPei / UfsHci.c
index 1ef6c8878bf9875e5f882f91d06cbe1835b0945d..55c780627966d53c0b7f2cecb2eb0bacf1c410a8 100644 (file)
@@ -407,6 +407,9 @@ UfsInitQueryRequestUpiu (
 \r
   if (Opcode == UtpQueryFuncOpcodeWrDesc) {\r
     CopyMem (QueryReq + 1, Data, DataSize);\r
+\r
+    SwapLittleEndianToBigEndian ((UINT8*)&DataSize, sizeof (UINT16));\r
+    QueryReq->DataSegLen = (UINT16)DataSize;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -419,6 +422,7 @@ UfsInitQueryRequestUpiu (
   @param[in]  Lun               The Lun on which the SCSI command is executed.\r
   @param[in]  Packet            The pointer to the UFS_SCSI_REQUEST_PACKET data structure.\r
   @param[in]  Trd               The pointer to the UTP Transfer Request Descriptor.\r
+  @param[out] BufferMap         A resulting value, if not NULL, to pass to IoMmuUnmap().\r
 \r
   @retval EFI_SUCCESS           The creation succeed.\r
   @retval EFI_DEVICE_ERROR      The creation failed.\r
@@ -427,10 +431,11 @@ UfsInitQueryRequestUpiu (
 **/\r
 EFI_STATUS\r
 UfsCreateScsiCommandDesc (\r
-  IN  UFS_PEIM_HC_PRIVATE_DATA            *Private,\r
-  IN  UINT8                               Lun,\r
-  IN  UFS_SCSI_REQUEST_PACKET             *Packet,\r
-  IN  UTP_TRD                             *Trd\r
+  IN     UFS_PEIM_HC_PRIVATE_DATA         *Private,\r
+  IN     UINT8                            Lun,\r
+  IN     UFS_SCSI_REQUEST_PACKET          *Packet,\r
+  IN     UTP_TRD                          *Trd,\r
+     OUT VOID                             **BufferMap\r
   )\r
 {\r
   UINT8                    *CommandDesc;\r
@@ -441,21 +446,37 @@ UfsCreateScsiCommandDesc (
   UTP_COMMAND_UPIU         *CommandUpiu;\r
   UTP_TR_PRD               *PrdtBase;\r
   UFS_DATA_DIRECTION       DataDirection;\r
+  EFI_STATUS               Status;\r
+  EDKII_IOMMU_OPERATION    MapOp;\r
+  UINTN                    MapLength;\r
+  EFI_PHYSICAL_ADDRESS     BufferPhyAddr;\r
 \r
   ASSERT ((Private != NULL) && (Packet != NULL) && (Trd != NULL));\r
 \r
+  BufferPhyAddr = 0;\r
+\r
   if (Packet->DataDirection == UfsDataIn) {\r
-    Buffer = Packet->InDataBuffer;\r
-    Length = Packet->InTransferLength;\r
+    Buffer        = Packet->InDataBuffer;\r
+    Length        = Packet->InTransferLength;\r
     DataDirection = UfsDataIn;\r
+    MapOp         = EdkiiIoMmuOperationBusMasterWrite;\r
   } else {\r
     Buffer = Packet->OutDataBuffer;\r
     Length = Packet->OutTransferLength;\r
     DataDirection = UfsDataOut;\r
+    MapOp         = EdkiiIoMmuOperationBusMasterRead;\r
   }\r
 \r
   if (Length == 0) {\r
     DataDirection = UfsNoData;\r
+  } else {\r
+    MapLength = Length;\r
+    Status = IoMmuMap (MapOp, Buffer, &MapLength, &BufferPhyAddr, BufferMap);\r
+\r
+    if (EFI_ERROR (Status) || (MapLength != Length)) {\r
+      DEBUG ((DEBUG_ERROR, "UfsCreateScsiCommandDesc: Fail to map data buffer.\n"));\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
   }\r
 \r
   PrdtNumber = (UINTN)DivU64x32 ((UINT64)Length + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);\r
@@ -470,7 +491,7 @@ UfsCreateScsiCommandDesc (
   PrdtBase     = (UTP_TR_PRD*)(CommandDesc + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
 \r
   UfsInitCommandUpiu (CommandUpiu, Lun, Private->TaskTag++, Packet->Cdb, Packet->CdbLength, DataDirection, Length);\r
-  UfsInitUtpPrdt (PrdtBase, Buffer, Length);\r
+  UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)BufferPhyAddr, Length);\r
 \r
   //\r
   // Fill UTP_TRD associated fields\r
@@ -1283,6 +1304,7 @@ UfsExecScsiCmds (
   UTP_RESPONSE_UPIU                    *Response;\r
   UINT16                               SenseDataLen;\r
   UINT32                               ResTranCount;\r
+  VOID                                 *PacketBufferMap;\r
 \r
   //\r
   // Find out which slot of transfer request list is available.\r
@@ -1293,11 +1315,12 @@ UfsExecScsiCmds (
   }\r
 \r
   Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
+  PacketBufferMap = NULL;\r
 \r
   //\r
   // Fill transfer request descriptor to this slot.\r
   //\r
-  Status = UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd);\r
+  Status = UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd, &PacketBufferMap);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -1359,6 +1382,9 @@ UfsExecScsiCmds (
   }\r
 \r
 Exit:\r
+  if (PacketBufferMap != NULL) {\r
+    IoMmuUnmap (PacketBufferMap);\r
+  }\r
   UfsStopExecCmd (Private, Slot);\r
   UfsPeimFreeMem (Private->Pool, CmdDescBase, CmdDescSize);\r
 \r
@@ -1584,7 +1610,9 @@ UfsInitTaskManagementRequestList (
   UINTN                  Address;\r
   UINT32                 Data;\r
   UINT8                  Nutmrs;\r
-  EFI_PHYSICAL_ADDRESS   Buffer;\r
+  VOID                   *CmdDescHost;\r
+  EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;\r
+  VOID                   *CmdDescMapping;\r
   EFI_STATUS             Status;\r
   \r
   //\r
@@ -1598,28 +1626,29 @@ UfsInitTaskManagementRequestList (
   // Allocate and initialize UTP Task Management Request List.\r
   //\r
   Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);\r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesCode,\r
+  Status = IoMmuAllocateBuffer (\r
              EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD)),\r
-             &Buffer\r
+             &CmdDescHost,\r
+             &CmdDescPhyAddr,\r
+             &CmdDescMapping\r
              );\r
-\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  ZeroMem ((VOID*)(UINTN)Buffer, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD))));\r
+  ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD))));\r
 \r
   //\r
   // Program the UTP Task Management Request List Base Address and UTP Task Management\r
   // Request List Base Address with a 64-bit address allocated at step 6.\r
   //\r
   Address = Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)(UINTN)Buffer);\r
+  MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
   Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32));\r
-  Private->UtpTmrlBase = (VOID*)(UINTN)Buffer;\r
+  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  Private->UtpTmrlBase = (VOID*)(UINTN)CmdDescHost;\r
   Private->Nutmrs      = Nutmrs;\r
+  Private->TmrlMapping = CmdDescMapping;\r
 \r
   //\r
   // Enable the UTP Task Management Request List by setting the UTP Task Management\r
@@ -1648,7 +1677,9 @@ UfsInitTransferRequestList (
   UINTN                  Address;\r
   UINT32                 Data;\r
   UINT8                  Nutrs;\r
-  EFI_PHYSICAL_ADDRESS   Buffer;\r
+  VOID                   *CmdDescHost;\r
+  EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;\r
+  VOID                   *CmdDescMapping;\r
   EFI_STATUS             Status;\r
   \r
   //\r
@@ -1662,28 +1693,29 @@ UfsInitTransferRequestList (
   // Allocate and initialize UTP Transfer Request List.\r
   //\r
   Nutrs  = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesCode,\r
+  Status = IoMmuAllocateBuffer (\r
              EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD)),\r
-             &Buffer\r
+             &CmdDescHost,\r
+             &CmdDescPhyAddr,\r
+             &CmdDescMapping\r
              );\r
-\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  ZeroMem ((VOID*)(UINTN)Buffer, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD))));\r
+  ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD))));\r
 \r
   //\r
   // Program the UTP Transfer Request List Base Address and UTP Transfer Request List\r
   // Base Address with a 64-bit address allocated at step 8.\r
   //\r
   Address = Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)(UINTN)Buffer);\r
+  MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
   Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32));\r
-  Private->UtpTrlBase = (VOID*)(UINTN)Buffer;\r
+  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  Private->UtpTrlBase = (VOID*)(UINTN)CmdDescHost;\r
   Private->Nutrs      = Nutrs;\r
+  Private->TrlMapping = CmdDescMapping;\r
   \r
   //\r
   // Enable the UTP Transfer Request List by setting the UTP Transfer Request List\r
@@ -1732,6 +1764,16 @@ UfsControllerInit (
   Status = UfsInitTransferRequestList (Private);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "UfsDevicePei: Transfer list initialization Fails, Status = %r\n", Status));\r
+\r
+    if (Private->TmrlMapping != NULL) {\r
+      IoMmuFreeBuffer (\r
+        EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)),\r
+        Private->UtpTmrlBase,\r
+        Private->TmrlMapping\r
+        );\r
+      Private->TmrlMapping = NULL;\r
+    }\r
+\r
     return Status;\r
   }\r
 \r