MdeModulePkg/AtaAtapiPassThru: Spin up Power up in Standby devices
The patch adds support to certain devices that support PUIS (Power up in Standby). For those devices that supports SET_FEATURE spin up, SW needs to send SET_FEATURE subcommand to spin up the devices. For those devices that doesn't support SET_FEATURE spin up, SW needs to send read sectors command to spin up the devices. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Chasel Chiu <chasel.chiu@intel.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
This commit is contained in:
parent
d78675d195
commit
8d3c4b552f
|
@ -1,7 +1,7 @@
|
||||||
/** @file
|
/** @file
|
||||||
The file for AHCI mode of ATA host controller.
|
The file for AHCI mode of ATA host controller.
|
||||||
|
|
||||||
Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||||
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -1826,6 +1826,7 @@ AhciIdentifyPacket (
|
||||||
@param PortMultiplier The port multiplier port number.
|
@param PortMultiplier The port multiplier port number.
|
||||||
@param Feature The data to send Feature register.
|
@param Feature The data to send Feature register.
|
||||||
@param FeatureSpecificData The specific data for SET FEATURE cmd.
|
@param FeatureSpecificData The specific data for SET FEATURE cmd.
|
||||||
|
@param Timeout The timeout value of SET FEATURE cmd, uses 100ns as a unit.
|
||||||
|
|
||||||
@retval EFI_DEVICE_ERROR The cmd abort with error occurs.
|
@retval EFI_DEVICE_ERROR The cmd abort with error occurs.
|
||||||
@retval EFI_TIMEOUT The operation is time out.
|
@retval EFI_TIMEOUT The operation is time out.
|
||||||
|
@ -1841,7 +1842,8 @@ AhciDeviceSetFeature (
|
||||||
IN UINT8 Port,
|
IN UINT8 Port,
|
||||||
IN UINT8 PortMultiplier,
|
IN UINT8 PortMultiplier,
|
||||||
IN UINT16 Feature,
|
IN UINT16 Feature,
|
||||||
IN UINT32 FeatureSpecificData
|
IN UINT32 FeatureSpecificData,
|
||||||
|
IN UINT64 Timeout
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
@ -1868,7 +1870,7 @@ AhciDeviceSetFeature (
|
||||||
0,
|
0,
|
||||||
&AtaCommandBlock,
|
&AtaCommandBlock,
|
||||||
&AtaStatusBlock,
|
&AtaStatusBlock,
|
||||||
ATA_ATAPI_TIMEOUT,
|
Timeout,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2216,6 +2218,104 @@ Error6:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Spin-up disk if IDD was incomplete or PUIS feature is enabled
|
||||||
|
|
||||||
|
@param PciIo The PCI IO protocol instance.
|
||||||
|
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||||
|
@param Port The number of port.
|
||||||
|
@param PortMultiplier The multiplier of port.
|
||||||
|
@param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
AhciSpinUpDisk (
|
||||||
|
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||||
|
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||||
|
IN UINT8 Port,
|
||||||
|
IN UINT8 PortMultiplier,
|
||||||
|
IN OUT EFI_IDENTIFY_DATA *IdentifyData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
|
||||||
|
EFI_ATA_STATUS_BLOCK AtaStatusBlock;
|
||||||
|
UINT8 Buffer[512];
|
||||||
|
|
||||||
|
if (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE) {
|
||||||
|
//
|
||||||
|
// Use SET_FEATURE subcommand to spin up the device.
|
||||||
|
//
|
||||||
|
Status = AhciDeviceSetFeature (
|
||||||
|
PciIo, AhciRegisters, Port, PortMultiplier,
|
||||||
|
ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP, 0x00, ATA_SPINUP_TIMEOUT
|
||||||
|
);
|
||||||
|
DEBUG ((DEBUG_INFO, "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
|
||||||
|
Port, PortMultiplier, Status));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ASSERT (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
|
||||||
|
//
|
||||||
|
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
|
||||||
|
ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
|
||||||
|
//
|
||||||
|
// Perform READ SECTORS PIO Data-In command to Read LBA 0
|
||||||
|
//
|
||||||
|
AtaCommandBlock.AtaCommand = ATA_CMD_READ_SECTORS;
|
||||||
|
AtaCommandBlock.AtaSectorCount = 0x1;
|
||||||
|
|
||||||
|
Status = AhciPioTransfer (
|
||||||
|
PciIo,
|
||||||
|
AhciRegisters,
|
||||||
|
Port,
|
||||||
|
PortMultiplier,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
TRUE,
|
||||||
|
&AtaCommandBlock,
|
||||||
|
&AtaStatusBlock,
|
||||||
|
&Buffer,
|
||||||
|
sizeof (Buffer),
|
||||||
|
ATA_SPINUP_TIMEOUT,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
DEBUG ((DEBUG_INFO, "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
|
||||||
|
Port, PortMultiplier, Status));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read the complete IDENTIFY DEVICE data.
|
||||||
|
//
|
||||||
|
ZeroMem (IdentifyData, sizeof (*IdentifyData));
|
||||||
|
Status = AhciIdentify (PciIo, AhciRegisters, Port, PortMultiplier, IdentifyData);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
|
||||||
|
Port, PortMultiplier, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
|
||||||
|
IdentifyData->AtaData.config, IdentifyData->AtaData.specific_config,
|
||||||
|
IdentifyData->AtaData.command_set_supported_83, IdentifyData->AtaData.command_set_feature_enb_86));
|
||||||
|
//
|
||||||
|
// Check if IDD is incomplete
|
||||||
|
//
|
||||||
|
if ((IdentifyData->AtaData.config & BIT2) != 0) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize ATA host controller at AHCI mode.
|
Initialize ATA host controller at AHCI mode.
|
||||||
|
|
||||||
|
@ -2458,6 +2558,28 @@ AhciModeInitialization (
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
|
||||||
|
Buffer.AtaData.config, Buffer.AtaData.specific_config,
|
||||||
|
Buffer.AtaData.command_set_supported_83, Buffer.AtaData.command_set_feature_enb_86
|
||||||
|
));
|
||||||
|
if ((Buffer.AtaData.config & BIT2) != 0) {
|
||||||
|
//
|
||||||
|
// SpinUp disk if device reported incomplete IDENTIFY DEVICE.
|
||||||
|
//
|
||||||
|
Status = AhciSpinUpDisk (
|
||||||
|
PciIo,
|
||||||
|
AhciRegisters,
|
||||||
|
Port,
|
||||||
|
0,
|
||||||
|
&Buffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Spin up standby device failed - %r\n", Status));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DeviceType = EfiIdeHarddisk;
|
DeviceType = EfiIdeHarddisk;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -2523,7 +2645,7 @@ AhciModeInitialization (
|
||||||
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
|
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));
|
Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode), ATA_ATAPI_TIMEOUT);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
|
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/** @file
|
/** @file
|
||||||
Header file for ATA/ATAPI PASS THRU driver.
|
Header file for ATA/ATAPI PASS THRU driver.
|
||||||
|
|
||||||
Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -148,6 +148,7 @@ struct _ATA_NONBLOCK_TASK {
|
||||||
// It means 3 second span.
|
// It means 3 second span.
|
||||||
//
|
//
|
||||||
#define ATA_ATAPI_TIMEOUT EFI_TIMER_PERIOD_SECONDS(3)
|
#define ATA_ATAPI_TIMEOUT EFI_TIMER_PERIOD_SECONDS(3)
|
||||||
|
#define ATA_SPINUP_TIMEOUT EFI_TIMER_PERIOD_SECONDS(10)
|
||||||
|
|
||||||
#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
|
#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue