]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
912d6f82022ac6b2a21b60552ae915e511a3a372
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsPassThruDxe / UfsPassThruHci.c
1 /** @file
2 UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface
3 for upper layer application to execute UFS-supported SCSI cmds.
4
5 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UfsPassThru.h"
11
12 /**
13 Read 32bits data from specified UFS MMIO register.
14
15 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
16 @param[in] Offset The offset within the UFS Host Controller MMIO space to start
17 the memory operation.
18 @param[out] Value The data buffer to store.
19
20 @retval EFI_TIMEOUT The operation is time out.
21 @retval EFI_SUCCESS The operation succeeds.
22 @retval Others The operation fails.
23
24 **/
25 EFI_STATUS
26 UfsMmioRead32 (
27 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
28 IN UINTN Offset,
29 OUT UINT32 *Value
30 )
31 {
32 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
33 EFI_STATUS Status;
34
35 UfsHc = Private->UfsHostController;
36
37 Status = UfsHc->Read (UfsHc, EfiUfsHcWidthUint32, Offset, 1, Value);
38
39 return Status;
40 }
41
42 /**
43 Write 32bits data to specified UFS MMIO register.
44
45 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
46 @param[in] Offset The offset within the UFS Host Controller MMIO space to start
47 the memory operation.
48 @param[in] Value The data to write.
49
50 @retval EFI_TIMEOUT The operation is time out.
51 @retval EFI_SUCCESS The operation succeeds.
52 @retval Others The operation fails.
53
54 **/
55 EFI_STATUS
56 UfsMmioWrite32 (
57 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
58 IN UINTN Offset,
59 IN UINT32 Value
60 )
61 {
62 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
63 EFI_STATUS Status;
64
65 UfsHc = Private->UfsHostController;
66
67 Status = UfsHc->Write (UfsHc, EfiUfsHcWidthUint32, Offset, 1, &Value);
68
69 return Status;
70 }
71
72 /**
73 Wait for the value of the specified system memory set to the test value.
74
75 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
76 @param[in] Offset The offset within the UFS Host Controller MMIO space to start
77 the memory operation.
78 @param[in] MaskValue The mask value of memory.
79 @param[in] TestValue The test value of memory.
80 @param[in] Timeout The time out value for wait memory set, uses 100ns as a unit.
81
82 @retval EFI_TIMEOUT The system memory setting is time out.
83 @retval EFI_SUCCESS The system memory is correct set.
84 @retval Others The operation fails.
85
86 **/
87 EFI_STATUS
88 UfsWaitMemSet (
89 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
90 IN UINTN Offset,
91 IN UINT32 MaskValue,
92 IN UINT32 TestValue,
93 IN UINT64 Timeout
94 )
95 {
96 UINT32 Value;
97 UINT64 Delay;
98 BOOLEAN InfiniteWait;
99 EFI_STATUS Status;
100
101 if (Timeout == 0) {
102 InfiniteWait = TRUE;
103 } else {
104 InfiniteWait = FALSE;
105 }
106
107 Delay = DivU64x32 (Timeout, 10) + 1;
108
109 do {
110 //
111 // Access PCI MMIO space to see if the value is the tested one.
112 //
113 Status = UfsMmioRead32 (Private, Offset, &Value);
114 if (EFI_ERROR (Status)) {
115 return Status;
116 }
117
118 Value &= MaskValue;
119
120 if (Value == TestValue) {
121 return EFI_SUCCESS;
122 }
123
124 //
125 // Stall for 1 microseconds.
126 //
127 MicroSecondDelay (1);
128
129 Delay--;
130
131 } while (InfiniteWait || (Delay > 0));
132
133 return EFI_TIMEOUT;
134 }
135
136 /**
137 Dump UIC command execution result for debugging.
138
139 @param[in] UicOpcode The executed UIC opcode.
140 @param[in] Result The result to be parsed.
141
142 **/
143 VOID
144 DumpUicCmdExecResult (
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
201 /**
202 Dump QUERY RESPONSE UPIU result for debugging.
203
204 @param[in] Result The result to be parsed.
205
206 **/
207 VOID
208 DumpQueryResponseResult (
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
249 /**
250 Swap little endian to big endian.
251
252 @param[in, out] Buffer The data buffer. In input, it contains little endian data.
253 In output, it will become big endian.
254 @param[in] BufferSize The length of converted data.
255
256 **/
257 VOID
258 SwapLittleEndianToBigEndian (
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
275 /**
276 Fill TSF field of QUERY REQUEST UPIU.
277
278 @param[in, out] TsfBase The base address of TSF field of QUERY REQUEST UPIU.
279 @param[in] Opcode The opcode of request.
280 @param[in] DescId The descriptor ID of request.
281 @param[in] Index The index of request.
282 @param[in] Selector The selector of request.
283 @param[in] Length The length of transferred data. The maximum is 4.
284 @param[in] Value The value of transferred data.
285
286 **/
287 VOID
288 UfsFillTsfOfQueryReqUpiu (
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
319 /**
320 Initialize COMMAND UPIU.
321
322 @param[in, out] Command The base address of COMMAND UPIU.
323 @param[in] Lun The Lun on which the SCSI command is executed.
324 @param[in] TaskTag The task tag of request.
325 @param[in] Cdb The cdb buffer containing SCSI command.
326 @param[in] CdbLength The cdb length.
327 @param[in] DataDirection The direction of data transfer.
328 @param[in] ExpDataTranLen The expected transfer data length.
329
330 @retval EFI_SUCCESS The initialization succeed.
331
332 **/
333 EFI_STATUS
334 UfsInitCommandUpiu (
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
375 /**
376 Initialize UTP PRDT for data transfer.
377
378 @param[in] Prdt The base address of PRDT.
379 @param[in] Buffer The buffer to be read or written.
380 @param[in] BufferSize The data size to be read or written.
381
382 @retval EFI_SUCCESS The initialization succeed.
383
384 **/
385 EFI_STATUS
386 UfsInitUtpPrdt (
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
424 /**
425 Initialize QUERY REQUEST UPIU.
426
427 @param[in, out] QueryReq The base address of QUERY REQUEST UPIU.
428 @param[in] TaskTag The task tag of request.
429 @param[in] Opcode The opcode of request.
430 @param[in] DescId The descriptor ID of request.
431 @param[in] Index The index of request.
432 @param[in] Selector The selector of request.
433 @param[in] DataSize The data size to be read or written.
434 @param[in] Data The buffer to be read or written.
435
436 @retval EFI_SUCCESS The initialization succeed.
437
438 **/
439 EFI_STATUS
440 UfsInitQueryRequestUpiu (
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
479 /**
480 Allocate COMMAND/RESPONSE UPIU for filling UTP TRD's command descriptor field.
481
482 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
483 @param[in] Lun The Lun on which the SCSI command is executed.
484 @param[in] Packet The pointer to the EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET data structure.
485 @param[in] Trd The pointer to the UTP Transfer Request Descriptor.
486 @param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
487 @param[out] CmdDescMapping A resulting value to pass to Unmap().
488
489 @retval EFI_SUCCESS The creation succeed.
490 @retval EFI_DEVICE_ERROR The creation failed.
491 @retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
492
493 **/
494 EFI_STATUS
495 UfsCreateScsiCommandDesc (
496 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
497 IN UINT8 Lun,
498 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
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
557 /**
558 Allocate QUERY REQUEST/QUERY RESPONSE UPIU for filling UTP TRD's command descriptor field.
559
560 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
561 @param[in] Packet The pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET data structure.
562 @param[in] Trd The pointer to the UTP Transfer Request Descriptor.
563 @param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
564 @param[out] CmdDescMapping A resulting value to pass to Unmap().
565
566 @retval EFI_SUCCESS The creation succeed.
567 @retval EFI_DEVICE_ERROR The creation failed.
568 @retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
569 @retval EFI_INVALID_PARAMETER The parameter passed in is invalid.
570
571 **/
572 EFI_STATUS
573 UfsCreateDMCommandDesc (
574 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
575 IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet,
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 TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);
606 } else {
607 TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));
608 }
609
610 Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
611 if (EFI_ERROR (Status)) {
612 return Status;
613 }
614
615 //
616 // Initialize UTP QUERY REQUEST UPIU
617 //
618 QueryReqUpiu = (UTP_QUERY_REQ_UPIU*)*CmdDescHost;
619 ASSERT (QueryReqUpiu != NULL);
620 UfsInitQueryRequestUpiu (
621 QueryReqUpiu,
622 Private->TaskTag++,
623 Opcode,
624 Packet->DescId,
625 Packet->Index,
626 Packet->Selector,
627 DataSize,
628 Data
629 );
630
631 //
632 // Fill UTP_TRD associated fields
633 // NOTE: Some UFS host controllers request the Query Response UPIU *MUST* be located at a 64-bit aligned boundary.
634 //
635 Trd->Int = UFS_INTERRUPT_COMMAND;
636 Trd->Dd = DataDirection;
637 Trd->Ct = UFS_STORAGE_COMMAND_TYPE;
638 Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;
639 Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
640 Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
641 if (Opcode == UtpQueryFuncOpcodeWrDesc) {
642 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)), sizeof (UINT32));
643 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));
644 } else {
645 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));
646 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)), sizeof (UINT32));
647 }
648
649 return EFI_SUCCESS;
650 }
651
652 /**
653 Allocate NOP IN and NOP OUT UPIU for filling UTP TRD's command descriptor field.
654
655 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
656 @param[in] Trd The pointer to the UTP Transfer Request Descriptor.
657 @param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
658 @param[out] CmdDescMapping A resulting value to pass to Unmap().
659
660 @retval EFI_SUCCESS The creation succeed.
661 @retval EFI_DEVICE_ERROR The creation failed.
662 @retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
663
664 **/
665 EFI_STATUS
666 UfsCreateNopCommandDesc (
667 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
668 IN UTP_TRD *Trd,
669 OUT VOID **CmdDescHost,
670 OUT VOID **CmdDescMapping
671 )
672 {
673 UINTN TotalLen;
674 UTP_NOP_OUT_UPIU *NopOutUpiu;
675 EFI_STATUS Status;
676 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
677
678 ASSERT ((Private != NULL) && (Trd != NULL));
679
680 TotalLen = ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)) + ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU));
681 Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
682 if (EFI_ERROR (Status)) {
683 return Status;
684 }
685
686 NopOutUpiu = (UTP_NOP_OUT_UPIU*)*CmdDescHost;
687 ASSERT (NopOutUpiu != NULL);
688 NopOutUpiu->TaskTag = Private->TaskTag++;
689
690 //
691 // Fill UTP_TRD associated fields
692 // NOTE: Some UFS host controllers request the Nop Out UPIU *MUST* be located at a 64-bit aligned boundary.
693 //
694 Trd->Int = UFS_INTERRUPT_COMMAND;
695 Trd->Dd = 0x00;
696 Trd->Ct = UFS_STORAGE_COMMAND_TYPE;
697 Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;
698 Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
699 Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
700 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU)), sizeof (UINT32));
701 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)), sizeof (UINT32));
702
703 return EFI_SUCCESS;
704 }
705
706 /**
707 Find out available slot in transfer list of a UFS device.
708
709 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
710 @param[out] Slot The available slot.
711
712 @retval EFI_SUCCESS The available slot was found successfully.
713 @retval EFI_NOT_READY No slot is available at this moment.
714
715 **/
716 EFI_STATUS
717 UfsFindAvailableSlotInTrl (
718 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
719 OUT UINT8 *Slot
720 )
721 {
722 UINT8 Nutrs;
723 UINT8 Index;
724 UINT32 Data;
725 EFI_STATUS Status;
726
727 ASSERT ((Private != NULL) && (Slot != NULL));
728
729 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);
730 if (EFI_ERROR (Status)) {
731 return Status;
732 }
733
734 Nutrs = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);
735
736 for (Index = 0; Index < Nutrs; Index++) {
737 if ((Data & (BIT0 << Index)) == 0) {
738 *Slot = Index;
739 return EFI_SUCCESS;
740 }
741 }
742
743 return EFI_NOT_READY;
744 }
745
746
747 /**
748 Start specified slot in transfer list of a UFS device.
749
750 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
751 @param[in] Slot The slot to be started.
752
753 **/
754 EFI_STATUS
755 UfsStartExecCmd (
756 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
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
783 /**
784 Stop specified slot in transfer list of a UFS device.
785
786 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
787 @param[in] Slot The slot to be stop.
788
789 **/
790 EFI_STATUS
791 UfsStopExecCmd (
792 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
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
819 /**
820 Extracts return data from query response upiu.
821
822 @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.
823 @param[in] QueryResp Pointer to the query response.
824
825 @retval EFI_INVALID_PARAMETER Packet or QueryResp are empty or opcode is invalid.
826 @retval EFI_DEVICE_ERROR Data returned from device is invalid.
827 @retval EFI_SUCCESS Data extracted.
828
829 **/
830 EFI_STATUS
831 UfsGetReturnDataFromQueryResponse (
832 IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet,
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 CopyMem (Packet->DataBuffer, &QueryResp->Tsf.Value, sizeof (UINT8));
867 break;
868 case UtpQueryFuncOpcodeRdAttr:
869 case UtpQueryFuncOpcodeWrAttr:
870 ReturnData = QueryResp->Tsf.Value;
871 SwapLittleEndianToBigEndian ((UINT8*) &ReturnData, sizeof (UINT32));
872 CopyMem (Packet->DataBuffer, &ReturnData, sizeof (UINT32));
873 break;
874 default:
875 return EFI_INVALID_PARAMETER;
876 }
877
878 return EFI_SUCCESS;
879 }
880
881 /**
882 Creates Transfer Request descriptor and sends Query Request to the device.
883
884 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.
885 @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.
886
887 @retval EFI_SUCCESS The device descriptor was read/written successfully.
888 @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid
889 combination to point to a type of UFS device descriptor.
890 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.
891 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.
892
893 **/
894 EFI_STATUS
895 UfsSendDmRequestRetry (
896 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
897 IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet
898 )
899 {
900 UINT8 Slot;
901 UTP_TRD *Trd;
902 VOID *CmdDescHost;
903 VOID *CmdDescMapping;
904 UINT32 CmdDescSize;
905 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
906 UTP_QUERY_RESP_UPIU *QueryResp;
907 EFI_STATUS Status;
908
909 //
910 // Find out which slot of transfer request list is available.
911 //
912 Status = UfsFindAvailableSlotInTrl (Private, &Slot);
913 if (EFI_ERROR (Status)) {
914 return Status;
915 }
916
917 Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
918 //
919 // Fill transfer request descriptor to this slot.
920 //
921 Status = UfsCreateDMCommandDesc (Private, Packet, Trd, &CmdDescHost, &CmdDescMapping);
922 if (EFI_ERROR (Status)) {
923 DEBUG ((DEBUG_ERROR, "Failed to create DM command descriptor\n"));
924 return Status;
925 }
926
927 UfsHc = Private->UfsHostController;
928 QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
929 ASSERT (QueryResp != NULL);
930 CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
931
932 //
933 // Start to execute the transfer request.
934 //
935 UfsStartExecCmd (Private, Slot);
936
937 //
938 // Wait for the completion of the transfer request.
939 //
940 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);
941 if (EFI_ERROR (Status)) {
942 goto Exit;
943 }
944
945 if (Trd->Ocs != 0 || QueryResp->QueryResp != UfsUtpQueryResponseSuccess) {
946 DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));
947 DumpQueryResponseResult (QueryResp->QueryResp);
948
949 if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||
950 (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||
951 (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn)) {
952 Status = EFI_INVALID_PARAMETER;
953 } else {
954 Status = EFI_DEVICE_ERROR;
955 }
956 goto Exit;
957 }
958
959 Status = UfsGetReturnDataFromQueryResponse (Packet, QueryResp);
960 if (EFI_ERROR (Status)) {
961 DEBUG ((DEBUG_ERROR, "Failed to get return data from query response\n"));
962 goto Exit;
963 }
964
965 Exit:
966 UfsHc->Flush (UfsHc);
967
968 UfsStopExecCmd (Private, Slot);
969
970 if (CmdDescMapping != NULL) {
971 UfsHc->Unmap (UfsHc, CmdDescMapping);
972 }
973 if (CmdDescHost != NULL) {
974 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
975 }
976
977 return Status;
978 }
979
980 /**
981 Sends Query Request to the device. Query is sent until device responds correctly or counter runs out.
982
983 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.
984 @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_PACKET.
985
986 @retval EFI_SUCCESS The device responded correctly to the Query request.
987 @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid
988 combination to point to a type of UFS device descriptor.
989 @retval EFI_DEVICE_ERROR A device error occurred while waiting for the response from the device.
990 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of the operation.
991
992 **/
993 EFI_STATUS
994 UfsSendDmRequest (
995 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
996 IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet
997 )
998 {
999 EFI_STATUS Status;
1000 UINT8 Retry;
1001
1002 Status = EFI_SUCCESS;
1003
1004 for (Retry = 0; Retry < 5; Retry ++) {
1005 Status = UfsSendDmRequestRetry (Private, Packet);
1006 if (!EFI_ERROR (Status)) {
1007 return EFI_SUCCESS;
1008 }
1009 }
1010
1011 DEBUG ((DEBUG_ERROR, "Failed to get response from the device after %d retries\n", Retry));
1012 return Status;
1013 }
1014
1015 /**
1016 Read or write specified device descriptor of a UFS device.
1017
1018 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1019 @param[in] Read The boolean variable to show r/w direction.
1020 @param[in] DescId The ID of device descriptor.
1021 @param[in] Index The Index of device descriptor.
1022 @param[in] Selector The Selector of device descriptor.
1023 @param[in, out] Descriptor The buffer of device descriptor to be read or written.
1024 @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes,
1025 of the data buffer specified by Descriptor. On output, the number
1026 of bytes that were actually transferred.
1027
1028 @retval EFI_SUCCESS The device descriptor was read/written successfully.
1029 @retval EFI_INVALID_PARAMETER DescId, Index and Selector are invalid combination to point to a
1030 type of UFS device descriptor.
1031 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.
1032 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.
1033
1034 **/
1035 EFI_STATUS
1036 UfsRwDeviceDesc (
1037 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1038 IN BOOLEAN Read,
1039 IN UINT8 DescId,
1040 IN UINT8 Index,
1041 IN UINT8 Selector,
1042 IN OUT VOID *Descriptor,
1043 IN OUT UINT32 *DescSize
1044 )
1045 {
1046 UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
1047 EFI_STATUS Status;
1048
1049 if (DescSize == NULL) {
1050 return EFI_INVALID_PARAMETER;
1051 }
1052
1053 ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
1054
1055 if (Read) {
1056 Packet.DataDirection = UfsDataIn;
1057 Packet.Opcode = UtpQueryFuncOpcodeRdDesc;
1058 } else {
1059 Packet.DataDirection = UfsDataOut;
1060 Packet.Opcode = UtpQueryFuncOpcodeWrDesc;
1061 }
1062 Packet.DataBuffer = Descriptor;
1063 Packet.TransferLength = *DescSize;
1064 Packet.DescId = DescId;
1065 Packet.Index = Index;
1066 Packet.Selector = Selector;
1067 Packet.Timeout = UFS_TIMEOUT;
1068
1069 Status = UfsSendDmRequest (Private, &Packet);
1070 if (EFI_ERROR (Status)) {
1071 *DescSize = 0;
1072 } else {
1073 *DescSize = Packet.TransferLength;
1074 }
1075
1076 return Status;
1077 }
1078
1079 /**
1080 Read or write specified attribute of a UFS device.
1081
1082 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1083 @param[in] Read The boolean variable to show r/w direction.
1084 @param[in] AttrId The ID of Attribute.
1085 @param[in] Index The Index of Attribute.
1086 @param[in] Selector The Selector of Attribute.
1087 @param[in, out] Attributes The value of Attribute to be read or written.
1088
1089 @retval EFI_SUCCESS The Attribute was read/written successfully.
1090 @retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a
1091 type of UFS device descriptor.
1092 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.
1093 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.
1094
1095 **/
1096 EFI_STATUS
1097 UfsRwAttributes (
1098 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1099 IN BOOLEAN Read,
1100 IN UINT8 AttrId,
1101 IN UINT8 Index,
1102 IN UINT8 Selector,
1103 IN OUT UINT32 *Attributes
1104 )
1105 {
1106 UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
1107
1108 ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
1109
1110 if (Read) {
1111 Packet.DataDirection = UfsDataIn;
1112 Packet.Opcode = UtpQueryFuncOpcodeRdAttr;
1113 } else {
1114 Packet.DataDirection = UfsDataOut;
1115 Packet.Opcode = UtpQueryFuncOpcodeWrAttr;
1116 }
1117 Packet.DataBuffer = Attributes;
1118 Packet.DescId = AttrId;
1119 Packet.Index = Index;
1120 Packet.Selector = Selector;
1121 Packet.Timeout = UFS_TIMEOUT;
1122
1123 return UfsSendDmRequest (Private, &Packet);
1124 }
1125
1126 /**
1127 Read or write specified flag of a UFS device.
1128
1129 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1130 @param[in] Read The boolean variable to show r/w direction.
1131 @param[in] FlagId The ID of flag to be read or written.
1132 @param[in, out] Value The value to set or clear flag.
1133
1134 @retval EFI_SUCCESS The flag was read/written successfully.
1135 @retval EFI_INVALID_PARAMETER FlagId is an invalid UFS flag ID.
1136 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the flag.
1137 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the flag.
1138
1139 **/
1140 EFI_STATUS
1141 UfsRwFlags (
1142 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1143 IN BOOLEAN Read,
1144 IN UINT8 FlagId,
1145 IN OUT UINT8 *Value
1146 )
1147 {
1148 UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
1149
1150 if (Value == NULL) {
1151 return EFI_INVALID_PARAMETER;
1152 }
1153
1154 ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
1155
1156 if (Read) {
1157 ASSERT (Value != NULL);
1158 Packet.DataDirection = UfsDataIn;
1159 Packet.Opcode = UtpQueryFuncOpcodeRdFlag;
1160 } else {
1161 Packet.DataDirection = UfsDataOut;
1162 if (*Value == 1) {
1163 Packet.Opcode = UtpQueryFuncOpcodeSetFlag;
1164 } else if (*Value == 0) {
1165 Packet.Opcode = UtpQueryFuncOpcodeClrFlag;
1166 } else {
1167 return EFI_INVALID_PARAMETER;
1168 }
1169 }
1170 Packet.DataBuffer = Value;
1171 Packet.DescId = FlagId;
1172 Packet.Index = 0;
1173 Packet.Selector = 0;
1174 Packet.Timeout = UFS_TIMEOUT;
1175
1176 return UfsSendDmRequest (Private, &Packet);
1177 }
1178
1179 /**
1180 Set specified flag to 1 on a UFS device.
1181
1182 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1183 @param[in] FlagId The ID of flag to be set.
1184
1185 @retval EFI_SUCCESS The flag was set successfully.
1186 @retval EFI_DEVICE_ERROR A device error occurred while attempting to set the flag.
1187 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of setting the flag.
1188
1189 **/
1190 EFI_STATUS
1191 UfsSetFlag (
1192 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1193 IN UINT8 FlagId
1194 )
1195 {
1196 EFI_STATUS Status;
1197 UINT8 Value;
1198
1199 Value = 1;
1200 Status = UfsRwFlags (Private, FALSE, FlagId, &Value);
1201
1202 return Status;
1203 }
1204
1205
1206
1207 /**
1208 Read specified flag from a UFS device.
1209
1210 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1211 @param[in] FlagId The ID of flag to be read.
1212 @param[out] Value The flag's value.
1213
1214 @retval EFI_SUCCESS The flag was read successfully.
1215 @retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.
1216 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.
1217
1218 **/
1219 EFI_STATUS
1220 UfsReadFlag (
1221 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1222 IN UINT8 FlagId,
1223 OUT UINT8 *Value
1224 )
1225 {
1226 EFI_STATUS Status;
1227
1228 Status = UfsRwFlags (Private, TRUE, FlagId, Value);
1229
1230 return Status;
1231 }
1232
1233 /**
1234 Sends NOP IN cmd to a UFS device for initialization process request.
1235 For more details, please refer to UFS 2.0 spec Figure 13.3.
1236
1237 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1238
1239 @retval EFI_SUCCESS The NOP IN command was sent by the host. The NOP OUT response was
1240 received successfully.
1241 @retval EFI_DEVICE_ERROR A device error occurred while attempting to execute NOP IN command.
1242 @retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
1243 @retval EFI_TIMEOUT A timeout occurred while waiting for the NOP IN command to execute.
1244
1245 **/
1246 EFI_STATUS
1247 UfsExecNopCmds (
1248 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1249 )
1250 {
1251 EFI_STATUS Status;
1252 UINT8 Slot;
1253 UTP_TRD *Trd;
1254 UTP_NOP_IN_UPIU *NopInUpiu;
1255 UINT32 CmdDescSize;
1256 VOID *CmdDescHost;
1257 VOID *CmdDescMapping;
1258 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1259
1260 //
1261 // Find out which slot of transfer request list is available.
1262 //
1263 Status = UfsFindAvailableSlotInTrl (Private, &Slot);
1264 if (EFI_ERROR (Status)) {
1265 return Status;
1266 }
1267
1268 Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
1269 Status = UfsCreateNopCommandDesc (Private, Trd, &CmdDescHost, &CmdDescMapping);
1270 if (EFI_ERROR (Status)) {
1271 return Status;
1272 }
1273
1274 //
1275 // Check the transfer request result.
1276 //
1277 UfsHc = Private->UfsHostController;
1278 NopInUpiu = (UTP_NOP_IN_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
1279 ASSERT (NopInUpiu != NULL);
1280 CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
1281
1282 //
1283 // Start to execute the transfer request.
1284 //
1285 UfsStartExecCmd (Private, Slot);
1286
1287 //
1288 // Wait for the completion of the transfer request.
1289 //
1290 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);
1291 if (EFI_ERROR (Status)) {
1292 goto Exit;
1293 }
1294
1295 if (NopInUpiu->Resp != 0) {
1296 Status = EFI_DEVICE_ERROR;
1297 } else {
1298 Status = EFI_SUCCESS;
1299 }
1300
1301 Exit:
1302 UfsHc->Flush (UfsHc);
1303
1304 UfsStopExecCmd (Private, Slot);
1305
1306 if (CmdDescMapping != NULL) {
1307 UfsHc->Unmap (UfsHc, CmdDescMapping);
1308 }
1309 if (CmdDescHost != NULL) {
1310 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
1311 }
1312
1313 return Status;
1314 }
1315
1316 /**
1317 Cleanup data buffers after data transfer. This function
1318 also takes care to copy all data to user memory pool for
1319 unaligned data transfers.
1320
1321 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA
1322 @param[in] TransReq Pointer to the transfer request
1323 **/
1324 VOID
1325 UfsReconcileDataTransferBuffer (
1326 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1327 IN UFS_PASS_THRU_TRANS_REQ *TransReq
1328 )
1329 {
1330 if (TransReq->DataBufMapping != NULL) {
1331 Private->UfsHostController->Unmap (
1332 Private->UfsHostController,
1333 TransReq->DataBufMapping
1334 );
1335 }
1336
1337 //
1338 // Check if unaligned transfer was performed. If it was and we read
1339 // data from device copy memory to user data buffers before cleanup.
1340 // The assumption is if auxiliary aligned data buffer is not NULL then
1341 // unaligned transfer has been performed.
1342 //
1343 if (TransReq->AlignedDataBuf != NULL) {
1344 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1345 CopyMem (TransReq->Packet->InDataBuffer, TransReq->AlignedDataBuf, TransReq->Packet->InTransferLength);
1346 }
1347 //
1348 // Wipe out the transfer buffer in case it contains sensitive data.
1349 //
1350 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1351 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1352 TransReq->AlignedDataBuf = NULL;
1353 }
1354 }
1355
1356 /**
1357 Prepare data buffer for transfer.
1358
1359 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA
1360 @param[in, out] TransReq Pointer to the transfer request
1361
1362 @retval EFI_DEVICE_ERROR Failed to prepare buffer for transfer
1363 @retval EFI_SUCCESS Buffer ready for transfer
1364 **/
1365 EFI_STATUS
1366 UfsPrepareDataTransferBuffer (
1367 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1368 IN OUT UFS_PASS_THRU_TRANS_REQ *TransReq
1369 )
1370 {
1371 EFI_STATUS Status;
1372 VOID *DataBuf;
1373 UINT32 DataLen;
1374 UINTN MapLength;
1375 EFI_PHYSICAL_ADDRESS DataBufPhyAddr;
1376 EDKII_UFS_HOST_CONTROLLER_OPERATION Flag;
1377 UTP_TR_PRD *PrdtBase;
1378
1379 DataBufPhyAddr = 0;
1380 DataBuf = NULL;
1381
1382 //
1383 // For unaligned data transfers we allocate auxiliary DWORD aligned memory pool.
1384 // When command is finished auxiliary memory pool is copied into actual user memory.
1385 // This is requiered to assure data transfer safety(DWORD alignment required by UFS spec.)
1386 //
1387 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1388 if (((UINTN)TransReq->Packet->InDataBuffer % 4 != 0) || (TransReq->Packet->InTransferLength % 4 != 0)) {
1389 DataLen = TransReq->Packet->InTransferLength + (4 - (TransReq->Packet->InTransferLength % 4));
1390 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1391 if (DataBuf == NULL) {
1392 return EFI_DEVICE_ERROR;
1393 }
1394 ZeroMem (DataBuf, DataLen);
1395 TransReq->AlignedDataBuf = DataBuf;
1396 TransReq->AlignedDataBufSize = DataLen;
1397 } else {
1398 DataLen = TransReq->Packet->InTransferLength;
1399 DataBuf = TransReq->Packet->InDataBuffer;
1400 }
1401 Flag = EdkiiUfsHcOperationBusMasterWrite;
1402 } else {
1403 if (((UINTN)TransReq->Packet->OutDataBuffer % 4 != 0) || (TransReq->Packet->OutTransferLength % 4 != 0)) {
1404 DataLen = TransReq->Packet->OutTransferLength + (4 - (TransReq->Packet->OutTransferLength % 4));
1405 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1406 if (DataBuf == NULL) {
1407 return EFI_DEVICE_ERROR;
1408 }
1409 CopyMem (DataBuf, TransReq->Packet->OutDataBuffer, TransReq->Packet->OutTransferLength);
1410 TransReq->AlignedDataBuf = DataBuf;
1411 TransReq->AlignedDataBufSize = DataLen;
1412 } else {
1413 DataLen = TransReq->Packet->OutTransferLength;
1414 DataBuf = TransReq->Packet->OutDataBuffer;
1415 }
1416 Flag = EdkiiUfsHcOperationBusMasterRead;
1417 }
1418
1419 if (DataLen != 0) {
1420 MapLength = DataLen;
1421 Status = Private->UfsHostController->Map (
1422 Private->UfsHostController,
1423 Flag,
1424 DataBuf,
1425 &MapLength,
1426 &DataBufPhyAddr,
1427 &TransReq->DataBufMapping
1428 );
1429
1430 if (EFI_ERROR (Status) || (DataLen != MapLength)) {
1431 if (TransReq->AlignedDataBuf != NULL) {
1432 //
1433 // Wipe out the transfer buffer in case it contains sensitive data.
1434 //
1435 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1436 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1437 TransReq->AlignedDataBuf = NULL;
1438 }
1439 return EFI_DEVICE_ERROR;
1440 }
1441 }
1442
1443 //
1444 // Fill PRDT table of Command UPIU for executed SCSI cmd.
1445 //
1446 PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));
1447 ASSERT (PrdtBase != NULL);
1448 UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);
1449
1450 return EFI_SUCCESS;
1451 }
1452
1453 /**
1454 Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
1455
1456 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1457 @param[in] Lun The LUN of the UFS device to send the SCSI Request Packet.
1458 @param[in, out] Packet A pointer to the SCSI Request Packet to send to a specified Lun of the
1459 UFS device.
1460 @param[in] Event If nonblocking I/O is not supported then Event is ignored, and blocking
1461 I/O is performed. If Event is NULL, then blocking I/O is performed. If
1462 Event is not NULL and non blocking I/O is supported, then
1463 nonblocking I/O is performed, and Event will be signaled when the
1464 SCSI Request Packet completes.
1465
1466 @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
1467 commands, InTransferLength bytes were transferred from
1468 InDataBuffer. For write and bi-directional commands,
1469 OutTransferLength bytes were transferred by
1470 OutDataBuffer.
1471 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
1472 Packet.
1473 @retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
1474 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1475
1476 **/
1477 EFI_STATUS
1478 UfsExecScsiCmds (
1479 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1480 IN UINT8 Lun,
1481 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
1482 IN EFI_EVENT Event OPTIONAL
1483 )
1484 {
1485 EFI_STATUS Status;
1486 UTP_RESPONSE_UPIU *Response;
1487 UINT16 SenseDataLen;
1488 UINT32 ResTranCount;
1489 EFI_TPL OldTpl;
1490 UFS_PASS_THRU_TRANS_REQ *TransReq;
1491 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1492
1493 TransReq = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));
1494 if (TransReq == NULL) {
1495 return EFI_OUT_OF_RESOURCES;
1496 }
1497
1498 TransReq->Signature = UFS_PASS_THRU_TRANS_REQ_SIG;
1499 TransReq->TimeoutRemain = Packet->Timeout;
1500 TransReq->Packet = Packet;
1501
1502 UfsHc = Private->UfsHostController;
1503 //
1504 // Find out which slot of transfer request list is available.
1505 //
1506 Status = UfsFindAvailableSlotInTrl (Private, &TransReq->Slot);
1507 if (EFI_ERROR (Status)) {
1508 return Status;
1509 }
1510
1511 TransReq->Trd = ((UTP_TRD*)Private->UtpTrlBase) + TransReq->Slot;
1512
1513 //
1514 // Fill transfer request descriptor to this slot.
1515 //
1516 Status = UfsCreateScsiCommandDesc (
1517 Private,
1518 Lun,
1519 Packet,
1520 TransReq->Trd,
1521 &TransReq->CmdDescHost,
1522 &TransReq->CmdDescMapping
1523 );
1524 if (EFI_ERROR (Status)) {
1525 return Status;
1526 }
1527
1528 TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);
1529
1530 Status = UfsPrepareDataTransferBuffer (Private, TransReq);
1531 if (EFI_ERROR (Status)) {
1532 goto Exit1;
1533 }
1534
1535 //
1536 // Insert the async SCSI cmd to the Async I/O list
1537 //
1538 if (Event != NULL) {
1539 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1540 TransReq->CallerEvent = Event;
1541 InsertTailList (&Private->Queue, &TransReq->TransferList);
1542 gBS->RestoreTPL (OldTpl);
1543 }
1544
1545 //
1546 // Start to execute the transfer request.
1547 //
1548 UfsStartExecCmd (Private, TransReq->Slot);
1549
1550 //
1551 // Immediately return for async I/O.
1552 //
1553 if (Event != NULL) {
1554 return EFI_SUCCESS;
1555 }
1556
1557 //
1558 // Wait for the completion of the transfer request.
1559 //
1560 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);
1561 if (EFI_ERROR (Status)) {
1562 goto Exit;
1563 }
1564
1565 //
1566 // Get sense data if exists
1567 //
1568 Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
1569 ASSERT (Response != NULL);
1570 SenseDataLen = Response->SenseDataLen;
1571 SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
1572
1573 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
1574 //
1575 // Make sure the hardware device does not return more data than expected.
1576 //
1577 if (SenseDataLen <= Packet->SenseDataLength) {
1578 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
1579 Packet->SenseDataLength = (UINT8)SenseDataLen;
1580 } else {
1581 Packet->SenseDataLength = 0;
1582 }
1583 }
1584
1585 //
1586 // Check the transfer request result.
1587 //
1588 Packet->TargetStatus = Response->Status;
1589 if (Response->Response != 0) {
1590 DEBUG ((DEBUG_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));
1591 Status = EFI_DEVICE_ERROR;
1592 goto Exit;
1593 }
1594
1595 if (TransReq->Trd->Ocs == 0) {
1596 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1597 if ((Response->Flags & BIT5) == BIT5) {
1598 ResTranCount = Response->ResTranCount;
1599 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
1600 Packet->InTransferLength -= ResTranCount;
1601 }
1602 } else {
1603 if ((Response->Flags & BIT5) == BIT5) {
1604 ResTranCount = Response->ResTranCount;
1605 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
1606 Packet->OutTransferLength -= ResTranCount;
1607 }
1608 }
1609 } else {
1610 Status = EFI_DEVICE_ERROR;
1611 }
1612
1613 Exit:
1614 UfsHc->Flush (UfsHc);
1615
1616 UfsStopExecCmd (Private, TransReq->Slot);
1617
1618 UfsReconcileDataTransferBuffer (Private, TransReq);
1619
1620 Exit1:
1621 if (TransReq->CmdDescMapping != NULL) {
1622 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
1623 }
1624 if (TransReq->CmdDescHost != NULL) {
1625 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (TransReq->CmdDescSize), TransReq->CmdDescHost);
1626 }
1627 if (TransReq != NULL) {
1628 FreePool (TransReq);
1629 }
1630 return Status;
1631 }
1632
1633 /**
1634 Send UIC command.
1635
1636 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1637 @param[in] UicOpcode The opcode of the UIC command.
1638 @param[in] Arg1 The value for 1st argument of the UIC command.
1639 @param[in] Arg2 The value for 2nd argument of the UIC command.
1640 @param[in] Arg3 The value for 3rd argument of the UIC command.
1641
1642 @return EFI_SUCCESS Successfully execute this UIC command and detect attached UFS device.
1643 @return EFI_DEVICE_ERROR Fail to execute this UIC command and detect attached UFS device.
1644
1645 **/
1646 EFI_STATUS
1647 UfsExecUicCommands (
1648 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1649 IN UINT8 UicOpcode,
1650 IN UINT32 Arg1,
1651 IN UINT32 Arg2,
1652 IN UINT32 Arg3
1653 )
1654 {
1655 EFI_STATUS Status;
1656 UINT32 Data;
1657
1658 Status = UfsMmioRead32 (Private, UFS_HC_IS_OFFSET, &Data);
1659 if (EFI_ERROR (Status)) {
1660 return Status;
1661 }
1662
1663 if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) {
1664 //
1665 // Clear IS.BIT10 UIC Command Completion Status (UCCS) at first.
1666 //
1667 Status = UfsMmioWrite32 (Private, UFS_HC_IS_OFFSET, Data);
1668 if (EFI_ERROR (Status)) {
1669 return Status;
1670 }
1671 }
1672
1673 //
1674 // When programming UIC command registers, host software shall set the register UICCMD
1675 // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)
1676 // are set.
1677 //
1678 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, Arg1);
1679 if (EFI_ERROR (Status)) {
1680 return Status;
1681 }
1682
1683 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, Arg2);
1684 if (EFI_ERROR (Status)) {
1685 return Status;
1686 }
1687
1688 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, Arg3);
1689 if (EFI_ERROR (Status)) {
1690 return Status;
1691 }
1692
1693 //
1694 // Host software shall only set the UICCMD if HCS.UCRDY is set to 1.
1695 //
1696 Status = UfsWaitMemSet (Private, UFS_HC_STATUS_OFFSET, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);
1697 if (EFI_ERROR (Status)) {
1698 return Status;
1699 }
1700
1701 Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, (UINT32)UicOpcode);
1702 if (EFI_ERROR (Status)) {
1703 return Status;
1704 }
1705
1706 //
1707 // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)
1708 // This bit is set to '1' by the host controller upon completion of a UIC command.
1709 //
1710 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);
1711 if (EFI_ERROR (Status)) {
1712 return Status;
1713 }
1714
1715 if (UicOpcode != UfsUicDmeReset) {
1716 Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &Data);
1717 if (EFI_ERROR (Status)) {
1718 return Status;
1719 }
1720 if ((Data & 0xFF) != 0) {
1721 DEBUG_CODE_BEGIN();
1722 DumpUicCmdExecResult (UicOpcode, (UINT8)(Data & 0xFF));
1723 DEBUG_CODE_END();
1724 return EFI_DEVICE_ERROR;
1725 }
1726 }
1727
1728 return EFI_SUCCESS;
1729 }
1730
1731 /**
1732 Allocate common buffer for host and UFS bus master access simultaneously.
1733
1734 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1735 @param[in] Size The length of buffer to be allocated.
1736 @param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
1737 @param[out] CmdDescPhyAddr The resulting map address for the UFS bus master to use to access the hosts CmdDescHost.
1738 @param[out] CmdDescMapping A resulting value to pass to Unmap().
1739
1740 @retval EFI_SUCCESS The common buffer was allocated successfully.
1741 @retval EFI_DEVICE_ERROR The allocation fails.
1742 @retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
1743
1744 **/
1745 EFI_STATUS
1746 UfsAllocateAlignCommonBuffer (
1747 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1748 IN UINTN Size,
1749 OUT VOID **CmdDescHost,
1750 OUT EFI_PHYSICAL_ADDRESS *CmdDescPhyAddr,
1751 OUT VOID **CmdDescMapping
1752 )
1753 {
1754 EFI_STATUS Status;
1755 UINTN Bytes;
1756 BOOLEAN Is32BitAddr;
1757 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1758
1759 if ((Private->Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {
1760 Is32BitAddr = FALSE;
1761 } else {
1762 Is32BitAddr = TRUE;
1763 }
1764
1765 UfsHc = Private->UfsHostController;
1766 Status = UfsHc->AllocateBuffer (
1767 UfsHc,
1768 AllocateAnyPages,
1769 EfiBootServicesData,
1770 EFI_SIZE_TO_PAGES (Size),
1771 CmdDescHost,
1772 0
1773 );
1774 if (EFI_ERROR (Status)) {
1775 *CmdDescMapping = NULL;
1776 *CmdDescHost = NULL;
1777 *CmdDescPhyAddr = 0;
1778 return EFI_OUT_OF_RESOURCES;
1779 }
1780
1781 Bytes = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size));
1782 Status = UfsHc->Map (
1783 UfsHc,
1784 EdkiiUfsHcOperationBusMasterCommonBuffer,
1785 *CmdDescHost,
1786 &Bytes,
1787 CmdDescPhyAddr,
1788 CmdDescMapping
1789 );
1790
1791 if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)))) {
1792 UfsHc->FreeBuffer (
1793 UfsHc,
1794 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
1795 *CmdDescHost
1796 );
1797 *CmdDescHost = NULL;
1798 return EFI_OUT_OF_RESOURCES;
1799 }
1800
1801 if (Is32BitAddr && ((*CmdDescPhyAddr) > 0x100000000ULL)) {
1802 //
1803 // The UFS host controller doesn't support 64bit addressing, so should not get a >4G UFS bus master address.
1804 //
1805 UfsHc->Unmap (
1806 UfsHc,
1807 *CmdDescMapping
1808 );
1809 UfsHc->FreeBuffer (
1810 UfsHc,
1811 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
1812 *CmdDescHost
1813 );
1814 *CmdDescMapping = NULL;
1815 *CmdDescHost = NULL;
1816 return EFI_DEVICE_ERROR;
1817 }
1818
1819 ZeroMem (*CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)));
1820 return EFI_SUCCESS;
1821 }
1822
1823 /**
1824 Enable the UFS host controller for accessing.
1825
1826 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1827
1828 @retval EFI_SUCCESS The UFS host controller enabling was executed successfully.
1829 @retval EFI_DEVICE_ERROR A device error occurred while enabling the UFS host controller.
1830
1831 **/
1832 EFI_STATUS
1833 UfsEnableHostController (
1834 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1835 )
1836 {
1837 EFI_STATUS Status;
1838 UINT32 Data;
1839
1840 //
1841 // UFS 2.0 spec section 7.1.1 - Host Controller Initialization
1842 //
1843 // Reinitialize the UFS host controller if HCE bit of HC register is set.
1844 //
1845 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
1846 if (EFI_ERROR (Status)) {
1847 return Status;
1848 }
1849
1850 if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) {
1851 //
1852 // Write a 0 to the HCE register at first to disable the host controller.
1853 //
1854 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
1855 if (EFI_ERROR (Status)) {
1856 return Status;
1857 }
1858 //
1859 // Wait until HCE is read as '0' before continuing.
1860 //
1861 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
1862 if (EFI_ERROR (Status)) {
1863 return EFI_DEVICE_ERROR;
1864 }
1865 }
1866
1867 //
1868 // Write a 1 to the HCE register to enable the UFS host controller.
1869 //
1870 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN);
1871 if (EFI_ERROR (Status)) {
1872 return Status;
1873 }
1874
1875 //
1876 // Wait until HCE is read as '1' before continuing.
1877 //
1878 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);
1879 if (EFI_ERROR (Status)) {
1880 return EFI_DEVICE_ERROR;
1881 }
1882
1883 return EFI_SUCCESS;
1884 }
1885
1886 /**
1887 Detect if a UFS device attached.
1888
1889 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1890
1891 @retval EFI_SUCCESS The UFS device detection was executed successfully.
1892 @retval EFI_NOT_FOUND Not found a UFS device attached.
1893 @retval EFI_DEVICE_ERROR A device error occurred while detecting the UFS device.
1894
1895 **/
1896 EFI_STATUS
1897 UfsDeviceDetection (
1898 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1899 )
1900 {
1901 UINTN Retry;
1902 EFI_STATUS Status;
1903 UINT32 Data;
1904
1905 //
1906 // Start UFS device detection.
1907 // Try up to 3 times for establishing data link with device.
1908 //
1909 for (Retry = 0; Retry < 3; Retry++) {
1910 Status = UfsExecUicCommands (Private, UfsUicDmeLinkStartup, 0, 0, 0);
1911 if (EFI_ERROR (Status)) {
1912 return EFI_DEVICE_ERROR;
1913 }
1914
1915 Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);
1916 if (EFI_ERROR (Status)) {
1917 return EFI_DEVICE_ERROR;
1918 }
1919
1920 if ((Data & UFS_HC_HCS_DP) == 0) {
1921 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);
1922 if (EFI_ERROR (Status)) {
1923 return EFI_DEVICE_ERROR;
1924 }
1925 } else {
1926 return EFI_SUCCESS;
1927 }
1928 }
1929
1930 return EFI_NOT_FOUND;
1931 }
1932
1933 /**
1934 Initialize UFS task management request list related h/w context.
1935
1936 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1937
1938 @retval EFI_SUCCESS The UFS task management list was initialzed successfully.
1939 @retval EFI_DEVICE_ERROR The initialization fails.
1940
1941 **/
1942 EFI_STATUS
1943 UfsInitTaskManagementRequestList (
1944 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1945 )
1946 {
1947 UINT32 Data;
1948 UINT8 Nutmrs;
1949 VOID *CmdDescHost;
1950 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
1951 VOID *CmdDescMapping;
1952 EFI_STATUS Status;
1953
1954 //
1955 // Initial h/w and s/w context for future operations.
1956 //
1957 CmdDescHost = NULL;
1958 CmdDescMapping = NULL;
1959 CmdDescPhyAddr = 0;
1960
1961 Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
1962 if (EFI_ERROR (Status)) {
1963 return Status;
1964 }
1965
1966 Private->Capabilities = Data;
1967
1968 //
1969 // Allocate and initialize UTP Task Management Request List.
1970 //
1971 Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);
1972 Status = UfsAllocateAlignCommonBuffer (Private, Nutmrs * sizeof (UTP_TMRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
1973 if (EFI_ERROR (Status)) {
1974 return Status;
1975 }
1976
1977 //
1978 // Program the UTP Task Management Request List Base Address and UTP Task Management
1979 // Request List Base Address with a 64-bit address allocated at step 6.
1980 //
1981 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
1982 if (EFI_ERROR (Status)) {
1983 return Status;
1984 }
1985
1986 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
1987 if (EFI_ERROR (Status)) {
1988 return Status;
1989 }
1990 Private->UtpTmrlBase = CmdDescHost;
1991 Private->Nutmrs = Nutmrs;
1992 Private->TmrlMapping = CmdDescMapping;
1993
1994 //
1995 // Enable the UTP Task Management Request List by setting the UTP Task Management
1996 // Request List RunStop Register (UTMRLRSR) to '1'.
1997 //
1998 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, UFS_HC_UTMRLRSR);
1999 if (EFI_ERROR (Status)) {
2000 return Status;
2001 }
2002
2003 return EFI_SUCCESS;
2004 }
2005
2006 /**
2007 Initialize UFS transfer request list related h/w context.
2008
2009 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2010
2011 @retval EFI_SUCCESS The UFS transfer list was initialzed successfully.
2012 @retval EFI_DEVICE_ERROR The initialization fails.
2013
2014 **/
2015 EFI_STATUS
2016 UfsInitTransferRequestList (
2017 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2018 )
2019 {
2020 UINT32 Data;
2021 UINT8 Nutrs;
2022 VOID *CmdDescHost;
2023 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
2024 VOID *CmdDescMapping;
2025 EFI_STATUS Status;
2026
2027 //
2028 // Initial h/w and s/w context for future operations.
2029 //
2030 CmdDescHost = NULL;
2031 CmdDescMapping = NULL;
2032 CmdDescPhyAddr = 0;
2033
2034 Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
2035 if (EFI_ERROR (Status)) {
2036 return Status;
2037 }
2038
2039 Private->Capabilities = Data;
2040
2041 //
2042 // Allocate and initialize UTP Transfer Request List.
2043 //
2044 Nutrs = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);
2045 Status = UfsAllocateAlignCommonBuffer (Private, Nutrs * sizeof (UTP_TRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
2046 if (EFI_ERROR (Status)) {
2047 return Status;
2048 }
2049
2050 //
2051 // Program the UTP Transfer Request List Base Address and UTP Transfer Request List
2052 // Base Address with a 64-bit address allocated at step 8.
2053 //
2054 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
2055 if (EFI_ERROR (Status)) {
2056 return Status;
2057 }
2058
2059 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
2060 if (EFI_ERROR (Status)) {
2061 return Status;
2062 }
2063
2064 Private->UtpTrlBase = CmdDescHost;
2065 Private->Nutrs = Nutrs;
2066 Private->TrlMapping = CmdDescMapping;
2067
2068 //
2069 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2070 // RunStop Register (UTRLRSR) to '1'.
2071 //
2072 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
2073 if (EFI_ERROR (Status)) {
2074 return Status;
2075 }
2076
2077 return EFI_SUCCESS;
2078 }
2079
2080 /**
2081 Initialize the UFS host controller.
2082
2083 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2084
2085 @retval EFI_SUCCESS The Ufs Host Controller is initialized successfully.
2086 @retval Others A device error occurred while initializing the controller.
2087
2088 **/
2089 EFI_STATUS
2090 UfsControllerInit (
2091 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2092 )
2093 {
2094 EFI_STATUS Status;
2095
2096 Status = UfsEnableHostController (Private);
2097 if (EFI_ERROR (Status)) {
2098 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));
2099 return Status;
2100 }
2101
2102 Status = UfsDeviceDetection (Private);
2103 if (EFI_ERROR (Status)) {
2104 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));
2105 return Status;
2106 }
2107
2108 Status = UfsInitTaskManagementRequestList (Private);
2109 if (EFI_ERROR (Status)) {
2110 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));
2111 return Status;
2112 }
2113
2114 Status = UfsInitTransferRequestList (Private);
2115 if (EFI_ERROR (Status)) {
2116 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));
2117 return Status;
2118 }
2119
2120 DEBUG ((DEBUG_INFO, "UfsControllerInit Finished\n"));
2121 return EFI_SUCCESS;
2122 }
2123
2124 /**
2125 Stop the UFS host controller.
2126
2127 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2128
2129 @retval EFI_SUCCESS The Ufs Host Controller is stopped successfully.
2130 @retval Others A device error occurred while stopping the controller.
2131
2132 **/
2133 EFI_STATUS
2134 UfsControllerStop (
2135 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2136 )
2137 {
2138 EFI_STATUS Status;
2139 UINT32 Data;
2140
2141 //
2142 // Enable the UTP Task Management Request List by setting the UTP Task Management
2143 // Request List RunStop Register (UTMRLRSR) to '1'.
2144 //
2145 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, 0);
2146 if (EFI_ERROR (Status)) {
2147 return Status;
2148 }
2149
2150 //
2151 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2152 // RunStop Register (UTRLRSR) to '1'.
2153 //
2154 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, 0);
2155 if (EFI_ERROR (Status)) {
2156 return Status;
2157 }
2158
2159 //
2160 // Write a 0 to the HCE register in order to disable the host controller.
2161 //
2162 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
2163 if (EFI_ERROR (Status)) {
2164 return Status;
2165 }
2166 ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN);
2167
2168 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
2169 if (EFI_ERROR (Status)) {
2170 return Status;
2171 }
2172
2173 //
2174 // Wait until HCE is read as '0' before continuing.
2175 //
2176 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
2177 if (EFI_ERROR (Status)) {
2178 return EFI_DEVICE_ERROR;
2179 }
2180
2181 DEBUG ((DEBUG_INFO, "UfsController is stopped\n"));
2182
2183 return EFI_SUCCESS;
2184 }
2185
2186 /**
2187 Internal helper function which will signal the caller event and clean up
2188 resources.
2189
2190 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data
2191 structure.
2192 @param[in] TransReq The pointer to the UFS_PASS_THRU_TRANS_REQ data
2193 structure.
2194
2195 **/
2196 VOID
2197 EFIAPI
2198 SignalCallerEvent (
2199 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
2200 IN UFS_PASS_THRU_TRANS_REQ *TransReq
2201 )
2202 {
2203 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
2204 EFI_EVENT CallerEvent;
2205
2206 ASSERT ((Private != NULL) && (TransReq != NULL));
2207
2208 UfsHc = Private->UfsHostController;
2209 CallerEvent = TransReq->CallerEvent;
2210
2211 RemoveEntryList (&TransReq->TransferList);
2212
2213 UfsHc->Flush (UfsHc);
2214
2215 UfsStopExecCmd (Private, TransReq->Slot);
2216
2217 UfsReconcileDataTransferBuffer (Private, TransReq);
2218
2219 if (TransReq->CmdDescMapping != NULL) {
2220 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
2221 }
2222 if (TransReq->CmdDescHost != NULL) {
2223 UfsHc->FreeBuffer (
2224 UfsHc,
2225 EFI_SIZE_TO_PAGES (TransReq->CmdDescSize),
2226 TransReq->CmdDescHost
2227 );
2228 }
2229
2230 FreePool (TransReq);
2231
2232 gBS->SignalEvent (CallerEvent);
2233 return;
2234 }
2235
2236 /**
2237 Call back function when the timer event is signaled.
2238
2239 @param[in] Event The Event this notify function registered to.
2240 @param[in] Context Pointer to the context data registered to the Event.
2241
2242 **/
2243 VOID
2244 EFIAPI
2245 ProcessAsyncTaskList (
2246 IN EFI_EVENT Event,
2247 IN VOID *Context
2248 )
2249 {
2250 UFS_PASS_THRU_PRIVATE_DATA *Private;
2251 LIST_ENTRY *Entry;
2252 LIST_ENTRY *NextEntry;
2253 UFS_PASS_THRU_TRANS_REQ *TransReq;
2254 EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet;
2255 UTP_RESPONSE_UPIU *Response;
2256 UINT16 SenseDataLen;
2257 UINT32 ResTranCount;
2258 UINT32 SlotsMap;
2259 UINT32 Value;
2260 EFI_STATUS Status;
2261
2262 Private = (UFS_PASS_THRU_PRIVATE_DATA*) Context;
2263 SlotsMap = 0;
2264
2265 //
2266 // Check the entries in the async I/O queue are done or not.
2267 //
2268 if (!IsListEmpty(&Private->Queue)) {
2269 EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
2270 TransReq = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
2271 Packet = TransReq->Packet;
2272
2273 if ((SlotsMap & (BIT0 << TransReq->Slot)) != 0) {
2274 return;
2275 }
2276 SlotsMap |= BIT0 << TransReq->Slot;
2277
2278 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Value);
2279 if (EFI_ERROR (Status)) {
2280 //
2281 // TODO: Should find/add a proper host adapter return status for this
2282 // case.
2283 //
2284 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
2285 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));
2286 SignalCallerEvent (Private, TransReq);
2287 continue;
2288 }
2289
2290 if ((Value & (BIT0 << TransReq->Slot)) != 0) {
2291 //
2292 // Scsi cmd not finished yet.
2293 //
2294 if (TransReq->TimeoutRemain > UFS_HC_ASYNC_TIMER) {
2295 TransReq->TimeoutRemain -= UFS_HC_ASYNC_TIMER;
2296 continue;
2297 } else {
2298 //
2299 // Timeout occurs.
2300 //
2301 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
2302 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));
2303 SignalCallerEvent (Private, TransReq);
2304 continue;
2305 }
2306 } else {
2307 //
2308 // Scsi cmd finished.
2309 //
2310 // Get sense data if exists
2311 //
2312 Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
2313 ASSERT (Response != NULL);
2314 SenseDataLen = Response->SenseDataLen;
2315 SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
2316
2317 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
2318 //
2319 // Make sure the hardware device does not return more data than expected.
2320 //
2321 if (SenseDataLen <= Packet->SenseDataLength) {
2322 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
2323 Packet->SenseDataLength = (UINT8)SenseDataLen;
2324 } else {
2325 Packet->SenseDataLength = 0;
2326 }
2327 }
2328
2329 //
2330 // Check the transfer request result.
2331 //
2332 Packet->TargetStatus = Response->Status;
2333 if (Response->Response != 0) {
2334 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));
2335 SignalCallerEvent (Private, TransReq);
2336 continue;
2337 }
2338
2339 if (TransReq->Trd->Ocs == 0) {
2340 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
2341 if ((Response->Flags & BIT5) == BIT5) {
2342 ResTranCount = Response->ResTranCount;
2343 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
2344 Packet->InTransferLength -= ResTranCount;
2345 }
2346 } else {
2347 if ((Response->Flags & BIT5) == BIT5) {
2348 ResTranCount = Response->ResTranCount;
2349 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
2350 Packet->OutTransferLength -= ResTranCount;
2351 }
2352 }
2353 } else {
2354 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));
2355 SignalCallerEvent (Private, TransReq);
2356 continue;
2357 }
2358
2359 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));
2360 SignalCallerEvent (Private, TransReq);
2361 }
2362 }
2363 }
2364 }
2365