]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
MdeModulePkg/AtaBus: remove TPer Reset operation in DriverBindingStart
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaBusDxe / AtaPassThruExecute.c
... / ...
CommitLineData
1/** @file\r
2 This file implements ATA pass through transaction for ATA bus driver.\r
3\r
4 This file implements the low level execution of ATA pass through transaction.\r
5 It transforms the high level identity, read/write, reset command to ATA pass\r
6 through command and protocol.\r
7\r
8 NOTE: This file also implements the StorageSecurityCommandProtocol(SSP). For input\r
9 parameter SecurityProtocolSpecificData, ATA spec has no explicitly definition\r
10 for Security Protocol Specific layout. This implementation uses big endian for\r
11 Cylinder register.\r
12\r
13 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
14 This program and the accompanying materials\r
15 are licensed and made available under the terms and conditions of the BSD License\r
16 which accompanies this distribution. The full text of the license may be found at\r
17 http://opensource.org/licenses/bsd-license.php\r
18\r
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
21\r
22\r
23**/\r
24\r
25#include "AtaBus.h"\r
26\r
27#define ATA_CMD_TRUST_NON_DATA 0x5B\r
28#define ATA_CMD_TRUST_RECEIVE 0x5C\r
29#define ATA_CMD_TRUST_RECEIVE_DMA 0x5D\r
30#define ATA_CMD_TRUST_SEND 0x5E\r
31#define ATA_CMD_TRUST_SEND_DMA 0x5F\r
32\r
33//\r
34// Look up table (UdmaValid, IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL\r
35//\r
36EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols[][2] = {\r
37 {\r
38 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN,\r
39 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT\r
40 },\r
41 {\r
42 EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN,\r
43 EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT,\r
44 }\r
45};\r
46\r
47//\r
48// Look up table (UdmaValid, Lba48Bit, IsIsWrite) for ATA_CMD\r
49//\r
50UINT8 mAtaCommands[][2][2] = {\r
51 {\r
52 {\r
53 ATA_CMD_READ_SECTORS, // 28-bit LBA; PIO read\r
54 ATA_CMD_WRITE_SECTORS // 28-bit LBA; PIO write\r
55 },\r
56 {\r
57 ATA_CMD_READ_SECTORS_EXT, // 48-bit LBA; PIO read\r
58 ATA_CMD_WRITE_SECTORS_EXT // 48-bit LBA; PIO write\r
59 }\r
60 },\r
61 {\r
62 {\r
63 ATA_CMD_READ_DMA, // 28-bit LBA; DMA read\r
64 ATA_CMD_WRITE_DMA // 28-bit LBA; DMA write\r
65 },\r
66 {\r
67 ATA_CMD_READ_DMA_EXT, // 48-bit LBA; DMA read\r
68 ATA_CMD_WRITE_DMA_EXT // 48-bit LBA; DMA write\r
69 }\r
70 }\r
71};\r
72\r
73//\r
74// Look up table (UdmaValid, IsTrustSend) for ATA_CMD\r
75//\r
76UINT8 mAtaTrustCommands[2][2] = {\r
77 {\r
78 ATA_CMD_TRUST_RECEIVE, // PIO read\r
79 ATA_CMD_TRUST_SEND // PIO write\r
80 },\r
81 {\r
82 ATA_CMD_TRUST_RECEIVE_DMA, // DMA read\r
83 ATA_CMD_TRUST_SEND_DMA // DMA write\r
84 }\r
85};\r
86\r
87\r
88//\r
89// Look up table (Lba48Bit) for maximum transfer block number\r
90//\r
91UINTN mMaxTransferBlockNumber[] = {\r
92 MAX_28BIT_TRANSFER_BLOCK_NUM,\r
93 MAX_48BIT_TRANSFER_BLOCK_NUM\r
94};\r
95\r
96\r
97/**\r
98 Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.PassThru().\r
99\r
100 This function wraps the PassThru() invocation for ATA pass through function\r
101 for an ATA device. It assembles the ATA pass through command packet for ATA\r
102 transaction.\r
103\r
104 @param[in, out] AtaDevice The ATA child device involved for the operation.\r
105 @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,\r
106 if it is NULL, blocking mode, and use the packet\r
107 in AtaDevice. If it is not NULL, non blocking mode,\r
108 and pass down this Packet.\r
109 @param[in, out] Event If Event is NULL, then blocking I/O is performed.\r
110 If Event is not NULL and non-blocking I/O is\r
111 supported,then non-blocking I/O is performed,\r
112 and Event will be signaled when the write\r
113 request is completed.\r
114\r
115 @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().\r
116\r
117**/\r
118EFI_STATUS\r
119AtaDevicePassThru (\r
120 IN OUT ATA_DEVICE *AtaDevice,\r
121 IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL\r
122 IN OUT EFI_EVENT Event OPTIONAL\r
123 )\r
124{\r
125 EFI_STATUS Status;\r
126 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
127 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;\r
128\r
129 //\r
130 // Assemble packet. If it is non blocking mode, the Ata driver should keep each\r
131 // subtask and clean them when the event is signaled.\r
132 //\r
133 if (TaskPacket != NULL) {\r
134 Packet = TaskPacket;\r
135 Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (EFI_ATA_STATUS_BLOCK));\r
136 if (Packet->Asb == NULL) {\r
137 return EFI_OUT_OF_RESOURCES;\r
138 }\r
139\r
140 CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
141 Packet->Acb = AllocateCopyPool (sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb);\r
142 } else {\r
143 Packet = &AtaDevice->Packet;\r
144 Packet->Asb = AtaDevice->Asb;\r
145 Packet->Acb = &AtaDevice->Acb;\r
146 }\r
147\r
148 AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
149\r
150 Status = AtaPassThru->PassThru (\r
151 AtaPassThru,\r
152 AtaDevice->Port,\r
153 AtaDevice->PortMultiplierPort,\r
154 Packet,\r
155 Event\r
156 );\r
157 //\r
158 // Ensure ATA pass through caller and callee have the same\r
159 // interpretation of ATA pass through protocol.\r
160 //\r
161 ASSERT (Status != EFI_INVALID_PARAMETER);\r
162 ASSERT (Status != EFI_BAD_BUFFER_SIZE);\r
163\r
164 return Status;\r
165}\r
166\r
167\r
168/**\r
169 Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.ResetDevice().\r
170\r
171 This function wraps the ResetDevice() invocation for ATA pass through function\r
172 for an ATA device.\r
173\r
174 @param AtaDevice The ATA child device involved for the operation.\r
175\r
176 @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().\r
177\r
178**/\r
179EFI_STATUS\r
180ResetAtaDevice (\r
181 IN ATA_DEVICE *AtaDevice\r
182 )\r
183{\r
184 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
185\r
186 AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
187\r
188 //\r
189 // Report Status Code to indicate reset happens\r
190 //\r
191 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
192 EFI_PROGRESS_CODE,\r
193 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
194 AtaDevice->AtaBusDriverData->ParentDevicePath\r
195 );\r
196\r
197 return AtaPassThru->ResetDevice (\r
198 AtaPassThru,\r
199 AtaDevice->Port,\r
200 AtaDevice->PortMultiplierPort\r
201 );\r
202}\r
203\r
204\r
205/**\r
206 Prints ATA model name to ATA device structure.\r
207\r
208 This function converts ATA device model name from ATA identify data\r
209 to a string in ATA device structure. It needs to change the character\r
210 order in the original model name string.\r
211\r
212 @param AtaDevice The ATA child device involved for the operation.\r
213\r
214**/\r
215VOID\r
216PrintAtaModelName (\r
217 IN OUT ATA_DEVICE *AtaDevice\r
218 )\r
219{\r
220 UINTN Index;\r
221 CHAR8 *Source;\r
222 CHAR16 *Destination;\r
223\r
224 Source = AtaDevice->IdentifyData->ModelName;\r
225 Destination = AtaDevice->ModelName;\r
226\r
227 //\r
228 // Swap the byte order in the original module name.\r
229 //\r
230 for (Index = 0; Index < MAX_MODEL_NAME_LEN; Index += 2) {\r
231 Destination[Index] = Source[Index + 1];\r
232 Destination[Index + 1] = Source[Index];\r
233 }\r
234 AtaDevice->ModelName[MAX_MODEL_NAME_LEN] = L'\0';\r
235}\r
236\r
237\r
238/**\r
239 Gets ATA device Capacity according to ATA 6.\r
240\r
241 This function returns the capacity of the ATA device if it follows\r
242 ATA 6 to support 48 bit addressing.\r
243\r
244 @param AtaDevice The ATA child device involved for the operation.\r
245\r
246 @return The capacity of the ATA device or 0 if the device does not support\r
247 48-bit addressing defined in ATA 6.\r
248\r
249**/\r
250EFI_LBA\r
251GetAtapi6Capacity (\r
252 IN ATA_DEVICE *AtaDevice\r
253 )\r
254{\r
255 EFI_LBA Capacity;\r
256 EFI_LBA TmpLba;\r
257 UINTN Index;\r
258 ATA_IDENTIFY_DATA *IdentifyData;\r
259\r
260 IdentifyData = AtaDevice->IdentifyData;\r
261 if ((IdentifyData->command_set_supported_83 & BIT10) == 0) {\r
262 //\r
263 // The device doesn't support 48 bit addressing\r
264 //\r
265 return 0;\r
266 }\r
267\r
268 //\r
269 // 48 bit address feature set is supported, get maximum capacity\r
270 //\r
271 Capacity = 0;\r
272 for (Index = 0; Index < 4; Index++) {\r
273 //\r
274 // Lower byte goes first: word[100] is the lowest word, word[103] is highest\r
275 //\r
276 TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index];\r
277 Capacity |= LShiftU64 (TmpLba, 16 * Index);\r
278 }\r
279\r
280 return Capacity;\r
281}\r
282\r
283\r
284/**\r
285 Identifies ATA device via the Identify data.\r
286\r
287 This function identifies the ATA device and initializes the Media information in\r
288 Block IO protocol interface.\r
289\r
290 @param AtaDevice The ATA child device involved for the operation.\r
291\r
292 @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).\r
293 @retval EFI_SUCCESS The device is successfully identified and Media information\r
294 is correctly initialized.\r
295\r
296**/\r
297EFI_STATUS\r
298IdentifyAtaDevice (\r
299 IN OUT ATA_DEVICE *AtaDevice\r
300 )\r
301{\r
302 ATA_IDENTIFY_DATA *IdentifyData;\r
303 EFI_BLOCK_IO_MEDIA *BlockMedia;\r
304 EFI_LBA Capacity;\r
305 UINT16 PhyLogicSectorSupport;\r
306 UINT16 UdmaMode;\r
307\r
308 IdentifyData = AtaDevice->IdentifyData;\r
309\r
310 if ((IdentifyData->config & BIT15) != 0) {\r
311 //\r
312 // This is not an hard disk\r
313 //\r
314 return EFI_UNSUPPORTED;\r
315 }\r
316\r
317 DEBUG ((EFI_D_INFO, "AtaBus - Identify Device: Port %x PortMultiplierPort %x\n", AtaDevice->Port, AtaDevice->PortMultiplierPort));\r
318\r
319 //\r
320 // Check whether the WORD 88 (supported UltraDMA by drive) is valid\r
321 //\r
322 if ((IdentifyData->field_validity & BIT2) != 0) {\r
323 UdmaMode = IdentifyData->ultra_dma_mode;\r
324 if ((UdmaMode & (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6)) != 0) {\r
325 //\r
326 // If BIT0~BIT6 is selected, then UDMA is supported\r
327 //\r
328 AtaDevice->UdmaValid = TRUE;\r
329 }\r
330 }\r
331\r
332 Capacity = GetAtapi6Capacity (AtaDevice);\r
333 if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {\r
334 //\r
335 // Capacity exceeds 120GB. 48-bit addressing is really needed\r
336 //\r
337 AtaDevice->Lba48Bit = TRUE;\r
338 } else {\r
339 //\r
340 // This is a hard disk <= 120GB capacity, treat it as normal hard disk\r
341 //\r
342 Capacity = ((UINT32)IdentifyData->user_addressable_sectors_hi << 16) | IdentifyData->user_addressable_sectors_lo;\r
343 AtaDevice->Lba48Bit = FALSE;\r
344 }\r
345\r
346 //\r
347 // Block Media Information:\r
348 //\r
349 BlockMedia = &AtaDevice->BlockMedia;\r
350 BlockMedia->LastBlock = Capacity - 1;\r
351 BlockMedia->IoAlign = AtaDevice->AtaBusDriverData->AtaPassThru->Mode->IoAlign;\r
352 //\r
353 // Check whether Long Physical Sector Feature is supported\r
354 //\r
355 PhyLogicSectorSupport = IdentifyData->phy_logic_sector_support;\r
356 if ((PhyLogicSectorSupport & (BIT14 | BIT15)) == BIT14) {\r
357 //\r
358 // Check whether one physical block contains multiple physical blocks\r
359 //\r
360 if ((PhyLogicSectorSupport & BIT13) != 0) {\r
361 BlockMedia->LogicalBlocksPerPhysicalBlock = (UINT32) (1 << (PhyLogicSectorSupport & 0x000f));\r
362 //\r
363 // Check lowest alignment of logical blocks within physical block\r
364 //\r
365 if ((IdentifyData->alignment_logic_in_phy_blocks & (BIT14 | BIT15)) == BIT14) {\r
366 BlockMedia->LowestAlignedLba = (EFI_LBA) ((BlockMedia->LogicalBlocksPerPhysicalBlock - ((UINT32)IdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) %\r
367 BlockMedia->LogicalBlocksPerPhysicalBlock);\r
368 }\r
369 }\r
370 //\r
371 // Check logical block size\r
372 //\r
373 if ((PhyLogicSectorSupport & BIT12) != 0) {\r
374 BlockMedia->BlockSize = (UINT32) (((IdentifyData->logic_sector_size_hi << 16) | IdentifyData->logic_sector_size_lo) * sizeof (UINT16));\r
375 }\r
376 AtaDevice->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;\r
377 }\r
378 //\r
379 // Get ATA model name from identify data structure.\r
380 //\r
381 PrintAtaModelName (AtaDevice);\r
382\r
383 return EFI_SUCCESS;\r
384}\r
385\r
386\r
387/**\r
388 Discovers whether it is a valid ATA device.\r
389\r
390 This function issues ATA_CMD_IDENTIFY_DRIVE command to the ATA device to identify it.\r
391 If the command is executed successfully, it then identifies it and initializes\r
392 the Media information in Block IO protocol interface.\r
393\r
394 @param AtaDevice The ATA child device involved for the operation.\r
395\r
396 @retval EFI_SUCCESS The device is successfully identified and Media information\r
397 is correctly initialized.\r
398 @return others Some error occurs when discovering the ATA device.\r
399\r
400**/\r
401EFI_STATUS\r
402DiscoverAtaDevice (\r
403 IN OUT ATA_DEVICE *AtaDevice\r
404 )\r
405{\r
406 EFI_STATUS Status;\r
407 EFI_ATA_COMMAND_BLOCK *Acb;\r
408 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;\r
409 UINTN Retry;\r
410\r
411 //\r
412 // Prepare for ATA command block.\r
413 //\r
414 Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
415 Acb->AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
416 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
417\r
418 //\r
419 // Prepare for ATA pass through packet.\r
420 //\r
421 Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
422 Packet->InDataBuffer = AtaDevice->IdentifyData;\r
423 Packet->InTransferLength = sizeof (ATA_IDENTIFY_DATA);\r
424 Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;\r
425 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
426 Packet->Timeout = ATA_TIMEOUT;\r
427\r
428 Retry = MAX_RETRY_TIMES;\r
429 do {\r
430 Status = AtaDevicePassThru (AtaDevice, NULL, NULL);\r
431 if (!EFI_ERROR (Status)) {\r
432 //\r
433 // The command is issued successfully\r
434 //\r
435 Status = IdentifyAtaDevice (AtaDevice);\r
436 return Status;\r
437 }\r
438 } while (Retry-- > 0);\r
439\r
440 return Status;\r
441}\r
442\r
443/**\r
444 Transfer data from ATA device.\r
445\r
446 This function performs one ATA pass through transaction to transfer data from/to\r
447 ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru\r
448 interface of ATA pass through.\r
449\r
450 @param[in, out] AtaDevice The ATA child device involved for the operation.\r
451 @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,\r
452 if it is NULL, blocking mode, and use the packet\r
453 in AtaDevice. If it is not NULL, non blocking mode,\r
454 and pass down this Packet.\r
455 @param[in, out] Buffer The pointer to the current transaction buffer.\r
456 @param[in] StartLba The starting logical block address to be accessed.\r
457 @param[in] TransferLength The block number or sector count of the transfer.\r
458 @param[in] IsWrite Indicates whether it is a write operation.\r
459 @param[in] Event If Event is NULL, then blocking I/O is performed.\r
460 If Event is not NULL and non-blocking I/O is\r
461 supported,then non-blocking I/O is performed,\r
462 and Event will be signaled when the write\r
463 request is completed.\r
464\r
465 @retval EFI_SUCCESS The data transfer is complete successfully.\r
466 @return others Some error occurs when transferring data.\r
467\r
468**/\r
469EFI_STATUS\r
470TransferAtaDevice (\r
471 IN OUT ATA_DEVICE *AtaDevice,\r
472 IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL\r
473 IN OUT VOID *Buffer,\r
474 IN EFI_LBA StartLba,\r
475 IN UINT32 TransferLength,\r
476 IN BOOLEAN IsWrite,\r
477 IN EFI_EVENT Event OPTIONAL\r
478 )\r
479{\r
480 EFI_ATA_COMMAND_BLOCK *Acb;\r
481 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;\r
482\r
483 //\r
484 // Ensure AtaDevice->UdmaValid, AtaDevice->Lba48Bit and IsWrite are valid boolean values\r
485 //\r
486 ASSERT ((UINTN) AtaDevice->UdmaValid < 2);\r
487 ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);\r
488 ASSERT ((UINTN) IsWrite < 2);\r
489 //\r
490 // Prepare for ATA command block.\r
491 //\r
492 Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
493 Acb->AtaCommand = mAtaCommands[AtaDevice->UdmaValid][AtaDevice->Lba48Bit][IsWrite];\r
494 Acb->AtaSectorNumber = (UINT8) StartLba;\r
495 Acb->AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8);\r
496 Acb->AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16);\r
497 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
498 Acb->AtaSectorCount = (UINT8) TransferLength;\r
499 if (AtaDevice->Lba48Bit) {\r
500 Acb->AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);\r
501 Acb->AtaCylinderLowExp = (UINT8) RShiftU64 (StartLba, 32);\r
502 Acb->AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40);\r
503 Acb->AtaSectorCountExp = (UINT8) (TransferLength >> 8);\r
504 } else {\r
505 Acb->AtaDeviceHead = (UINT8) (Acb->AtaDeviceHead | RShiftU64 (StartLba, 24));\r
506 }\r
507\r
508 //\r
509 // Prepare for ATA pass through packet.\r
510 //\r
511 if (TaskPacket != NULL) {\r
512 Packet = ZeroMem (TaskPacket, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
513 } else {\r
514 Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
515 }\r
516\r
517 if (IsWrite) {\r
518 Packet->OutDataBuffer = Buffer;\r
519 Packet->OutTransferLength = TransferLength;\r
520 } else {\r
521 Packet->InDataBuffer = Buffer;\r
522 Packet->InTransferLength = TransferLength;\r
523 }\r
524\r
525 Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite];\r
526 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
527 //\r
528 // |------------------------|-----------------|------------------------|-----------------|\r
529 // | ATA PIO Transfer Mode | Transfer Rate | ATA DMA Transfer Mode | Transfer Rate |\r
530 // |------------------------|-----------------|------------------------|-----------------|\r
531 // | PIO Mode 0 | 3.3Mbytes/sec | Single-word DMA Mode 0 | 2.1Mbytes/sec |\r
532 // |------------------------|-----------------|------------------------|-----------------|\r
533 // | PIO Mode 1 | 5.2Mbytes/sec | Single-word DMA Mode 1 | 4.2Mbytes/sec |\r
534 // |------------------------|-----------------|------------------------|-----------------|\r
535 // | PIO Mode 2 | 8.3Mbytes/sec | Single-word DMA Mode 2 | 8.4Mbytes/sec |\r
536 // |------------------------|-----------------|------------------------|-----------------|\r
537 // | PIO Mode 3 | 11.1Mbytes/sec | Multi-word DMA Mode 0 | 4.2Mbytes/sec |\r
538 // |------------------------|-----------------|------------------------|-----------------|\r
539 // | PIO Mode 4 | 16.6Mbytes/sec | Multi-word DMA Mode 1 | 13.3Mbytes/sec |\r
540 // |------------------------|-----------------|------------------------|-----------------|\r
541 //\r
542 // As AtaBus is used to manage ATA devices, we have to use the lowest transfer rate to\r
543 // calculate the possible maximum timeout value for each read/write operation.\r
544 // The timout value is rounded up to nearest integar and here an additional 30s is added\r
545 // to follow ATA spec in which it mentioned that the device may take up to 30s to respond\r
546 // commands in the Standby/Idle mode.\r
547 //\r
548 if (AtaDevice->UdmaValid) {\r
549 //\r
550 // Calculate the maximum timeout value for DMA read/write operation.\r
551 //\r
552 Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 2100000) + 31);\r
553 } else {\r
554 //\r
555 // Calculate the maximum timeout value for PIO read/write operation\r
556 //\r
557 Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 3300000) + 31);\r
558 }\r
559\r
560 return AtaDevicePassThru (AtaDevice, TaskPacket, Event);\r
561}\r
562\r
563/**\r
564 Free SubTask.\r
565\r
566 @param[in, out] Task Pointer to task to be freed.\r
567\r
568**/\r
569VOID\r
570EFIAPI\r
571FreeAtaSubTask (\r
572 IN OUT ATA_BUS_ASYN_SUB_TASK *Task\r
573 )\r
574{\r
575 if (Task->Packet.Asb != NULL) {\r
576 FreeAlignedBuffer (Task->Packet.Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
577 }\r
578 if (Task->Packet.Acb != NULL) {\r
579 FreePool (Task->Packet.Acb);\r
580 }\r
581\r
582 FreePool (Task);\r
583}\r
584\r
585/**\r
586 Terminate any in-flight non-blocking I/O requests by signaling an EFI_ABORTED\r
587 in the TransactionStatus member of the EFI_BLOCK_IO2_TOKEN for the non-blocking\r
588 I/O. After that it is safe to free any Token or Buffer data structures that\r
589 were allocated to initiate the non-blockingI/O requests that were in-flight for\r
590 this device.\r
591\r
592 @param[in] AtaDevice The ATA child device involved for the operation.\r
593\r
594**/\r
595VOID\r
596EFIAPI\r
597AtaTerminateNonBlockingTask (\r
598 IN ATA_DEVICE *AtaDevice\r
599 )\r
600{\r
601 BOOLEAN SubTaskEmpty;\r
602 EFI_TPL OldTpl;\r
603 ATA_BUS_ASYN_TASK *AtaTask;\r
604 LIST_ENTRY *Entry;\r
605 LIST_ENTRY *List;\r
606\r
607 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
608 //\r
609 // Abort all executing tasks from now.\r
610 //\r
611 AtaDevice->Abort = TRUE;\r
612\r
613 List = &AtaDevice->AtaTaskList;\r
614 for (Entry = GetFirstNode (List); !IsNull (List, Entry);) {\r
615 AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry);\r
616 AtaTask->Token->TransactionStatus = EFI_ABORTED;\r
617 gBS->SignalEvent (AtaTask->Token->Event);\r
618\r
619 Entry = RemoveEntryList (Entry);\r
620 FreePool (AtaTask);\r
621 }\r
622 gBS->RestoreTPL (OldTpl);\r
623\r
624 do {\r
625 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
626 //\r
627 // Wait for executing subtasks done.\r
628 //\r
629 SubTaskEmpty = IsListEmpty (&AtaDevice->AtaSubTaskList);\r
630 gBS->RestoreTPL (OldTpl);\r
631 } while (!SubTaskEmpty);\r
632\r
633 //\r
634 // Aborting operation has been done. From now on, don't need to abort normal operation.\r
635 // \r
636 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
637 AtaDevice->Abort = FALSE;\r
638 gBS->RestoreTPL (OldTpl);\r
639}\r
640\r
641/**\r
642 Call back funtion when the event is signaled.\r
643\r
644 @param[in] Event The Event this notify function registered to.\r
645 @param[in] Context Pointer to the context data registered to the\r
646 Event.\r
647\r
648**/\r
649VOID\r
650EFIAPI\r
651AtaNonBlockingCallBack (\r
652 IN EFI_EVENT Event,\r
653 IN VOID *Context\r
654 )\r
655{\r
656 ATA_BUS_ASYN_SUB_TASK *Task;\r
657 ATA_BUS_ASYN_TASK *AtaTask;\r
658 ATA_DEVICE *AtaDevice;\r
659 LIST_ENTRY *Entry;\r
660 EFI_STATUS Status;\r
661\r
662 Task = (ATA_BUS_ASYN_SUB_TASK *) Context;\r
663 gBS->CloseEvent (Event);\r
664\r
665 AtaDevice = Task->AtaDevice;\r
666\r
667 //\r
668 // Check the command status.\r
669 // If there is error during the sub task source allocation, the error status\r
670 // should be returned to the caller directly, so here the Task->Token may already\r
671 // be deleted by the caller and no need to update the status.\r
672 //\r
673 if ((!(*Task->IsError)) && ((Task->Packet.Asb->AtaStatus & 0x01) == 0x01)) {\r
674 Task->Token->TransactionStatus = EFI_DEVICE_ERROR;\r
675 }\r
676\r
677 if (AtaDevice->Abort) {\r
678 Task->Token->TransactionStatus = EFI_ABORTED;\r
679 }\r
680\r
681 DEBUG ((\r
682 EFI_D_BLKIO,\r
683 "NON-BLOCKING EVENT FINISHED!- STATUS = %r\n",\r
684 Task->Token->TransactionStatus\r
685 ));\r
686\r
687 //\r
688 // Reduce the SubEventCount, till it comes to zero.\r
689 //\r
690 (*Task->UnsignalledEventCount) --;\r
691 DEBUG ((EFI_D_BLKIO, "UnsignalledEventCount = %d\n", *Task->UnsignalledEventCount));\r
692\r
693 //\r
694 // Remove the SubTask from the Task list.\r
695 //\r
696 RemoveEntryList (&Task->TaskEntry);\r
697 if ((*Task->UnsignalledEventCount) == 0) {\r
698 //\r
699 // All Sub tasks are done, then signal the upper layer event.\r
700 // Except there is error during the sub task source allocation.\r
701 //\r
702 if (!(*Task->IsError)) {\r
703 gBS->SignalEvent (Task->Token->Event);\r
704 DEBUG ((EFI_D_BLKIO, "Signal the upper layer event!\n"));\r
705 }\r
706\r
707 FreePool (Task->UnsignalledEventCount);\r
708 FreePool (Task->IsError);\r
709\r
710\r
711 //\r
712 // Finish all subtasks and move to the next task in AtaTaskList.\r
713 //\r
714 if (!IsListEmpty (&AtaDevice->AtaTaskList)) {\r
715 Entry = GetFirstNode (&AtaDevice->AtaTaskList);\r
716 AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry);\r
717 DEBUG ((EFI_D_BLKIO, "Start to embark a new Ata Task\n"));\r
718 DEBUG ((EFI_D_BLKIO, "AtaTask->NumberOfBlocks = %x; AtaTask->Token=%x\n", AtaTask->NumberOfBlocks, AtaTask->Token));\r
719 Status = AccessAtaDevice (\r
720 AtaTask->AtaDevice,\r
721 AtaTask->Buffer,\r
722 AtaTask->StartLba,\r
723 AtaTask->NumberOfBlocks,\r
724 AtaTask->IsWrite,\r
725 AtaTask->Token\r
726 );\r
727 if (EFI_ERROR (Status)) {\r
728 AtaTask->Token->TransactionStatus = Status;\r
729 gBS->SignalEvent (AtaTask->Token->Event);\r
730 }\r
731 RemoveEntryList (Entry);\r
732 FreePool (AtaTask);\r
733 }\r
734 }\r
735\r
736 DEBUG ((\r
737 EFI_D_BLKIO,\r
738 "PACKET INFO: Write=%s, Length=%x, LowCylinder=%x, HighCylinder=%x, SectionNumber=%x\n",\r
739 Task->Packet.OutDataBuffer != NULL ? L"YES" : L"NO",\r
740 Task->Packet.OutDataBuffer != NULL ? Task->Packet.OutTransferLength : Task->Packet.InTransferLength,\r
741 Task->Packet.Acb->AtaCylinderLow,\r
742 Task->Packet.Acb->AtaCylinderHigh,\r
743 Task->Packet.Acb->AtaSectorCount\r
744 ));\r
745\r
746 //\r
747 // Free the buffer of SubTask.\r
748 //\r
749 FreeAtaSubTask (Task);\r
750}\r
751\r
752/**\r
753 Read or write a number of blocks from ATA device.\r
754\r
755 This function performs ATA pass through transactions to read/write data from/to\r
756 ATA device. It may separate the read/write request into several ATA pass through\r
757 transactions.\r
758\r
759 @param[in, out] AtaDevice The ATA child device involved for the operation.\r
760 @param[in, out] Buffer The pointer to the current transaction buffer.\r
761 @param[in] StartLba The starting logical block address to be accessed.\r
762 @param[in] NumberOfBlocks The block number or sector count of the transfer.\r
763 @param[in] IsWrite Indicates whether it is a write operation.\r
764 @param[in, out] Token A pointer to the token associated with the transaction.\r
765\r
766 @retval EFI_SUCCESS The data transfer is complete successfully.\r
767 @return others Some error occurs when transferring data.\r
768\r
769**/\r
770EFI_STATUS\r
771AccessAtaDevice(\r
772 IN OUT ATA_DEVICE *AtaDevice,\r
773 IN OUT UINT8 *Buffer,\r
774 IN EFI_LBA StartLba,\r
775 IN UINTN NumberOfBlocks,\r
776 IN BOOLEAN IsWrite,\r
777 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
778 )\r
779{\r
780 EFI_STATUS Status;\r
781 UINTN MaxTransferBlockNumber;\r
782 UINTN TransferBlockNumber;\r
783 UINTN BlockSize;\r
784 ATA_BUS_ASYN_SUB_TASK *SubTask;\r
785 UINTN *EventCount;\r
786 UINTN TempCount;\r
787 ATA_BUS_ASYN_TASK *AtaTask;\r
788 EFI_EVENT SubEvent;\r
789 UINTN Index;\r
790 BOOLEAN *IsError;\r
791 EFI_TPL OldTpl;\r
792\r
793 TempCount = 0;\r
794 Status = EFI_SUCCESS;\r
795 EventCount = NULL;\r
796 IsError = NULL;\r
797 Index = 0;\r
798 SubTask = NULL;\r
799 SubEvent = NULL;\r
800 AtaTask = NULL;\r
801\r
802 //\r
803 // Ensure AtaDevice->Lba48Bit is a valid boolean value\r
804 //\r
805 ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);\r
806 MaxTransferBlockNumber = mMaxTransferBlockNumber[AtaDevice->Lba48Bit];\r
807 BlockSize = AtaDevice->BlockMedia.BlockSize;\r
808\r
809 //\r
810 // Initial the return status and shared account for Non Blocking.\r
811 //\r
812 if ((Token != NULL) && (Token->Event != NULL)) {\r
813 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
814\r
815 if (!IsListEmpty (&AtaDevice->AtaSubTaskList)) {\r
816 AtaTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK));\r
817 if (AtaTask == NULL) {\r
818 gBS->RestoreTPL (OldTpl);\r
819 return EFI_OUT_OF_RESOURCES;\r
820 }\r
821 AtaTask->AtaDevice = AtaDevice;\r
822 AtaTask->Buffer = Buffer;\r
823 AtaTask->IsWrite = IsWrite;\r
824 AtaTask->NumberOfBlocks = NumberOfBlocks;\r
825 AtaTask->Signature = ATA_TASK_SIGNATURE;\r
826 AtaTask->StartLba = StartLba;\r
827 AtaTask->Token = Token;\r
828\r
829 InsertTailList (&AtaDevice->AtaTaskList, &AtaTask->TaskEntry);\r
830 gBS->RestoreTPL (OldTpl);\r
831 return EFI_SUCCESS;\r
832 }\r
833 gBS->RestoreTPL (OldTpl);\r
834\r
835 Token->TransactionStatus = EFI_SUCCESS;\r
836 EventCount = AllocateZeroPool (sizeof (UINTN));\r
837 if (EventCount == NULL) {\r
838 return EFI_OUT_OF_RESOURCES;\r
839 }\r
840\r
841 IsError = AllocateZeroPool (sizeof (BOOLEAN));\r
842 if (IsError == NULL) {\r
843 FreePool (EventCount);\r
844 return EFI_OUT_OF_RESOURCES;\r
845 }\r
846 DEBUG ((EFI_D_BLKIO, "Allocation IsError Addr=%x\n", IsError));\r
847 *IsError = FALSE;\r
848 TempCount = (NumberOfBlocks + MaxTransferBlockNumber - 1) / MaxTransferBlockNumber;\r
849 *EventCount = TempCount;\r
850 DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, NumberOfBlocks=%x\n", NumberOfBlocks));\r
851 DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, MaxTransferBlockNumber=%x\n", MaxTransferBlockNumber));\r
852 DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, EventCount=%x\n", TempCount));\r
853 } else {\r
854 while (!IsListEmpty (&AtaDevice->AtaTaskList) || !IsListEmpty (&AtaDevice->AtaSubTaskList)) {\r
855 //\r
856 // Stall for 100us.\r
857 //\r
858 MicroSecondDelay (100);\r
859 }\r
860 }\r
861\r
862 do {\r
863 if (NumberOfBlocks > MaxTransferBlockNumber) {\r
864 TransferBlockNumber = MaxTransferBlockNumber;\r
865 NumberOfBlocks -= MaxTransferBlockNumber;\r
866 } else {\r
867 TransferBlockNumber = NumberOfBlocks;\r
868 NumberOfBlocks = 0;\r
869 }\r
870\r
871 //\r
872 // Create sub event for the sub ata task. Non-blocking mode.\r
873 //\r
874 if ((Token != NULL) && (Token->Event != NULL)) {\r
875 SubTask = NULL;\r
876 SubEvent = NULL;\r
877\r
878 SubTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_SUB_TASK));\r
879 if (SubTask == NULL) {\r
880 Status = EFI_OUT_OF_RESOURCES;\r
881 goto EXIT;\r
882 }\r
883\r
884 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
885 SubTask->UnsignalledEventCount = EventCount;\r
886 SubTask->Signature = ATA_SUB_TASK_SIGNATURE;\r
887 SubTask->AtaDevice = AtaDevice;\r
888 SubTask->Token = Token;\r
889 SubTask->IsError = IsError;\r
890 InsertTailList (&AtaDevice->AtaSubTaskList, &SubTask->TaskEntry);\r
891 gBS->RestoreTPL (OldTpl);\r
892\r
893 Status = gBS->CreateEvent (\r
894 EVT_NOTIFY_SIGNAL,\r
895 TPL_NOTIFY,\r
896 AtaNonBlockingCallBack,\r
897 SubTask,\r
898 &SubEvent\r
899 );\r
900 //\r
901 // If resource allocation fail, the un-signalled event count should equal to\r
902 // the original one minus the unassigned subtasks number.\r
903 //\r
904 if (EFI_ERROR (Status)) {\r
905 Status = EFI_OUT_OF_RESOURCES;\r
906 goto EXIT;\r
907 }\r
908\r
909 Status = TransferAtaDevice (AtaDevice, &SubTask->Packet, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, SubEvent);\r
910 } else {\r
911 //\r
912 // Blocking Mode.\r
913 //\r
914 DEBUG ((EFI_D_BLKIO, "Blocking AccessAtaDevice, TransferBlockNumber=%x; StartLba = %x\n", TransferBlockNumber, StartLba));\r
915 Status = TransferAtaDevice (AtaDevice, NULL, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, NULL);\r
916 }\r
917\r
918 if (EFI_ERROR (Status)) {\r
919 goto EXIT;\r
920 }\r
921\r
922 Index++;\r
923 StartLba += TransferBlockNumber;\r
924 Buffer += TransferBlockNumber * BlockSize;\r
925 } while (NumberOfBlocks > 0);\r
926\r
927EXIT:\r
928 if ((Token != NULL) && (Token->Event != NULL)) {\r
929 //\r
930 // Release resource at non-blocking mode.\r
931 //\r
932 if (EFI_ERROR (Status)) {\r
933 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
934 Token->TransactionStatus = Status;\r
935 *EventCount = (*EventCount) - (TempCount - Index);\r
936 *IsError = TRUE;\r
937\r
938 if (*EventCount == 0) {\r
939 FreePool (EventCount);\r
940 FreePool (IsError);\r
941 }\r
942\r
943 if (SubTask != NULL) {\r
944 RemoveEntryList (&SubTask->TaskEntry);\r
945 FreeAtaSubTask (SubTask);\r
946 }\r
947\r
948 if (SubEvent != NULL) {\r
949 gBS->CloseEvent (SubEvent);\r
950 }\r
951 gBS->RestoreTPL (OldTpl);\r
952 }\r
953 }\r
954\r
955 return Status;\r
956}\r
957\r
958/**\r
959 Trust transfer data from/to ATA device.\r
960\r
961 This function performs one ATA pass through transaction to do a trust transfer from/to\r
962 ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru\r
963 interface of ATA pass through.\r
964\r
965 @param AtaDevice The ATA child device involved for the operation.\r
966 @param Buffer The pointer to the current transaction buffer.\r
967 @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
968 the security protocol command to be sent.\r
969 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
970 of the security protocol command to be sent.\r
971 @param TransferLength The block number or sector count of the transfer.\r
972 @param IsTrustSend Indicates whether it is a trust send operation or not.\r
973 @param Timeout The timeout, in 100ns units, to use for the execution\r
974 of the security protocol command. A Timeout value of 0\r
975 means that this function will wait indefinitely for the\r
976 security protocol command to execute. If Timeout is greater\r
977 than zero, then this function will return EFI_TIMEOUT\r
978 if the time required to execute the receive data command\r
979 is greater than Timeout.\r
980 @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data\r
981 written to the buffer. Ignore it when IsTrustSend is TRUE.\r
982\r
983 @retval EFI_SUCCESS The data transfer is complete successfully.\r
984 @return others Some error occurs when transferring data.\r
985\r
986**/\r
987EFI_STATUS\r
988EFIAPI\r
989TrustTransferAtaDevice (\r
990 IN OUT ATA_DEVICE *AtaDevice,\r
991 IN OUT VOID *Buffer,\r
992 IN UINT8 SecurityProtocolId,\r
993 IN UINT16 SecurityProtocolSpecificData,\r
994 IN UINTN TransferLength,\r
995 IN BOOLEAN IsTrustSend,\r
996 IN UINT64 Timeout,\r
997 OUT UINTN *TransferLengthOut\r
998 )\r
999{\r
1000 EFI_ATA_COMMAND_BLOCK *Acb;\r
1001 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;\r
1002 EFI_STATUS Status;\r
1003 VOID *NewBuffer;\r
1004 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
1005\r
1006 //\r
1007 // Ensure AtaDevice->UdmaValid and IsTrustSend are valid boolean values\r
1008 //\r
1009 ASSERT ((UINTN) AtaDevice->UdmaValid < 2);\r
1010 ASSERT ((UINTN) IsTrustSend < 2);\r
1011 //\r
1012 // Prepare for ATA command block.\r
1013 //\r
1014 Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
1015 if (TransferLength == 0) {\r
1016 Acb->AtaCommand = ATA_CMD_TRUST_NON_DATA;\r
1017 } else {\r
1018 Acb->AtaCommand = mAtaTrustCommands[AtaDevice->UdmaValid][IsTrustSend];\r
1019 }\r
1020 Acb->AtaFeatures = SecurityProtocolId;\r
1021 Acb->AtaSectorCount = (UINT8) (TransferLength / 512);\r
1022 Acb->AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8);\r
1023 //\r
1024 // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.\r
1025 // Here use big endian for Cylinder register.\r
1026 //\r
1027 Acb->AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData;\r
1028 Acb->AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8);\r
1029 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
1030\r
1031 //\r
1032 // Prepare for ATA pass through packet.\r
1033 //\r
1034 Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
1035 if (TransferLength == 0) {\r
1036 Packet->InTransferLength = 0;\r
1037 Packet->OutTransferLength = 0;\r
1038 Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;\r
1039 } else if (IsTrustSend) {\r
1040 //\r
1041 // Check the alignment of the incoming buffer prior to invoking underlying ATA PassThru\r
1042 //\r
1043 AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
1044 if ((AtaPassThru->Mode->IoAlign > 1) && !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) {\r
1045 NewBuffer = AllocateAlignedBuffer (AtaDevice, TransferLength);\r
1046 if (NewBuffer == NULL) {\r
1047 return EFI_OUT_OF_RESOURCES;\r
1048 }\r
1049\r
1050 CopyMem (NewBuffer, Buffer, TransferLength);\r
1051 FreePool (Buffer);\r
1052 Buffer = NewBuffer;\r
1053 }\r
1054 Packet->OutDataBuffer = Buffer;\r
1055 Packet->OutTransferLength = (UINT32) TransferLength;\r
1056 Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];\r
1057 } else {\r
1058 Packet->InDataBuffer = Buffer;\r
1059 Packet->InTransferLength = (UINT32) TransferLength;\r
1060 Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];\r
1061 }\r
1062 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
1063 Packet->Timeout = Timeout;\r
1064\r
1065 Status = AtaDevicePassThru (AtaDevice, NULL, NULL);\r
1066 if (TransferLengthOut != NULL) {\r
1067 if (! IsTrustSend) {\r
1068 *TransferLengthOut = Packet->InTransferLength;\r
1069 }\r
1070 }\r
1071 return Status;\r
1072}\r