TianoCore EDK2 master
Loading...
Searching...
No Matches
UfsPassThruHci.c
Go to the documentation of this file.
1
11#include "UfsPassThru.h"
12
29 IN UINTN Offset,
30 OUT UINT32 *Value
31 )
32{
34 EFI_STATUS Status;
35
36 UfsHc = Private->UfsHostController;
37
38 Status = UfsHc->Read (UfsHc, EfiUfsHcWidthUint32, Offset, 1, Value);
39
40 return Status;
41}
42
59 IN UINTN Offset,
60 IN UINT32 Value
61 )
62{
64 EFI_STATUS Status;
65
66 UfsHc = Private->UfsHostController;
67
68 Status = UfsHc->Write (UfsHc, EfiUfsHcWidthUint32, Offset, 1, &Value);
69
70 return Status;
71}
72
91 IN UINTN Offset,
92 IN UINT32 MaskValue,
93 IN UINT32 TestValue,
94 IN UINT64 Timeout
95 )
96{
97 UINT32 Value;
98 UINT64 Delay;
99 BOOLEAN InfiniteWait;
100 EFI_STATUS Status;
101
102 if (Timeout == 0) {
103 InfiniteWait = TRUE;
104 } else {
105 InfiniteWait = FALSE;
106 }
107
108 Delay = DivU64x32 (Timeout, 10) + 1;
109
110 do {
111 //
112 // Access PCI MMIO space to see if the value is the tested one.
113 //
114 Status = UfsMmioRead32 (Private, Offset, &Value);
115 if (EFI_ERROR (Status)) {
116 return Status;
117 }
118
119 Value &= MaskValue;
120
121 if (Value == TestValue) {
122 return EFI_SUCCESS;
123 }
124
125 //
126 // Stall for 1 microseconds.
127 //
129
130 Delay--;
131 } while (InfiniteWait || (Delay > 0));
132
133 return EFI_TIMEOUT;
134}
135
143VOID
145 IN UINT8 UicOpcode,
146 IN UINT8 Result
147 )
148{
149 if (UicOpcode <= UfsUicDmePeerSet) {
150 switch (Result) {
151 case 0x00:
152 break;
153 case 0x01:
154 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE\n"));
155 break;
156 case 0x02:
157 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE_VALUE\n"));
158 break;
159 case 0x03:
160 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - READ_ONLY_MIB_ATTRIBUTE\n"));
161 break;
162 case 0x04:
163 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - WRITE_ONLY_MIB_ATTRIBUTE\n"));
164 break;
165 case 0x05:
166 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BAD_INDEX\n"));
167 break;
168 case 0x06:
169 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - LOCKED_MIB_ATTRIBUTE\n"));
170 break;
171 case 0x07:
172 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BAD_TEST_FEATURE_INDEX\n"));
173 break;
174 case 0x08:
175 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));
176 break;
177 case 0x09:
178 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BUSY\n"));
179 break;
180 case 0x0A:
181 DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - DME_FAILURE\n"));
182 break;
183 default:
184 ASSERT (FALSE);
185 break;
186 }
187 } else {
188 switch (Result) {
189 case 0x00:
190 break;
191 case 0x01:
192 DEBUG ((DEBUG_VERBOSE, "UIC control command fails - FAILURE\n"));
193 break;
194 default:
195 ASSERT (FALSE);
196 break;
197 }
198 }
199}
200
207VOID
209 IN UINT8 Result
210 )
211{
212 switch (Result) {
213 case 0xF6:
214 DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Not Readable\n"));
215 break;
216 case 0xF7:
217 DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Not Writeable\n"));
218 break;
219 case 0xF8:
220 DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Already Written\n"));
221 break;
222 case 0xF9:
223 DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Length\n"));
224 break;
225 case 0xFA:
226 DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Value\n"));
227 break;
228 case 0xFB:
229 DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Selector\n"));
230 break;
231 case 0xFC:
232 DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Index\n"));
233 break;
234 case 0xFD:
235 DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Idn\n"));
236 break;
237 case 0xFE:
238 DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Opcode\n"));
239 break;
240 case 0xFF:
241 DEBUG ((DEBUG_VERBOSE, "Query Response with General Failure\n"));
242 break;
243 default:
244 ASSERT (FALSE);
245 break;
246 }
247}
248
257VOID
259 IN OUT UINT8 *Buffer,
260 IN UINT32 BufferSize
261 )
262{
263 UINT32 Index;
264 UINT8 Temp;
265 UINT32 SwapCount;
266
267 SwapCount = BufferSize / 2;
268 for (Index = 0; Index < SwapCount; Index++) {
269 Temp = Buffer[Index];
270 Buffer[Index] = Buffer[BufferSize - 1 - Index];
271 Buffer[BufferSize - 1 - Index] = Temp;
272 }
273}
274
287VOID
289 IN OUT UTP_UPIU_TSF *TsfBase,
290 IN UINT8 Opcode,
291 IN UINT8 DescId OPTIONAL,
292 IN UINT8 Index OPTIONAL,
293 IN UINT8 Selector OPTIONAL,
294 IN UINT16 Length OPTIONAL,
295 IN UINT32 Value OPTIONAL
296 )
297{
298 ASSERT (TsfBase != NULL);
299 ASSERT (Opcode <= UtpQueryFuncOpcodeTogFlag);
300
301 TsfBase->Opcode = Opcode;
302 if (Opcode != UtpQueryFuncOpcodeNop) {
303 TsfBase->DescId = DescId;
304 TsfBase->Index = Index;
305 TsfBase->Selector = Selector;
306
307 if ((Opcode == UtpQueryFuncOpcodeRdDesc) || (Opcode == UtpQueryFuncOpcodeWrDesc)) {
308 SwapLittleEndianToBigEndian ((UINT8 *)&Length, sizeof (Length));
309 TsfBase->Length = Length;
310 }
311
312 if (Opcode == UtpQueryFuncOpcodeWrAttr) {
313 SwapLittleEndianToBigEndian ((UINT8 *)&Value, sizeof (Value));
314 TsfBase->Value = Value;
315 }
316 }
317}
318
335 IN OUT UTP_COMMAND_UPIU *Command,
336 IN UINT8 Lun,
337 IN UINT8 TaskTag,
338 IN UINT8 *Cdb,
339 IN UINT8 CdbLength,
340 IN UFS_DATA_DIRECTION DataDirection,
341 IN UINT32 ExpDataTranLen
342 )
343{
344 UINT8 Flags;
345
346 ASSERT ((Command != NULL) && (Cdb != NULL));
347
348 //
349 // Task attribute is hard-coded to Ordered.
350 //
351 if (DataDirection == UfsDataIn) {
352 Flags = BIT0 | BIT6;
353 } else if (DataDirection == UfsDataOut) {
354 Flags = BIT0 | BIT5;
355 } else {
356 Flags = BIT0;
357 }
358
359 //
360 // Fill UTP COMMAND UPIU associated fields.
361 //
362 Command->TransCode = 0x01;
363 Command->Flags = Flags;
364 Command->Lun = Lun;
365 Command->TaskTag = TaskTag;
366 Command->CmdSet = 0x00;
367 SwapLittleEndianToBigEndian ((UINT8 *)&ExpDataTranLen, sizeof (ExpDataTranLen));
368 Command->ExpDataTranLen = ExpDataTranLen;
369
370 CopyMem (Command->Cdb, Cdb, CdbLength);
371
372 return EFI_SUCCESS;
373}
374
387 IN UTP_TR_PRD *Prdt,
388 IN VOID *Buffer,
389 IN UINT32 BufferSize
390 )
391{
392 UINT32 PrdtIndex;
393 UINT32 RemainingLen;
394 UINT8 *Remaining;
395 UINTN PrdtNumber;
396
397 ASSERT (((UINTN)Buffer & (BIT0 | BIT1)) == 0);
398 ASSERT ((BufferSize & (BIT1 | BIT0)) == 0);
399
400 if (BufferSize == 0) {
401 return EFI_SUCCESS;
402 }
403
404 RemainingLen = BufferSize;
405 Remaining = Buffer;
406 PrdtNumber = (UINTN)DivU64x32 ((UINT64)BufferSize + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);
407
408 for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
409 if (RemainingLen < UFS_MAX_DATA_LEN_PER_PRD) {
410 Prdt[PrdtIndex].DbCount = (UINT32)RemainingLen - 1;
411 } else {
412 Prdt[PrdtIndex].DbCount = UFS_MAX_DATA_LEN_PER_PRD - 1;
413 }
414
415 Prdt[PrdtIndex].DbAddr = (UINT32)RShiftU64 ((UINT64)(UINTN)Remaining, 2);
416 Prdt[PrdtIndex].DbAddrU = (UINT32)RShiftU64 ((UINT64)(UINTN)Remaining, 32);
417 RemainingLen -= UFS_MAX_DATA_LEN_PER_PRD;
418 Remaining += UFS_MAX_DATA_LEN_PER_PRD;
419 }
420
421 return EFI_SUCCESS;
422}
423
441 IN OUT UTP_QUERY_REQ_UPIU *QueryReq,
442 IN UINT8 TaskTag,
443 IN UINT8 Opcode,
444 IN UINT8 DescId,
445 IN UINT8 Index,
446 IN UINT8 Selector,
447 IN UINTN DataSize OPTIONAL,
448 IN UINT8 *Data OPTIONAL
449 )
450{
451 ASSERT (QueryReq != NULL);
452
453 QueryReq->TransCode = 0x16;
454 QueryReq->TaskTag = TaskTag;
455 if ((Opcode == UtpQueryFuncOpcodeRdDesc) || (Opcode == UtpQueryFuncOpcodeRdFlag) || (Opcode == UtpQueryFuncOpcodeRdAttr)) {
456 QueryReq->QueryFunc = QUERY_FUNC_STD_READ_REQ;
457 } else {
458 QueryReq->QueryFunc = QUERY_FUNC_STD_WRITE_REQ;
459 }
460
461 if (Opcode == UtpQueryFuncOpcodeWrAttr) {
462 UfsFillTsfOfQueryReqUpiu (&QueryReq->Tsf, Opcode, DescId, Index, Selector, 0, *(UINT32 *)Data);
463 } else if ((Opcode == UtpQueryFuncOpcodeRdDesc) || (Opcode == UtpQueryFuncOpcodeWrDesc)) {
464 UfsFillTsfOfQueryReqUpiu (&QueryReq->Tsf, Opcode, DescId, Index, Selector, (UINT16)DataSize, 0);
465 } else {
466 UfsFillTsfOfQueryReqUpiu (&QueryReq->Tsf, Opcode, DescId, Index, Selector, 0, 0);
467 }
468
469 if (Opcode == UtpQueryFuncOpcodeWrDesc) {
470 CopyMem (QueryReq + 1, Data, DataSize);
471
472 SwapLittleEndianToBigEndian ((UINT8 *)&DataSize, sizeof (UINT16));
473 QueryReq->DataSegLen = (UINT16)DataSize;
474 }
475
476 return EFI_SUCCESS;
477}
478
497 IN UINT8 Lun,
499 IN UTP_TRD *Trd,
500 OUT VOID **CmdDescHost,
501 OUT VOID **CmdDescMapping
502 )
503{
504 UINTN TotalLen;
505 UINTN PrdtNumber;
506 UTP_COMMAND_UPIU *CommandUpiu;
507 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
508 EFI_STATUS Status;
509 UINT32 DataLen;
510 UFS_DATA_DIRECTION DataDirection;
511
512 ASSERT ((Private != NULL) && (Packet != NULL) && (Trd != NULL));
513
514 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
515 DataLen = Packet->InTransferLength;
516 DataDirection = UfsDataIn;
517 } else {
518 DataLen = Packet->OutTransferLength;
519 DataDirection = UfsDataOut;
520 }
521
522 if (DataLen == 0) {
523 DataDirection = UfsNoData;
524 }
525
526 PrdtNumber = (UINTN)DivU64x32 ((UINT64)DataLen + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);
527
528 TotalLen = ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)) + PrdtNumber * sizeof (UTP_TR_PRD);
529
530 Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
531 if (EFI_ERROR (Status)) {
532 return Status;
533 }
534
535 CommandUpiu = (UTP_COMMAND_UPIU *)*CmdDescHost;
536
537 UfsInitCommandUpiu (CommandUpiu, Lun, Private->TaskTag++, Packet->Cdb, Packet->CdbLength, DataDirection, DataLen);
538
539 //
540 // Fill UTP_TRD associated fields
541 // NOTE: Some UFS host controllers request the Response UPIU and the Physical Region Description Table
542 // *MUST* be located at a 64-bit aligned boundary.
543 //
544 Trd->Int = UFS_INTERRUPT_COMMAND;
545 Trd->Dd = DataDirection;
546 Trd->Ct = UFS_STORAGE_COMMAND_TYPE;
547 Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;
548 Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
549 Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
550 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)), sizeof (UINT32));
551 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)), sizeof (UINT32));
552 Trd->PrdtL = (UINT16)PrdtNumber;
553 Trd->PrdtO = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU))), sizeof (UINT32));
554 return EFI_SUCCESS;
555}
556
576 IN UTP_TRD *Trd,
577 OUT VOID **CmdDescHost,
578 OUT VOID **CmdDescMapping
579 )
580{
581 UINTN TotalLen;
582 UTP_QUERY_REQ_UPIU *QueryReqUpiu;
583 UINT8 Opcode;
584 UINT32 DataSize;
585 UINT8 *Data;
586 UINT8 DataDirection;
587 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
588 EFI_STATUS Status;
589
590 ASSERT ((Private != NULL) && (Packet != NULL) && (Trd != NULL));
591
592 Opcode = Packet->Opcode;
593 if ((Opcode > UtpQueryFuncOpcodeTogFlag) || (Opcode == UtpQueryFuncOpcodeNop)) {
594 return EFI_INVALID_PARAMETER;
595 }
596
597 DataDirection = Packet->DataDirection;
598 DataSize = Packet->TransferLength;
599 Data = Packet->DataBuffer;
600
601 if ((Opcode == UtpQueryFuncOpcodeWrDesc) || (Opcode == UtpQueryFuncOpcodeRdDesc)) {
602 if ((DataSize == 0) || (Data == NULL)) {
603 return EFI_INVALID_PARAMETER;
604 }
605
606 TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);
607 } else {
608 TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));
609 }
610
611 Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
612 if (EFI_ERROR (Status)) {
613 return Status;
614 }
615
616 //
617 // Initialize UTP QUERY REQUEST UPIU
618 //
619 QueryReqUpiu = (UTP_QUERY_REQ_UPIU *)*CmdDescHost;
620 ASSERT (QueryReqUpiu != NULL);
622 QueryReqUpiu,
623 Private->TaskTag++,
624 Opcode,
625 Packet->DescId,
626 Packet->Index,
627 Packet->Selector,
628 DataSize,
629 Data
630 );
631
632 //
633 // Fill UTP_TRD associated fields
634 // NOTE: Some UFS host controllers request the Query Response UPIU *MUST* be located at a 64-bit aligned boundary.
635 //
636 Trd->Int = UFS_INTERRUPT_COMMAND;
637 Trd->Dd = DataDirection;
638 Trd->Ct = UFS_STORAGE_COMMAND_TYPE;
639 Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;
640 Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
641 Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
642 if (Opcode == UtpQueryFuncOpcodeWrDesc) {
643 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)), sizeof (UINT32));
644 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));
645 } else {
646 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));
647 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)), sizeof (UINT32));
648 }
649
650 return EFI_SUCCESS;
651}
652
669 IN UTP_TRD *Trd,
670 OUT VOID **CmdDescHost,
671 OUT VOID **CmdDescMapping
672 )
673{
674 UINTN TotalLen;
675 UTP_NOP_OUT_UPIU *NopOutUpiu;
676 EFI_STATUS Status;
677 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
678
679 ASSERT ((Private != NULL) && (Trd != NULL));
680
681 TotalLen = ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)) + ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU));
682 Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
683 if (EFI_ERROR (Status)) {
684 return Status;
685 }
686
687 NopOutUpiu = (UTP_NOP_OUT_UPIU *)*CmdDescHost;
688 ASSERT (NopOutUpiu != NULL);
689 NopOutUpiu->TaskTag = Private->TaskTag++;
690
691 //
692 // Fill UTP_TRD associated fields
693 // NOTE: Some UFS host controllers request the Nop Out UPIU *MUST* be located at a 64-bit aligned boundary.
694 //
695 Trd->Int = UFS_INTERRUPT_COMMAND;
696 Trd->Dd = 0x00;
697 Trd->Ct = UFS_STORAGE_COMMAND_TYPE;
698 Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;
699 Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
700 Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
701 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU)), sizeof (UINT32));
702 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)), sizeof (UINT32));
703
704 return EFI_SUCCESS;
705}
706
720 OUT UINT8 *Slot
721 )
722{
723 UINT8 Nutrs;
724 UINT8 Index;
725 UINT32 Data;
726 EFI_STATUS Status;
727
728 ASSERT ((Private != NULL) && (Slot != NULL));
729
730 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);
731 if (EFI_ERROR (Status)) {
732 return Status;
733 }
734
735 Nutrs = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);
736
737 for (Index = 0; Index < Nutrs; Index++) {
738 if ((Data & (BIT0 << Index)) == 0) {
739 *Slot = Index;
740 return EFI_SUCCESS;
741 }
742 }
743
744 return EFI_NOT_READY;
745}
746
757 IN UINT8 Slot
758 )
759{
760 UINT32 Data;
761 EFI_STATUS Status;
762
763 Status = UfsMmioRead32 (Private, UFS_HC_UTRLRSR_OFFSET, &Data);
764 if (EFI_ERROR (Status)) {
765 return Status;
766 }
767
768 if ((Data & UFS_HC_UTRLRSR) != UFS_HC_UTRLRSR) {
769 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
770 if (EFI_ERROR (Status)) {
771 return Status;
772 }
773 }
774
775 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot);
776 if (EFI_ERROR (Status)) {
777 return Status;
778 }
779
780 return EFI_SUCCESS;
781}
782
793 IN UINT8 Slot
794 )
795{
796 UINT32 Data;
797 EFI_STATUS Status;
798
799 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);
800 if (EFI_ERROR (Status)) {
801 return Status;
802 }
803
804 if ((Data & (BIT0 << Slot)) != 0) {
805 Status = UfsMmioRead32 (Private, UFS_HC_UTRLCLR_OFFSET, &Data);
806 if (EFI_ERROR (Status)) {
807 return Status;
808 }
809
810 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLCLR_OFFSET, Data & ~(BIT0 << Slot));
811 if (EFI_ERROR (Status)) {
812 return Status;
813 }
814 }
815
816 return EFI_SUCCESS;
817}
818
833 IN UTP_QUERY_RESP_UPIU *QueryResp
834 )
835{
836 UINT16 ReturnDataSize;
837 UINT32 ReturnData;
838
839 if ((Packet == NULL) || (QueryResp == NULL)) {
840 return EFI_INVALID_PARAMETER;
841 }
842
843 switch (Packet->Opcode) {
844 case UtpQueryFuncOpcodeRdDesc:
845 ReturnDataSize = QueryResp->Tsf.Length;
846 SwapLittleEndianToBigEndian ((UINT8 *)&ReturnDataSize, sizeof (UINT16));
847 //
848 // Make sure the hardware device does not return more data than expected.
849 //
850 if (ReturnDataSize > Packet->TransferLength) {
851 return EFI_DEVICE_ERROR;
852 }
853
854 CopyMem (Packet->DataBuffer, (QueryResp + 1), ReturnDataSize);
855 Packet->TransferLength = ReturnDataSize;
856 break;
857 case UtpQueryFuncOpcodeWrDesc:
858 ReturnDataSize = QueryResp->Tsf.Length;
859 SwapLittleEndianToBigEndian ((UINT8 *)&ReturnDataSize, sizeof (UINT16));
860 Packet->TransferLength = ReturnDataSize;
861 break;
862 case UtpQueryFuncOpcodeRdFlag:
863 case UtpQueryFuncOpcodeSetFlag:
864 case UtpQueryFuncOpcodeClrFlag:
865 case UtpQueryFuncOpcodeTogFlag:
866 //
867 // The 'FLAG VALUE' field is at byte offset 3 of QueryResp->Tsf.Value
868 //
869 *((UINT8 *)(Packet->DataBuffer)) = *((UINT8 *)&(QueryResp->Tsf.Value) + 3);
870 break;
871 case UtpQueryFuncOpcodeRdAttr:
872 case UtpQueryFuncOpcodeWrAttr:
873 ReturnData = QueryResp->Tsf.Value;
874 SwapLittleEndianToBigEndian ((UINT8 *)&ReturnData, sizeof (UINT32));
875 CopyMem (Packet->DataBuffer, &ReturnData, sizeof (UINT32));
876 break;
877 default:
878 return EFI_INVALID_PARAMETER;
879 }
880
881 return EFI_SUCCESS;
882}
883
901 )
902{
903 UINT8 Slot;
904 UTP_TRD *Trd;
905 VOID *CmdDescHost;
906 VOID *CmdDescMapping;
907 UINT32 CmdDescSize;
909 UTP_QUERY_RESP_UPIU *QueryResp;
910 EFI_STATUS Status;
911
912 //
913 // Find out which slot of transfer request list is available.
914 //
915 Status = UfsFindAvailableSlotInTrl (Private, &Slot);
916 if (EFI_ERROR (Status)) {
917 return Status;
918 }
919
920 Trd = ((UTP_TRD *)Private->UtpTrlBase) + Slot;
921 //
922 // Fill transfer request descriptor to this slot.
923 //
924 Status = UfsCreateDMCommandDesc (Private, Packet, Trd, &CmdDescHost, &CmdDescMapping);
925 if (EFI_ERROR (Status)) {
926 DEBUG ((DEBUG_ERROR, "Failed to create DM command descriptor\n"));
927 return Status;
928 }
929
930 UfsHc = Private->UfsHostController;
931 QueryResp = (UTP_QUERY_RESP_UPIU *)((UINT8 *)CmdDescHost + Trd->RuO * sizeof (UINT32));
932 ASSERT (QueryResp != NULL);
933 CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
934
935 //
936 // Start to execute the transfer request.
937 //
938 UfsStartExecCmd (Private, Slot);
939
940 //
941 // Wait for the completion of the transfer request.
942 //
943 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);
944 if (EFI_ERROR (Status)) {
945 goto Exit;
946 }
947
948 if ((Trd->Ocs != 0) || (QueryResp->QueryResp != UfsUtpQueryResponseSuccess)) {
949 DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));
950 DumpQueryResponseResult (QueryResp->QueryResp);
951
952 if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||
953 (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||
954 (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn))
955 {
956 Status = EFI_INVALID_PARAMETER;
957 } else {
958 Status = EFI_DEVICE_ERROR;
959 }
960
961 goto Exit;
962 }
963
964 Status = UfsGetReturnDataFromQueryResponse (Packet, QueryResp);
965 if (EFI_ERROR (Status)) {
966 DEBUG ((DEBUG_ERROR, "Failed to get return data from query response\n"));
967 goto Exit;
968 }
969
970Exit:
971 UfsHc->Flush (UfsHc);
972
973 UfsStopExecCmd (Private, Slot);
974
975 if (CmdDescMapping != NULL) {
976 UfsHc->Unmap (UfsHc, CmdDescMapping);
977 }
978
979 if (CmdDescHost != NULL) {
980 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
981 }
982
983 return Status;
984}
985
1003 )
1004{
1005 EFI_STATUS Status;
1006 UINT8 Retry;
1007
1008 Status = EFI_SUCCESS;
1009
1010 for (Retry = 0; Retry < 5; Retry++) {
1011 Status = UfsSendDmRequestRetry (Private, Packet);
1012 if (!EFI_ERROR (Status)) {
1013 return EFI_SUCCESS;
1014 }
1015 }
1016
1017 DEBUG ((DEBUG_ERROR, "Failed to get response from the device after %d retries\n", Retry));
1018 return Status;
1019}
1020
1044 IN BOOLEAN Read,
1045 IN UINT8 DescId,
1046 IN UINT8 Index,
1047 IN UINT8 Selector,
1048 IN OUT VOID *Descriptor,
1049 IN OUT UINT32 *DescSize
1050 )
1051{
1053 EFI_STATUS Status;
1054
1055 if (DescSize == NULL) {
1056 return EFI_INVALID_PARAMETER;
1057 }
1058
1060
1061 if (Read) {
1062 Packet.DataDirection = UfsDataIn;
1063 Packet.Opcode = UtpQueryFuncOpcodeRdDesc;
1064 } else {
1065 Packet.DataDirection = UfsDataOut;
1066 Packet.Opcode = UtpQueryFuncOpcodeWrDesc;
1067 }
1068
1069 Packet.DataBuffer = Descriptor;
1070 Packet.TransferLength = *DescSize;
1071 Packet.DescId = DescId;
1072 Packet.Index = Index;
1073 Packet.Selector = Selector;
1074 Packet.Timeout = UFS_TIMEOUT;
1075
1076 Status = UfsSendDmRequest (Private, &Packet);
1077 if (EFI_ERROR (Status)) {
1078 *DescSize = 0;
1079 } else {
1080 *DescSize = Packet.TransferLength;
1081 }
1082
1083 return Status;
1084}
1085
1106 IN BOOLEAN Read,
1107 IN UINT8 AttrId,
1108 IN UINT8 Index,
1109 IN UINT8 Selector,
1110 IN OUT UINT32 *Attributes
1111 )
1112{
1114
1116
1117 if (Read) {
1118 Packet.DataDirection = UfsDataIn;
1119 Packet.Opcode = UtpQueryFuncOpcodeRdAttr;
1120 } else {
1121 Packet.DataDirection = UfsDataOut;
1122 Packet.Opcode = UtpQueryFuncOpcodeWrAttr;
1123 }
1124
1125 Packet.DataBuffer = Attributes;
1126 Packet.DescId = AttrId;
1127 Packet.Index = Index;
1128 Packet.Selector = Selector;
1129 Packet.Timeout = UFS_TIMEOUT;
1130
1131 return UfsSendDmRequest (Private, &Packet);
1132}
1133
1151 IN BOOLEAN Read,
1152 IN UINT8 FlagId,
1153 IN OUT UINT8 *Value
1154 )
1155{
1157
1158 if (Value == NULL) {
1159 return EFI_INVALID_PARAMETER;
1160 }
1161
1163
1164 if (Read) {
1165 ASSERT (Value != NULL);
1166 Packet.DataDirection = UfsDataIn;
1167 Packet.Opcode = UtpQueryFuncOpcodeRdFlag;
1168 } else {
1169 Packet.DataDirection = UfsDataOut;
1170 if (*Value == 1) {
1171 Packet.Opcode = UtpQueryFuncOpcodeSetFlag;
1172 } else if (*Value == 0) {
1173 Packet.Opcode = UtpQueryFuncOpcodeClrFlag;
1174 } else {
1175 return EFI_INVALID_PARAMETER;
1176 }
1177 }
1178
1179 Packet.DataBuffer = Value;
1180 Packet.DescId = FlagId;
1181 Packet.Index = 0;
1182 Packet.Selector = 0;
1183 Packet.Timeout = UFS_TIMEOUT;
1184
1185 return UfsSendDmRequest (Private, &Packet);
1186}
1187
1202 IN UINT8 FlagId
1203 )
1204{
1205 EFI_STATUS Status;
1206 UINT8 Value;
1207
1208 Value = 1;
1209 Status = UfsRwFlags (Private, FALSE, FlagId, &Value);
1210
1211 return Status;
1212}
1213
1229 IN UINT8 FlagId,
1230 OUT UINT8 *Value
1231 )
1232{
1233 EFI_STATUS Status;
1234
1235 Status = UfsRwFlags (Private, TRUE, FlagId, Value);
1236
1237 return Status;
1238}
1239
1256 )
1257{
1258 EFI_STATUS Status;
1259 UINT8 Slot;
1260 UTP_TRD *Trd;
1261 UTP_NOP_IN_UPIU *NopInUpiu;
1262 UINT32 CmdDescSize;
1263 VOID *CmdDescHost;
1264 VOID *CmdDescMapping;
1266
1267 //
1268 // Find out which slot of transfer request list is available.
1269 //
1270 Status = UfsFindAvailableSlotInTrl (Private, &Slot);
1271 if (EFI_ERROR (Status)) {
1272 return Status;
1273 }
1274
1275 Trd = ((UTP_TRD *)Private->UtpTrlBase) + Slot;
1276 Status = UfsCreateNopCommandDesc (Private, Trd, &CmdDescHost, &CmdDescMapping);
1277 if (EFI_ERROR (Status)) {
1278 return Status;
1279 }
1280
1281 //
1282 // Check the transfer request result.
1283 //
1284 UfsHc = Private->UfsHostController;
1285 NopInUpiu = (UTP_NOP_IN_UPIU *)((UINT8 *)CmdDescHost + Trd->RuO * sizeof (UINT32));
1286 ASSERT (NopInUpiu != NULL);
1287 CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
1288
1289 //
1290 // Start to execute the transfer request.
1291 //
1292 UfsStartExecCmd (Private, Slot);
1293
1294 //
1295 // Wait for the completion of the transfer request.
1296 //
1297 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);
1298 if (EFI_ERROR (Status)) {
1299 goto Exit;
1300 }
1301
1302 if (NopInUpiu->Resp != 0) {
1303 Status = EFI_DEVICE_ERROR;
1304 } else {
1305 Status = EFI_SUCCESS;
1306 }
1307
1308Exit:
1309 UfsHc->Flush (UfsHc);
1310
1311 UfsStopExecCmd (Private, Slot);
1312
1313 if (CmdDescMapping != NULL) {
1314 UfsHc->Unmap (UfsHc, CmdDescMapping);
1315 }
1316
1317 if (CmdDescHost != NULL) {
1318 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
1319 }
1320
1321 return Status;
1322}
1323
1332VOID
1335 IN UFS_PASS_THRU_TRANS_REQ *TransReq
1336 )
1337{
1338 if (TransReq->DataBufMapping != NULL) {
1339 Private->UfsHostController->Unmap (
1340 Private->UfsHostController,
1341 TransReq->DataBufMapping
1342 );
1343 }
1344
1345 //
1346 // Check if unaligned transfer was performed. If it was and we read
1347 // data from device copy memory to user data buffers before cleanup.
1348 // The assumption is if auxiliary aligned data buffer is not NULL then
1349 // unaligned transfer has been performed.
1350 //
1351 if (TransReq->AlignedDataBuf != NULL) {
1352 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1353 CopyMem (TransReq->Packet->InDataBuffer, TransReq->AlignedDataBuf, TransReq->Packet->InTransferLength);
1354 }
1355
1356 //
1357 // Wipe out the transfer buffer in case it contains sensitive data.
1358 //
1359 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1360 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1361 TransReq->AlignedDataBuf = NULL;
1362 }
1363}
1364
1378 )
1379{
1380 EFI_STATUS Status;
1381 VOID *DataBuf;
1382 UINT32 DataLen;
1383 UINTN MapLength;
1384 EFI_PHYSICAL_ADDRESS DataBufPhyAddr;
1386 UTP_TR_PRD *PrdtBase;
1387
1388 DataBufPhyAddr = 0;
1389 DataBuf = NULL;
1390
1391 //
1392 // For unaligned data transfers we allocate auxiliary DWORD aligned memory pool.
1393 // When command is finished auxiliary memory pool is copied into actual user memory.
1394 // This is requiered to assure data transfer safety(DWORD alignment required by UFS spec.)
1395 //
1396 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1397 if (((UINTN)TransReq->Packet->InDataBuffer % 4 != 0) || (TransReq->Packet->InTransferLength % 4 != 0)) {
1398 DataLen = TransReq->Packet->InTransferLength + (4 - (TransReq->Packet->InTransferLength % 4));
1399 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1400 if (DataBuf == NULL) {
1401 return EFI_DEVICE_ERROR;
1402 }
1403
1404 ZeroMem (DataBuf, DataLen);
1405 TransReq->AlignedDataBuf = DataBuf;
1406 TransReq->AlignedDataBufSize = DataLen;
1407 } else {
1408 DataLen = TransReq->Packet->InTransferLength;
1409 DataBuf = TransReq->Packet->InDataBuffer;
1410 }
1411
1413 } else {
1414 if (((UINTN)TransReq->Packet->OutDataBuffer % 4 != 0) || (TransReq->Packet->OutTransferLength % 4 != 0)) {
1415 DataLen = TransReq->Packet->OutTransferLength + (4 - (TransReq->Packet->OutTransferLength % 4));
1416 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1417 if (DataBuf == NULL) {
1418 return EFI_DEVICE_ERROR;
1419 }
1420
1421 CopyMem (DataBuf, TransReq->Packet->OutDataBuffer, TransReq->Packet->OutTransferLength);
1422 TransReq->AlignedDataBuf = DataBuf;
1423 TransReq->AlignedDataBufSize = DataLen;
1424 } else {
1425 DataLen = TransReq->Packet->OutTransferLength;
1426 DataBuf = TransReq->Packet->OutDataBuffer;
1427 }
1428
1430 }
1431
1432 if (DataLen != 0) {
1433 MapLength = DataLen;
1434 Status = Private->UfsHostController->Map (
1435 Private->UfsHostController,
1436 Flag,
1437 DataBuf,
1438 &MapLength,
1439 &DataBufPhyAddr,
1440 &TransReq->DataBufMapping
1441 );
1442
1443 if (EFI_ERROR (Status) || (DataLen != MapLength)) {
1444 if (TransReq->AlignedDataBuf != NULL) {
1445 //
1446 // Wipe out the transfer buffer in case it contains sensitive data.
1447 //
1448 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1449 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1450 TransReq->AlignedDataBuf = NULL;
1451 }
1452
1453 return EFI_DEVICE_ERROR;
1454 }
1455 }
1456
1457 //
1458 // Fill PRDT table of Command UPIU for executed SCSI cmd.
1459 //
1460 PrdtBase = (UTP_TR_PRD *)((UINT8 *)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));
1461 ASSERT (PrdtBase != NULL);
1462 UfsInitUtpPrdt (PrdtBase, (VOID *)(UINTN)DataBufPhyAddr, DataLen);
1463
1464 return EFI_SUCCESS;
1465}
1466
1494 IN UINT8 Lun,
1496 IN EFI_EVENT Event OPTIONAL
1497 )
1498{
1499 EFI_STATUS Status;
1500 UTP_RESPONSE_UPIU *Response;
1501 UINT16 SenseDataLen;
1502 UINT32 ResTranCount;
1503 EFI_TPL OldTpl;
1504 UFS_PASS_THRU_TRANS_REQ *TransReq;
1506
1507 TransReq = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));
1508 if (TransReq == NULL) {
1509 return EFI_OUT_OF_RESOURCES;
1510 }
1511
1512 TransReq->Signature = UFS_PASS_THRU_TRANS_REQ_SIG;
1513 TransReq->TimeoutRemain = Packet->Timeout;
1514 TransReq->Packet = Packet;
1515
1516 UfsHc = Private->UfsHostController;
1517 //
1518 // Find out which slot of transfer request list is available.
1519 //
1520 Status = UfsFindAvailableSlotInTrl (Private, &TransReq->Slot);
1521 if (EFI_ERROR (Status)) {
1522 return Status;
1523 }
1524
1525 TransReq->Trd = ((UTP_TRD *)Private->UtpTrlBase) + TransReq->Slot;
1526
1527 //
1528 // Fill transfer request descriptor to this slot.
1529 //
1530 Status = UfsCreateScsiCommandDesc (
1531 Private,
1532 Lun,
1533 Packet,
1534 TransReq->Trd,
1535 &TransReq->CmdDescHost,
1536 &TransReq->CmdDescMapping
1537 );
1538 if (EFI_ERROR (Status)) {
1539 return Status;
1540 }
1541
1542 TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);
1543
1544 Status = UfsPrepareDataTransferBuffer (Private, TransReq);
1545 if (EFI_ERROR (Status)) {
1546 goto Exit1;
1547 }
1548
1549 //
1550 // Insert the async SCSI cmd to the Async I/O list
1551 //
1552 if (Event != NULL) {
1553 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1554 TransReq->CallerEvent = Event;
1555 InsertTailList (&Private->Queue, &TransReq->TransferList);
1556 gBS->RestoreTPL (OldTpl);
1557 }
1558
1559 //
1560 // Start to execute the transfer request.
1561 //
1562 UfsStartExecCmd (Private, TransReq->Slot);
1563
1564 //
1565 // Immediately return for async I/O.
1566 //
1567 if (Event != NULL) {
1568 return EFI_SUCCESS;
1569 }
1570
1571 //
1572 // Wait for the completion of the transfer request.
1573 //
1574 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);
1575 if (EFI_ERROR (Status)) {
1576 goto Exit;
1577 }
1578
1579 //
1580 // Get sense data if exists
1581 //
1582 Response = (UTP_RESPONSE_UPIU *)((UINT8 *)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
1583 ASSERT (Response != NULL);
1584 SenseDataLen = Response->SenseDataLen;
1585 SwapLittleEndianToBigEndian ((UINT8 *)&SenseDataLen, sizeof (UINT16));
1586
1587 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
1588 //
1589 // Make sure the hardware device does not return more data than expected.
1590 //
1591 if (SenseDataLen <= Packet->SenseDataLength) {
1592 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
1593 Packet->SenseDataLength = (UINT8)SenseDataLen;
1594 } else {
1595 Packet->SenseDataLength = 0;
1596 }
1597 }
1598
1599 //
1600 // Check the transfer request result.
1601 //
1602 Packet->TargetStatus = Response->Status;
1603 if (Response->Response != 0) {
1604 DEBUG ((DEBUG_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));
1605 Status = EFI_DEVICE_ERROR;
1606 goto Exit;
1607 }
1608
1609 if (TransReq->Trd->Ocs == 0) {
1610 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1611 if ((Response->Flags & BIT5) == BIT5) {
1612 ResTranCount = Response->ResTranCount;
1613 SwapLittleEndianToBigEndian ((UINT8 *)&ResTranCount, sizeof (UINT32));
1614 Packet->InTransferLength -= ResTranCount;
1615 }
1616 } else {
1617 if ((Response->Flags & BIT5) == BIT5) {
1618 ResTranCount = Response->ResTranCount;
1619 SwapLittleEndianToBigEndian ((UINT8 *)&ResTranCount, sizeof (UINT32));
1620 Packet->OutTransferLength -= ResTranCount;
1621 }
1622 }
1623 } else {
1624 Status = EFI_DEVICE_ERROR;
1625 }
1626
1627Exit:
1628 UfsHc->Flush (UfsHc);
1629
1630 UfsStopExecCmd (Private, TransReq->Slot);
1631
1632 UfsReconcileDataTransferBuffer (Private, TransReq);
1633
1634Exit1:
1635 if (TransReq->CmdDescMapping != NULL) {
1636 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
1637 }
1638
1639 if (TransReq->CmdDescHost != NULL) {
1640 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (TransReq->CmdDescSize), TransReq->CmdDescHost);
1641 }
1642
1643 if (TransReq != NULL) {
1644 FreePool (TransReq);
1645 }
1646
1647 return Status;
1648}
1649
1663 IN OUT EDKII_UIC_COMMAND *UicCommand
1664 )
1665{
1666 EFI_STATUS Status;
1667 UINT32 Data;
1668
1669 Status = UfsMmioRead32 (Private, UFS_HC_IS_OFFSET, &Data);
1670 if (EFI_ERROR (Status)) {
1671 return Status;
1672 }
1673
1674 if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) {
1675 //
1676 // Clear IS.BIT10 UIC Command Completion Status (UCCS) at first.
1677 //
1678 Status = UfsMmioWrite32 (Private, UFS_HC_IS_OFFSET, Data);
1679 if (EFI_ERROR (Status)) {
1680 return Status;
1681 }
1682 }
1683
1684 //
1685 // When programming UIC command registers, host software shall set the register UICCMD
1686 // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)
1687 // are set.
1688 //
1689 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, UicCommand->Arg1);
1690 if (EFI_ERROR (Status)) {
1691 return Status;
1692 }
1693
1694 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, UicCommand->Arg2);
1695 if (EFI_ERROR (Status)) {
1696 return Status;
1697 }
1698
1699 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, UicCommand->Arg3);
1700 if (EFI_ERROR (Status)) {
1701 return Status;
1702 }
1703
1704 //
1705 // Host software shall only set the UICCMD if HCS.UCRDY is set to 1.
1706 //
1707 Status = UfsWaitMemSet (Private, UFS_HC_STATUS_OFFSET, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);
1708 if (EFI_ERROR (Status)) {
1709 return Status;
1710 }
1711
1712 Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, UicCommand->Opcode);
1713 if (EFI_ERROR (Status)) {
1714 return Status;
1715 }
1716
1717 //
1718 // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)
1719 // This bit is set to '1' by the host controller upon completion of a UIC command.
1720 //
1721 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);
1722 if (EFI_ERROR (Status)) {
1723 return Status;
1724 }
1725
1726 if (UicCommand->Opcode != UfsUicDmeReset) {
1727 Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &UicCommand->Arg2);
1728 if (EFI_ERROR (Status)) {
1729 return Status;
1730 }
1731
1732 Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG3_OFFSET, &UicCommand->Arg3);
1733 if (EFI_ERROR (Status)) {
1734 return Status;
1735 }
1736
1737 if ((UicCommand->Arg2 & 0xFF) != 0) {
1739 DumpUicCmdExecResult ((UINT8)UicCommand->Opcode, (UINT8)(UicCommand->Arg2 & 0xFF));
1740 DEBUG_CODE_END ();
1741 return EFI_DEVICE_ERROR;
1742 }
1743 }
1744
1745 return EFI_SUCCESS;
1746}
1747
1765 IN UINTN Size,
1766 OUT VOID **CmdDescHost,
1767 OUT EFI_PHYSICAL_ADDRESS *CmdDescPhyAddr,
1768 OUT VOID **CmdDescMapping
1769 )
1770{
1771 EFI_STATUS Status;
1772 UINTN Bytes;
1773 BOOLEAN Is32BitAddr;
1775
1776 if ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {
1777 Is32BitAddr = FALSE;
1778 } else {
1779 Is32BitAddr = TRUE;
1780 }
1781
1782 UfsHc = Private->UfsHostController;
1783 Status = UfsHc->AllocateBuffer (
1784 UfsHc,
1787 EFI_SIZE_TO_PAGES (Size),
1788 CmdDescHost,
1789 0
1790 );
1791 if (EFI_ERROR (Status)) {
1792 *CmdDescMapping = NULL;
1793 *CmdDescHost = NULL;
1794 *CmdDescPhyAddr = 0;
1795 return EFI_OUT_OF_RESOURCES;
1796 }
1797
1798 Bytes = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size));
1799 Status = UfsHc->Map (
1800 UfsHc,
1802 *CmdDescHost,
1803 &Bytes,
1804 CmdDescPhyAddr,
1805 CmdDescMapping
1806 );
1807
1808 if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)))) {
1809 UfsHc->FreeBuffer (
1810 UfsHc,
1812 *CmdDescHost
1813 );
1814 *CmdDescHost = NULL;
1815 return EFI_OUT_OF_RESOURCES;
1816 }
1817
1818 if (Is32BitAddr && ((*CmdDescPhyAddr) > 0x100000000ULL)) {
1819 //
1820 // The UFS host controller doesn't support 64bit addressing, so should not get a >4G UFS bus master address.
1821 //
1822 UfsHc->Unmap (
1823 UfsHc,
1824 *CmdDescMapping
1825 );
1826 UfsHc->FreeBuffer (
1827 UfsHc,
1829 *CmdDescHost
1830 );
1831 *CmdDescMapping = NULL;
1832 *CmdDescHost = NULL;
1833 return EFI_DEVICE_ERROR;
1834 }
1835
1836 ZeroMem (*CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)));
1837 return EFI_SUCCESS;
1838}
1839
1852 )
1853{
1854 EFI_STATUS Status;
1855 UINT32 Data;
1856
1857 if ((mUfsHcPlatform != NULL) && (mUfsHcPlatform->Callback != NULL)) {
1858 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPreHce, &Private->UfsHcDriverInterface);
1859 if (EFI_ERROR (Status)) {
1860 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreHce, Status = %r\n", Status));
1861 return Status;
1862 }
1863 }
1864
1865 //
1866 // UFS 2.0 spec section 7.1.1 - Host Controller Initialization
1867 //
1868 // Reinitialize the UFS host controller if HCE bit of HC register is set.
1869 //
1870 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
1871 if (EFI_ERROR (Status)) {
1872 return Status;
1873 }
1874
1875 if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) {
1876 //
1877 // Write a 0 to the HCE register at first to disable the host controller.
1878 //
1879 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
1880 if (EFI_ERROR (Status)) {
1881 return Status;
1882 }
1883
1884 //
1885 // Wait until HCE is read as '0' before continuing.
1886 //
1887 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
1888 if (EFI_ERROR (Status)) {
1889 return EFI_DEVICE_ERROR;
1890 }
1891 }
1892
1893 //
1894 // Write a 1 to the HCE register to enable the UFS host controller.
1895 //
1896 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN);
1897 if (EFI_ERROR (Status)) {
1898 return Status;
1899 }
1900
1901 //
1902 // Wait until HCE is read as '1' before continuing.
1903 //
1904 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);
1905 if (EFI_ERROR (Status)) {
1906 return EFI_DEVICE_ERROR;
1907 }
1908
1909 if ((mUfsHcPlatform != NULL) && (mUfsHcPlatform->Callback != NULL)) {
1910 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPostHce, &Private->UfsHcDriverInterface);
1911 if (EFI_ERROR (Status)) {
1912 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostHce, Status = %r\n", Status));
1913 return Status;
1914 }
1915 }
1916
1917 return EFI_SUCCESS;
1918}
1919
1933 )
1934{
1935 UINTN Retry;
1936 EFI_STATUS Status;
1937 UINT32 Data;
1938 EDKII_UIC_COMMAND LinkStartupCommand;
1939
1940 if ((mUfsHcPlatform != NULL) && (mUfsHcPlatform->Callback != NULL)) {
1941 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPreLinkStartup, &Private->UfsHcDriverInterface);
1942 if (EFI_ERROR (Status)) {
1943 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreLinkStartup, Status = %r\n", Status));
1944 return Status;
1945 }
1946 }
1947
1948 //
1949 // Start UFS device detection.
1950 // Try up to 3 times for establishing data link with device.
1951 //
1952 for (Retry = 0; Retry < 3; Retry++) {
1953 LinkStartupCommand.Opcode = UfsUicDmeLinkStartup;
1954 LinkStartupCommand.Arg1 = 0;
1955 LinkStartupCommand.Arg2 = 0;
1956 LinkStartupCommand.Arg3 = 0;
1957 Status = UfsExecUicCommands (Private, &LinkStartupCommand);
1958 if (EFI_ERROR (Status)) {
1959 return EFI_DEVICE_ERROR;
1960 }
1961
1962 Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);
1963 if (EFI_ERROR (Status)) {
1964 return EFI_DEVICE_ERROR;
1965 }
1966
1967 if ((Data & UFS_HC_HCS_DP) == 0) {
1968 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);
1969 if (EFI_ERROR (Status)) {
1970 return EFI_DEVICE_ERROR;
1971 }
1972 } else {
1973 return EFI_SUCCESS;
1974 }
1975 }
1976
1977 return EFI_NOT_FOUND;
1978}
1979
1992 )
1993{
1994 UINT8 Nutmrs;
1995 VOID *CmdDescHost;
1996 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
1997 VOID *CmdDescMapping;
1998 EFI_STATUS Status;
1999
2000 //
2001 // Initial h/w and s/w context for future operations.
2002 //
2003 CmdDescHost = NULL;
2004 CmdDescMapping = NULL;
2005 CmdDescPhyAddr = 0;
2006
2007 //
2008 // Allocate and initialize UTP Task Management Request List.
2009 //
2010 Nutmrs = (UINT8)(RShiftU64 ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);
2011 Status = UfsAllocateAlignCommonBuffer (Private, Nutmrs * sizeof (UTP_TMRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
2012 if (EFI_ERROR (Status)) {
2013 return Status;
2014 }
2015
2016 //
2017 // Program the UTP Task Management Request List Base Address and UTP Task Management
2018 // Request List Base Address with a 64-bit address allocated at step 6.
2019 //
2020 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
2021 if (EFI_ERROR (Status)) {
2022 return Status;
2023 }
2024
2025 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
2026 if (EFI_ERROR (Status)) {
2027 return Status;
2028 }
2029
2030 Private->UtpTmrlBase = CmdDescHost;
2031 Private->Nutmrs = Nutmrs;
2032 Private->TmrlMapping = CmdDescMapping;
2033
2034 //
2035 // Enable the UTP Task Management Request List by setting the UTP Task Management
2036 // Request List RunStop Register (UTMRLRSR) to '1'.
2037 //
2038 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, UFS_HC_UTMRLRSR);
2039 if (EFI_ERROR (Status)) {
2040 return Status;
2041 }
2042
2043 return EFI_SUCCESS;
2044}
2045
2058 )
2059{
2060 UINT8 Nutrs;
2061 VOID *CmdDescHost;
2062 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
2063 VOID *CmdDescMapping;
2064 EFI_STATUS Status;
2065
2066 //
2067 // Initial h/w and s/w context for future operations.
2068 //
2069 CmdDescHost = NULL;
2070 CmdDescMapping = NULL;
2071 CmdDescPhyAddr = 0;
2072
2073 //
2074 // Allocate and initialize UTP Transfer Request List.
2075 //
2076 Nutrs = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);
2077 Status = UfsAllocateAlignCommonBuffer (Private, Nutrs * sizeof (UTP_TRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
2078 if (EFI_ERROR (Status)) {
2079 return Status;
2080 }
2081
2082 //
2083 // Program the UTP Transfer Request List Base Address and UTP Transfer Request List
2084 // Base Address with a 64-bit address allocated at step 8.
2085 //
2086 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
2087 if (EFI_ERROR (Status)) {
2088 return Status;
2089 }
2090
2091 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
2092 if (EFI_ERROR (Status)) {
2093 return Status;
2094 }
2095
2096 Private->UtpTrlBase = CmdDescHost;
2097 Private->Nutrs = Nutrs;
2098 Private->TrlMapping = CmdDescMapping;
2099
2100 //
2101 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2102 // RunStop Register (UTRLRSR) to '1'.
2103 //
2104 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
2105 if (EFI_ERROR (Status)) {
2106 return Status;
2107 }
2108
2109 return EFI_SUCCESS;
2110}
2111
2124 )
2125{
2126 EFI_STATUS Status;
2127
2128 Status = UfsEnableHostController (Private);
2129 if (EFI_ERROR (Status)) {
2130 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));
2131 return Status;
2132 }
2133
2134 Status = UfsDeviceDetection (Private);
2135 if (EFI_ERROR (Status)) {
2136 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));
2137 return Status;
2138 }
2139
2140 Status = UfsInitTaskManagementRequestList (Private);
2141 if (EFI_ERROR (Status)) {
2142 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));
2143 return Status;
2144 }
2145
2146 Status = UfsInitTransferRequestList (Private);
2147 if (EFI_ERROR (Status)) {
2148 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));
2149 return Status;
2150 }
2151
2152 DEBUG ((DEBUG_INFO, "UfsControllerInit Finished\n"));
2153 return EFI_SUCCESS;
2154}
2155
2168 )
2169{
2170 EFI_STATUS Status;
2171 UINT32 Data;
2172
2173 //
2174 // Enable the UTP Task Management Request List by setting the UTP Task Management
2175 // Request List RunStop Register (UTMRLRSR) to '1'.
2176 //
2177 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, 0);
2178 if (EFI_ERROR (Status)) {
2179 return Status;
2180 }
2181
2182 //
2183 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2184 // RunStop Register (UTRLRSR) to '1'.
2185 //
2186 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, 0);
2187 if (EFI_ERROR (Status)) {
2188 return Status;
2189 }
2190
2191 //
2192 // Write a 0 to the HCE register in order to disable the host controller.
2193 //
2194 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
2195 if (EFI_ERROR (Status)) {
2196 return Status;
2197 }
2198
2199 ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN);
2200
2201 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
2202 if (EFI_ERROR (Status)) {
2203 return Status;
2204 }
2205
2206 //
2207 // Wait until HCE is read as '0' before continuing.
2208 //
2209 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
2210 if (EFI_ERROR (Status)) {
2211 return EFI_DEVICE_ERROR;
2212 }
2213
2214 DEBUG ((DEBUG_INFO, "UfsController is stopped\n"));
2215
2216 return EFI_SUCCESS;
2217}
2218
2229VOID
2230EFIAPI
2233 IN UFS_PASS_THRU_TRANS_REQ *TransReq
2234 )
2235{
2237 EFI_EVENT CallerEvent;
2238
2239 ASSERT ((Private != NULL) && (TransReq != NULL));
2240
2241 UfsHc = Private->UfsHostController;
2242 CallerEvent = TransReq->CallerEvent;
2243
2244 RemoveEntryList (&TransReq->TransferList);
2245
2246 UfsHc->Flush (UfsHc);
2247
2248 UfsStopExecCmd (Private, TransReq->Slot);
2249
2250 UfsReconcileDataTransferBuffer (Private, TransReq);
2251
2252 if (TransReq->CmdDescMapping != NULL) {
2253 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
2254 }
2255
2256 if (TransReq->CmdDescHost != NULL) {
2257 UfsHc->FreeBuffer (
2258 UfsHc,
2259 EFI_SIZE_TO_PAGES (TransReq->CmdDescSize),
2260 TransReq->CmdDescHost
2261 );
2262 }
2263
2264 FreePool (TransReq);
2265
2266 gBS->SignalEvent (CallerEvent);
2267 return;
2268}
2269
2277VOID
2278EFIAPI
2280 IN EFI_EVENT Event,
2281 IN VOID *Context
2282 )
2283{
2285 LIST_ENTRY *Entry;
2286 LIST_ENTRY *NextEntry;
2287 UFS_PASS_THRU_TRANS_REQ *TransReq;
2289 UTP_RESPONSE_UPIU *Response;
2290 UINT16 SenseDataLen;
2291 UINT32 ResTranCount;
2292 UINT32 SlotsMap;
2293 UINT32 Value;
2294 EFI_STATUS Status;
2295
2296 Private = (UFS_PASS_THRU_PRIVATE_DATA *)Context;
2297 SlotsMap = 0;
2298
2299 //
2300 // Check the entries in the async I/O queue are done or not.
2301 //
2302 if (!IsListEmpty (&Private->Queue)) {
2303 BASE_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
2304 TransReq = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
2305 Packet = TransReq->Packet;
2306
2307 if ((SlotsMap & (BIT0 << TransReq->Slot)) != 0) {
2308 return;
2309 }
2310
2311 SlotsMap |= BIT0 << TransReq->Slot;
2312
2313 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Value);
2314 if (EFI_ERROR (Status)) {
2315 //
2316 // TODO: Should find/add a proper host adapter return status for this
2317 // case.
2318 //
2319 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
2320 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));
2321 SignalCallerEvent (Private, TransReq);
2322 continue;
2323 }
2324
2325 if ((Value & (BIT0 << TransReq->Slot)) != 0) {
2326 //
2327 // Scsi cmd not finished yet.
2328 //
2329 if (TransReq->TimeoutRemain > UFS_HC_ASYNC_TIMER) {
2330 TransReq->TimeoutRemain -= UFS_HC_ASYNC_TIMER;
2331 continue;
2332 } else {
2333 //
2334 // Timeout occurs.
2335 //
2336 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
2337 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));
2338 SignalCallerEvent (Private, TransReq);
2339 continue;
2340 }
2341 } else {
2342 //
2343 // Scsi cmd finished.
2344 //
2345 // Get sense data if exists
2346 //
2347 Response = (UTP_RESPONSE_UPIU *)((UINT8 *)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
2348 ASSERT (Response != NULL);
2349 SenseDataLen = Response->SenseDataLen;
2350 SwapLittleEndianToBigEndian ((UINT8 *)&SenseDataLen, sizeof (UINT16));
2351
2352 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
2353 //
2354 // Make sure the hardware device does not return more data than expected.
2355 //
2356 if (SenseDataLen <= Packet->SenseDataLength) {
2357 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
2358 Packet->SenseDataLength = (UINT8)SenseDataLen;
2359 } else {
2360 Packet->SenseDataLength = 0;
2361 }
2362 }
2363
2364 //
2365 // Check the transfer request result.
2366 //
2367 Packet->TargetStatus = Response->Status;
2368 if (Response->Response != 0) {
2369 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));
2370 SignalCallerEvent (Private, TransReq);
2371 continue;
2372 }
2373
2374 if (TransReq->Trd->Ocs == 0) {
2375 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
2376 if ((Response->Flags & BIT5) == BIT5) {
2377 ResTranCount = Response->ResTranCount;
2378 SwapLittleEndianToBigEndian ((UINT8 *)&ResTranCount, sizeof (UINT32));
2379 Packet->InTransferLength -= ResTranCount;
2380 }
2381 } else {
2382 if ((Response->Flags & BIT5) == BIT5) {
2383 ResTranCount = Response->ResTranCount;
2384 SwapLittleEndianToBigEndian ((UINT8 *)&ResTranCount, sizeof (UINT32));
2385 Packet->OutTransferLength -= ResTranCount;
2386 }
2387 }
2388 } else {
2389 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));
2390 SignalCallerEvent (Private, TransReq);
2391 continue;
2392 }
2393
2394 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));
2395 SignalCallerEvent (Private, TransReq);
2396 }
2397 }
2398 }
2399}
2400
2412EFIAPI
2415 IN OUT EDKII_UIC_COMMAND *UicCommand
2416 )
2417{
2419
2420 if ((This == NULL) || (UicCommand == NULL)) {
2421 return EFI_INVALID_PARAMETER;
2422 }
2423
2424 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DRIVER_INTF (This);
2425
2426 return UfsExecUicCommands (Private, UicCommand);
2427}
2428
2440 )
2441{
2442 UINT32 Data;
2443 EFI_STATUS Status;
2444
2445 Status = UfsMmioRead32 (Private, UFS_HC_VER_OFFSET, &Data);
2446 if (EFI_ERROR (Status)) {
2447 return Status;
2448 }
2449
2450 Private->UfsHcInfo.Version = Data;
2451
2452 Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
2453 if (EFI_ERROR (Status)) {
2454 return Status;
2455 }
2456
2457 Private->UfsHcInfo.Capabilities = Data;
2458
2459 if ((mUfsHcPlatform != NULL) && (mUfsHcPlatform->OverrideHcInfo != NULL)) {
2460 Status = mUfsHcPlatform->OverrideHcInfo (Private->Handle, &Private->UfsHcInfo);
2461 if (EFI_ERROR (Status)) {
2462 DEBUG ((DEBUG_ERROR, "Failure from platform on OverrideHcInfo, Status = %r\n", Status));
2463 return Status;
2464 }
2465 }
2466
2467 return EFI_SUCCESS;
2468}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
#define BASE_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead)
Definition: BaseLib.h:2929
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID EFIAPI FreeAlignedPages(IN VOID *Buffer, IN UINTN Pages)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
VOID *EFIAPI AllocateAlignedPages(IN UINTN Pages, IN UINTN Alignment)
EDKII_UFS_HOST_CONTROLLER_OPERATION
@ EdkiiUfsHcOperationBusMasterWrite
@ EdkiiUfsHcOperationBusMasterRead
@ EdkiiUfsHcOperationBusMasterCommonBuffer
VOID EFIAPI Exit(IN EFI_STATUS Status)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ EfiBootServicesData
@ AllocateAnyPages
Definition: UefiSpec.h:33
EFI_STATUS UfsWaitMemSet(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINTN Offset, IN UINT32 MaskValue, IN UINT32 TestValue, IN UINT64 Timeout)
EFI_STATUS UfsGetReturnDataFromQueryResponse(IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet, IN UTP_QUERY_RESP_UPIU *QueryResp)
EFI_STATUS UfsMmioWrite32(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINTN Offset, IN UINT32 Value)
EFI_STATUS UfsInitTransferRequestList(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS UfsExecScsiCmds(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINT8 Lun, IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, IN EFI_EVENT Event OPTIONAL)
EFI_STATUS UfsEnableHostController(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS UfsAllocateAlignCommonBuffer(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINTN Size, OUT VOID **CmdDescHost, OUT EFI_PHYSICAL_ADDRESS *CmdDescPhyAddr, OUT VOID **CmdDescMapping)
EFI_STATUS UfsSendDmRequest(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet)
VOID SwapLittleEndianToBigEndian(IN OUT UINT8 *Buffer, IN UINT32 BufferSize)
VOID UfsReconcileDataTransferBuffer(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_PASS_THRU_TRANS_REQ *TransReq)
EFI_STATUS UfsSendDmRequestRetry(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet)
EFI_STATUS UfsRwDeviceDesc(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN BOOLEAN Read, IN UINT8 DescId, IN UINT8 Index, IN UINT8 Selector, IN OUT VOID *Descriptor, IN OUT UINT32 *DescSize)
EFI_STATUS GetUfsHcInfo(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS UfsExecNopCmds(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS EFIAPI UfsHcDriverInterfaceExecUicCommand(IN EDKII_UFS_HC_DRIVER_INTERFACE *This, IN OUT EDKII_UIC_COMMAND *UicCommand)
EFI_STATUS UfsRwFlags(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN BOOLEAN Read, IN UINT8 FlagId, IN OUT UINT8 *Value)
EFI_STATUS UfsDeviceDetection(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS UfsReadFlag(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINT8 FlagId, OUT UINT8 *Value)
VOID UfsFillTsfOfQueryReqUpiu(IN OUT UTP_UPIU_TSF *TsfBase, IN UINT8 Opcode, IN UINT8 DescId OPTIONAL, IN UINT8 Index OPTIONAL, IN UINT8 Selector OPTIONAL, IN UINT16 Length OPTIONAL, IN UINT32 Value OPTIONAL)
VOID DumpUicCmdExecResult(IN UINT8 UicOpcode, IN UINT8 Result)
VOID EFIAPI SignalCallerEvent(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_PASS_THRU_TRANS_REQ *TransReq)
EFI_STATUS UfsMmioRead32(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINTN Offset, OUT UINT32 *Value)
EFI_STATUS UfsInitUtpPrdt(IN UTP_TR_PRD *Prdt, IN VOID *Buffer, IN UINT32 BufferSize)
EFI_STATUS UfsStopExecCmd(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINT8 Slot)
EFI_STATUS UfsRwAttributes(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN BOOLEAN Read, IN UINT8 AttrId, IN UINT8 Index, IN UINT8 Selector, IN OUT UINT32 *Attributes)
VOID EFIAPI ProcessAsyncTaskList(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS UfsStartExecCmd(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINT8 Slot)
EFI_STATUS UfsInitTaskManagementRequestList(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS UfsCreateNopCommandDesc(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UTP_TRD *Trd, OUT VOID **CmdDescHost, OUT VOID **CmdDescMapping)
EFI_STATUS UfsPrepareDataTransferBuffer(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN OUT UFS_PASS_THRU_TRANS_REQ *TransReq)
EFI_STATUS UfsExecUicCommands(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN OUT EDKII_UIC_COMMAND *UicCommand)
EFI_STATUS UfsInitCommandUpiu(IN OUT UTP_COMMAND_UPIU *Command, IN UINT8 Lun, IN UINT8 TaskTag, IN UINT8 *Cdb, IN UINT8 CdbLength, IN UFS_DATA_DIRECTION DataDirection, IN UINT32 ExpDataTranLen)
EFI_STATUS UfsControllerStop(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS UfsFindAvailableSlotInTrl(IN UFS_PASS_THRU_PRIVATE_DATA *Private, OUT UINT8 *Slot)
EFI_STATUS UfsCreateScsiCommandDesc(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINT8 Lun, IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, IN UTP_TRD *Trd, OUT VOID **CmdDescHost, OUT VOID **CmdDescMapping)
VOID DumpQueryResponseResult(IN UINT8 Result)
EFI_STATUS UfsCreateDMCommandDesc(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet, IN UTP_TRD *Trd, OUT VOID **CmdDescHost, OUT VOID **CmdDescMapping)
EFI_STATUS UfsControllerInit(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS UfsInitQueryRequestUpiu(IN OUT UTP_QUERY_REQ_UPIU *QueryReq, IN UINT8 TaskTag, IN UINT8 Opcode, IN UINT8 DescId, IN UINT8 Index, IN UINT8 Selector, IN UINTN DataSize OPTIONAL, IN UINT8 *Data OPTIONAL)
EFI_STATUS UfsSetFlag(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UINT8 FlagId)
EDKII_UFS_HC_PLATFORM_OVERRIDE_HC_INFO OverrideHcInfo
EDKII_UFS_HC_PLATFORM_CALLBACK Callback