for Security Protocol Specific layout. This implementation uses big endian for\r
Cylinder register.\r
\r
- Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
\r
**/\r
if (TaskPacket != NULL) {\r
Packet = TaskPacket;\r
Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (EFI_ATA_STATUS_BLOCK));\r
+ if (Packet->Asb == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
Packet->Acb = AllocateCopyPool (sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb);\r
} else {\r
\r
AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
\r
+ //\r
+ // Report Status Code to indicate reset happens\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
+ AtaDevice->AtaBusDriverData->ParentDevicePath\r
+ );\r
+\r
return AtaPassThru->ResetDevice (\r
AtaPassThru,\r
AtaDevice->Port,\r
//\r
Acb = ZeroMem (&AtaDevice->Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
Acb->AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
- Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
+ Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort == 0xFFFF ? 0 : (AtaDevice->PortMultiplierPort << 4)));\r
\r
//\r
// Prepare for ATA pass through packet.\r
// The command is issued successfully\r
//\r
Status = IdentifyAtaDevice (AtaDevice);\r
- if (!EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ return Status;\r
}\r
} while (Retry-- > 0);\r
\r
Acb->AtaSectorNumber = (UINT8) StartLba;\r
Acb->AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8);\r
Acb->AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16);\r
- Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
+ Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort == 0xFFFF ? 0 : (AtaDevice->PortMultiplierPort << 4)));\r
Acb->AtaSectorCount = (UINT8) TransferLength;\r
if (AtaDevice->Lba48Bit) {\r
Acb->AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);\r
\r
Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite];\r
Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
- Packet->Timeout = ATA_TIMEOUT;\r
+ //\r
+ // |------------------------|-----------------|------------------------|-----------------|\r
+ // | ATA PIO Transfer Mode | Transfer Rate | ATA DMA Transfer Mode | Transfer Rate |\r
+ // |------------------------|-----------------|------------------------|-----------------|\r
+ // | PIO Mode 0 | 3.3Mbytes/sec | Single-word DMA Mode 0 | 2.1Mbytes/sec |\r
+ // |------------------------|-----------------|------------------------|-----------------|\r
+ // | PIO Mode 1 | 5.2Mbytes/sec | Single-word DMA Mode 1 | 4.2Mbytes/sec |\r
+ // |------------------------|-----------------|------------------------|-----------------|\r
+ // | PIO Mode 2 | 8.3Mbytes/sec | Single-word DMA Mode 2 | 8.4Mbytes/sec |\r
+ // |------------------------|-----------------|------------------------|-----------------|\r
+ // | PIO Mode 3 | 11.1Mbytes/sec | Multi-word DMA Mode 0 | 4.2Mbytes/sec |\r
+ // |------------------------|-----------------|------------------------|-----------------|\r
+ // | PIO Mode 4 | 16.6Mbytes/sec | Multi-word DMA Mode 1 | 13.3Mbytes/sec |\r
+ // |------------------------|-----------------|------------------------|-----------------|\r
+ //\r
+ // As AtaBus is used to manage ATA devices, we have to use the lowest transfer rate to\r
+ // calculate the possible maximum timeout value for each read/write operation.\r
+ // The timout value is rounded up to nearest integar and here an additional 30s is added\r
+ // to follow ATA spec in which it mentioned that the device may take up to 30s to respond\r
+ // commands in the Standby/Idle mode.\r
+ //\r
+ if (AtaDevice->UdmaValid) {\r
+ //\r
+ // Calculate the maximum timeout value for DMA read/write operation.\r
+ //\r
+ Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 2100000) + 31);\r
+ } else {\r
+ //\r
+ // Calculate the maximum timeout value for PIO read/write operation\r
+ //\r
+ Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 3300000) + 31);\r
+ }\r
\r
return AtaDevicePassThru (AtaDevice, TaskPacket, Event);\r
}\r
FreePool (Task);\r
}\r
\r
+/**\r
+ Terminate any in-flight non-blocking I/O requests by signaling an EFI_ABORTED\r
+ in the TransactionStatus member of the EFI_BLOCK_IO2_TOKEN for the non-blocking\r
+ I/O. After that it is safe to free any Token or Buffer data structures that\r
+ were allocated to initiate the non-blockingI/O requests that were in-flight for\r
+ this device.\r
+\r
+ @param[in] AtaDevice The ATA child device involved for the operation.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AtaTerminateNonBlockingTask (\r
+ IN ATA_DEVICE *AtaDevice\r
+ )\r
+{\r
+ BOOLEAN SubTaskEmpty;\r
+ EFI_TPL OldTpl;\r
+ ATA_BUS_ASYN_TASK *AtaTask;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *List;\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ //\r
+ // Abort all executing tasks from now.\r
+ //\r
+ AtaDevice->Abort = TRUE;\r
+\r
+ List = &AtaDevice->AtaTaskList;\r
+ for (Entry = GetFirstNode (List); !IsNull (List, Entry);) {\r
+ AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry);\r
+ AtaTask->Token->TransactionStatus = EFI_ABORTED;\r
+ gBS->SignalEvent (AtaTask->Token->Event);\r
+\r
+ Entry = RemoveEntryList (Entry);\r
+ FreePool (AtaTask);\r
+ }\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ do {\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ //\r
+ // Wait for executing subtasks done.\r
+ //\r
+ SubTaskEmpty = IsListEmpty (&AtaDevice->AtaSubTaskList);\r
+ gBS->RestoreTPL (OldTpl);\r
+ } while (!SubTaskEmpty);\r
+\r
+ //\r
+ // Aborting operation has been done. From now on, don't need to abort normal operation.\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ AtaDevice->Abort = FALSE;\r
+ gBS->RestoreTPL (OldTpl);\r
+}\r
+\r
/**\r
Call back funtion when the event is signaled.\r
\r
if ((!(*Task->IsError)) && ((Task->Packet.Asb->AtaStatus & 0x01) == 0x01)) {\r
Task->Token->TransactionStatus = EFI_DEVICE_ERROR;\r
}\r
+\r
+ if (AtaDevice->Abort) {\r
+ Task->Token->TransactionStatus = EFI_ABORTED;\r
+ }\r
+\r
DEBUG ((\r
EFI_D_BLKIO,\r
"NON-BLOCKING EVENT FINISHED!- STATUS = %r\n",\r
//\r
if (!IsListEmpty (&AtaDevice->AtaTaskList)) {\r
Entry = GetFirstNode (&AtaDevice->AtaTaskList);\r
- AtaTask = ATA_AYNS_TASK_FROM_ENTRY (Entry);\r
+ AtaTask = ATA_ASYN_TASK_FROM_ENTRY (Entry);\r
DEBUG ((EFI_D_BLKIO, "Start to embark a new Ata Task\n"));\r
DEBUG ((EFI_D_BLKIO, "AtaTask->NumberOfBlocks = %x; AtaTask->Token=%x\n", AtaTask->NumberOfBlocks, AtaTask->Token));\r
Status = AccessAtaDevice (\r
SubTask = NULL;\r
SubEvent = NULL;\r
AtaTask = NULL;\r
- \r
+\r
//\r
// Ensure AtaDevice->Lba48Bit is a valid boolean value\r
//\r
//\r
if ((Token != NULL) && (Token->Event != NULL)) {\r
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
if (!IsListEmpty (&AtaDevice->AtaSubTaskList)) {\r
AtaTask = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK));\r
if (AtaTask == NULL) {\r
DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, NumberOfBlocks=%x\n", NumberOfBlocks));\r
DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, MaxTransferBlockNumber=%x\n", MaxTransferBlockNumber));\r
DEBUG ((EFI_D_BLKIO, "AccessAtaDevice, EventCount=%x\n", TempCount));\r
- }else {\r
+ } else {\r
while (!IsListEmpty (&AtaDevice->AtaTaskList) || !IsListEmpty (&AtaDevice->AtaSubTaskList)) {\r
//\r
// Stall for 100us.\r
//\r
Acb->AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData;\r
Acb->AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8);\r
- Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
+ Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort == 0xFFFF ? 0 : (AtaDevice->PortMultiplierPort << 4)));\r
\r
//\r
// Prepare for ATA pass through packet.\r
AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
if ((AtaPassThru->Mode->IoAlign > 1) && !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) {\r
NewBuffer = AllocateAlignedBuffer (AtaDevice, TransferLength);\r
+ if (NewBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
CopyMem (NewBuffer, Buffer, TransferLength);\r
FreePool (Buffer);\r
Buffer = NewBuffer;\r