1ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** @file 2ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This file implements ATA pass through transaction for ATA bus driver. 3ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 4ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This file implements the low level execution of ATA pass through transaction. 5ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang It transforms the high level identity, read/write, reset command to ATA pass 6c24097a59ffb10d63c805c4da65476ed6e297c5chhuan through command and protocol. 7c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 83c063fedc4bd816ef427065003dca41ba1f885d2erictian NOTE: This file also implements the StorageSecurityCommandProtocol(SSP). For input 958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang parameter SecurityProtocolSpecificData, ATA spec has no explicitly definition 1058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang for Security Protocol Specific layout. This implementation uses big endian for 11c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Cylinder register. 1258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 134c33f8b190a439bb931a92eb63eb3cc1806c7cccHao Wu Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR> 142d273c8db95430b680e542e38cf07b97f9b57d11Cinnamon Shia (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> 15cd5ebaa06dca3e6ef3c464081e6defe00d358c69hhtian This program and the accompanying materials 16ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang are licensed and made available under the terms and conditions of the BSD License 17ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang which accompanies this distribution. The full text of the license may be found at 18ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang http://opensource.org/licenses/bsd-license.php 19ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 20ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 21ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 22ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 23ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 24ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 25ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 26ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang#include "AtaBus.h" 27ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 28c24097a59ffb10d63c805c4da65476ed6e297c5chhuan#define ATA_CMD_TRUST_NON_DATA 0x5B 29c24097a59ffb10d63c805c4da65476ed6e297c5chhuan#define ATA_CMD_TRUST_RECEIVE 0x5C 30c24097a59ffb10d63c805c4da65476ed6e297c5chhuan#define ATA_CMD_TRUST_RECEIVE_DMA 0x5D 31c24097a59ffb10d63c805c4da65476ed6e297c5chhuan#define ATA_CMD_TRUST_SEND 0x5E 32c24097a59ffb10d63c805c4da65476ed6e297c5chhuan#define ATA_CMD_TRUST_SEND_DMA 0x5F 33c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 34ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// 35ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// Look up table (UdmaValid, IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL 36ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// 37ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangEFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols[][2] = { 38ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 39ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN, 40ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT 41ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang }, 42ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 43ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN, 44ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT, 45ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 46ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang}; 47ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 48ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// 49ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// Look up table (UdmaValid, Lba48Bit, IsIsWrite) for ATA_CMD 50ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// 51ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangUINT8 mAtaCommands[][2][2] = { 52ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 53ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 54ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_READ_SECTORS, // 28-bit LBA; PIO read 55ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_WRITE_SECTORS // 28-bit LBA; PIO write 56ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang }, 57ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 58ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_READ_SECTORS_EXT, // 48-bit LBA; PIO read 59ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_WRITE_SECTORS_EXT // 48-bit LBA; PIO write 60ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 61ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang }, 62ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 63ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 64ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_READ_DMA, // 28-bit LBA; DMA read 65ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_WRITE_DMA // 28-bit LBA; DMA write 66ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang }, 67ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang { 68ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_READ_DMA_EXT, // 48-bit LBA; DMA read 69ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA_CMD_WRITE_DMA_EXT // 48-bit LBA; DMA write 70ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 71ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 72ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang}; 73ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 74ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// 75c24097a59ffb10d63c805c4da65476ed6e297c5chhuan// Look up table (UdmaValid, IsTrustSend) for ATA_CMD 76c24097a59ffb10d63c805c4da65476ed6e297c5chhuan// 7758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyangUINT8 mAtaTrustCommands[2][2] = { 78c24097a59ffb10d63c805c4da65476ed6e297c5chhuan { 79c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ATA_CMD_TRUST_RECEIVE, // PIO read 80c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ATA_CMD_TRUST_SEND // PIO write 81c24097a59ffb10d63c805c4da65476ed6e297c5chhuan }, 82c24097a59ffb10d63c805c4da65476ed6e297c5chhuan { 83c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ATA_CMD_TRUST_RECEIVE_DMA, // DMA read 84c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ATA_CMD_TRUST_SEND_DMA // DMA write 85c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } 86c24097a59ffb10d63c805c4da65476ed6e297c5chhuan}; 87c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 88c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 89c24097a59ffb10d63c805c4da65476ed6e297c5chhuan// 90ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// Look up table (Lba48Bit) for maximum transfer block number 91ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang// 92ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangUINTN mMaxTransferBlockNumber[] = { 93ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang MAX_28BIT_TRANSFER_BLOCK_NUM, 94ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang MAX_48BIT_TRANSFER_BLOCK_NUM 95ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang}; 96ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 97ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 98ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 99ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.PassThru(). 100ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 101ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This function wraps the PassThru() invocation for ATA pass through function 102ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang for an ATA device. It assembles the ATA pass through command packet for ATA 103ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang transaction. 104ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 105490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in, out] AtaDevice The ATA child device involved for the operation. 10658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional, 107490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if it is NULL, blocking mode, and use the packet 108490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang in AtaDevice. If it is not NULL, non blocking mode, 109490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang and pass down this Packet. 11086d8e1994269161ae77ab46383415a4f0338b8dfqianouyang @param[in, out] Event If Event is NULL, then blocking I/O is performed. 111490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang If Event is not NULL and non-blocking I/O is 112490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang supported,then non-blocking I/O is performed, 113490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang and Event will be signaled when the write 114490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang request is completed. 115ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 116ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru(). 117ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 118ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 119ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangEFI_STATUS 120ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangAtaDevicePassThru ( 121490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN OUT ATA_DEVICE *AtaDevice, 122490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL 123490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN OUT EFI_EVENT Event OPTIONAL 124ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 125ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 126ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_STATUS Status; 127ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru; 128ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet; 129ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 130ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 13158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Assemble packet. If it is non blocking mode, the Ata driver should keep each 132490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // subtask and clean them when the event is signaled. 133ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 134490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if (TaskPacket != NULL) { 135490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Packet = TaskPacket; 1363c063fedc4bd816ef427065003dca41ba1f885d2erictian Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (EFI_ATA_STATUS_BLOCK)); 1373d267c70b2f69118fe06fcec753fd62a049669ebydong if (Packet->Asb == NULL) { 1383d267c70b2f69118fe06fcec753fd62a049669ebydong return EFI_OUT_OF_RESOURCES; 1393d267c70b2f69118fe06fcec753fd62a049669ebydong } 1403d267c70b2f69118fe06fcec753fd62a049669ebydong 1413c063fedc4bd816ef427065003dca41ba1f885d2erictian CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (EFI_ATA_STATUS_BLOCK)); 1423c063fedc4bd816ef427065003dca41ba1f885d2erictian Packet->Acb = AllocateCopyPool (sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb); 143490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } else { 144490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Packet = &AtaDevice->Packet; 145490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Packet->Asb = AtaDevice->Asb; 146490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Packet->Acb = &AtaDevice->Acb; 147490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 148ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 149ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru; 150ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 151ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Status = AtaPassThru->PassThru ( 152ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaPassThru, 153ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->Port, 154ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->PortMultiplierPort, 155ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet, 156490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Event 157ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ); 158ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 159ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Ensure ATA pass through caller and callee have the same 16058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // interpretation of ATA pass through protocol. 161ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 162ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ASSERT (Status != EFI_INVALID_PARAMETER); 163ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ASSERT (Status != EFI_BAD_BUFFER_SIZE); 164ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 165ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return Status; 166ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 167ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 168ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 169ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 170ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.ResetDevice(). 171ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 172ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This function wraps the ResetDevice() invocation for ATA pass through function 17358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang for an ATA device. 174ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 175ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @param AtaDevice The ATA child device involved for the operation. 176ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 177ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru(). 178ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 179ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 180ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangEFI_STATUS 181ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangResetAtaDevice ( 182ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN ATA_DEVICE *AtaDevice 183ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 184ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 185ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru; 18658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 187ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru; 18858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 18937623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin // 19037623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin // Report Status Code to indicate reset happens 19137623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin // 19237623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 19337623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin EFI_PROGRESS_CODE, 19437623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), 19537623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin AtaDevice->AtaBusDriverData->ParentDevicePath 19637623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin ); 19737623a5c029e5415fe24b86bf4f6481f8fdfad94li-elvin 198ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return AtaPassThru->ResetDevice ( 199ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaPassThru, 200ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->Port, 201ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->PortMultiplierPort 202ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ); 203ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 204ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 205ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 206ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 207ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Prints ATA model name to ATA device structure. 208ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 20958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang This function converts ATA device model name from ATA identify data 210ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang to a string in ATA device structure. It needs to change the character 211ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang order in the original model name string. 212ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 213ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @param AtaDevice The ATA child device involved for the operation. 214ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 215ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 216ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangVOID 217ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangPrintAtaModelName ( 218ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN OUT ATA_DEVICE *AtaDevice 219ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 220ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 221ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINTN Index; 222ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang CHAR8 *Source; 223ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang CHAR16 *Destination; 224ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 2256ea8e37bfa9990180454ca5d35c9ed935a0f4b49qhuang Source = AtaDevice->IdentifyData->ModelName; 226ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Destination = AtaDevice->ModelName; 227ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 228ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 229ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Swap the byte order in the original module name. 230ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 231ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang for (Index = 0; Index < MAX_MODEL_NAME_LEN; Index += 2) { 232ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Destination[Index] = Source[Index + 1]; 233ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Destination[Index + 1] = Source[Index]; 234ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 235ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->ModelName[MAX_MODEL_NAME_LEN] = L'\0'; 236ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 237ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 238ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 239ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 240ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Gets ATA device Capacity according to ATA 6. 241ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 242ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This function returns the capacity of the ATA device if it follows 243ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA 6 to support 48 bit addressing. 244ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 245ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @param AtaDevice The ATA child device involved for the operation. 246ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 247ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @return The capacity of the ATA device or 0 if the device does not support 248ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 48-bit addressing defined in ATA 6. 249ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 250ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 251ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangEFI_LBA 252ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangGetAtapi6Capacity ( 253ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN ATA_DEVICE *AtaDevice 254ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 255ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 256ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_LBA Capacity; 257ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_LBA TmpLba; 258ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINTN Index; 2596ea8e37bfa9990180454ca5d35c9ed935a0f4b49qhuang ATA_IDENTIFY_DATA *IdentifyData; 260ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 2616ea8e37bfa9990180454ca5d35c9ed935a0f4b49qhuang IdentifyData = AtaDevice->IdentifyData; 2626ea8e37bfa9990180454ca5d35c9ed935a0f4b49qhuang if ((IdentifyData->command_set_supported_83 & BIT10) == 0) { 263ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 264ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // The device doesn't support 48 bit addressing 265ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 266ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return 0; 267ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 268ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 269ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 270ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 48 bit address feature set is supported, get maximum capacity 271ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 272ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Capacity = 0; 273ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang for (Index = 0; Index < 4; Index++) { 274ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 275ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Lower byte goes first: word[100] is the lowest word, word[103] is highest 276ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 2776ea8e37bfa9990180454ca5d35c9ed935a0f4b49qhuang TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index]; 278ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Capacity |= LShiftU64 (TmpLba, 16 * Index); 279ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 280ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 281ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return Capacity; 282ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 283ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 284ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 285ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 286ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Identifies ATA device via the Identify data. 287ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 28858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang This function identifies the ATA device and initializes the Media information in 289ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Block IO protocol interface. 290ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 291ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @param AtaDevice The ATA child device involved for the operation. 292ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 293ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk). 294ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @retval EFI_SUCCESS The device is successfully identified and Media information 295ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang is correctly initialized. 296ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 297ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 298ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangEFI_STATUS 299ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangIdentifyAtaDevice ( 300ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN OUT ATA_DEVICE *AtaDevice 301ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 302ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 3036ea8e37bfa9990180454ca5d35c9ed935a0f4b49qhuang ATA_IDENTIFY_DATA *IdentifyData; 304ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_BLOCK_IO_MEDIA *BlockMedia; 305ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_LBA Capacity; 306ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINT16 PhyLogicSectorSupport; 307ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINT16 UdmaMode; 308ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 3096ea8e37bfa9990180454ca5d35c9ed935a0f4b49qhuang IdentifyData = AtaDevice->IdentifyData; 310ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 311ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if ((IdentifyData->config & BIT15) != 0) { 312ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 313ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // This is not an hard disk 314ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 315ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return EFI_UNSUPPORTED; 316ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 317ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 31825dd150b585f0bc498482dc00325cf9b67362665lzeng DEBUG ((EFI_D_INFO, "AtaBus - Identify Device: Port %x PortMultiplierPort %x\n", AtaDevice->Port, AtaDevice->PortMultiplierPort)); 319490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 320ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 321ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Check whether the WORD 88 (supported UltraDMA by drive) is valid 322ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 323ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if ((IdentifyData->field_validity & BIT2) != 0) { 324ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UdmaMode = IdentifyData->ultra_dma_mode; 325ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if ((UdmaMode & (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6)) != 0) { 326ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 327ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // If BIT0~BIT6 is selected, then UDMA is supported 328ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 329ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->UdmaValid = TRUE; 330ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 331ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 332ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 333ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Capacity = GetAtapi6Capacity (AtaDevice); 334ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) { 335ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 336ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Capacity exceeds 120GB. 48-bit addressing is really needed 337ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 338ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->Lba48Bit = TRUE; 339ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } else { 340ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 341ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // This is a hard disk <= 120GB capacity, treat it as normal hard disk 342ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 343ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Capacity = ((UINT32)IdentifyData->user_addressable_sectors_hi << 16) | IdentifyData->user_addressable_sectors_lo; 344ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->Lba48Bit = FALSE; 345ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 346ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 347ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 348ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Block Media Information: 349ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 350ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang BlockMedia = &AtaDevice->BlockMedia; 351ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang BlockMedia->LastBlock = Capacity - 1; 352907c1a003937905217bf80f577671ef48d153725qhuang BlockMedia->IoAlign = AtaDevice->AtaBusDriverData->AtaPassThru->Mode->IoAlign; 353ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 354ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Check whether Long Physical Sector Feature is supported 355ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 356ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang PhyLogicSectorSupport = IdentifyData->phy_logic_sector_support; 357ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if ((PhyLogicSectorSupport & (BIT14 | BIT15)) == BIT14) { 358ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 359ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Check whether one physical block contains multiple physical blocks 360ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 361ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if ((PhyLogicSectorSupport & BIT13) != 0) { 362ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang BlockMedia->LogicalBlocksPerPhysicalBlock = (UINT32) (1 << (PhyLogicSectorSupport & 0x000f)); 363ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 364ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Check lowest alignment of logical blocks within physical block 365ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 366ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if ((IdentifyData->alignment_logic_in_phy_blocks & (BIT14 | BIT15)) == BIT14) { 367c61f936286cd8b929835dce81424a19fbcebba95erictian BlockMedia->LowestAlignedLba = (EFI_LBA) ((BlockMedia->LogicalBlocksPerPhysicalBlock - ((UINT32)IdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) % 368c61f936286cd8b929835dce81424a19fbcebba95erictian BlockMedia->LogicalBlocksPerPhysicalBlock); 369ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 370ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 371ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 372ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Check logical block size 373ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 374ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if ((PhyLogicSectorSupport & BIT12) != 0) { 375ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang BlockMedia->BlockSize = (UINT32) (((IdentifyData->logic_sector_size_hi << 16) | IdentifyData->logic_sector_size_lo) * sizeof (UINT16)); 376ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 377ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang AtaDevice->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; 378ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 379ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 38058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Get ATA model name from identify data structure. 381ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 382490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang PrintAtaModelName (AtaDevice); 383ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 384ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return EFI_SUCCESS; 385ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 386ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 387ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 388ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 389ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Discovers whether it is a valid ATA device. 390ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 391ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This function issues ATA_CMD_IDENTIFY_DRIVE command to the ATA device to identify it. 392ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang If the command is executed successfully, it then identifies it and initializes 393ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang the Media information in Block IO protocol interface. 394ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 395ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @param AtaDevice The ATA child device involved for the operation. 396ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 397ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @retval EFI_SUCCESS The device is successfully identified and Media information 398ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang is correctly initialized. 39958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang @return others Some error occurs when discovering the ATA device. 400ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 401ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 402ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangEFI_STATUS 403ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangDiscoverAtaDevice ( 404ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN OUT ATA_DEVICE *AtaDevice 405ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 406ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 407ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_STATUS Status; 408ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_COMMAND_BLOCK *Acb; 409ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet; 410ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINTN Retry; 411ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 412ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 413ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Prepare for ATA command block. 414ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 4153c063fedc4bd816ef427065003dca41ba1f885d2erictian Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK)); 416ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Acb->AtaCommand = ATA_CMD_IDENTIFY_DRIVE; 4172d273c8db95430b680e542e38cf07b97f9b57d11Cinnamon Shia Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort == 0xFFFF ? 0 : (AtaDevice->PortMultiplierPort << 4))); 418ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 419ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 420ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Prepare for ATA pass through packet. 421ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 4223c063fedc4bd816ef427065003dca41ba1f885d2erictian Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET)); 423ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->InDataBuffer = AtaDevice->IdentifyData; 4243c063fedc4bd816ef427065003dca41ba1f885d2erictian Packet->InTransferLength = sizeof (ATA_IDENTIFY_DATA); 425ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN; 426490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT; 427490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Packet->Timeout = ATA_TIMEOUT; 428ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 429ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Retry = MAX_RETRY_TIMES; 430ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang do { 431490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Status = AtaDevicePassThru (AtaDevice, NULL, NULL); 432ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if (!EFI_ERROR (Status)) { 433ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 434ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // The command is issued successfully 435ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 436ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Status = IdentifyAtaDevice (AtaDevice); 4370d5df2aba72e7c8f2f172900fb7cfece27851a8ferictian return Status; 438ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 439ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } while (Retry-- > 0); 440ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 441ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return Status; 442ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 443ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 444ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 445ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Transfer data from ATA device. 446ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 447ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This function performs one ATA pass through transaction to transfer data from/to 448ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru 449ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang interface of ATA pass through. 450ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 451490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in, out] AtaDevice The ATA child device involved for the operation. 45258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional, 453490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if it is NULL, blocking mode, and use the packet 454490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang in AtaDevice. If it is not NULL, non blocking mode, 455490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang and pass down this Packet. 456490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in, out] Buffer The pointer to the current transaction buffer. 457490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] StartLba The starting logical block address to be accessed. 458490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] TransferLength The block number or sector count of the transfer. 459490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] IsWrite Indicates whether it is a write operation. 460490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] Event If Event is NULL, then blocking I/O is performed. 461490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang If Event is not NULL and non-blocking I/O is 462490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang supported,then non-blocking I/O is performed, 463490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang and Event will be signaled when the write 464490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang request is completed. 465ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 466ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @retval EFI_SUCCESS The data transfer is complete successfully. 46758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang @return others Some error occurs when transferring data. 468ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 469ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 470ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangEFI_STATUS 471ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangTransferAtaDevice ( 472490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN OUT ATA_DEVICE *AtaDevice, 473490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL 474490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN OUT VOID *Buffer, 475490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN EFI_LBA StartLba, 476490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN UINT32 TransferLength, 47758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang IN BOOLEAN IsWrite, 478490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN EFI_EVENT Event OPTIONAL 479ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 480ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 481ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_COMMAND_BLOCK *Acb; 482ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet; 483ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 484ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 48558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Ensure AtaDevice->UdmaValid, AtaDevice->Lba48Bit and IsWrite are valid boolean values 486423401f9ea83daffc754864b922f56f06a84cbabqhuang // 48761d4f8f92a62e16190fd0d9e3568aba801a151deqhuang ASSERT ((UINTN) AtaDevice->UdmaValid < 2); 488423401f9ea83daffc754864b922f56f06a84cbabqhuang ASSERT ((UINTN) AtaDevice->Lba48Bit < 2); 489423401f9ea83daffc754864b922f56f06a84cbabqhuang ASSERT ((UINTN) IsWrite < 2); 490423401f9ea83daffc754864b922f56f06a84cbabqhuang // 491ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Prepare for ATA command block. 492ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 4933c063fedc4bd816ef427065003dca41ba1f885d2erictian Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK)); 494ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Acb->AtaCommand = mAtaCommands[AtaDevice->UdmaValid][AtaDevice->Lba48Bit][IsWrite]; 495ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Acb->AtaSectorNumber = (UINT8) StartLba; 496ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Acb->AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8); 497ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Acb->AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16); 4984c33f8b190a439bb931a92eb63eb3cc1806c7cccHao Wu Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort == 0xFFFF ? 0 : (AtaDevice->PortMultiplierPort << 4))); 499423401f9ea83daffc754864b922f56f06a84cbabqhuang Acb->AtaSectorCount = (UINT8) TransferLength; 500ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if (AtaDevice->Lba48Bit) { 501ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Acb->AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24); 502423401f9ea83daffc754864b922f56f06a84cbabqhuang Acb->AtaCylinderLowExp = (UINT8) RShiftU64 (StartLba, 32); 503423401f9ea83daffc754864b922f56f06a84cbabqhuang Acb->AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40); 504423401f9ea83daffc754864b922f56f06a84cbabqhuang Acb->AtaSectorCountExp = (UINT8) (TransferLength >> 8); 505ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } else { 506ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Acb->AtaDeviceHead = (UINT8) (Acb->AtaDeviceHead | RShiftU64 (StartLba, 24)); 507ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 508ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 509ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 510ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // Prepare for ATA pass through packet. 511ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang // 512490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if (TaskPacket != NULL) { 5133c063fedc4bd816ef427065003dca41ba1f885d2erictian Packet = ZeroMem (TaskPacket, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET)); 514490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } else { 5153c063fedc4bd816ef427065003dca41ba1f885d2erictian Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET)); 516490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 517490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 518ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if (IsWrite) { 519ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->OutDataBuffer = Buffer; 520ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->OutTransferLength = TransferLength; 521ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } else { 522ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->InDataBuffer = Buffer; 523ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->InTransferLength = TransferLength; 524ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 525490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 526ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite]; 527ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT; 5289690325d1e8b1602dac5091a1bab8e1076954900erictian // 5299690325d1e8b1602dac5091a1bab8e1076954900erictian // |------------------------|-----------------|------------------------|-----------------| 5309690325d1e8b1602dac5091a1bab8e1076954900erictian // | ATA PIO Transfer Mode | Transfer Rate | ATA DMA Transfer Mode | Transfer Rate | 5319690325d1e8b1602dac5091a1bab8e1076954900erictian // |------------------------|-----------------|------------------------|-----------------| 5329690325d1e8b1602dac5091a1bab8e1076954900erictian // | PIO Mode 0 | 3.3Mbytes/sec | Single-word DMA Mode 0 | 2.1Mbytes/sec | 5339690325d1e8b1602dac5091a1bab8e1076954900erictian // |------------------------|-----------------|------------------------|-----------------| 5349690325d1e8b1602dac5091a1bab8e1076954900erictian // | PIO Mode 1 | 5.2Mbytes/sec | Single-word DMA Mode 1 | 4.2Mbytes/sec | 5359690325d1e8b1602dac5091a1bab8e1076954900erictian // |------------------------|-----------------|------------------------|-----------------| 5369690325d1e8b1602dac5091a1bab8e1076954900erictian // | PIO Mode 2 | 8.3Mbytes/sec | Single-word DMA Mode 2 | 8.4Mbytes/sec | 5379690325d1e8b1602dac5091a1bab8e1076954900erictian // |------------------------|-----------------|------------------------|-----------------| 5389690325d1e8b1602dac5091a1bab8e1076954900erictian // | PIO Mode 3 | 11.1Mbytes/sec | Multi-word DMA Mode 0 | 4.2Mbytes/sec | 5399690325d1e8b1602dac5091a1bab8e1076954900erictian // |------------------------|-----------------|------------------------|-----------------| 5409690325d1e8b1602dac5091a1bab8e1076954900erictian // | PIO Mode 4 | 16.6Mbytes/sec | Multi-word DMA Mode 1 | 13.3Mbytes/sec | 5419690325d1e8b1602dac5091a1bab8e1076954900erictian // |------------------------|-----------------|------------------------|-----------------| 5429690325d1e8b1602dac5091a1bab8e1076954900erictian // 5439690325d1e8b1602dac5091a1bab8e1076954900erictian // As AtaBus is used to manage ATA devices, we have to use the lowest transfer rate to 5449690325d1e8b1602dac5091a1bab8e1076954900erictian // calculate the possible maximum timeout value for each read/write operation. 5458e1f06124c1631da5619def8c09ca4d7236f75b5Feng Tian // The timout value is rounded up to nearest integar and here an additional 30s is added 5468e1f06124c1631da5619def8c09ca4d7236f75b5Feng Tian // to follow ATA spec in which it mentioned that the device may take up to 30s to respond 5478e1f06124c1631da5619def8c09ca4d7236f75b5Feng Tian // commands in the Standby/Idle mode. 5489690325d1e8b1602dac5091a1bab8e1076954900erictian // 5499690325d1e8b1602dac5091a1bab8e1076954900erictian if (AtaDevice->UdmaValid) { 5509690325d1e8b1602dac5091a1bab8e1076954900erictian // 5519690325d1e8b1602dac5091a1bab8e1076954900erictian // Calculate the maximum timeout value for DMA read/write operation. 5529690325d1e8b1602dac5091a1bab8e1076954900erictian // 5538e1f06124c1631da5619def8c09ca4d7236f75b5Feng Tian Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 2100000) + 31); 5549690325d1e8b1602dac5091a1bab8e1076954900erictian } else { 5559690325d1e8b1602dac5091a1bab8e1076954900erictian // 5569690325d1e8b1602dac5091a1bab8e1076954900erictian // Calculate the maximum timeout value for PIO read/write operation 5579690325d1e8b1602dac5091a1bab8e1076954900erictian // 5588e1f06124c1631da5619def8c09ca4d7236f75b5Feng Tian Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 3300000) + 31); 5599690325d1e8b1602dac5091a1bab8e1076954900erictian } 560490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 561490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang return AtaDevicePassThru (AtaDevice, TaskPacket, Event); 562490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang} 563490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 564490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang/** 56558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang Free SubTask. 566490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 567490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in, out] Task Pointer to task to be freed. 568490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 569490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang**/ 570490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyangVOID 57158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyangEFIAPI 572490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyangFreeAtaSubTask ( 57358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang IN OUT ATA_BUS_ASYN_SUB_TASK *Task 574490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang ) 575490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang{ 576490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if (Task->Packet.Asb != NULL) { 5773c063fedc4bd816ef427065003dca41ba1f885d2erictian FreeAlignedBuffer (Task->Packet.Asb, sizeof (EFI_ATA_STATUS_BLOCK)); 578490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 579490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if (Task->Packet.Acb != NULL) { 580490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang FreePool (Task->Packet.Acb); 581490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 582490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 583490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang FreePool (Task); 584490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang} 585490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 586490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang/** 58771fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng Terminate any in-flight non-blocking I/O requests by signaling an EFI_ABORTED 58871fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng in the TransactionStatus member of the EFI_BLOCK_IO2_TOKEN for the non-blocking 58971fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng I/O. After that it is safe to free any Token or Buffer data structures that 59071fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng were allocated to initiate the non-blockingI/O requests that were in-flight for 59171fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng this device. 59271fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 59371fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng @param[in] AtaDevice The ATA child device involved for the operation. 59471fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 59571fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng**/ 59671fd9fae8bda10f41a9c6445f01eed82b99883daTian, FengVOID 59771fd9fae8bda10f41a9c6445f01eed82b99883daTian, FengEFIAPI 59871fd9fae8bda10f41a9c6445f01eed82b99883daTian, FengAtaTerminateNonBlockingTask ( 59971fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng IN ATA_DEVICE *AtaDevice 60071fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng ) 60171fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng{ 60271fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng BOOLEAN SubTaskEmpty; 60371fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng EFI_TPL OldTpl; 60471fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng ATA_BUS_ASYN_TASK *AtaTask; 60571fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng LIST_ENTRY *Entry; 60671fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng LIST_ENTRY *List; 60771fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 60871fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 60971fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // 61071fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // Abort all executing tasks from now. 61171fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // 61271fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng AtaDevice->Abort = TRUE; 61371fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 61471fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng List = &AtaDevice->AtaTaskList; 61571fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng for (Entry = GetFirstNode (List); !IsNull (List, Entry);) { 61671fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry); 61771fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng AtaTask->Token->TransactionStatus = EFI_ABORTED; 61871fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng gBS->SignalEvent (AtaTask->Token->Event); 61971fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 62071fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng Entry = RemoveEntryList (Entry); 62171fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng FreePool (AtaTask); 62271fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng } 62371fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng gBS->RestoreTPL (OldTpl); 62471fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 62571fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng do { 62671fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 62771fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // 62871fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // Wait for executing subtasks done. 62971fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // 63071fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng SubTaskEmpty = IsListEmpty (&AtaDevice->AtaSubTaskList); 63171fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng gBS->RestoreTPL (OldTpl); 63271fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng } while (!SubTaskEmpty); 63371fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 63471fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // 63571fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // Aborting operation has been done. From now on, don't need to abort normal operation. 63671fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng // 63771fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 63871fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng AtaDevice->Abort = FALSE; 63971fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng gBS->RestoreTPL (OldTpl); 64071fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng} 64171fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 64271fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng/** 643490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Call back funtion when the event is signaled. 644490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 645490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] Event The Event this notify function registered to. 6463c063fedc4bd816ef427065003dca41ba1f885d2erictian @param[in] Context Pointer to the context data registered to the 647490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Event. 648490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 649490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang**/ 650490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyangVOID 65158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyangEFIAPI 652490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyangAtaNonBlockingCallBack ( 653490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN EFI_EVENT Event, 654490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN VOID *Context 655490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang ) 656490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang{ 65758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang ATA_BUS_ASYN_SUB_TASK *Task; 65858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang ATA_BUS_ASYN_TASK *AtaTask; 65958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang ATA_DEVICE *AtaDevice; 66058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang LIST_ENTRY *Entry; 66158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang EFI_STATUS Status; 662490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 66358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang Task = (ATA_BUS_ASYN_SUB_TASK *) Context; 664490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang gBS->CloseEvent (Event); 665490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 66658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaDevice = Task->AtaDevice; 66758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 668490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 669490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // Check the command status. 670490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // If there is error during the sub task source allocation, the error status 671490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // should be returned to the caller directly, so here the Task->Token may already 672490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // be deleted by the caller and no need to update the status. 673490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 6743c063fedc4bd816ef427065003dca41ba1f885d2erictian if ((!(*Task->IsError)) && ((Task->Packet.Asb->AtaStatus & 0x01) == 0x01)) { 675490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Task->Token->TransactionStatus = EFI_DEVICE_ERROR; 676490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 67771fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 67871fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng if (AtaDevice->Abort) { 67971fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng Task->Token->TransactionStatus = EFI_ABORTED; 68071fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng } 68171fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 682490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang DEBUG (( 68325dd150b585f0bc498482dc00325cf9b67362665lzeng EFI_D_BLKIO, 68425dd150b585f0bc498482dc00325cf9b67362665lzeng "NON-BLOCKING EVENT FINISHED!- STATUS = %r\n", 685490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Task->Token->TransactionStatus 686490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang )); 687490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 688490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 689490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // Reduce the SubEventCount, till it comes to zero. 690490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 691490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang (*Task->UnsignalledEventCount) --; 69225dd150b585f0bc498482dc00325cf9b67362665lzeng DEBUG ((EFI_D_BLKIO, "UnsignalledEventCount = %d\n", *Task->UnsignalledEventCount)); 693490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 694490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 695490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // Remove the SubTask from the Task list. 696490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 697490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang RemoveEntryList (&Task->TaskEntry); 698490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if ((*Task->UnsignalledEventCount) == 0) { 699490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 7003c063fedc4bd816ef427065003dca41ba1f885d2erictian // All Sub tasks are done, then signal the upper layer event. 701490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // Except there is error during the sub task source allocation. 702490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 703490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if (!(*Task->IsError)) { 704490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang gBS->SignalEvent (Task->Token->Event); 70525dd150b585f0bc498482dc00325cf9b67362665lzeng DEBUG ((EFI_D_BLKIO, "Signal the upper layer event!\n")); 706490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 70758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 708490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang FreePool (Task->UnsignalledEventCount); 709490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang FreePool (Task->IsError); 71058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 71158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 71258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // 71358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Finish all subtasks and move to the next task in AtaTaskList. 71458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // 71558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang if (!IsListEmpty (&AtaDevice->AtaTaskList)) { 71658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang Entry = GetFirstNode (&AtaDevice->AtaTaskList); 71771fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry); 71858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang DEBUG ((EFI_D_BLKIO, "Start to embark a new Ata Task\n")); 71958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang DEBUG ((EFI_D_BLKIO, "AtaTask->NumberOfBlocks = %x; AtaTask->Token=%x\n", AtaTask->NumberOfBlocks, AtaTask->Token)); 72058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang Status = AccessAtaDevice ( 72158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->AtaDevice, 72258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->Buffer, 72358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->StartLba, 72458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->NumberOfBlocks, 72558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->IsWrite, 72658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->Token 72758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang ); 72858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang if (EFI_ERROR (Status)) { 72958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->Token->TransactionStatus = Status; 73058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang gBS->SignalEvent (AtaTask->Token->Event); 73158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang } 73258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang RemoveEntryList (Entry); 73358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang FreePool (AtaTask); 73458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang } 735490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 736ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 737490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang DEBUG (( 73825dd150b585f0bc498482dc00325cf9b67362665lzeng EFI_D_BLKIO, 73925dd150b585f0bc498482dc00325cf9b67362665lzeng "PACKET INFO: Write=%s, Length=%x, LowCylinder=%x, HighCylinder=%x, SectionNumber=%x\n", 740490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Task->Packet.OutDataBuffer != NULL ? L"YES" : L"NO", 741490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Task->Packet.OutDataBuffer != NULL ? Task->Packet.OutTransferLength : Task->Packet.InTransferLength, 742490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Task->Packet.Acb->AtaCylinderLow, 743490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Task->Packet.Acb->AtaCylinderHigh, 744490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Task->Packet.Acb->AtaSectorCount 745490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang )); 746490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 747490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 748490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // Free the buffer of SubTask. 749490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 750490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang FreeAtaSubTask (Task); 751ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 752ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 753ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang/** 754ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Read or write a number of blocks from ATA device. 755ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 756ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang This function performs ATA pass through transactions to read/write data from/to 757ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ATA device. It may separate the read/write request into several ATA pass through 758ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang transactions. 759ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 760490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in, out] AtaDevice The ATA child device involved for the operation. 761490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in, out] Buffer The pointer to the current transaction buffer. 762490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] StartLba The starting logical block address to be accessed. 763490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] NumberOfBlocks The block number or sector count of the transfer. 764490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in] IsWrite Indicates whether it is a write operation. 765490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang @param[in, out] Token A pointer to the token associated with the transaction. 766ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 767ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang @retval EFI_SUCCESS The data transfer is complete successfully. 76858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang @return others Some error occurs when transferring data. 769ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 770ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang**/ 77158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyangEFI_STATUS 772ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuangAccessAtaDevice( 773ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN OUT ATA_DEVICE *AtaDevice, 774ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN OUT UINT8 *Buffer, 775ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN EFI_LBA StartLba, 776ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang IN UINTN NumberOfBlocks, 777490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN BOOLEAN IsWrite, 778490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang IN OUT EFI_BLOCK_IO2_TOKEN *Token 779ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang ) 780ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang{ 781ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang EFI_STATUS Status; 782ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINTN MaxTransferBlockNumber; 783ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINTN TransferBlockNumber; 784ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang UINTN BlockSize; 78558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang ATA_BUS_ASYN_SUB_TASK *SubTask; 786490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang UINTN *EventCount; 787490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang UINTN TempCount; 78858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang ATA_BUS_ASYN_TASK *AtaTask; 789490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang EFI_EVENT SubEvent; 790490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang UINTN Index; 791490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang BOOLEAN *IsError; 792490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang EFI_TPL OldTpl; 793490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 7943c063fedc4bd816ef427065003dca41ba1f885d2erictian TempCount = 0; 7953c063fedc4bd816ef427065003dca41ba1f885d2erictian Status = EFI_SUCCESS; 7963c063fedc4bd816ef427065003dca41ba1f885d2erictian EventCount = NULL; 7973c063fedc4bd816ef427065003dca41ba1f885d2erictian IsError = NULL; 7983c063fedc4bd816ef427065003dca41ba1f885d2erictian Index = 0; 79958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask = NULL; 8003c063fedc4bd816ef427065003dca41ba1f885d2erictian SubEvent = NULL; 80158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask = NULL; 80271fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 803423401f9ea83daffc754864b922f56f06a84cbabqhuang // 80458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Ensure AtaDevice->Lba48Bit is a valid boolean value 805423401f9ea83daffc754864b922f56f06a84cbabqhuang // 806423401f9ea83daffc754864b922f56f06a84cbabqhuang ASSERT ((UINTN) AtaDevice->Lba48Bit < 2); 807ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang MaxTransferBlockNumber = mMaxTransferBlockNumber[AtaDevice->Lba48Bit]; 808490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang BlockSize = AtaDevice->BlockMedia.BlockSize; 809490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 8103c063fedc4bd816ef427065003dca41ba1f885d2erictian // 8113c063fedc4bd816ef427065003dca41ba1f885d2erictian // Initial the return status and shared account for Non Blocking. 8123c063fedc4bd816ef427065003dca41ba1f885d2erictian // 8133c063fedc4bd816ef427065003dca41ba1f885d2erictian if ((Token != NULL) && (Token->Event != NULL)) { 81458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 81571fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng 81658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang if (!IsListEmpty (&AtaDevice->AtaSubTaskList)) { 81758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK)); 81858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang if (AtaTask == NULL) { 81958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang gBS->RestoreTPL (OldTpl); 82058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang return EFI_OUT_OF_RESOURCES; 82158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang } 82258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->AtaDevice = AtaDevice; 82358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->Buffer = Buffer; 82458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->IsWrite = IsWrite; 82558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->NumberOfBlocks = NumberOfBlocks; 82658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->Signature = ATA_TASK_SIGNATURE; 82758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->StartLba = StartLba; 82858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang AtaTask->Token = Token; 82958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 83058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang InsertTailList (&AtaDevice->AtaTaskList, &AtaTask->TaskEntry); 83158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang gBS->RestoreTPL (OldTpl); 83258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang return EFI_SUCCESS; 83358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang } 83458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang gBS->RestoreTPL (OldTpl); 8353c063fedc4bd816ef427065003dca41ba1f885d2erictian 83658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang Token->TransactionStatus = EFI_SUCCESS; 8373c063fedc4bd816ef427065003dca41ba1f885d2erictian EventCount = AllocateZeroPool (sizeof (UINTN)); 8383c063fedc4bd816ef427065003dca41ba1f885d2erictian if (EventCount == NULL) { 8393c063fedc4bd816ef427065003dca41ba1f885d2erictian return EFI_OUT_OF_RESOURCES; 8403c063fedc4bd816ef427065003dca41ba1f885d2erictian } 84158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 8423c063fedc4bd816ef427065003dca41ba1f885d2erictian IsError = AllocateZeroPool (sizeof (BOOLEAN)); 8433c063fedc4bd816ef427065003dca41ba1f885d2erictian if (IsError == NULL) { 8443c063fedc4bd816ef427065003dca41ba1f885d2erictian FreePool (EventCount); 8453c063fedc4bd816ef427065003dca41ba1f885d2erictian return EFI_OUT_OF_RESOURCES; 8463c063fedc4bd816ef427065003dca41ba1f885d2erictian } 84758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang DEBUG ((EFI_D_BLKIO, "Allocation IsError Addr=%x\n", IsError)); 8483c063fedc4bd816ef427065003dca41ba1f885d2erictian *IsError = FALSE; 8493c063fedc4bd816ef427065003dca41ba1f885d2erictian TempCount = (NumberOfBlocks + MaxTransferBlockNumber - 1) / MaxTransferBlockNumber; 8503c063fedc4bd816ef427065003dca41ba1f885d2erictian *EventCount = TempCount; 85158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, NumberOfBlocks=%x\n", NumberOfBlocks)); 85258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, MaxTransferBlockNumber=%x\n", MaxTransferBlockNumber)); 85358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, EventCount=%x\n", TempCount)); 85471fd9fae8bda10f41a9c6445f01eed82b99883daTian, Feng } else { 85558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang while (!IsListEmpty (&AtaDevice->AtaTaskList) || !IsListEmpty (&AtaDevice->AtaSubTaskList)) { 85658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // 85758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Stall for 100us. 85858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // 85958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang MicroSecondDelay (100); 86058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang } 8613c063fedc4bd816ef427065003dca41ba1f885d2erictian } 862490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 863ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang do { 864ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if (NumberOfBlocks > MaxTransferBlockNumber) { 865ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang TransferBlockNumber = MaxTransferBlockNumber; 866490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang NumberOfBlocks -= MaxTransferBlockNumber; 867ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } else { 868ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang TransferBlockNumber = NumberOfBlocks; 8693c063fedc4bd816ef427065003dca41ba1f885d2erictian NumberOfBlocks = 0; 870ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 871ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 872490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 8733c063fedc4bd816ef427065003dca41ba1f885d2erictian // Create sub event for the sub ata task. Non-blocking mode. 874490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 8753c063fedc4bd816ef427065003dca41ba1f885d2erictian if ((Token != NULL) && (Token->Event != NULL)) { 87658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask = NULL; 8773c063fedc4bd816ef427065003dca41ba1f885d2erictian SubEvent = NULL; 8783c063fedc4bd816ef427065003dca41ba1f885d2erictian 87958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_SUB_TASK)); 88058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang if (SubTask == NULL) { 8813c063fedc4bd816ef427065003dca41ba1f885d2erictian Status = EFI_OUT_OF_RESOURCES; 882490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang goto EXIT; 883490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 884490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 8853c063fedc4bd816ef427065003dca41ba1f885d2erictian OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 88658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask->UnsignalledEventCount = EventCount; 88758727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask->Signature = ATA_SUB_TASK_SIGNATURE; 88858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask->AtaDevice = AtaDevice; 88958727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask->Token = Token; 89058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask->IsError = IsError; 89158727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang InsertTailList (&AtaDevice->AtaSubTaskList, &SubTask->TaskEntry); 89258727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang gBS->RestoreTPL (OldTpl); 893490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 894490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Status = gBS->CreateEvent ( 895490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang EVT_NOTIFY_SIGNAL, 896490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang TPL_NOTIFY, 897490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang AtaNonBlockingCallBack, 89858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang SubTask, 899490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang &SubEvent 900490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang ); 901490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 902490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // If resource allocation fail, the un-signalled event count should equal to 903490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // the original one minus the unassigned subtasks number. 904490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 905490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang if (EFI_ERROR (Status)) { 9063c063fedc4bd816ef427065003dca41ba1f885d2erictian Status = EFI_OUT_OF_RESOURCES; 907490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang goto EXIT; 908490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 909490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 91058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang Status = TransferAtaDevice (AtaDevice, &SubTask->Packet, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, SubEvent); 9113c063fedc4bd816ef427065003dca41ba1f885d2erictian } else { 912490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 913490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // Blocking Mode. 914490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang // 91558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang DEBUG ((EFI_D_BLKIO, "Blocking AccessAtaDevice, TransferBlockNumber=%x; StartLba = %x\n", TransferBlockNumber, StartLba)); 916490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang Status = TransferAtaDevice (AtaDevice, NULL, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, NULL); 917490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang } 918490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 919ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang if (EFI_ERROR (Status)) { 920490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang goto EXIT; 921ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } 922490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 9233c063fedc4bd816ef427065003dca41ba1f885d2erictian Index++; 924ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang StartLba += TransferBlockNumber; 925ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang Buffer += TransferBlockNumber * BlockSize; 926ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang } while (NumberOfBlocks > 0); 927ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang 928490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyangEXIT: 9293c063fedc4bd816ef427065003dca41ba1f885d2erictian if ((Token != NULL) && (Token->Event != NULL)) { 9303c063fedc4bd816ef427065003dca41ba1f885d2erictian // 9313c063fedc4bd816ef427065003dca41ba1f885d2erictian // Release resource at non-blocking mode. 9323c063fedc4bd816ef427065003dca41ba1f885d2erictian // 9333c063fedc4bd816ef427065003dca41ba1f885d2erictian if (EFI_ERROR (Status)) { 9343c063fedc4bd816ef427065003dca41ba1f885d2erictian OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 9353c063fedc4bd816ef427065003dca41ba1f885d2erictian Token->TransactionStatus = Status; 9363c063fedc4bd816ef427065003dca41ba1f885d2erictian *EventCount = (*EventCount) - (TempCount - Index); 9373c063fedc4bd816ef427065003dca41ba1f885d2erictian *IsError = TRUE; 93858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 9393c063fedc4bd816ef427065003dca41ba1f885d2erictian if (*EventCount == 0) { 9403c063fedc4bd816ef427065003dca41ba1f885d2erictian FreePool (EventCount); 9413c063fedc4bd816ef427065003dca41ba1f885d2erictian FreePool (IsError); 9423c063fedc4bd816ef427065003dca41ba1f885d2erictian } 94358727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang 94458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang if (SubTask != NULL) { 94558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang RemoveEntryList (&SubTask->TaskEntry); 94658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang FreeAtaSubTask (SubTask); 9473c063fedc4bd816ef427065003dca41ba1f885d2erictian } 948490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 9493c063fedc4bd816ef427065003dca41ba1f885d2erictian if (SubEvent != NULL) { 95058727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang gBS->CloseEvent (SubEvent); 9513c063fedc4bd816ef427065003dca41ba1f885d2erictian } 9523c063fedc4bd816ef427065003dca41ba1f885d2erictian gBS->RestoreTPL (OldTpl); 9533c063fedc4bd816ef427065003dca41ba1f885d2erictian } 95458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang } 955490b5ea10bcdab3579d4c12056b177cea52d6f8eqianouyang 956ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang return Status; 957ad86a50ae7fb2ef9db89b22e0b94d54748ffb24fqhuang} 958c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 959c24097a59ffb10d63c805c4da65476ed6e297c5chhuan/** 960c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Trust transfer data from/to ATA device. 961c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 962c24097a59ffb10d63c805c4da65476ed6e297c5chhuan This function performs one ATA pass through transaction to do a trust transfer from/to 963c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru 964c24097a59ffb10d63c805c4da65476ed6e297c5chhuan interface of ATA pass through. 965c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 966c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @param AtaDevice The ATA child device involved for the operation. 967c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @param Buffer The pointer to the current transaction buffer. 968c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @param SecurityProtocolId The value of the "Security Protocol" parameter of 969c24097a59ffb10d63c805c4da65476ed6e297c5chhuan the security protocol command to be sent. 970c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter 971c24097a59ffb10d63c805c4da65476ed6e297c5chhuan of the security protocol command to be sent. 972c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @param TransferLength The block number or sector count of the transfer. 973c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @param IsTrustSend Indicates whether it is a trust send operation or not. 974c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @param Timeout The timeout, in 100ns units, to use for the execution 975c24097a59ffb10d63c805c4da65476ed6e297c5chhuan of the security protocol command. A Timeout value of 0 976c24097a59ffb10d63c805c4da65476ed6e297c5chhuan means that this function will wait indefinitely for the 977c24097a59ffb10d63c805c4da65476ed6e297c5chhuan security protocol command to execute. If Timeout is greater 978c24097a59ffb10d63c805c4da65476ed6e297c5chhuan than zero, then this function will return EFI_TIMEOUT 979c24097a59ffb10d63c805c4da65476ed6e297c5chhuan if the time required to execute the receive data command 980c24097a59ffb10d63c805c4da65476ed6e297c5chhuan is greater than Timeout. 98186d8e1994269161ae77ab46383415a4f0338b8dfqianouyang @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data 98286d8e1994269161ae77ab46383415a4f0338b8dfqianouyang written to the buffer. Ignore it when IsTrustSend is TRUE. 983c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 984c24097a59ffb10d63c805c4da65476ed6e297c5chhuan @retval EFI_SUCCESS The data transfer is complete successfully. 98558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang @return others Some error occurs when transferring data. 986c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 987c24097a59ffb10d63c805c4da65476ed6e297c5chhuan**/ 988c24097a59ffb10d63c805c4da65476ed6e297c5chhuanEFI_STATUS 989c24097a59ffb10d63c805c4da65476ed6e297c5chhuanEFIAPI 990c24097a59ffb10d63c805c4da65476ed6e297c5chhuanTrustTransferAtaDevice ( 991c24097a59ffb10d63c805c4da65476ed6e297c5chhuan IN OUT ATA_DEVICE *AtaDevice, 992c24097a59ffb10d63c805c4da65476ed6e297c5chhuan IN OUT VOID *Buffer, 993c24097a59ffb10d63c805c4da65476ed6e297c5chhuan IN UINT8 SecurityProtocolId, 994c24097a59ffb10d63c805c4da65476ed6e297c5chhuan IN UINT16 SecurityProtocolSpecificData, 995c24097a59ffb10d63c805c4da65476ed6e297c5chhuan IN UINTN TransferLength, 996c24097a59ffb10d63c805c4da65476ed6e297c5chhuan IN BOOLEAN IsTrustSend, 997c24097a59ffb10d63c805c4da65476ed6e297c5chhuan IN UINT64 Timeout, 998c24097a59ffb10d63c805c4da65476ed6e297c5chhuan OUT UINTN *TransferLengthOut 999c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ) 1000c24097a59ffb10d63c805c4da65476ed6e297c5chhuan{ 1001c24097a59ffb10d63c805c4da65476ed6e297c5chhuan EFI_ATA_COMMAND_BLOCK *Acb; 1002c24097a59ffb10d63c805c4da65476ed6e297c5chhuan EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet; 1003c24097a59ffb10d63c805c4da65476ed6e297c5chhuan EFI_STATUS Status; 1004c24097a59ffb10d63c805c4da65476ed6e297c5chhuan VOID *NewBuffer; 1005c24097a59ffb10d63c805c4da65476ed6e297c5chhuan EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru; 1006c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 1007c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 100858727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Ensure AtaDevice->UdmaValid and IsTrustSend are valid boolean values 1009c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 1010c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ASSERT ((UINTN) AtaDevice->UdmaValid < 2); 1011c24097a59ffb10d63c805c4da65476ed6e297c5chhuan ASSERT ((UINTN) IsTrustSend < 2); 1012c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 1013c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // Prepare for ATA command block. 1014c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 10153c063fedc4bd816ef427065003dca41ba1f885d2erictian Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK)); 1016c24097a59ffb10d63c805c4da65476ed6e297c5chhuan if (TransferLength == 0) { 1017c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Acb->AtaCommand = ATA_CMD_TRUST_NON_DATA; 1018c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } else { 1019c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Acb->AtaCommand = mAtaTrustCommands[AtaDevice->UdmaValid][IsTrustSend]; 1020c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } 1021c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Acb->AtaFeatures = SecurityProtocolId; 1022c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Acb->AtaSectorCount = (UINT8) (TransferLength / 512); 1023c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Acb->AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8); 1024c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 102558727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout. 102658727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang // Here use big endian for Cylinder register. 1027c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 1028c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Acb->AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData; 1029c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Acb->AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8); 10304c33f8b190a439bb931a92eb63eb3cc1806c7cccHao Wu Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort == 0xFFFF ? 0 : (AtaDevice->PortMultiplierPort << 4))); 1031c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 1032c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 1033c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // Prepare for ATA pass through packet. 1034c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 10353c063fedc4bd816ef427065003dca41ba1f885d2erictian Packet = ZeroMem (&AtaDevice->Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET)); 1036c24097a59ffb10d63c805c4da65476ed6e297c5chhuan if (TransferLength == 0) { 1037c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->InTransferLength = 0; 1038c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->OutTransferLength = 0; 1039c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA; 1040c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } else if (IsTrustSend) { 1041c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 1042c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // Check the alignment of the incoming buffer prior to invoking underlying ATA PassThru 1043c24097a59ffb10d63c805c4da65476ed6e297c5chhuan // 1044c24097a59ffb10d63c805c4da65476ed6e297c5chhuan AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru; 1045c24097a59ffb10d63c805c4da65476ed6e297c5chhuan if ((AtaPassThru->Mode->IoAlign > 1) && !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) { 1046c24097a59ffb10d63c805c4da65476ed6e297c5chhuan NewBuffer = AllocateAlignedBuffer (AtaDevice, TransferLength); 10473d267c70b2f69118fe06fcec753fd62a049669ebydong if (NewBuffer == NULL) { 10483d267c70b2f69118fe06fcec753fd62a049669ebydong return EFI_OUT_OF_RESOURCES; 10493d267c70b2f69118fe06fcec753fd62a049669ebydong } 10503d267c70b2f69118fe06fcec753fd62a049669ebydong 1051c24097a59ffb10d63c805c4da65476ed6e297c5chhuan CopyMem (NewBuffer, Buffer, TransferLength); 1052c24097a59ffb10d63c805c4da65476ed6e297c5chhuan FreePool (Buffer); 1053c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Buffer = NewBuffer; 105458727f29ea4da2618e18a0c0d5c819f29badaf26qianouyang } 1055c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->OutDataBuffer = Buffer; 1056c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->OutTransferLength = (UINT32) TransferLength; 1057c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend]; 1058c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } else { 1059c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->InDataBuffer = Buffer; 1060c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->InTransferLength = (UINT32) TransferLength; 1061c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend]; 1062c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } 1063c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES; 1064c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Packet->Timeout = Timeout; 1065c24097a59ffb10d63c805c4da65476ed6e297c5chhuan 1066c24097a59ffb10d63c805c4da65476ed6e297c5chhuan Status = AtaDevicePassThru (AtaDevice, NULL, NULL); 1067c24097a59ffb10d63c805c4da65476ed6e297c5chhuan if (TransferLengthOut != NULL) { 1068c24097a59ffb10d63c805c4da65476ed6e297c5chhuan if (! IsTrustSend) { 1069c24097a59ffb10d63c805c4da65476ed6e297c5chhuan *TransferLengthOut = Packet->InTransferLength; 1070c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } 1071c24097a59ffb10d63c805c4da65476ed6e297c5chhuan } 1072c24097a59ffb10d63c805c4da65476ed6e297c5chhuan return Status; 1073c24097a59ffb10d63c805c4da65476ed6e297c5chhuan} 1074