UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface\r
for upper layer application to execute UFS-supported SCSI cmds.\r
\r
- Copyright (c) 2014 - 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
- 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 ((DEBUG_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));\r
- break; \r
+ break;\r
case 0x09:\r
DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BUSY\n"));\r
break;\r
case 0x0A:\r
DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_VERBOSE, "Query Response with Invalid Opcode\n"));\r
- break; \r
+ break;\r
case 0xFF:\r
DEBUG ((DEBUG_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
}\r
\r
DataDirection = Packet->DataDirection;\r
- if (DataDirection == UfsDataIn) {\r
- DataSize = Packet->InTransferLength;\r
- Data = Packet->InDataBuffer;\r
- } else if (DataDirection == UfsDataOut) {\r
- DataSize = Packet->OutTransferLength;\r
- Data = Packet->OutDataBuffer;\r
- } else {\r
- DataSize = 0;\r
- Data = NULL;\r
- }\r
-\r
- if (((Opcode != UtpQueryFuncOpcodeSetFlag) && (Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag))\r
- && ((DataSize == 0) || (Data == NULL))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (((Opcode == UtpQueryFuncOpcodeSetFlag) || (Opcode == UtpQueryFuncOpcodeClrFlag) || (Opcode == UtpQueryFuncOpcodeTogFlag))\r
- && ((DataSize != 0) || (Data != NULL))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((Opcode == UtpQueryFuncOpcodeWrAttr) && (DataSize != sizeof (UINT32))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ DataSize = Packet->TransferLength;\r
+ Data = Packet->DataBuffer;\r
\r
if ((Opcode == UtpQueryFuncOpcodeWrDesc) || (Opcode == UtpQueryFuncOpcodeRdDesc)) {\r
+ if (DataSize == 0 || Data == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);\r
} else {\r
TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));\r
return EFI_NOT_READY;\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_PASS_THRU_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_PASS_THRU_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_PASS_THRU_PRIVATE_DATA *Private,\r
IN UINT8 Slot\r
- ) \r
+ )\r
{\r
UINT32 Data;\r
EFI_STATUS Status;\r
UfsStopExecCmd (\r
IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
IN UINT8 Slot\r
- ) \r
+ )\r
{\r
UINT32 Data;\r
EFI_STATUS Status;\r
}\r
\r
/**\r
- Read or write specified device descriptor of a UFS device.\r
+ Extracts return data from query response upiu.\r
\r
- @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
- @param[in] Read The boolean variable to show r/w direction.\r
- @param[in] DescId The ID of device descriptor.\r
- @param[in] Index The Index of device descriptor.\r
- @param[in] Selector The Selector of device descriptor.\r
- @param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
- @param[in] DescSize The size of device descriptor buffer.\r
+ @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
+ @param[in] QueryResp Pointer to the query response.\r
\r
- @retval EFI_SUCCESS The device descriptor was read/written successfully.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+ @retval EFI_INVALID_PARAMETER Packet or QueryResp are empty or opcode is invalid.\r
+ @retval EFI_DEVICE_ERROR Data returned from device is invalid.\r
+ @retval EFI_SUCCESS Data extracted.\r
\r
**/\r
EFI_STATUS\r
-UfsRwDeviceDesc (\r
- IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
- IN BOOLEAN Read,\r
- IN UINT8 DescId,\r
- IN UINT8 Index,\r
- IN UINT8 Selector,\r
- IN OUT VOID *Descriptor,\r
- IN UINT32 DescSize\r
+UfsGetReturnDataFromQueryResponse (\r
+ IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet,\r
+ IN UTP_QUERY_RESP_UPIU *QueryResp\r
)\r
{\r
- EFI_STATUS Status;\r
- UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
- UINT8 Slot;\r
- UTP_TRD *Trd;\r
- UTP_QUERY_RESP_UPIU *QueryResp;\r
- UINT32 CmdDescSize;\r
- UINT16 ReturnDataSize;\r
- VOID *CmdDescHost;\r
- VOID *CmdDescMapping;\r
- EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
+ UINT16 ReturnDataSize;\r
+ UINT32 ReturnData;\r
\r
- ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
+ if (Packet == NULL || QueryResp == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- if (Read) {\r
- Packet.DataDirection = UfsDataIn;\r
- Packet.InDataBuffer = Descriptor;\r
- Packet.InTransferLength = DescSize;\r
- Packet.Opcode = UtpQueryFuncOpcodeRdDesc;\r
- } else {\r
- Packet.DataDirection = UfsDataOut;\r
- Packet.OutDataBuffer = Descriptor;\r
- Packet.OutTransferLength = DescSize;\r
- Packet.Opcode = UtpQueryFuncOpcodeWrDesc;\r
+ switch (Packet->Opcode) {\r
+ case UtpQueryFuncOpcodeRdDesc:\r
+ ReturnDataSize = QueryResp->Tsf.Length;\r
+ SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+ //\r
+ // Make sure the hardware device does not return more data than expected.\r
+ //\r
+ if (ReturnDataSize > Packet->TransferLength) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ CopyMem (Packet->DataBuffer, (QueryResp + 1), ReturnDataSize);\r
+ Packet->TransferLength = ReturnDataSize;\r
+ break;\r
+ case UtpQueryFuncOpcodeWrDesc:\r
+ ReturnDataSize = QueryResp->Tsf.Length;\r
+ SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+ Packet->TransferLength = ReturnDataSize;\r
+ break;\r
+ case UtpQueryFuncOpcodeRdFlag:\r
+ case UtpQueryFuncOpcodeSetFlag:\r
+ case UtpQueryFuncOpcodeClrFlag:\r
+ case UtpQueryFuncOpcodeTogFlag:\r
+ CopyMem (Packet->DataBuffer, &QueryResp->Tsf.Value, sizeof (UINT8));\r
+ break;\r
+ case UtpQueryFuncOpcodeRdAttr:\r
+ case UtpQueryFuncOpcodeWrAttr:\r
+ ReturnData = QueryResp->Tsf.Value;\r
+ SwapLittleEndianToBigEndian ((UINT8*) &ReturnData, sizeof (UINT32));\r
+ CopyMem (Packet->DataBuffer, &ReturnData, sizeof (UINT32));\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
}\r
- Packet.DescId = DescId;\r
- Packet.Index = Index;\r
- Packet.Selector = Selector;\r
- Packet.Timeout = UFS_TIMEOUT;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Creates Transfer Request descriptor and sends Query Request to the device.\r
+\r
+ @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+ @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
+\r
+ @retval EFI_SUCCESS The device descriptor was read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+ combination to point to a type of UFS device descriptor.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsSendDmRequestRetry (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet\r
+ )\r
+{\r
+ UINT8 Slot;\r
+ UTP_TRD *Trd;\r
+ VOID *CmdDescHost;\r
+ VOID *CmdDescMapping;\r
+ UINT32 CmdDescSize;\r
+ EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
+ UTP_QUERY_RESP_UPIU *QueryResp;\r
+ EFI_STATUS Status;\r
\r
//\r
// Find out which slot of transfer request list is available.\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
- Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
+ Status = UfsCreateDMCommandDesc (Private, Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to create DM command descriptor\n"));\r
return Status;\r
}\r
\r
- //\r
- // Check the transfer request result.\r
- //\r
UfsHc = Private->UfsHostController;\r
QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
ASSERT (QueryResp != NULL);\r
\r
//\r
// Wait for the completion of the transfer request.\r
- // \r
- Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, Packet.Timeout);\r
+ //\r
+ Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
\r
- if (QueryResp->QueryResp != 0) {\r
+ if (Trd->Ocs != 0 || QueryResp->QueryResp != UfsUtpQueryResponseSuccess) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));\r
DumpQueryResponseResult (QueryResp->QueryResp);\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
- }\r
-\r
- if (Trd->Ocs == 0) {\r
- ReturnDataSize = QueryResp->Tsf.Length;\r
- SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
\r
- if (Read) {\r
- CopyMem (Packet.InDataBuffer, (QueryResp + 1), ReturnDataSize);\r
- Packet.InTransferLength = ReturnDataSize;\r
+ if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||\r
+ (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||\r
+ (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
} else {\r
- Packet.OutTransferLength = ReturnDataSize;\r
+ Status = EFI_DEVICE_ERROR;\r
}\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = UfsGetReturnDataFromQueryResponse (Packet, QueryResp);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to get return data from query response\n"));\r
+ goto Exit;\r
}\r
\r
Exit:\r
return Status;\r
}\r
\r
+/**\r
+ Sends Query Request to the device. Query is sent until device responds correctly or counter runs out.\r
+\r
+ @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+ @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_PACKET.\r
+\r
+ @retval EFI_SUCCESS The device responded correctly to the Query request.\r
+ @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+ combination to point to a type of UFS device descriptor.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while waiting for the response from the device.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of the operation.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsSendDmRequest (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 Retry;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Retry = 0; Retry < 5; Retry ++) {\r
+ Status = UfsSendDmRequestRetry (Private, Packet);\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ DEBUG ((DEBUG_ERROR, "Failed to get response from the device after %d retries\n", Retry));\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Read or write specified device descriptor of a UFS device.\r
+\r
+ @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] DescId The ID of device descriptor.\r
+ @param[in] Index The Index of device descriptor.\r
+ @param[in] Selector The Selector of device descriptor.\r
+ @param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
+ @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes,\r
+ of the data buffer specified by Descriptor. On output, the number\r
+ of bytes that were actually transferred.\r
+\r
+ @retval EFI_SUCCESS The device descriptor was read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER DescId, Index and Selector are invalid combination to point to a\r
+ type of UFS device descriptor.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsRwDeviceDesc (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 DescId,\r
+ IN UINT8 Index,\r
+ IN UINT8 Selector,\r
+ IN OUT VOID *Descriptor,\r
+ IN OUT UINT32 *DescSize\r
+ )\r
+{\r
+ UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
+ EFI_STATUS Status;\r
+\r
+ if (DescSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
+\r
+ if (Read) {\r
+ Packet.DataDirection = UfsDataIn;\r
+ Packet.Opcode = UtpQueryFuncOpcodeRdDesc;\r
+ } else {\r
+ Packet.DataDirection = UfsDataOut;\r
+ Packet.Opcode = UtpQueryFuncOpcodeWrDesc;\r
+ }\r
+ Packet.DataBuffer = Descriptor;\r
+ Packet.TransferLength = *DescSize;\r
+ Packet.DescId = DescId;\r
+ Packet.Index = Index;\r
+ Packet.Selector = Selector;\r
+ Packet.Timeout = UFS_TIMEOUT;\r
+\r
+ Status = UfsSendDmRequest (Private, &Packet);\r
+ if (EFI_ERROR (Status)) {\r
+ *DescSize = 0;\r
+ } else {\r
+ *DescSize = Packet.TransferLength;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Read or write specified attribute of a UFS device.\r
\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_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a\r
+ type of UFS device descriptor.\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
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
- UTP_QUERY_RESP_UPIU *QueryResp;\r
- UINT32 CmdDescSize;\r
- UINT32 ReturnData;\r
- VOID *CmdDescHost;\r
- VOID *CmdDescMapping;\r
- EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
\r
ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
\r
Packet.DataDirection = UfsDataOut;\r
Packet.Opcode = UtpQueryFuncOpcodeWrAttr;\r
}\r
+ Packet.DataBuffer = Attributes;\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, &CmdDescHost, &CmdDescMapping);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Check the transfer request result.\r
- //\r
- UfsHc = Private->UfsHostController;\r
- QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
- ASSERT (QueryResp != NULL);\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
- Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 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
- UfsHc->Flush (UfsHc);\r
-\r
- UfsStopExecCmd (Private, Slot);\r
-\r
- if (CmdDescMapping != NULL) {\r
- UfsHc->Unmap (UfsHc, CmdDescMapping);\r
- }\r
-\r
- if (CmdDescHost != NULL) {\r
- UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
- }\r
-\r
- return Status;\r
+ return UfsSendDmRequest (Private, &Packet);\r
}\r
\r
/**\r
@param[in, out] Value The value to set or clear flag.\r
\r
@retval EFI_SUCCESS The flag was read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER FlagId is an invalid UFS flag ID.\r
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the flag.\r
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the flag.\r
\r
IN OUT UINT8 *Value\r
)\r
{\r
- EFI_STATUS Status;\r
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
- UINT8 Slot;\r
- UTP_TRD *Trd;\r
- UTP_QUERY_RESP_UPIU *QueryResp;\r
- UINT32 CmdDescSize;\r
- VOID *CmdDescHost;\r
- VOID *CmdDescMapping;\r
- EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
\r
if (Value == NULL) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
+ Packet.DataBuffer = Value;\r
Packet.DescId = FlagId;\r
Packet.Index = 0;\r
Packet.Selector = 0;\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
- //\r
- // Fill transfer request descriptor to this slot.\r
- //\r
- Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
- Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Check the transfer request result.\r
- //\r
- UfsHc = Private->UfsHostController;\r
- QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
- ASSERT (QueryResp != NULL);\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
- Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 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
- *Value = (UINT8)QueryResp->Tsf.Value;\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
-\r
-Exit:\r
- UfsHc->Flush (UfsHc);\r
-\r
- UfsStopExecCmd (Private, Slot);\r
-\r
- if (CmdDescMapping != NULL) {\r
- UfsHc->Unmap (UfsHc, CmdDescMapping);\r
- }\r
- if (CmdDescHost != NULL) {\r
- UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
- }\r
-\r
- return Status;\r
+ return UfsSendDmRequest (Private, &Packet);\r
}\r
\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_PASS_THRU_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_PASS_THRU_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
//\r
// Wait for the completion of the transfer request.\r
- // \r
+ //\r
Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
\r
//\r
// Wait for the completion of the transfer request.\r
- // \r
+ //\r
Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
ASSERT (Response != NULL);\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
// 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
Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);\r
if (EFI_ERROR (Status)) {\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
UINT8 Nutrs;\r
VOID *CmdDescHost;\r
EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;\r
- VOID *CmdDescMapping; \r
+ VOID *CmdDescMapping;\r
EFI_STATUS Status;\r
\r
//\r
}\r
\r
Private->UtpTrlBase = CmdDescHost;\r
- Private->Nutrs = Nutrs; \r
+ Private->Nutrs = Nutrs;\r
Private->TrlMapping = CmdDescMapping;\r
\r
//\r
SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));\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