]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
MdeModulePkg/AtaBus: wait up to 30s for ATA cmd response in Standby/Idle mode to...
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaBusDxe / AtaPassThruExecute.c
CommitLineData
ad86a50a 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
c24097a5 6 through command and protocol.\r
7\r
3c063fed 8 NOTE: This file also implements the StorageSecurityCommandProtocol(SSP). For input\r
58727f29 9 parameter SecurityProtocolSpecificData, ATA spec has no explicitly definition\r
10 for Security Protocol Specific layout. This implementation uses big endian for\r
c24097a5 11 Cylinder register.\r
58727f29 12\r
8e1f0612 13 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 14 This program and the accompanying materials\r
ad86a50a 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
c24097a5 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
ad86a50a 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
c24097a5 73//\r
74// Look up table (UdmaValid, IsTrustSend) for ATA_CMD\r
75//\r
58727f29 76UINT8 mAtaTrustCommands[2][2] = {\r
c24097a5 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
ad86a50a 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
490b5ea1 104 @param[in, out] AtaDevice The ATA child device involved for the operation.\r
58727f29 105 @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,\r
490b5ea1 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
86d8e199 109 @param[in, out] Event If Event is NULL, then blocking I/O is performed.\r
490b5ea1 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
ad86a50a 114\r
115 @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().\r
116\r
117**/\r
118EFI_STATUS\r
119AtaDevicePassThru (\r
490b5ea1 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
ad86a50a 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
58727f29 130 // Assemble packet. If it is non blocking mode, the Ata driver should keep each\r
490b5ea1 131 // subtask and clean them when the event is signaled.\r
ad86a50a 132 //\r
490b5ea1 133 if (TaskPacket != NULL) {\r
134 Packet = TaskPacket;\r
3c063fed 135 Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (EFI_ATA_STATUS_BLOCK));\r
3d267c70
ED
136 if (Packet->Asb == NULL) {\r
137 return EFI_OUT_OF_RESOURCES;\r
138 }\r
139\r
3c063fed 140 CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
141 Packet->Acb = AllocateCopyPool (sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb);\r
490b5ea1 142 } else {\r
143 Packet = &AtaDevice->Packet;\r
144 Packet->Asb = AtaDevice->Asb;\r
145 Packet->Acb = &AtaDevice->Acb;\r
146 }\r
ad86a50a 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
490b5ea1 155 Event\r
ad86a50a 156 );\r
157 //\r
158 // Ensure ATA pass through caller and callee have the same\r
58727f29 159 // interpretation of ATA pass through protocol.\r
ad86a50a 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
58727f29 172 for an ATA device.\r
ad86a50a 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
58727f29 185\r
ad86a50a 186 AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
58727f29 187\r
37623a5c 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
ad86a50a 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
58727f29 208 This function converts ATA device model name from ATA identify data\r
ad86a50a 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
6ea8e37b 224 Source = AtaDevice->IdentifyData->ModelName;\r
ad86a50a 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
6ea8e37b 258 ATA_IDENTIFY_DATA *IdentifyData;\r
ad86a50a 259\r
6ea8e37b 260 IdentifyData = AtaDevice->IdentifyData;\r
261 if ((IdentifyData->command_set_supported_83 & BIT10) == 0) {\r
ad86a50a 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
6ea8e37b 276 TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index];\r
ad86a50a 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
58727f29 287 This function identifies the ATA device and initializes the Media information in\r
ad86a50a 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
6ea8e37b 302 ATA_IDENTIFY_DATA *IdentifyData;\r
ad86a50a 303 EFI_BLOCK_IO_MEDIA *BlockMedia;\r
304 EFI_LBA Capacity;\r
305 UINT16 PhyLogicSectorSupport;\r
306 UINT16 UdmaMode;\r
307\r
6ea8e37b 308 IdentifyData = AtaDevice->IdentifyData;\r
ad86a50a 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
25dd150b 317 DEBUG ((EFI_D_INFO, "AtaBus - Identify Device: Port %x PortMultiplierPort %x\n", AtaDevice->Port, AtaDevice->PortMultiplierPort));\r
490b5ea1 318\r
ad86a50a 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
907c1a00 351 BlockMedia->IoAlign = AtaDevice->AtaBusDriverData->AtaPassThru->Mode->IoAlign;\r
ad86a50a 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
c61f9362 366 BlockMedia->LowestAlignedLba = (EFI_LBA) ((BlockMedia->LogicalBlocksPerPhysicalBlock - ((UINT32)IdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) %\r
367 BlockMedia->LogicalBlocksPerPhysicalBlock);\r
ad86a50a 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
58727f29 379 // Get ATA model name from identify data structure.\r
ad86a50a 380 //\r
490b5ea1 381 PrintAtaModelName (AtaDevice);\r
ad86a50a 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
58727f29 398 @return others Some error occurs when discovering the ATA device.\r
ad86a50a 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
3c063fed 414 Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
ad86a50a 415 Acb->AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
490b5ea1 416 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
ad86a50a 417\r
418 //\r
419 // Prepare for ATA pass through packet.\r
420 //\r
3c063fed 421 Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
ad86a50a 422 Packet->InDataBuffer = AtaDevice->IdentifyData;\r
3c063fed 423 Packet->InTransferLength = sizeof (ATA_IDENTIFY_DATA);\r
ad86a50a 424 Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;\r
490b5ea1 425 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
426 Packet->Timeout = ATA_TIMEOUT;\r
ad86a50a 427\r
428 Retry = MAX_RETRY_TIMES;\r
429 do {\r
490b5ea1 430 Status = AtaDevicePassThru (AtaDevice, NULL, NULL);\r
ad86a50a 431 if (!EFI_ERROR (Status)) {\r
432 //\r
433 // The command is issued successfully\r
434 //\r
435 Status = IdentifyAtaDevice (AtaDevice);\r
0d5df2ab 436 return Status;\r
ad86a50a 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
490b5ea1 450 @param[in, out] AtaDevice The ATA child device involved for the operation.\r
58727f29 451 @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,\r
490b5ea1 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
ad86a50a 464\r
465 @retval EFI_SUCCESS The data transfer is complete successfully.\r
58727f29 466 @return others Some error occurs when transferring data.\r
ad86a50a 467\r
468**/\r
469EFI_STATUS\r
470TransferAtaDevice (\r
490b5ea1 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
58727f29 476 IN BOOLEAN IsWrite,\r
490b5ea1 477 IN EFI_EVENT Event OPTIONAL\r
ad86a50a 478 )\r
479{\r
480 EFI_ATA_COMMAND_BLOCK *Acb;\r
481 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;\r
482\r
423401f9 483 //\r
58727f29 484 // Ensure AtaDevice->UdmaValid, AtaDevice->Lba48Bit and IsWrite are valid boolean values\r
423401f9 485 //\r
61d4f8f9 486 ASSERT ((UINTN) AtaDevice->UdmaValid < 2);\r
423401f9 487 ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);\r
488 ASSERT ((UINTN) IsWrite < 2);\r
ad86a50a 489 //\r
490 // Prepare for ATA command block.\r
491 //\r
3c063fed 492 Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
ad86a50a 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
490b5ea1 497 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
423401f9 498 Acb->AtaSectorCount = (UINT8) TransferLength;\r
ad86a50a 499 if (AtaDevice->Lba48Bit) {\r
500 Acb->AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);\r
423401f9 501 Acb->AtaCylinderLowExp = (UINT8) RShiftU64 (StartLba, 32);\r
502 Acb->AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40);\r
503 Acb->AtaSectorCountExp = (UINT8) (TransferLength >> 8);\r
ad86a50a 504 } else {\r
505 Acb->AtaDeviceHead = (UINT8) (Acb->AtaDeviceHead | RShiftU64 (StartLba, 24));\r
506 }\r
ad86a50a 507\r
508 //\r
509 // Prepare for ATA pass through packet.\r
510 //\r
490b5ea1 511 if (TaskPacket != NULL) {\r
3c063fed 512 Packet = ZeroMem (TaskPacket, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
490b5ea1 513 } else {\r
3c063fed 514 Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
490b5ea1 515 }\r
516\r
ad86a50a 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
490b5ea1 524\r
ad86a50a 525 Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite];\r
526 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
9690325d 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
8e1f0612
FT
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
9690325d 547 //\r
548 if (AtaDevice->UdmaValid) {\r
549 //\r
550 // Calculate the maximum timeout value for DMA read/write operation.\r
551 //\r
8e1f0612 552 Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 2100000) + 31);\r
9690325d 553 } else {\r
554 //\r
555 // Calculate the maximum timeout value for PIO read/write operation\r
556 //\r
8e1f0612 557 Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 3300000) + 31);\r
9690325d 558 }\r
490b5ea1 559\r
560 return AtaDevicePassThru (AtaDevice, TaskPacket, Event);\r
561}\r
562\r
563/**\r
58727f29 564 Free SubTask.\r
490b5ea1 565\r
566 @param[in, out] Task Pointer to task to be freed.\r
567\r
568**/\r
569VOID\r
58727f29 570EFIAPI\r
490b5ea1 571FreeAtaSubTask (\r
58727f29 572 IN OUT ATA_BUS_ASYN_SUB_TASK *Task\r
490b5ea1 573 )\r
574{\r
575 if (Task->Packet.Asb != NULL) {\r
3c063fed 576 FreeAlignedBuffer (Task->Packet.Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
490b5ea1 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 Call back funtion when the event is signaled.\r
587\r
588 @param[in] Event The Event this notify function registered to.\r
3c063fed 589 @param[in] Context Pointer to the context data registered to the\r
490b5ea1 590 Event.\r
591\r
592**/\r
593VOID\r
58727f29 594EFIAPI\r
490b5ea1 595AtaNonBlockingCallBack (\r
596 IN EFI_EVENT Event,\r
597 IN VOID *Context\r
598 )\r
599{\r
58727f29 600 ATA_BUS_ASYN_SUB_TASK *Task;\r
601 ATA_BUS_ASYN_TASK *AtaTask;\r
602 ATA_DEVICE *AtaDevice;\r
603 LIST_ENTRY *Entry;\r
604 EFI_STATUS Status;\r
490b5ea1 605\r
58727f29 606 Task = (ATA_BUS_ASYN_SUB_TASK *) Context;\r
490b5ea1 607 gBS->CloseEvent (Event);\r
608\r
58727f29 609 AtaDevice = Task->AtaDevice;\r
610\r
490b5ea1 611 //\r
612 // Check the command status.\r
613 // If there is error during the sub task source allocation, the error status\r
614 // should be returned to the caller directly, so here the Task->Token may already\r
615 // be deleted by the caller and no need to update the status.\r
616 //\r
3c063fed 617 if ((!(*Task->IsError)) && ((Task->Packet.Asb->AtaStatus & 0x01) == 0x01)) {\r
490b5ea1 618 Task->Token->TransactionStatus = EFI_DEVICE_ERROR;\r
619 }\r
620 DEBUG ((\r
25dd150b
SZ
621 EFI_D_BLKIO,\r
622 "NON-BLOCKING EVENT FINISHED!- STATUS = %r\n",\r
490b5ea1 623 Task->Token->TransactionStatus\r
624 ));\r
625\r
626 //\r
627 // Reduce the SubEventCount, till it comes to zero.\r
628 //\r
629 (*Task->UnsignalledEventCount) --;\r
25dd150b 630 DEBUG ((EFI_D_BLKIO, "UnsignalledEventCount = %d\n", *Task->UnsignalledEventCount));\r
490b5ea1 631\r
632 //\r
633 // Remove the SubTask from the Task list.\r
634 //\r
635 RemoveEntryList (&Task->TaskEntry);\r
636 if ((*Task->UnsignalledEventCount) == 0) {\r
637 //\r
3c063fed 638 // All Sub tasks are done, then signal the upper layer event.\r
490b5ea1 639 // Except there is error during the sub task source allocation.\r
640 //\r
641 if (!(*Task->IsError)) {\r
642 gBS->SignalEvent (Task->Token->Event);\r
25dd150b 643 DEBUG ((EFI_D_BLKIO, "Signal the upper layer event!\n"));\r
490b5ea1 644 }\r
58727f29 645\r
490b5ea1 646 FreePool (Task->UnsignalledEventCount);\r
647 FreePool (Task->IsError);\r
58727f29 648\r
649\r
650 //\r
651 // Finish all subtasks and move to the next task in AtaTaskList.\r
652 //\r
653 if (!IsListEmpty (&AtaDevice->AtaTaskList)) {\r
654 Entry = GetFirstNode (&AtaDevice->AtaTaskList);\r
655 AtaTask = ATA_AYNS_TASK_FROM_ENTRY (Entry);\r
656 DEBUG ((EFI_D_BLKIO, "Start to embark a new Ata Task\n"));\r
657 DEBUG ((EFI_D_BLKIO, "AtaTask->NumberOfBlocks = %x; AtaTask->Token=%x\n", AtaTask->NumberOfBlocks, AtaTask->Token));\r
658 Status = AccessAtaDevice (\r
659 AtaTask->AtaDevice,\r
660 AtaTask->Buffer,\r
661 AtaTask->StartLba,\r
662 AtaTask->NumberOfBlocks,\r
663 AtaTask->IsWrite,\r
664 AtaTask->Token\r
665 );\r
666 if (EFI_ERROR (Status)) {\r
667 AtaTask->Token->TransactionStatus = Status;\r
668 gBS->SignalEvent (AtaTask->Token->Event);\r
669 }\r
670 RemoveEntryList (Entry);\r
671 FreePool (AtaTask);\r
672 }\r
490b5ea1 673 }\r
ad86a50a 674\r
490b5ea1 675 DEBUG ((\r
25dd150b
SZ
676 EFI_D_BLKIO,\r
677 "PACKET INFO: Write=%s, Length=%x, LowCylinder=%x, HighCylinder=%x, SectionNumber=%x\n",\r
490b5ea1 678 Task->Packet.OutDataBuffer != NULL ? L"YES" : L"NO",\r
679 Task->Packet.OutDataBuffer != NULL ? Task->Packet.OutTransferLength : Task->Packet.InTransferLength,\r
680 Task->Packet.Acb->AtaCylinderLow,\r
681 Task->Packet.Acb->AtaCylinderHigh,\r
682 Task->Packet.Acb->AtaSectorCount\r
683 ));\r
684\r
685 //\r
686 // Free the buffer of SubTask.\r
687 //\r
688 FreeAtaSubTask (Task);\r
ad86a50a 689}\r
690\r
691/**\r
692 Read or write a number of blocks from ATA device.\r
693\r
694 This function performs ATA pass through transactions to read/write data from/to\r
695 ATA device. It may separate the read/write request into several ATA pass through\r
696 transactions.\r
697\r
490b5ea1 698 @param[in, out] AtaDevice The ATA child device involved for the operation.\r
699 @param[in, out] Buffer The pointer to the current transaction buffer.\r
700 @param[in] StartLba The starting logical block address to be accessed.\r
701 @param[in] NumberOfBlocks The block number or sector count of the transfer.\r
702 @param[in] IsWrite Indicates whether it is a write operation.\r
703 @param[in, out] Token A pointer to the token associated with the transaction.\r
ad86a50a 704\r
705 @retval EFI_SUCCESS The data transfer is complete successfully.\r
58727f29 706 @return others Some error occurs when transferring data.\r
ad86a50a 707\r
708**/\r
58727f29 709EFI_STATUS\r
ad86a50a 710AccessAtaDevice(\r
711 IN OUT ATA_DEVICE *AtaDevice,\r
712 IN OUT UINT8 *Buffer,\r
713 IN EFI_LBA StartLba,\r
714 IN UINTN NumberOfBlocks,\r
490b5ea1 715 IN BOOLEAN IsWrite,\r
716 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
ad86a50a 717 )\r
718{\r
719 EFI_STATUS Status;\r
720 UINTN MaxTransferBlockNumber;\r
721 UINTN TransferBlockNumber;\r
722 UINTN BlockSize;\r
58727f29 723 ATA_BUS_ASYN_SUB_TASK *SubTask;\r
490b5ea1 724 UINTN *EventCount;\r
725 UINTN TempCount;\r
58727f29 726 ATA_BUS_ASYN_TASK *AtaTask;\r
490b5ea1 727 EFI_EVENT SubEvent;\r
728 UINTN Index;\r
729 BOOLEAN *IsError;\r
730 EFI_TPL OldTpl;\r
731\r
3c063fed 732 TempCount = 0;\r
733 Status = EFI_SUCCESS;\r
734 EventCount = NULL;\r
735 IsError = NULL;\r
736 Index = 0;\r
58727f29 737 SubTask = NULL;\r
3c063fed 738 SubEvent = NULL;\r
58727f29 739 AtaTask = NULL;\r
740 \r
423401f9 741 //\r
58727f29 742 // Ensure AtaDevice->Lba48Bit is a valid boolean value\r
423401f9 743 //\r
744 ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);\r
ad86a50a 745 MaxTransferBlockNumber = mMaxTransferBlockNumber[AtaDevice->Lba48Bit];\r
490b5ea1 746 BlockSize = AtaDevice->BlockMedia.BlockSize;\r
747\r
3c063fed 748 //\r
749 // Initial the return status and shared account for Non Blocking.\r
750 //\r
751 if ((Token != NULL) && (Token->Event != NULL)) {\r
58727f29 752 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
753 if (!IsListEmpty (&AtaDevice->AtaSubTaskList)) {\r
754 AtaTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK));\r
755 if (AtaTask == NULL) {\r
756 gBS->RestoreTPL (OldTpl);\r
757 return EFI_OUT_OF_RESOURCES;\r
758 }\r
759 AtaTask->AtaDevice = AtaDevice;\r
760 AtaTask->Buffer = Buffer;\r
761 AtaTask->IsWrite = IsWrite;\r
762 AtaTask->NumberOfBlocks = NumberOfBlocks;\r
763 AtaTask->Signature = ATA_TASK_SIGNATURE;\r
764 AtaTask->StartLba = StartLba;\r
765 AtaTask->Token = Token;\r
766\r
767 InsertTailList (&AtaDevice->AtaTaskList, &AtaTask->TaskEntry);\r
768 gBS->RestoreTPL (OldTpl);\r
769 return EFI_SUCCESS;\r
770 }\r
771 gBS->RestoreTPL (OldTpl);\r
3c063fed 772\r
58727f29 773 Token->TransactionStatus = EFI_SUCCESS;\r
3c063fed 774 EventCount = AllocateZeroPool (sizeof (UINTN));\r
775 if (EventCount == NULL) {\r
776 return EFI_OUT_OF_RESOURCES;\r
777 }\r
58727f29 778\r
3c063fed 779 IsError = AllocateZeroPool (sizeof (BOOLEAN));\r
780 if (IsError == NULL) {\r
781 FreePool (EventCount);\r
782 return EFI_OUT_OF_RESOURCES;\r
783 }\r
58727f29 784 DEBUG ((EFI_D_BLKIO, "Allocation IsError Addr=%x\n", IsError));\r
3c063fed 785 *IsError = FALSE;\r
3c063fed 786 TempCount = (NumberOfBlocks + MaxTransferBlockNumber - 1) / MaxTransferBlockNumber;\r
787 *EventCount = TempCount;\r
58727f29 788 DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, NumberOfBlocks=%x\n", NumberOfBlocks));\r
789 DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, MaxTransferBlockNumber=%x\n", MaxTransferBlockNumber));\r
790 DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, EventCount=%x\n", TempCount));\r
791 }else {\r
792 while (!IsListEmpty (&AtaDevice->AtaTaskList) || !IsListEmpty (&AtaDevice->AtaSubTaskList)) {\r
793 //\r
794 // Stall for 100us.\r
795 //\r
796 MicroSecondDelay (100);\r
797 }\r
3c063fed 798 }\r
490b5ea1 799\r
ad86a50a 800 do {\r
801 if (NumberOfBlocks > MaxTransferBlockNumber) {\r
802 TransferBlockNumber = MaxTransferBlockNumber;\r
490b5ea1 803 NumberOfBlocks -= MaxTransferBlockNumber;\r
ad86a50a 804 } else {\r
805 TransferBlockNumber = NumberOfBlocks;\r
3c063fed 806 NumberOfBlocks = 0;\r
ad86a50a 807 }\r
808\r
490b5ea1 809 //\r
3c063fed 810 // Create sub event for the sub ata task. Non-blocking mode.\r
490b5ea1 811 //\r
3c063fed 812 if ((Token != NULL) && (Token->Event != NULL)) {\r
58727f29 813 SubTask = NULL;\r
3c063fed 814 SubEvent = NULL;\r
815\r
58727f29 816 SubTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_SUB_TASK));\r
817 if (SubTask == NULL) {\r
3c063fed 818 Status = EFI_OUT_OF_RESOURCES;\r
490b5ea1 819 goto EXIT;\r
820 }\r
821\r
3c063fed 822 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
58727f29 823 SubTask->UnsignalledEventCount = EventCount;\r
824 SubTask->Signature = ATA_SUB_TASK_SIGNATURE;\r
825 SubTask->AtaDevice = AtaDevice;\r
826 SubTask->Token = Token;\r
827 SubTask->IsError = IsError;\r
828 InsertTailList (&AtaDevice->AtaSubTaskList, &SubTask->TaskEntry);\r
829 gBS->RestoreTPL (OldTpl);\r
490b5ea1 830\r
831 Status = gBS->CreateEvent (\r
832 EVT_NOTIFY_SIGNAL,\r
833 TPL_NOTIFY,\r
834 AtaNonBlockingCallBack,\r
58727f29 835 SubTask,\r
490b5ea1 836 &SubEvent\r
837 );\r
838 //\r
839 // If resource allocation fail, the un-signalled event count should equal to\r
840 // the original one minus the unassigned subtasks number.\r
841 //\r
842 if (EFI_ERROR (Status)) {\r
3c063fed 843 Status = EFI_OUT_OF_RESOURCES;\r
490b5ea1 844 goto EXIT;\r
845 }\r
490b5ea1 846\r
58727f29 847 Status = TransferAtaDevice (AtaDevice, &SubTask->Packet, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, SubEvent);\r
3c063fed 848 } else {\r
490b5ea1 849 //\r
850 // Blocking Mode.\r
851 //\r
58727f29 852 DEBUG ((EFI_D_BLKIO, "Blocking AccessAtaDevice, TransferBlockNumber=%x; StartLba = %x\n", TransferBlockNumber, StartLba));\r
490b5ea1 853 Status = TransferAtaDevice (AtaDevice, NULL, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, NULL);\r
490b5ea1 854 }\r
855\r
ad86a50a 856 if (EFI_ERROR (Status)) {\r
490b5ea1 857 goto EXIT;\r
ad86a50a 858 }\r
490b5ea1 859\r
3c063fed 860 Index++;\r
ad86a50a 861 StartLba += TransferBlockNumber;\r
862 Buffer += TransferBlockNumber * BlockSize;\r
863 } while (NumberOfBlocks > 0);\r
864\r
490b5ea1 865EXIT:\r
3c063fed 866 if ((Token != NULL) && (Token->Event != NULL)) {\r
867 //\r
868 // Release resource at non-blocking mode.\r
869 //\r
870 if (EFI_ERROR (Status)) {\r
871 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
872 Token->TransactionStatus = Status;\r
873 *EventCount = (*EventCount) - (TempCount - Index);\r
874 *IsError = TRUE;\r
58727f29 875\r
3c063fed 876 if (*EventCount == 0) {\r
877 FreePool (EventCount);\r
878 FreePool (IsError);\r
879 }\r
58727f29 880\r
881 if (SubTask != NULL) {\r
882 RemoveEntryList (&SubTask->TaskEntry);\r
883 FreeAtaSubTask (SubTask);\r
3c063fed 884 }\r
490b5ea1 885\r
3c063fed 886 if (SubEvent != NULL) {\r
58727f29 887 gBS->CloseEvent (SubEvent);\r
3c063fed 888 }\r
3c063fed 889 gBS->RestoreTPL (OldTpl);\r
890 }\r
58727f29 891 }\r
490b5ea1 892\r
ad86a50a 893 return Status;\r
894}\r
c24097a5 895\r
896/**\r
897 Trust transfer data from/to ATA device.\r
898\r
899 This function performs one ATA pass through transaction to do a trust transfer from/to\r
900 ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru\r
901 interface of ATA pass through.\r
902\r
903 @param AtaDevice The ATA child device involved for the operation.\r
904 @param Buffer The pointer to the current transaction buffer.\r
905 @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
906 the security protocol command to be sent.\r
907 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
908 of the security protocol command to be sent.\r
909 @param TransferLength The block number or sector count of the transfer.\r
910 @param IsTrustSend Indicates whether it is a trust send operation or not.\r
911 @param Timeout The timeout, in 100ns units, to use for the execution\r
912 of the security protocol command. A Timeout value of 0\r
913 means that this function will wait indefinitely for the\r
914 security protocol command to execute. If Timeout is greater\r
915 than zero, then this function will return EFI_TIMEOUT\r
916 if the time required to execute the receive data command\r
917 is greater than Timeout.\r
86d8e199 918 @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data\r
919 written to the buffer. Ignore it when IsTrustSend is TRUE.\r
c24097a5 920\r
921 @retval EFI_SUCCESS The data transfer is complete successfully.\r
58727f29 922 @return others Some error occurs when transferring data.\r
c24097a5 923\r
924**/\r
925EFI_STATUS\r
926EFIAPI\r
927TrustTransferAtaDevice (\r
928 IN OUT ATA_DEVICE *AtaDevice,\r
929 IN OUT VOID *Buffer,\r
930 IN UINT8 SecurityProtocolId,\r
931 IN UINT16 SecurityProtocolSpecificData,\r
932 IN UINTN TransferLength,\r
933 IN BOOLEAN IsTrustSend,\r
934 IN UINT64 Timeout,\r
935 OUT UINTN *TransferLengthOut\r
936 )\r
937{\r
938 EFI_ATA_COMMAND_BLOCK *Acb;\r
939 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;\r
940 EFI_STATUS Status;\r
941 VOID *NewBuffer;\r
942 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
943\r
944 //\r
58727f29 945 // Ensure AtaDevice->UdmaValid and IsTrustSend are valid boolean values\r
c24097a5 946 //\r
947 ASSERT ((UINTN) AtaDevice->UdmaValid < 2);\r
948 ASSERT ((UINTN) IsTrustSend < 2);\r
949 //\r
950 // Prepare for ATA command block.\r
951 //\r
3c063fed 952 Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
c24097a5 953 if (TransferLength == 0) {\r
954 Acb->AtaCommand = ATA_CMD_TRUST_NON_DATA;\r
955 } else {\r
956 Acb->AtaCommand = mAtaTrustCommands[AtaDevice->UdmaValid][IsTrustSend];\r
957 }\r
958 Acb->AtaFeatures = SecurityProtocolId;\r
959 Acb->AtaSectorCount = (UINT8) (TransferLength / 512);\r
960 Acb->AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8);\r
961 //\r
58727f29 962 // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.\r
963 // Here use big endian for Cylinder register.\r
c24097a5 964 //\r
965 Acb->AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData;\r
966 Acb->AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8);\r
58727f29 967 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
c24097a5 968\r
969 //\r
970 // Prepare for ATA pass through packet.\r
971 //\r
3c063fed 972 Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));\r
c24097a5 973 if (TransferLength == 0) {\r
974 Packet->InTransferLength = 0;\r
975 Packet->OutTransferLength = 0;\r
976 Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;\r
977 } else if (IsTrustSend) {\r
978 //\r
979 // Check the alignment of the incoming buffer prior to invoking underlying ATA PassThru\r
980 //\r
981 AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
982 if ((AtaPassThru->Mode->IoAlign > 1) && !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) {\r
983 NewBuffer = AllocateAlignedBuffer (AtaDevice, TransferLength);\r
3d267c70
ED
984 if (NewBuffer == NULL) {\r
985 return EFI_OUT_OF_RESOURCES;\r
986 }\r
987\r
c24097a5 988 CopyMem (NewBuffer, Buffer, TransferLength);\r
989 FreePool (Buffer);\r
990 Buffer = NewBuffer;\r
58727f29 991 }\r
c24097a5 992 Packet->OutDataBuffer = Buffer;\r
993 Packet->OutTransferLength = (UINT32) TransferLength;\r
994 Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];\r
995 } else {\r
996 Packet->InDataBuffer = Buffer;\r
997 Packet->InTransferLength = (UINT32) TransferLength;\r
998 Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];\r
999 }\r
1000 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
1001 Packet->Timeout = Timeout;\r
1002\r
1003 Status = AtaDevicePassThru (AtaDevice, NULL, NULL);\r
1004 if (TransferLengthOut != NULL) {\r
1005 if (! IsTrustSend) {\r
1006 *TransferLengthOut = Packet->InTransferLength;\r
1007 }\r
1008 }\r
1009 return Status;\r
1010}\r