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