summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2017-08-02 09:54:47 +0800
committerGuo Mang <mang.guo@intel.com>2017-09-05 19:45:08 +0800
commit6c128c65b5ec0e5b8b5a0ccb165f3afd29e485f8 (patch)
tree444372d92a0ae8991fe4d15eb3937df43690dfda /MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
parentb207c6434d7a5a4502975d322312e07017e8a8cb (diff)
downloadedk2-platforms-6c128c65b5ec0e5b8b5a0ccb165f3afd29e485f8.tar.xz
Remove core packages since we can get them from edk2 repository
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c')
-rw-r--r--MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c1072
1 files changed, 0 insertions, 1072 deletions
diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
deleted file mode 100644
index a3008f92d9..0000000000
--- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
+++ /dev/null
@@ -1,1072 +0,0 @@
-/** @file
- This file implements ATA pass through transaction for ATA bus driver.
-
- This file implements the low level execution of ATA pass through transaction.
- It transforms the high level identity, read/write, reset command to ATA pass
- through command and protocol.
-
- NOTE: This file also implements the StorageSecurityCommandProtocol(SSP). For input
- parameter SecurityProtocolSpecificData, ATA spec has no explicitly definition
- for Security Protocol Specific layout. This implementation uses big endian for
- Cylinder register.
-
- Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-
-**/
-
-#include "AtaBus.h"
-
-#define ATA_CMD_TRUST_NON_DATA 0x5B
-#define ATA_CMD_TRUST_RECEIVE 0x5C
-#define ATA_CMD_TRUST_RECEIVE_DMA 0x5D
-#define ATA_CMD_TRUST_SEND 0x5E
-#define ATA_CMD_TRUST_SEND_DMA 0x5F
-
-//
-// Look up table (UdmaValid, IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL
-//
-EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols[][2] = {
- {
- EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN,
- EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
- },
- {
- EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN,
- EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT,
- }
-};
-
-//
-// Look up table (UdmaValid, Lba48Bit, IsIsWrite) for ATA_CMD
-//
-UINT8 mAtaCommands[][2][2] = {
- {
- {
- ATA_CMD_READ_SECTORS, // 28-bit LBA; PIO read
- ATA_CMD_WRITE_SECTORS // 28-bit LBA; PIO write
- },
- {
- ATA_CMD_READ_SECTORS_EXT, // 48-bit LBA; PIO read
- ATA_CMD_WRITE_SECTORS_EXT // 48-bit LBA; PIO write
- }
- },
- {
- {
- ATA_CMD_READ_DMA, // 28-bit LBA; DMA read
- ATA_CMD_WRITE_DMA // 28-bit LBA; DMA write
- },
- {
- ATA_CMD_READ_DMA_EXT, // 48-bit LBA; DMA read
- ATA_CMD_WRITE_DMA_EXT // 48-bit LBA; DMA write
- }
- }
-};
-
-//
-// Look up table (UdmaValid, IsTrustSend) for ATA_CMD
-//
-UINT8 mAtaTrustCommands[2][2] = {
- {
- ATA_CMD_TRUST_RECEIVE, // PIO read
- ATA_CMD_TRUST_SEND // PIO write
- },
- {
- ATA_CMD_TRUST_RECEIVE_DMA, // DMA read
- ATA_CMD_TRUST_SEND_DMA // DMA write
- }
-};
-
-
-//
-// Look up table (Lba48Bit) for maximum transfer block number
-//
-UINTN mMaxTransferBlockNumber[] = {
- MAX_28BIT_TRANSFER_BLOCK_NUM,
- MAX_48BIT_TRANSFER_BLOCK_NUM
-};
-
-
-/**
- Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
-
- This function wraps the PassThru() invocation for ATA pass through function
- for an ATA device. It assembles the ATA pass through command packet for ATA
- transaction.
-
- @param[in, out] AtaDevice The ATA child device involved for the operation.
- @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,
- if it is NULL, blocking mode, and use the packet
- in AtaDevice. If it is not NULL, non blocking mode,
- and pass down this Packet.
- @param[in, out] Event If Event is NULL, then blocking I/O is performed.
- If Event is not NULL and non-blocking I/O is
- supported,then non-blocking I/O is performed,
- and Event will be signaled when the write
- request is completed.
-
- @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
-
-**/
-EFI_STATUS
-AtaDevicePassThru (
- IN OUT ATA_DEVICE *AtaDevice,
- IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL
- IN OUT EFI_EVENT Event OPTIONAL
- )
-{
- EFI_STATUS Status;
- EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
- EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
-
- //
- // Assemble packet. If it is non blocking mode, the Ata driver should keep each
- // subtask and clean them when the event is signaled.
- //
- if (TaskPacket != NULL) {
- Packet = TaskPacket;
- Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (EFI_ATA_STATUS_BLOCK));
- if (Packet->Asb == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (EFI_ATA_STATUS_BLOCK));
- Packet->Acb = AllocateCopyPool (sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb);
- } else {
- Packet = &AtaDevice->Packet;
- Packet->Asb = AtaDevice->Asb;
- Packet->Acb = &AtaDevice->Acb;
- }
-
- AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;
-
- Status = AtaPassThru->PassThru (
- AtaPassThru,
- AtaDevice->Port,
- AtaDevice->PortMultiplierPort,
- Packet,
- Event
- );
- //
- // Ensure ATA pass through caller and callee have the same
- // interpretation of ATA pass through protocol.
- //
- ASSERT (Status != EFI_INVALID_PARAMETER);
- ASSERT (Status != EFI_BAD_BUFFER_SIZE);
-
- return Status;
-}
-
-
-/**
- Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.ResetDevice().
-
- This function wraps the ResetDevice() invocation for ATA pass through function
- for an ATA device.
-
- @param AtaDevice The ATA child device involved for the operation.
-
- @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
-
-**/
-EFI_STATUS
-ResetAtaDevice (
- IN ATA_DEVICE *AtaDevice
- )
-{
- EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
-
- AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;
-
- //
- // Report Status Code to indicate reset happens
- //
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
- AtaDevice->AtaBusDriverData->ParentDevicePath
- );
-
- return AtaPassThru->ResetDevice (
- AtaPassThru,
- AtaDevice->Port,
- AtaDevice->PortMultiplierPort
- );
-}
-
-
-/**
- Prints ATA model name to ATA device structure.
-
- This function converts ATA device model name from ATA identify data
- to a string in ATA device structure. It needs to change the character
- order in the original model name string.
-
- @param AtaDevice The ATA child device involved for the operation.
-
-**/
-VOID
-PrintAtaModelName (
- IN OUT ATA_DEVICE *AtaDevice
- )
-{
- UINTN Index;
- CHAR8 *Source;
- CHAR16 *Destination;
-
- Source = AtaDevice->IdentifyData->ModelName;
- Destination = AtaDevice->ModelName;
-
- //
- // Swap the byte order in the original module name.
- //
- for (Index = 0; Index < MAX_MODEL_NAME_LEN; Index += 2) {
- Destination[Index] = Source[Index + 1];
- Destination[Index + 1] = Source[Index];
- }
- AtaDevice->ModelName[MAX_MODEL_NAME_LEN] = L'\0';
-}
-
-
-/**
- Gets ATA device Capacity according to ATA 6.
-
- This function returns the capacity of the ATA device if it follows
- ATA 6 to support 48 bit addressing.
-
- @param AtaDevice The ATA child device involved for the operation.
-
- @return The capacity of the ATA device or 0 if the device does not support
- 48-bit addressing defined in ATA 6.
-
-**/
-EFI_LBA
-GetAtapi6Capacity (
- IN ATA_DEVICE *AtaDevice
- )
-{
- EFI_LBA Capacity;
- EFI_LBA TmpLba;
- UINTN Index;
- ATA_IDENTIFY_DATA *IdentifyData;
-
- IdentifyData = AtaDevice->IdentifyData;
- if ((IdentifyData->command_set_supported_83 & BIT10) == 0) {
- //
- // The device doesn't support 48 bit addressing
- //
- return 0;
- }
-
- //
- // 48 bit address feature set is supported, get maximum capacity
- //
- Capacity = 0;
- for (Index = 0; Index < 4; Index++) {
- //
- // Lower byte goes first: word[100] is the lowest word, word[103] is highest
- //
- TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index];
- Capacity |= LShiftU64 (TmpLba, 16 * Index);
- }
-
- return Capacity;
-}
-
-
-/**
- Identifies ATA device via the Identify data.
-
- This function identifies the ATA device and initializes the Media information in
- Block IO protocol interface.
-
- @param AtaDevice The ATA child device involved for the operation.
-
- @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).
- @retval EFI_SUCCESS The device is successfully identified and Media information
- is correctly initialized.
-
-**/
-EFI_STATUS
-IdentifyAtaDevice (
- IN OUT ATA_DEVICE *AtaDevice
- )
-{
- ATA_IDENTIFY_DATA *IdentifyData;
- EFI_BLOCK_IO_MEDIA *BlockMedia;
- EFI_LBA Capacity;
- UINT16 PhyLogicSectorSupport;
- UINT16 UdmaMode;
-
- IdentifyData = AtaDevice->IdentifyData;
-
- if ((IdentifyData->config & BIT15) != 0) {
- //
- // This is not an hard disk
- //
- return EFI_UNSUPPORTED;
- }
-
- DEBUG ((EFI_D_INFO, "AtaBus - Identify Device: Port %x PortMultiplierPort %x\n", AtaDevice->Port, AtaDevice->PortMultiplierPort));
-
- //
- // Check whether the WORD 88 (supported UltraDMA by drive) is valid
- //
- if ((IdentifyData->field_validity & BIT2) != 0) {
- UdmaMode = IdentifyData->ultra_dma_mode;
- if ((UdmaMode & (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6)) != 0) {
- //
- // If BIT0~BIT6 is selected, then UDMA is supported
- //
- AtaDevice->UdmaValid = TRUE;
- }
- }
-
- Capacity = GetAtapi6Capacity (AtaDevice);
- if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {
- //
- // Capacity exceeds 120GB. 48-bit addressing is really needed
- //
- AtaDevice->Lba48Bit = TRUE;
- } else {
- //
- // This is a hard disk <= 120GB capacity, treat it as normal hard disk
- //
- Capacity = ((UINT32)IdentifyData->user_addressable_sectors_hi << 16) | IdentifyData->user_addressable_sectors_lo;
- AtaDevice->Lba48Bit = FALSE;
- }
-
- //
- // Block Media Information:
- //
- BlockMedia = &AtaDevice->BlockMedia;
- BlockMedia->LastBlock = Capacity - 1;
- BlockMedia->IoAlign = AtaDevice->AtaBusDriverData->AtaPassThru->Mode->IoAlign;
- //
- // Check whether Long Physical Sector Feature is supported
- //
- PhyLogicSectorSupport = IdentifyData->phy_logic_sector_support;
- if ((PhyLogicSectorSupport & (BIT14 | BIT15)) == BIT14) {
- //
- // Check whether one physical block contains multiple physical blocks
- //
- if ((PhyLogicSectorSupport & BIT13) != 0) {
- BlockMedia->LogicalBlocksPerPhysicalBlock = (UINT32) (1 << (PhyLogicSectorSupport & 0x000f));
- //
- // Check lowest alignment of logical blocks within physical block
- //
- if ((IdentifyData->alignment_logic_in_phy_blocks & (BIT14 | BIT15)) == BIT14) {
- BlockMedia->LowestAlignedLba = (EFI_LBA) ((BlockMedia->LogicalBlocksPerPhysicalBlock - ((UINT32)IdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) %
- BlockMedia->LogicalBlocksPerPhysicalBlock);
- }
- }
- //
- // Check logical block size
- //
- if ((PhyLogicSectorSupport & BIT12) != 0) {
- BlockMedia->BlockSize = (UINT32) (((IdentifyData->logic_sector_size_hi << 16) | IdentifyData->logic_sector_size_lo) * sizeof (UINT16));
- }
- AtaDevice->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;
- }
- //
- // Get ATA model name from identify data structure.
- //
- PrintAtaModelName (AtaDevice);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Discovers whether it is a valid ATA device.
-
- This function issues ATA_CMD_IDENTIFY_DRIVE command to the ATA device to identify it.
- If the command is executed successfully, it then identifies it and initializes
- the Media information in Block IO protocol interface.
-
- @param AtaDevice The ATA child device involved for the operation.
-
- @retval EFI_SUCCESS The device is successfully identified and Media information
- is correctly initialized.
- @return others Some error occurs when discovering the ATA device.
-
-**/
-EFI_STATUS
-DiscoverAtaDevice (
- IN OUT ATA_DEVICE *AtaDevice
- )
-{
- EFI_STATUS Status;
- EFI_ATA_COMMAND_BLOCK *Acb;
- EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
- UINTN Retry;
-
- //
- // Prepare for ATA command block.
- //
- Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
- Acb->AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
- Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));
-
- //
- // Prepare for ATA pass through packet.
- //
- Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
- Packet->InDataBuffer = AtaDevice->IdentifyData;
- Packet->InTransferLength = sizeof (ATA_IDENTIFY_DATA);
- Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;
- Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
- Packet->Timeout = ATA_TIMEOUT;
-
- Retry = MAX_RETRY_TIMES;
- do {
- Status = AtaDevicePassThru (AtaDevice, NULL, NULL);
- if (!EFI_ERROR (Status)) {
- //
- // The command is issued successfully
- //
- Status = IdentifyAtaDevice (AtaDevice);
- return Status;
- }
- } while (Retry-- > 0);
-
- return Status;
-}
-
-/**
- Transfer data from ATA device.
-
- This function performs one ATA pass through transaction to transfer data from/to
- ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
- interface of ATA pass through.
-
- @param[in, out] AtaDevice The ATA child device involved for the operation.
- @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,
- if it is NULL, blocking mode, and use the packet
- in AtaDevice. If it is not NULL, non blocking mode,
- and pass down this Packet.
- @param[in, out] Buffer The pointer to the current transaction buffer.
- @param[in] StartLba The starting logical block address to be accessed.
- @param[in] TransferLength The block number or sector count of the transfer.
- @param[in] IsWrite Indicates whether it is a write operation.
- @param[in] Event If Event is NULL, then blocking I/O is performed.
- If Event is not NULL and non-blocking I/O is
- supported,then non-blocking I/O is performed,
- and Event will be signaled when the write
- request is completed.
-
- @retval EFI_SUCCESS The data transfer is complete successfully.
- @return others Some error occurs when transferring data.
-
-**/
-EFI_STATUS
-TransferAtaDevice (
- IN OUT ATA_DEVICE *AtaDevice,
- IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL
- IN OUT VOID *Buffer,
- IN EFI_LBA StartLba,
- IN UINT32 TransferLength,
- IN BOOLEAN IsWrite,
- IN EFI_EVENT Event OPTIONAL
- )
-{
- EFI_ATA_COMMAND_BLOCK *Acb;
- EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
-
- //
- // Ensure AtaDevice->UdmaValid, AtaDevice->Lba48Bit and IsWrite are valid boolean values
- //
- ASSERT ((UINTN) AtaDevice->UdmaValid < 2);
- ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);
- ASSERT ((UINTN) IsWrite < 2);
- //
- // Prepare for ATA command block.
- //
- Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
- Acb->AtaCommand = mAtaCommands[AtaDevice->UdmaValid][AtaDevice->Lba48Bit][IsWrite];
- Acb->AtaSectorNumber = (UINT8) StartLba;
- Acb->AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8);
- Acb->AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16);
- Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));
- Acb->AtaSectorCount = (UINT8) TransferLength;
- if (AtaDevice->Lba48Bit) {
- Acb->AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);
- Acb->AtaCylinderLowExp = (UINT8) RShiftU64 (StartLba, 32);
- Acb->AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40);
- Acb->AtaSectorCountExp = (UINT8) (TransferLength >> 8);
- } else {
- Acb->AtaDeviceHead = (UINT8) (Acb->AtaDeviceHead | RShiftU64 (StartLba, 24));
- }
-
- //
- // Prepare for ATA pass through packet.
- //
- if (TaskPacket != NULL) {
- Packet = ZeroMem (TaskPacket, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
- } else {
- Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
- }
-
- if (IsWrite) {
- Packet->OutDataBuffer = Buffer;
- Packet->OutTransferLength = TransferLength;
- } else {
- Packet->InDataBuffer = Buffer;
- Packet->InTransferLength = TransferLength;
- }
-
- Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite];
- Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
- //
- // |------------------------|-----------------|------------------------|-----------------|
- // | ATA PIO Transfer Mode | Transfer Rate | ATA DMA Transfer Mode | Transfer Rate |
- // |------------------------|-----------------|------------------------|-----------------|
- // | PIO Mode 0 | 3.3Mbytes/sec | Single-word DMA Mode 0 | 2.1Mbytes/sec |
- // |------------------------|-----------------|------------------------|-----------------|
- // | PIO Mode 1 | 5.2Mbytes/sec | Single-word DMA Mode 1 | 4.2Mbytes/sec |
- // |------------------------|-----------------|------------------------|-----------------|
- // | PIO Mode 2 | 8.3Mbytes/sec | Single-word DMA Mode 2 | 8.4Mbytes/sec |
- // |------------------------|-----------------|------------------------|-----------------|
- // | PIO Mode 3 | 11.1Mbytes/sec | Multi-word DMA Mode 0 | 4.2Mbytes/sec |
- // |------------------------|-----------------|------------------------|-----------------|
- // | PIO Mode 4 | 16.6Mbytes/sec | Multi-word DMA Mode 1 | 13.3Mbytes/sec |
- // |------------------------|-----------------|------------------------|-----------------|
- //
- // As AtaBus is used to manage ATA devices, we have to use the lowest transfer rate to
- // calculate the possible maximum timeout value for each read/write operation.
- // The timout value is rounded up to nearest integar and here an additional 30s is added
- // to follow ATA spec in which it mentioned that the device may take up to 30s to respond
- // commands in the Standby/Idle mode.
- //
- if (AtaDevice->UdmaValid) {
- //
- // Calculate the maximum timeout value for DMA read/write operation.
- //
- Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 2100000) + 31);
- } else {
- //
- // Calculate the maximum timeout value for PIO read/write operation
- //
- Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 3300000) + 31);
- }
-
- return AtaDevicePassThru (AtaDevice, TaskPacket, Event);
-}
-
-/**
- Free SubTask.
-
- @param[in, out] Task Pointer to task to be freed.
-
-**/
-VOID
-EFIAPI
-FreeAtaSubTask (
- IN OUT ATA_BUS_ASYN_SUB_TASK *Task
- )
-{
- if (Task->Packet.Asb != NULL) {
- FreeAlignedBuffer (Task->Packet.Asb, sizeof (EFI_ATA_STATUS_BLOCK));
- }
- if (Task->Packet.Acb != NULL) {
- FreePool (Task->Packet.Acb);
- }
-
- FreePool (Task);
-}
-
-/**
- Terminate any in-flight non-blocking I/O requests by signaling an EFI_ABORTED
- in the TransactionStatus member of the EFI_BLOCK_IO2_TOKEN for the non-blocking
- I/O. After that it is safe to free any Token or Buffer data structures that
- were allocated to initiate the non-blockingI/O requests that were in-flight for
- this device.
-
- @param[in] AtaDevice The ATA child device involved for the operation.
-
-**/
-VOID
-EFIAPI
-AtaTerminateNonBlockingTask (
- IN ATA_DEVICE *AtaDevice
- )
-{
- BOOLEAN SubTaskEmpty;
- EFI_TPL OldTpl;
- ATA_BUS_ASYN_TASK *AtaTask;
- LIST_ENTRY *Entry;
- LIST_ENTRY *List;
-
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- //
- // Abort all executing tasks from now.
- //
- AtaDevice->Abort = TRUE;
-
- List = &AtaDevice->AtaTaskList;
- for (Entry = GetFirstNode (List); !IsNull (List, Entry);) {
- AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry);
- AtaTask->Token->TransactionStatus = EFI_ABORTED;
- gBS->SignalEvent (AtaTask->Token->Event);
-
- Entry = RemoveEntryList (Entry);
- FreePool (AtaTask);
- }
- gBS->RestoreTPL (OldTpl);
-
- do {
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- //
- // Wait for executing subtasks done.
- //
- SubTaskEmpty = IsListEmpty (&AtaDevice->AtaSubTaskList);
- gBS->RestoreTPL (OldTpl);
- } while (!SubTaskEmpty);
-
- //
- // Aborting operation has been done. From now on, don't need to abort normal operation.
- //
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- AtaDevice->Abort = FALSE;
- gBS->RestoreTPL (OldTpl);
-}
-
-/**
- Call back funtion when the event is signaled.
-
- @param[in] Event The Event this notify function registered to.
- @param[in] Context Pointer to the context data registered to the
- Event.
-
-**/
-VOID
-EFIAPI
-AtaNonBlockingCallBack (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- ATA_BUS_ASYN_SUB_TASK *Task;
- ATA_BUS_ASYN_TASK *AtaTask;
- ATA_DEVICE *AtaDevice;
- LIST_ENTRY *Entry;
- EFI_STATUS Status;
-
- Task = (ATA_BUS_ASYN_SUB_TASK *) Context;
- gBS->CloseEvent (Event);
-
- AtaDevice = Task->AtaDevice;
-
- //
- // Check the command status.
- // If there is error during the sub task source allocation, the error status
- // should be returned to the caller directly, so here the Task->Token may already
- // be deleted by the caller and no need to update the status.
- //
- if ((!(*Task->IsError)) && ((Task->Packet.Asb->AtaStatus & 0x01) == 0x01)) {
- Task->Token->TransactionStatus = EFI_DEVICE_ERROR;
- }
-
- if (AtaDevice->Abort) {
- Task->Token->TransactionStatus = EFI_ABORTED;
- }
-
- DEBUG ((
- EFI_D_BLKIO,
- "NON-BLOCKING EVENT FINISHED!- STATUS = %r\n",
- Task->Token->TransactionStatus
- ));
-
- //
- // Reduce the SubEventCount, till it comes to zero.
- //
- (*Task->UnsignalledEventCount) --;
- DEBUG ((EFI_D_BLKIO, "UnsignalledEventCount = %d\n", *Task->UnsignalledEventCount));
-
- //
- // Remove the SubTask from the Task list.
- //
- RemoveEntryList (&Task->TaskEntry);
- if ((*Task->UnsignalledEventCount) == 0) {
- //
- // All Sub tasks are done, then signal the upper layer event.
- // Except there is error during the sub task source allocation.
- //
- if (!(*Task->IsError)) {
- gBS->SignalEvent (Task->Token->Event);
- DEBUG ((EFI_D_BLKIO, "Signal the upper layer event!\n"));
- }
-
- FreePool (Task->UnsignalledEventCount);
- FreePool (Task->IsError);
-
-
- //
- // Finish all subtasks and move to the next task in AtaTaskList.
- //
- if (!IsListEmpty (&AtaDevice->AtaTaskList)) {
- Entry = GetFirstNode (&AtaDevice->AtaTaskList);
- AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry);
- DEBUG ((EFI_D_BLKIO, "Start to embark a new Ata Task\n"));
- DEBUG ((EFI_D_BLKIO, "AtaTask->NumberOfBlocks = %x; AtaTask->Token=%x\n", AtaTask->NumberOfBlocks, AtaTask->Token));
- Status = AccessAtaDevice (
- AtaTask->AtaDevice,
- AtaTask->Buffer,
- AtaTask->StartLba,
- AtaTask->NumberOfBlocks,
- AtaTask->IsWrite,
- AtaTask->Token
- );
- if (EFI_ERROR (Status)) {
- AtaTask->Token->TransactionStatus = Status;
- gBS->SignalEvent (AtaTask->Token->Event);
- }
- RemoveEntryList (Entry);
- FreePool (AtaTask);
- }
- }
-
- DEBUG ((
- EFI_D_BLKIO,
- "PACKET INFO: Write=%s, Length=%x, LowCylinder=%x, HighCylinder=%x, SectionNumber=%x\n",
- Task->Packet.OutDataBuffer != NULL ? L"YES" : L"NO",
- Task->Packet.OutDataBuffer != NULL ? Task->Packet.OutTransferLength : Task->Packet.InTransferLength,
- Task->Packet.Acb->AtaCylinderLow,
- Task->Packet.Acb->AtaCylinderHigh,
- Task->Packet.Acb->AtaSectorCount
- ));
-
- //
- // Free the buffer of SubTask.
- //
- FreeAtaSubTask (Task);
-}
-
-/**
- Read or write a number of blocks from ATA device.
-
- This function performs ATA pass through transactions to read/write data from/to
- ATA device. It may separate the read/write request into several ATA pass through
- transactions.
-
- @param[in, out] AtaDevice The ATA child device involved for the operation.
- @param[in, out] Buffer The pointer to the current transaction buffer.
- @param[in] StartLba The starting logical block address to be accessed.
- @param[in] NumberOfBlocks The block number or sector count of the transfer.
- @param[in] IsWrite Indicates whether it is a write operation.
- @param[in, out] Token A pointer to the token associated with the transaction.
-
- @retval EFI_SUCCESS The data transfer is complete successfully.
- @return others Some error occurs when transferring data.
-
-**/
-EFI_STATUS
-AccessAtaDevice(
- IN OUT ATA_DEVICE *AtaDevice,
- IN OUT UINT8 *Buffer,
- IN EFI_LBA StartLba,
- IN UINTN NumberOfBlocks,
- IN BOOLEAN IsWrite,
- IN OUT EFI_BLOCK_IO2_TOKEN *Token
- )
-{
- EFI_STATUS Status;
- UINTN MaxTransferBlockNumber;
- UINTN TransferBlockNumber;
- UINTN BlockSize;
- ATA_BUS_ASYN_SUB_TASK *SubTask;
- UINTN *EventCount;
- UINTN TempCount;
- ATA_BUS_ASYN_TASK *AtaTask;
- EFI_EVENT SubEvent;
- UINTN Index;
- BOOLEAN *IsError;
- EFI_TPL OldTpl;
-
- TempCount = 0;
- Status = EFI_SUCCESS;
- EventCount = NULL;
- IsError = NULL;
- Index = 0;
- SubTask = NULL;
- SubEvent = NULL;
- AtaTask = NULL;
-
- //
- // Ensure AtaDevice->Lba48Bit is a valid boolean value
- //
- ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);
- MaxTransferBlockNumber = mMaxTransferBlockNumber[AtaDevice->Lba48Bit];
- BlockSize = AtaDevice->BlockMedia.BlockSize;
-
- //
- // Initial the return status and shared account for Non Blocking.
- //
- if ((Token != NULL) && (Token->Event != NULL)) {
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- if (!IsListEmpty (&AtaDevice->AtaSubTaskList)) {
- AtaTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK));
- if (AtaTask == NULL) {
- gBS->RestoreTPL (OldTpl);
- return EFI_OUT_OF_RESOURCES;
- }
- AtaTask->AtaDevice = AtaDevice;
- AtaTask->Buffer = Buffer;
- AtaTask->IsWrite = IsWrite;
- AtaTask->NumberOfBlocks = NumberOfBlocks;
- AtaTask->Signature = ATA_TASK_SIGNATURE;
- AtaTask->StartLba = StartLba;
- AtaTask->Token = Token;
-
- InsertTailList (&AtaDevice->AtaTaskList, &AtaTask->TaskEntry);
- gBS->RestoreTPL (OldTpl);
- return EFI_SUCCESS;
- }
- gBS->RestoreTPL (OldTpl);
-
- Token->TransactionStatus = EFI_SUCCESS;
- EventCount = AllocateZeroPool (sizeof (UINTN));
- if (EventCount == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- IsError = AllocateZeroPool (sizeof (BOOLEAN));
- if (IsError == NULL) {
- FreePool (EventCount);
- return EFI_OUT_OF_RESOURCES;
- }
- DEBUG ((EFI_D_BLKIO, "Allocation IsError Addr=%x\n", IsError));
- *IsError = FALSE;
- TempCount = (NumberOfBlocks + MaxTransferBlockNumber - 1) / MaxTransferBlockNumber;
- *EventCount = TempCount;
- DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, NumberOfBlocks=%x\n", NumberOfBlocks));
- DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, MaxTransferBlockNumber=%x\n", MaxTransferBlockNumber));
- DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, EventCount=%x\n", TempCount));
- } else {
- while (!IsListEmpty (&AtaDevice->AtaTaskList) || !IsListEmpty (&AtaDevice->AtaSubTaskList)) {
- //
- // Stall for 100us.
- //
- MicroSecondDelay (100);
- }
- }
-
- do {
- if (NumberOfBlocks > MaxTransferBlockNumber) {
- TransferBlockNumber = MaxTransferBlockNumber;
- NumberOfBlocks -= MaxTransferBlockNumber;
- } else {
- TransferBlockNumber = NumberOfBlocks;
- NumberOfBlocks = 0;
- }
-
- //
- // Create sub event for the sub ata task. Non-blocking mode.
- //
- if ((Token != NULL) && (Token->Event != NULL)) {
- SubTask = NULL;
- SubEvent = NULL;
-
- SubTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_SUB_TASK));
- if (SubTask == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto EXIT;
- }
-
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- SubTask->UnsignalledEventCount = EventCount;
- SubTask->Signature = ATA_SUB_TASK_SIGNATURE;
- SubTask->AtaDevice = AtaDevice;
- SubTask->Token = Token;
- SubTask->IsError = IsError;
- InsertTailList (&AtaDevice->AtaSubTaskList, &SubTask->TaskEntry);
- gBS->RestoreTPL (OldTpl);
-
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- AtaNonBlockingCallBack,
- SubTask,
- &SubEvent
- );
- //
- // If resource allocation fail, the un-signalled event count should equal to
- // the original one minus the unassigned subtasks number.
- //
- if (EFI_ERROR (Status)) {
- Status = EFI_OUT_OF_RESOURCES;
- goto EXIT;
- }
-
- Status = TransferAtaDevice (AtaDevice, &SubTask->Packet, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, SubEvent);
- } else {
- //
- // Blocking Mode.
- //
- DEBUG ((EFI_D_BLKIO, "Blocking AccessAtaDevice, TransferBlockNumber=%x; StartLba = %x\n", TransferBlockNumber, StartLba));
- Status = TransferAtaDevice (AtaDevice, NULL, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, NULL);
- }
-
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
-
- Index++;
- StartLba += TransferBlockNumber;
- Buffer += TransferBlockNumber * BlockSize;
- } while (NumberOfBlocks > 0);
-
-EXIT:
- if ((Token != NULL) && (Token->Event != NULL)) {
- //
- // Release resource at non-blocking mode.
- //
- if (EFI_ERROR (Status)) {
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- Token->TransactionStatus = Status;
- *EventCount = (*EventCount) - (TempCount - Index);
- *IsError = TRUE;
-
- if (*EventCount == 0) {
- FreePool (EventCount);
- FreePool (IsError);
- }
-
- if (SubTask != NULL) {
- RemoveEntryList (&SubTask->TaskEntry);
- FreeAtaSubTask (SubTask);
- }
-
- if (SubEvent != NULL) {
- gBS->CloseEvent (SubEvent);
- }
- gBS->RestoreTPL (OldTpl);
- }
- }
-
- return Status;
-}
-
-/**
- Trust transfer data from/to ATA device.
-
- This function performs one ATA pass through transaction to do a trust transfer from/to
- ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
- interface of ATA pass through.
-
- @param AtaDevice The ATA child device involved for the operation.
- @param Buffer The pointer to the current transaction buffer.
- @param SecurityProtocolId The value of the "Security Protocol" parameter of
- the security protocol command to be sent.
- @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
- of the security protocol command to be sent.
- @param TransferLength The block number or sector count of the transfer.
- @param IsTrustSend Indicates whether it is a trust send operation or not.
- @param Timeout The timeout, in 100ns units, to use for the execution
- of the security protocol command. A Timeout value of 0
- means that this function will wait indefinitely for the
- security protocol command to execute. If Timeout is greater
- than zero, then this function will return EFI_TIMEOUT
- if the time required to execute the receive data command
- is greater than Timeout.
- @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data
- written to the buffer. Ignore it when IsTrustSend is TRUE.
-
- @retval EFI_SUCCESS The data transfer is complete successfully.
- @return others Some error occurs when transferring data.
-
-**/
-EFI_STATUS
-EFIAPI
-TrustTransferAtaDevice (
- IN OUT ATA_DEVICE *AtaDevice,
- IN OUT VOID *Buffer,
- IN UINT8 SecurityProtocolId,
- IN UINT16 SecurityProtocolSpecificData,
- IN UINTN TransferLength,
- IN BOOLEAN IsTrustSend,
- IN UINT64 Timeout,
- OUT UINTN *TransferLengthOut
- )
-{
- EFI_ATA_COMMAND_BLOCK *Acb;
- EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
- EFI_STATUS Status;
- VOID *NewBuffer;
- EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
-
- //
- // Ensure AtaDevice->UdmaValid and IsTrustSend are valid boolean values
- //
- ASSERT ((UINTN) AtaDevice->UdmaValid < 2);
- ASSERT ((UINTN) IsTrustSend < 2);
- //
- // Prepare for ATA command block.
- //
- Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
- if (TransferLength == 0) {
- Acb->AtaCommand = ATA_CMD_TRUST_NON_DATA;
- } else {
- Acb->AtaCommand = mAtaTrustCommands[AtaDevice->UdmaValid][IsTrustSend];
- }
- Acb->AtaFeatures = SecurityProtocolId;
- Acb->AtaSectorCount = (UINT8) (TransferLength / 512);
- Acb->AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8);
- //
- // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
- // Here use big endian for Cylinder register.
- //
- Acb->AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData;
- Acb->AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8);
- Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));
-
- //
- // Prepare for ATA pass through packet.
- //
- Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
- if (TransferLength == 0) {
- Packet->InTransferLength = 0;
- Packet->OutTransferLength = 0;
- Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;
- } else if (IsTrustSend) {
- //
- // Check the alignment of the incoming buffer prior to invoking underlying ATA PassThru
- //
- AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;
- if ((AtaPassThru->Mode->IoAlign > 1) && !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) {
- NewBuffer = AllocateAlignedBuffer (AtaDevice, TransferLength);
- if (NewBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (NewBuffer, Buffer, TransferLength);
- FreePool (Buffer);
- Buffer = NewBuffer;
- }
- Packet->OutDataBuffer = Buffer;
- Packet->OutTransferLength = (UINT32) TransferLength;
- Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];
- } else {
- Packet->InDataBuffer = Buffer;
- Packet->InTransferLength = (UINT32) TransferLength;
- Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];
- }
- Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;
- Packet->Timeout = Timeout;
-
- Status = AtaDevicePassThru (AtaDevice, NULL, NULL);
- if (TransferLengthOut != NULL) {
- if (! IsTrustSend) {
- *TransferLengthOut = Packet->InTransferLength;
- }
- }
- return Status;
-}