}\r
};\r
\r
-/**\r
- Execute Request Sense SCSI command on a specific UFS device.\r
-\r
- @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.\r
- @param[in] Lun The lun on which the SCSI cmd executed.\r
- @param[out] DataBuffer A pointer to output sense data.\r
- @param[out] DataBufferLength The length of output sense data.\r
-\r
- @retval EFI_SUCCESS The command executed successfully.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsPeimRequestSense (\r
- IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
- IN UINTN Lun,\r
- OUT VOID *DataBuffer,\r
- OUT UINT32 *DataBufferLength\r
- )\r
-{\r
- UFS_SCSI_REQUEST_PACKET Packet;\r
- UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];\r
- EFI_STATUS Status;\r
\r
- ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));\r
- ZeroMem (Cdb, sizeof (Cdb));\r
-\r
- Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
-\r
- Packet.Timeout = UFS_TIMEOUT;\r
- Packet.Cdb = Cdb;\r
- Packet.CdbLength = sizeof (Cdb);\r
- Packet.DataDirection = UfsDataIn;\r
- Packet.InDataBuffer = DataBuffer;\r
- Packet.InTransferLength = *DataBufferLength;\r
- Packet.SenseData = NULL;\r
- Packet.SenseDataLength = 0;\r
-\r
- Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);\r
-\r
- if (!EFI_ERROR (Status)) {\r
- *DataBufferLength = Packet.InTransferLength;\r
- }\r
-\r
- return Status;\r
-}\r
\r
/**\r
Execute TEST UNITY READY SCSI command on a specific UFS device.\r
return Status;\r
}\r
\r
-/**\r
- Execute INQUIRY SCSI command on a specific UFS device.\r
-\r
- @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.\r
- @param[in] Lun The lun on which the SCSI cmd executed.\r
- @param[out] Inquiry A pointer to Inquiry data buffer.\r
- @param[out] InquiryLengths The length of output Inquiry data.\r
- @param[out] SenseData A pointer to output sense data.\r
- @param[out] SenseDataLength The length of output sense data.\r
-\r
- @retval EFI_SUCCESS The command executed successfully.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsPeimInquiry (\r
- IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
- IN UINTN Lun,\r
- OUT VOID *Inquiry,\r
- OUT UINT32 *InquiryLength,\r
- OUT VOID *SenseData, OPTIONAL\r
- OUT UINT8 *SenseDataLength\r
- )\r
-{\r
- UFS_SCSI_REQUEST_PACKET Packet;\r
- UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];\r
- EFI_STATUS Status;\r
-\r
- ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));\r
- ZeroMem (Cdb, sizeof (Cdb));\r
\r
- Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
- Cdb[4] = sizeof (EFI_SCSI_INQUIRY_DATA);\r
-\r
- Packet.Timeout = UFS_TIMEOUT;\r
- Packet.Cdb = Cdb;\r
- Packet.CdbLength = sizeof (Cdb);\r
- Packet.InDataBuffer = Inquiry;\r
- Packet.InTransferLength = *InquiryLength;\r
- Packet.DataDirection = UfsDataIn;\r
- Packet.SenseData = SenseData;\r
- Packet.SenseDataLength = *SenseDataLength;\r
-\r
- Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);\r
-\r
- if (*SenseDataLength != 0) {\r
- *SenseDataLength = Packet.SenseDataLength;\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- *InquiryLength = Packet.InTransferLength;\r
- }\r
-\r
- return Status;\r
-}\r
\r
/**\r
Execute READ CAPACITY(10) SCSI command on a specific UFS device.\r
return TRUE;\r
}\r
\r
-/**\r
- Unlink the memory block from the pool's list.\r
-\r
- @param Head The block list head of the memory's pool.\r
- @param BlockToUnlink The memory block to unlink.\r
\r
-**/\r
-VOID\r
-UfsPeimUnlinkMemBlock (\r
- IN UFS_PEIM_MEM_BLOCK *Head,\r
- IN UFS_PEIM_MEM_BLOCK *BlockToUnlink\r
- )\r
-{\r
- UFS_PEIM_MEM_BLOCK *Block;\r
-\r
- ASSERT ((Head != NULL) && (BlockToUnlink != NULL));\r
-\r
- for (Block = Head; Block != NULL; Block = Block->Next) {\r
- if (Block->Next == BlockToUnlink) {\r
- Block->Next = BlockToUnlink->Next;\r
- BlockToUnlink->Next = NULL;\r
- break;\r
- }\r
- }\r
-}\r
\r
/**\r
Initialize the memory management pool for the host controller.\r
\r
//\r
// Unlink all the memory blocks from the pool, then free them.\r
- // UfsPeimUnlinkMemBlock can't be used to unlink and free the\r
- // first block.\r
//\r
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {\r
UfsPeimFreeMemBlock (Pool, Block);\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
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 << 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
- 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
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