2 This file implements ATA pass through transaction for ATA bus driver.
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.
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
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
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.
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
34 // Look up table (UdmaValid, IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL
36 EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols
[][2] = {
38 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN
,
39 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
42 EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN
,
43 EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT
,
48 // Look up table (UdmaValid, Lba48Bit, IsIsWrite) for ATA_CMD
50 UINT8 mAtaCommands
[][2][2] = {
53 ATA_CMD_READ_SECTORS
, // 28-bit LBA; PIO read
54 ATA_CMD_WRITE_SECTORS
// 28-bit LBA; PIO write
57 ATA_CMD_READ_SECTORS_EXT
, // 48-bit LBA; PIO read
58 ATA_CMD_WRITE_SECTORS_EXT
// 48-bit LBA; PIO write
63 ATA_CMD_READ_DMA
, // 28-bit LBA; DMA read
64 ATA_CMD_WRITE_DMA
// 28-bit LBA; DMA write
67 ATA_CMD_READ_DMA_EXT
, // 48-bit LBA; DMA read
68 ATA_CMD_WRITE_DMA_EXT
// 48-bit LBA; DMA write
74 // Look up table (UdmaValid, IsTrustSend) for ATA_CMD
76 UINT8 mAtaTrustCommands
[2][2] = {
78 ATA_CMD_TRUST_RECEIVE
, // PIO read
79 ATA_CMD_TRUST_SEND
// PIO write
82 ATA_CMD_TRUST_RECEIVE_DMA
, // DMA read
83 ATA_CMD_TRUST_SEND_DMA
// DMA write
89 // Look up table (Lba48Bit) for maximum transfer block number
91 UINTN mMaxTransferBlockNumber
[] = {
92 MAX_28BIT_TRANSFER_BLOCK_NUM
,
93 MAX_48BIT_TRANSFER_BLOCK_NUM
98 Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
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
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.
115 @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
120 IN OUT ATA_DEVICE
*AtaDevice
,
121 IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET
*TaskPacket
, OPTIONAL
122 IN OUT EFI_EVENT Event OPTIONAL
126 EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
;
127 EFI_ATA_PASS_THRU_COMMAND_PACKET
*Packet
;
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.
133 if (TaskPacket
!= NULL
) {
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
);
139 Packet
= &AtaDevice
->Packet
;
140 Packet
->Asb
= AtaDevice
->Asb
;
141 Packet
->Acb
= &AtaDevice
->Acb
;
144 AtaPassThru
= AtaDevice
->AtaBusDriverData
->AtaPassThru
;
146 Status
= AtaPassThru
->PassThru (
149 AtaDevice
->PortMultiplierPort
,
154 // Ensure ATA pass through caller and callee have the same
155 // interpretation of ATA pass through protocol.
157 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
158 ASSERT (Status
!= EFI_BAD_BUFFER_SIZE
);
165 Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.ResetDevice().
167 This function wraps the ResetDevice() invocation for ATA pass through function
170 @param AtaDevice The ATA child device involved for the operation.
172 @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
177 IN ATA_DEVICE
*AtaDevice
180 EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
;
182 AtaPassThru
= AtaDevice
->AtaBusDriverData
->AtaPassThru
;
184 return AtaPassThru
->ResetDevice (
187 AtaDevice
->PortMultiplierPort
193 Prints ATA model name to ATA device structure.
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.
199 @param AtaDevice The ATA child device involved for the operation.
204 IN OUT ATA_DEVICE
*AtaDevice
211 Source
= AtaDevice
->IdentifyData
->ModelName
;
212 Destination
= AtaDevice
->ModelName
;
215 // Swap the byte order in the original module name.
217 for (Index
= 0; Index
< MAX_MODEL_NAME_LEN
; Index
+= 2) {
218 Destination
[Index
] = Source
[Index
+ 1];
219 Destination
[Index
+ 1] = Source
[Index
];
221 AtaDevice
->ModelName
[MAX_MODEL_NAME_LEN
] = L
'\0';
226 Gets ATA device Capacity according to ATA 6.
228 This function returns the capacity of the ATA device if it follows
229 ATA 6 to support 48 bit addressing.
231 @param AtaDevice The ATA child device involved for the operation.
233 @return The capacity of the ATA device or 0 if the device does not support
234 48-bit addressing defined in ATA 6.
239 IN ATA_DEVICE
*AtaDevice
245 ATA_IDENTIFY_DATA
*IdentifyData
;
247 IdentifyData
= AtaDevice
->IdentifyData
;
248 if ((IdentifyData
->command_set_supported_83
& BIT10
) == 0) {
250 // The device doesn't support 48 bit addressing
256 // 48 bit address feature set is supported, get maximum capacity
259 for (Index
= 0; Index
< 4; Index
++) {
261 // Lower byte goes first: word[100] is the lowest word, word[103] is highest
263 TmpLba
= IdentifyData
->maximum_lba_for_48bit_addressing
[Index
];
264 Capacity
|= LShiftU64 (TmpLba
, 16 * Index
);
272 Identifies ATA device via the Identify data.
274 This function identifies the ATA device and initializes the Media information in
275 Block IO protocol interface.
277 @param AtaDevice The ATA child device involved for the operation.
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.
286 IN OUT ATA_DEVICE
*AtaDevice
289 ATA_IDENTIFY_DATA
*IdentifyData
;
290 EFI_BLOCK_IO_MEDIA
*BlockMedia
;
292 UINT16 PhyLogicSectorSupport
;
295 IdentifyData
= AtaDevice
->IdentifyData
;
297 if ((IdentifyData
->config
& BIT15
) != 0) {
299 // This is not an hard disk
301 return EFI_UNSUPPORTED
;
304 DEBUG ((EFI_D_INFO
, "AtaBus - Identify Device: Port %x PortMultiplierPort %x\n", AtaDevice
->Port
, AtaDevice
->PortMultiplierPort
));
307 // Check whether the WORD 88 (supported UltraDMA by drive) is valid
309 if ((IdentifyData
->field_validity
& BIT2
) != 0) {
310 UdmaMode
= IdentifyData
->ultra_dma_mode
;
311 if ((UdmaMode
& (BIT0
| BIT1
| BIT2
| BIT3
| BIT4
| BIT5
| BIT6
)) != 0) {
313 // If BIT0~BIT6 is selected, then UDMA is supported
315 AtaDevice
->UdmaValid
= TRUE
;
319 Capacity
= GetAtapi6Capacity (AtaDevice
);
320 if (Capacity
> MAX_28BIT_ADDRESSING_CAPACITY
) {
322 // Capacity exceeds 120GB. 48-bit addressing is really needed
324 AtaDevice
->Lba48Bit
= TRUE
;
327 // This is a hard disk <= 120GB capacity, treat it as normal hard disk
329 Capacity
= ((UINT32
)IdentifyData
->user_addressable_sectors_hi
<< 16) | IdentifyData
->user_addressable_sectors_lo
;
330 AtaDevice
->Lba48Bit
= FALSE
;
334 // Block Media Information:
336 BlockMedia
= &AtaDevice
->BlockMedia
;
337 BlockMedia
->LastBlock
= Capacity
- 1;
338 BlockMedia
->IoAlign
= AtaDevice
->AtaBusDriverData
->AtaPassThru
->Mode
->IoAlign
;
340 // Check whether Long Physical Sector Feature is supported
342 PhyLogicSectorSupport
= IdentifyData
->phy_logic_sector_support
;
343 if ((PhyLogicSectorSupport
& (BIT14
| BIT15
)) == BIT14
) {
345 // Check whether one physical block contains multiple physical blocks
347 if ((PhyLogicSectorSupport
& BIT13
) != 0) {
348 BlockMedia
->LogicalBlocksPerPhysicalBlock
= (UINT32
) (1 << (PhyLogicSectorSupport
& 0x000f));
350 // Check lowest alignment of logical blocks within physical block
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
);
358 // Check logical block size
360 if ((PhyLogicSectorSupport
& BIT12
) != 0) {
361 BlockMedia
->BlockSize
= (UINT32
) (((IdentifyData
->logic_sector_size_hi
<< 16) | IdentifyData
->logic_sector_size_lo
) * sizeof (UINT16
));
363 AtaDevice
->BlockIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
366 // Get ATA model name from identify data structure.
368 PrintAtaModelName (AtaDevice
);
375 Discovers whether it is a valid ATA device.
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.
381 @param AtaDevice The ATA child device involved for the operation.
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.
390 IN OUT ATA_DEVICE
*AtaDevice
394 EFI_ATA_COMMAND_BLOCK
*Acb
;
395 EFI_ATA_PASS_THRU_COMMAND_PACKET
*Packet
;
399 // Prepare for ATA command block.
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));
406 // Prepare for ATA pass through packet.
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
;
415 Retry
= MAX_RETRY_TIMES
;
417 Status
= AtaDevicePassThru (AtaDevice
, NULL
, NULL
);
418 if (!EFI_ERROR (Status
)) {
420 // The command is issued successfully
422 Status
= IdentifyAtaDevice (AtaDevice
);
423 if (!EFI_ERROR (Status
)) {
427 } while (Retry
-- > 0);
433 Transfer data from ATA device.
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.
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.
454 @retval EFI_SUCCESS The data transfer is complete successfully.
455 @return others Some error occurs when transferring data.
460 IN OUT ATA_DEVICE
*AtaDevice
,
461 IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET
*TaskPacket
, OPTIONAL
464 IN UINT32 TransferLength
,
466 IN EFI_EVENT Event OPTIONAL
469 EFI_ATA_COMMAND_BLOCK
*Acb
;
470 EFI_ATA_PASS_THRU_COMMAND_PACKET
*Packet
;
473 // Ensure AtaDevice->UdmaValid, AtaDevice->Lba48Bit and IsWrite are valid boolean values
475 ASSERT ((UINTN
) AtaDevice
->UdmaValid
< 2);
476 ASSERT ((UINTN
) AtaDevice
->Lba48Bit
< 2);
477 ASSERT ((UINTN
) IsWrite
< 2);
479 // Prepare for ATA command block.
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);
494 Acb
->AtaDeviceHead
= (UINT8
) (Acb
->AtaDeviceHead
| RShiftU64 (StartLba
, 24));
498 // Prepare for ATA pass through packet.
500 if (TaskPacket
!= NULL
) {
501 Packet
= ZeroMem (TaskPacket
, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET
));
503 Packet
= ZeroMem (&AtaDevice
->Packet
, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET
));
507 Packet
->OutDataBuffer
= Buffer
;
508 Packet
->OutTransferLength
= TransferLength
;
510 Packet
->InDataBuffer
= Buffer
;
511 Packet
->InTransferLength
= TransferLength
;
514 Packet
->Protocol
= mAtaPassThruCmdProtocols
[AtaDevice
->UdmaValid
][IsWrite
];
515 Packet
->Length
= EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT
;
516 Packet
->Timeout
= ATA_TIMEOUT
;
518 return AtaDevicePassThru (AtaDevice
, TaskPacket
, Event
);
524 @param[in, out] Task Pointer to task to be freed.
530 IN OUT ATA_BUS_ASYN_TASK
*Task
533 if (Task
->Packet
.Asb
!= NULL
) {
534 FreeAlignedBuffer (Task
->Packet
.Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
536 if (Task
->Packet
.Acb
!= NULL
) {
537 FreePool (Task
->Packet
.Acb
);
544 Call back funtion when the event is signaled.
546 @param[in] Event The Event this notify function registered to.
547 @param[in] Context Pointer to the context data registered to the
553 AtaNonBlockingCallBack (
558 ATA_BUS_ASYN_TASK
*Task
;
560 Task
= (ATA_BUS_ASYN_TASK
*) Context
;
561 gBS
->CloseEvent (Event
);
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.
569 if ((!(*Task
->IsError
)) && ((Task
->Packet
.Asb
->AtaStatus
& 0x01) == 0x01)) {
570 Task
->Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
574 "NON-BLOCKING EVENT FINISHED!- STATUS = %r\n",
575 Task
->Token
->TransactionStatus
579 // Reduce the SubEventCount, till it comes to zero.
581 (*Task
->UnsignalledEventCount
) --;
582 DEBUG ((EFI_D_BLKIO
, "UnsignalledEventCount = %d\n", *Task
->UnsignalledEventCount
));
585 // Remove the SubTask from the Task list.
587 RemoveEntryList (&Task
->TaskEntry
);
588 if ((*Task
->UnsignalledEventCount
) == 0) {
590 // All Sub tasks are done, then signal the upper layer event.
591 // Except there is error during the sub task source allocation.
593 if (!(*Task
->IsError
)) {
594 gBS
->SignalEvent (Task
->Token
->Event
);
595 DEBUG ((EFI_D_BLKIO
, "Signal the upper layer event!\n"));
598 FreePool (Task
->UnsignalledEventCount
);
599 FreePool (Task
->IsError
);
604 "PACKET INFO: Write=%s, Length=%x, LowCylinder=%x, HighCylinder=%x, SectionNumber=%x\n",
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
613 // Free the buffer of SubTask.
615 FreeAtaSubTask (Task
);
619 Read or write a number of blocks from ATA device.
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
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.
632 @retval EFI_SUCCESS The data transfer is complete successfully.
633 @return others Some error occurs when transferring data.
638 IN OUT ATA_DEVICE
*AtaDevice
,
639 IN OUT UINT8
*Buffer
,
641 IN UINTN NumberOfBlocks
,
643 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
647 UINTN MaxTransferBlockNumber
;
648 UINTN TransferBlockNumber
;
652 ATA_BUS_ASYN_TASK
*Task
;
659 Status
= EFI_SUCCESS
;
667 // Ensure AtaDevice->Lba48Bit is a valid boolean value
669 ASSERT ((UINTN
) AtaDevice
->Lba48Bit
< 2);
670 MaxTransferBlockNumber
= mMaxTransferBlockNumber
[AtaDevice
->Lba48Bit
];
671 BlockSize
= AtaDevice
->BlockMedia
.BlockSize
;
674 // Initial the return status and shared account for Non Blocking.
676 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
677 Token
->TransactionStatus
= EFI_SUCCESS
;
679 EventCount
= AllocateZeroPool (sizeof (UINTN
));
680 if (EventCount
== NULL
) {
681 return EFI_OUT_OF_RESOURCES
;
684 IsError
= AllocateZeroPool (sizeof (BOOLEAN
));
685 if (IsError
== NULL
) {
686 FreePool (EventCount
);
687 return EFI_OUT_OF_RESOURCES
;
691 TempCount
= (NumberOfBlocks
+ MaxTransferBlockNumber
- 1) / MaxTransferBlockNumber
;
692 *EventCount
= TempCount
;
696 if (NumberOfBlocks
> MaxTransferBlockNumber
) {
697 TransferBlockNumber
= MaxTransferBlockNumber
;
698 NumberOfBlocks
-= MaxTransferBlockNumber
;
700 TransferBlockNumber
= NumberOfBlocks
;
705 // Create sub event for the sub ata task. Non-blocking mode.
707 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
711 Task
= AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK
));
713 Status
= EFI_OUT_OF_RESOURCES
;
717 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
718 Task
->UnsignalledEventCount
= EventCount
;
720 Task
->IsError
= IsError
;
721 InsertTailList (&AtaDevice
->AtaTaskList
, &Task
->TaskEntry
);
722 gBS
->RestoreTPL (OldTpl
);
724 Status
= gBS
->CreateEvent (
727 AtaNonBlockingCallBack
,
732 // If resource allocation fail, the un-signalled event count should equal to
733 // the original one minus the unassigned subtasks number.
735 if (EFI_ERROR (Status
)) {
736 Status
= EFI_OUT_OF_RESOURCES
;
740 Status
= TransferAtaDevice (AtaDevice
, &Task
->Packet
, Buffer
, StartLba
, (UINT32
) TransferBlockNumber
, IsWrite
, SubEvent
);
745 Status
= TransferAtaDevice (AtaDevice
, NULL
, Buffer
, StartLba
, (UINT32
) TransferBlockNumber
, IsWrite
, NULL
);
748 if (EFI_ERROR (Status
)) {
753 StartLba
+= TransferBlockNumber
;
754 Buffer
+= TransferBlockNumber
* BlockSize
;
755 } while (NumberOfBlocks
> 0);
758 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
760 // Release resource at non-blocking mode.
762 if (EFI_ERROR (Status
)) {
763 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
764 Token
->TransactionStatus
= Status
;
765 *EventCount
= (*EventCount
) - (TempCount
- Index
);
768 if (*EventCount
== 0) {
769 FreePool (EventCount
);
774 RemoveEntryList (&Task
->TaskEntry
);
775 FreeAtaSubTask (Task
);
778 if (SubEvent
!= NULL
) {
779 gBS
->CloseEvent (SubEvent
);
782 gBS
->RestoreTPL (OldTpl
);
790 Trust transfer data from/to ATA device.
792 This function performs one ATA pass through transaction to do a trust transfer from/to
793 ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
794 interface of ATA pass through.
796 @param AtaDevice The ATA child device involved for the operation.
797 @param Buffer The pointer to the current transaction buffer.
798 @param SecurityProtocolId The value of the "Security Protocol" parameter of
799 the security protocol command to be sent.
800 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
801 of the security protocol command to be sent.
802 @param TransferLength The block number or sector count of the transfer.
803 @param IsTrustSend Indicates whether it is a trust send operation or not.
804 @param Timeout The timeout, in 100ns units, to use for the execution
805 of the security protocol command. A Timeout value of 0
806 means that this function will wait indefinitely for the
807 security protocol command to execute. If Timeout is greater
808 than zero, then this function will return EFI_TIMEOUT
809 if the time required to execute the receive data command
810 is greater than Timeout.
811 @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data
812 written to the buffer. Ignore it when IsTrustSend is TRUE.
814 @retval EFI_SUCCESS The data transfer is complete successfully.
815 @return others Some error occurs when transferring data.
820 TrustTransferAtaDevice (
821 IN OUT ATA_DEVICE
*AtaDevice
,
823 IN UINT8 SecurityProtocolId
,
824 IN UINT16 SecurityProtocolSpecificData
,
825 IN UINTN TransferLength
,
826 IN BOOLEAN IsTrustSend
,
828 OUT UINTN
*TransferLengthOut
831 EFI_ATA_COMMAND_BLOCK
*Acb
;
832 EFI_ATA_PASS_THRU_COMMAND_PACKET
*Packet
;
835 EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
;
838 // Ensure AtaDevice->UdmaValid and IsTrustSend are valid boolean values
840 ASSERT ((UINTN
) AtaDevice
->UdmaValid
< 2);
841 ASSERT ((UINTN
) IsTrustSend
< 2);
843 // Prepare for ATA command block.
845 Acb
= ZeroMem (&AtaDevice
->Acb
, sizeof (EFI_ATA_COMMAND_BLOCK
));
846 if (TransferLength
== 0) {
847 Acb
->AtaCommand
= ATA_CMD_TRUST_NON_DATA
;
849 Acb
->AtaCommand
= mAtaTrustCommands
[AtaDevice
->UdmaValid
][IsTrustSend
];
851 Acb
->AtaFeatures
= SecurityProtocolId
;
852 Acb
->AtaSectorCount
= (UINT8
) (TransferLength
/ 512);
853 Acb
->AtaSectorNumber
= (UINT8
) ((TransferLength
/ 512) >> 8);
855 // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
856 // Here use big endian for Cylinder register.
858 Acb
->AtaCylinderHigh
= (UINT8
) SecurityProtocolSpecificData
;
859 Acb
->AtaCylinderLow
= (UINT8
) (SecurityProtocolSpecificData
>> 8);
860 Acb
->AtaDeviceHead
= (UINT8
) (BIT7
| BIT6
| BIT5
| (AtaDevice
->PortMultiplierPort
<< 4));
863 // Prepare for ATA pass through packet.
865 Packet
= ZeroMem (&AtaDevice
->Packet
, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET
));
866 if (TransferLength
== 0) {
867 Packet
->InTransferLength
= 0;
868 Packet
->OutTransferLength
= 0;
869 Packet
->Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA
;
870 } else if (IsTrustSend
) {
872 // Check the alignment of the incoming buffer prior to invoking underlying ATA PassThru
874 AtaPassThru
= AtaDevice
->AtaBusDriverData
->AtaPassThru
;
875 if ((AtaPassThru
->Mode
->IoAlign
> 1) && !IS_ALIGNED (Buffer
, AtaPassThru
->Mode
->IoAlign
)) {
876 NewBuffer
= AllocateAlignedBuffer (AtaDevice
, TransferLength
);
877 CopyMem (NewBuffer
, Buffer
, TransferLength
);
881 Packet
->OutDataBuffer
= Buffer
;
882 Packet
->OutTransferLength
= (UINT32
) TransferLength
;
883 Packet
->Protocol
= mAtaPassThruCmdProtocols
[AtaDevice
->UdmaValid
][IsTrustSend
];
885 Packet
->InDataBuffer
= Buffer
;
886 Packet
->InTransferLength
= (UINT32
) TransferLength
;
887 Packet
->Protocol
= mAtaPassThruCmdProtocols
[AtaDevice
->UdmaValid
][IsTrustSend
];
889 Packet
->Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
890 Packet
->Timeout
= Timeout
;
892 Status
= AtaDevicePassThru (AtaDevice
, NULL
, NULL
);
893 if (TransferLengthOut
!= NULL
) {
895 *TransferLengthOut
= Packet
->InTransferLength
;