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