/** @file\r
\r
- Copyright (c) 2014 - 2016, 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
- http://opensource.org/licenses/bsd-license.php.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
break;\r
case 0x08:\r
DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));\r
- break; \r
+ break;\r
case 0x09:\r
DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BUSY\n"));\r
break;\r
case 0x0A:\r
DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - DME_FAILURE\n"));\r
- break; \r
+ break;\r
default :\r
ASSERT (FALSE);\r
break;\r
break;\r
case 0x01:\r
DEBUG ((EFI_D_VERBOSE, "UIC control command fails - FAILURE\n"));\r
- break; \r
+ break;\r
default :\r
ASSERT (FALSE);\r
break;\r
break;\r
case 0xFE:\r
DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Opcode\n"));\r
- break; \r
+ break;\r
case 0xFF:\r
DEBUG ((EFI_D_VERBOSE, "Query Response with General Failure\n"));\r
break;\r
SwapLittleEndianToBigEndian ((UINT8*)&Length, sizeof (Length));\r
TsfBase->Length = Length;\r
}\r
- \r
+\r
if (Opcode == UtpQueryFuncOpcodeWrAttr) {\r
SwapLittleEndianToBigEndian ((UINT8*)&Value, sizeof (Value));\r
TsfBase->Value = Value;\r
\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
@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
**/\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
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
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
Trd->Int = UFS_INTERRUPT_COMMAND;\r
Trd->Dd = DataDirection;\r
Trd->Ct = UFS_STORAGE_COMMAND_TYPE;\r
+ Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;\r
Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)(UINTN)CommandUpiu, 7);\r
Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)(UINTN)CommandUpiu, 32);\r
Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)), sizeof (UINT32));\r
Trd->Int = UFS_INTERRUPT_COMMAND;\r
Trd->Dd = DataDirection;\r
Trd->Ct = UFS_STORAGE_COMMAND_TYPE;\r
- Trd->Ocs = 0x0F;\r
+ Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;\r
Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)(UINTN)QueryReqUpiu, 7);\r
Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)(UINTN)QueryReqUpiu, 32);\r
if (Opcode == UtpQueryFuncOpcodeWrDesc) {\r
Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)), sizeof (UINT32));\r
- Trd->RuO = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));\r
+ Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));\r
} else {\r
- Trd->RuL = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));\r
+ Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));\r
Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)), sizeof (UINT32));\r
}\r
\r
Trd->Int = UFS_INTERRUPT_COMMAND;\r
Trd->Dd = 0x00;\r
Trd->Ct = UFS_STORAGE_COMMAND_TYPE;\r
+ Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;\r
Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)(UINTN)NopOutUpiu, 7);\r
Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)(UINTN)NopOutUpiu, 32);\r
Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU)), sizeof (UINT32));\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Find out available slot in task management transfer list of a UFS device.\r
\r
- @param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.\r
- @param[out] Slot The available slot.\r
-\r
- @retval EFI_SUCCESS The available slot was found successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsFindAvailableSlotInTmrl (\r
- IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
- OUT UINT8 *Slot\r
- )\r
-{\r
- ASSERT ((Private != NULL) && (Slot != NULL));\r
-\r
- //\r
- // The simplest algo to always use slot 0.\r
- // TODO: enhance it to support async transfer with multiple slot.\r
- //\r
- *Slot = 0;\r
-\r
- return EFI_SUCCESS;\r
-}\r
\r
/**\r
Start specified slot in transfer list of a UFS device.\r
UfsStartExecCmd (\r
IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
IN UINT8 Slot\r
- ) \r
+ )\r
{\r
UINTN UfsHcBase;\r
UINTN Address;\r
\r
UfsHcBase = Private->UfsHcBase;\r
\r
- Address = UfsHcBase + UFS_HC_UTRLRSR_OFFSET; \r
+ Address = UfsHcBase + UFS_HC_UTRLRSR_OFFSET;\r
Data = MmioRead32 (Address);\r
if ((Data & UFS_HC_UTRLRSR) != UFS_HC_UTRLRSR) {\r
MmioWrite32 (Address, UFS_HC_UTRLRSR);\r
UfsStopExecCmd (\r
IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
IN UINT8 Slot\r
- ) \r
+ )\r
{\r
UINTN UfsHcBase;\r
UINTN Address;\r
\r
UfsHcBase = Private->UfsHcBase;\r
\r
- Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET; \r
+ Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
Data = MmioRead32 (Address);\r
if ((Data & (BIT0 << Slot)) != 0) {\r
- Address = UfsHcBase + UFS_HC_UTRLCLR_OFFSET; \r
+ Address = UfsHcBase + UFS_HC_UTRLCLR_OFFSET;\r
Data = MmioRead32 (Address);\r
MmioWrite32 (Address, (Data & ~(BIT0 << Slot)));\r
}\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
//\r
// Fill transfer request descriptor to this slot.\r
\r
//\r
// Wait for the completion of the transfer request.\r
- // \r
- Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; \r
- Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);\r
+ //\r
+ Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
+ Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, Packet.Timeout);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
\r
if (Read) {\r
+ //\r
+ // Make sure the hardware device does not return more data than expected.\r
+ //\r
+ if (ReturnDataSize > Packet.InTransferLength) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
CopyMem (Packet.InDataBuffer, (QueryResp + 1), ReturnDataSize);\r
Packet.InTransferLength = ReturnDataSize;\r
} else {\r
return Status;\r
}\r
\r
-/**\r
- Read or write specified attribute of a UFS device.\r
\r
- @param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.\r
- @param[in] Read The boolean variable to show r/w direction.\r
- @param[in] AttrId The ID of Attribute.\r
- @param[in] Index The Index of Attribute.\r
- @param[in] Selector The Selector of Attribute.\r
- @param[in, out] Attributes The value of Attribute to be read or written.\r
-\r
- @retval EFI_SUCCESS The Attribute was read/written successfully.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsRwAttributes (\r
- IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
- IN BOOLEAN Read,\r
- IN UINT8 AttrId,\r
- IN UINT8 Index,\r
- IN UINT8 Selector,\r
- IN OUT UINT32 *Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
- UINT8 Slot;\r
- UTP_TRD *Trd;\r
- UINTN Address;\r
- UTP_QUERY_RESP_UPIU *QueryResp;\r
- UINT8 *CmdDescBase;\r
- UINT32 CmdDescSize;\r
- UINT32 ReturnData;\r
-\r
- ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
-\r
- if (Read) {\r
- Packet.DataDirection = UfsDataIn;\r
- Packet.Opcode = UtpQueryFuncOpcodeRdAttr;\r
- } else {\r
- Packet.DataDirection = UfsDataOut;\r
- Packet.Opcode = UtpQueryFuncOpcodeWrAttr;\r
- }\r
- Packet.DescId = AttrId;\r
- Packet.Index = Index;\r
- Packet.Selector = Selector;\r
- Packet.Timeout = UFS_TIMEOUT;\r
-\r
- //\r
- // Find out which slot of transfer request list is available.\r
- //\r
- Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- \r
- Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
- //\r
- // Fill transfer request descriptor to this slot.\r
- //\r
- Status = UfsCreateDMCommandDesc (Private, &Packet, Trd);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Check the transfer request result.\r
- //\r
- CmdDescBase = (UINT8 *)(UINTN)(LShiftU64 ((UINT64)Trd->UcdBaU, 32) | LShiftU64 ((UINT64)Trd->UcdBa, 7));\r
- QueryResp = (UTP_QUERY_RESP_UPIU*)(CmdDescBase + Trd->RuO * sizeof (UINT32));\r
- CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);\r
-\r
- //\r
- // Start to execute the transfer request.\r
- //\r
- UfsStartExecCmd (Private, Slot);\r
-\r
- //\r
- // Wait for the completion of the transfer request.\r
- // \r
- Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; \r
- Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
- }\r
-\r
- if (QueryResp->QueryResp != 0) {\r
- DumpQueryResponseResult (QueryResp->QueryResp);\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
- }\r
-\r
- if (Trd->Ocs == 0) {\r
- ReturnData = QueryResp->Tsf.Value;\r
- SwapLittleEndianToBigEndian ((UINT8*)&ReturnData, sizeof (UINT32));\r
- *Attributes = ReturnData;\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
-\r
-Exit:\r
- UfsStopExecCmd (Private, Slot);\r
- UfsPeimFreeMem (Private->Pool, CmdDescBase, CmdDescSize);\r
-\r
- return Status;\r
-}\r
\r
/**\r
Read or write specified flag of a UFS device.\r
\r
//\r
// Wait for the completion of the transfer request.\r
- // \r
- Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; \r
- Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);\r
+ //\r
+ Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
+ Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, Packet.Timeout);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
}\r
\r
if (Trd->Ocs == 0) {\r
- *Value = (UINT8)QueryResp->Tsf.Value;\r
+ //\r
+ // The 'FLAG VALUE' field is at byte offset 3 of QueryResp->Tsf.Value\r
+ //\r
+ *Value = *((UINT8*)&(QueryResp->Tsf.Value) + 3);\r
} else {\r
Status = EFI_DEVICE_ERROR;\r
}\r
return Status;\r
}\r
\r
-/**\r
- Clear specified flag to 0 on a UFS device.\r
-\r
- @param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.\r
- @param[in] FlagId The ID of flag to be cleared.\r
-\r
- @retval EFI_SUCCESS The flag was cleared successfully.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to clear the flag.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of clearing the flag.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsClearFlag (\r
- IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
- IN UINT8 FlagId\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT8 Value;\r
-\r
- Value = 0;\r
- Status = UfsRwFlags (Private, FALSE, FlagId, &Value);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Read specified flag from a UFS device.\r
-\r
- @param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.\r
- @param[in] FlagId The ID of flag to be read.\r
- @param[out] Value The flag's value.\r
-\r
- @retval EFI_SUCCESS The flag was read successfully.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsReadFlag (\r
- IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
- IN UINT8 FlagId,\r
- OUT UINT8 *Value\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = UfsRwFlags (Private, TRUE, FlagId, Value);\r
\r
- return Status;\r
-}\r
\r
/**\r
Sends NOP IN cmd to a UFS device for initialization process request.\r
\r
//\r
// Wait for the completion of the transfer request.\r
- // \r
- Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; \r
- Status = UfsWaitMemSet (Address, BIT0, 0, UFS_TIMEOUT);\r
+ //\r
+ Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
+ Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, UFS_TIMEOUT);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
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
}\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
\r
//\r
// Wait for the completion of the transfer request.\r
- // \r
- Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; \r
- Status = UfsWaitMemSet (Address, BIT0, 0, Packet->Timeout);\r
+ //\r
+ Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
+ Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, Packet->Timeout);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
Response = (UTP_RESPONSE_UPIU*)(CmdDescBase + Trd->RuO * sizeof (UINT32));\r
SenseDataLen = Response->SenseDataLen;\r
SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));\r
- \r
+\r
if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {\r
- CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
- Packet->SenseDataLength = (UINT8)SenseDataLen;\r
+ //\r
+ // Make sure the hardware device does not return more data than expected.\r
+ //\r
+ if (SenseDataLen <= Packet->SenseDataLength) {\r
+ CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
+ Packet->SenseDataLength = (UINT8)SenseDataLen;\r
+ } else {\r
+ Packet->SenseDataLength = 0;\r
+ }\r
}\r
\r
//\r
}\r
\r
Exit:\r
+ if (PacketBufferMap != NULL) {\r
+ IoMmuUnmap (PacketBufferMap);\r
+ }\r
UfsStopExecCmd (Private, Slot);\r
UfsPeimFreeMem (Private->Pool, CmdDescBase, CmdDescSize);\r
\r
\r
//\r
// UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)\r
- // This bit is set to '1' by the host controller upon completion of a UIC command. \r
+ // This bit is set to '1' by the host controller upon completion of a UIC command.\r
//\r
Address = UfsHcBase + UFS_HC_IS_OFFSET;\r
Data = MmioRead32 (Address);\r
//\r
// Check value of HCS.DP and make sure that there is a device attached to the Link.\r
//\r
- Address = UfsHcBase + UFS_HC_STATUS_OFFSET; \r
+ Address = UfsHcBase + UFS_HC_STATUS_OFFSET;\r
Data = MmioRead32 (Address);\r
if ((Data & UFS_HC_HCS_DP) == 0) {\r
Address = UfsHcBase + UFS_HC_IS_OFFSET;\r
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
//\r
// Initial h/w and s/w context for future operations.\r
//\r
- Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET; \r
+ Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;\r
Data = MmioRead32 (Address);\r
Private->Capabilities = Data;\r
\r
// 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
- Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET; \r
- MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32));\r
- Private->UtpTmrlBase = (VOID*)(UINTN)Buffer;\r
+ Address = Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET;\r
+ MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
+ Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET;\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
// Request List RunStop Register (UTMRLRSR) to '1'.\r
//\r
- Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET; \r
+ Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;\r
MmioWrite32 (Address, UFS_HC_UTMRLRSR);\r
\r
return EFI_SUCCESS;\r
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
//\r
// Initial h/w and s/w context for future operations.\r
//\r
- Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET; \r
+ Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;\r
Data = MmioRead32 (Address);\r
Private->Capabilities = Data;\r
\r
// 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
- Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET; \r
- MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32));\r
- Private->UtpTrlBase = (VOID*)(UINTN)Buffer;\r
+ Address = Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET;\r
+ MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
+ Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET;\r
+ MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+ Private->UtpTrlBase = (VOID*)(UINTN)CmdDescHost;\r
Private->Nutrs = Nutrs;\r
- \r
+ Private->TrlMapping = CmdDescMapping;\r
+\r
//\r
// Enable the UTP Transfer Request List by setting the UTP Transfer Request List\r
// RunStop Register (UTRLRSR) to '1'.\r
//\r
- Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET; \r
+ Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;\r
MmioWrite32 (Address, UFS_HC_UTRLRSR);\r
\r
return EFI_SUCCESS;\r
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
// Enable the UTP Task Management Request List by setting the UTP Task Management\r
// Request List RunStop Register (UTMRLRSR) to '1'.\r
//\r
- Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET; \r
+ Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;\r
MmioWrite32 (Address, 0);\r
\r
//\r
// Enable the UTP Transfer Request List by setting the UTP Transfer Request List\r
// RunStop Register (UTRLRSR) to '1'.\r
//\r
- Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET; \r
+ Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;\r
MmioWrite32 (Address, 0);\r
\r
//\r