MdeModulePkg/AhciPei: Add PEI BlockIO support
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1483 This commit will add the PEI BlockIO (2) PPIs support for AHCI mode ATA devices. More specifically, the driver will consume the ATA AHCI host controller PPI for ATA controllers working under AHCI code within the system. And then produces the below additional PPIs for each controller: EFI PEI Recovery Block IO PPI EFI PEI Recovery Block IO2 PPI Cc: Eric Dong <eric.dong@intel.com> Cc: Jian J Wang <jian.j.wang@intel.com> Signed-off-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
@@ -1872,6 +1872,124 @@ AhciModeInitialization (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Transfer data from ATA device.
|
||||
|
||||
This function performs one ATA pass through transaction to transfer data from/to
|
||||
ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
|
||||
interface of ATA pass through.
|
||||
|
||||
@param[in] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
|
||||
@param[in,out] Buffer The pointer to the current transaction buffer.
|
||||
@param[in] StartLba The starting logical block address to be accessed.
|
||||
@param[in] TransferLength The block number or sector count of the transfer.
|
||||
@param[in] IsWrite Indicates whether it is a write operation.
|
||||
|
||||
@retval EFI_SUCCESS The data transfer is complete successfully.
|
||||
@return others Some error occurs when transferring data.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TransferAtaDevice (
|
||||
IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData,
|
||||
IN OUT VOID *Buffer,
|
||||
IN EFI_LBA StartLba,
|
||||
IN UINT32 TransferLength,
|
||||
IN BOOLEAN IsWrite
|
||||
)
|
||||
{
|
||||
PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EDKII_PEI_ATA_PASS_THRU_PPI *AtaPassThru;
|
||||
EFI_ATA_COMMAND_BLOCK Acb;
|
||||
EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
Private = DeviceData->Private;
|
||||
AtaPassThru = &Private->AtaPassThruPpi;
|
||||
|
||||
//
|
||||
// Ensure Lba48Bit and IsWrite are valid boolean values
|
||||
//
|
||||
ASSERT ((UINTN) DeviceData->Lba48Bit < 2);
|
||||
ASSERT ((UINTN) IsWrite < 2);
|
||||
if (((UINTN) DeviceData->Lba48Bit >= 2) ||
|
||||
((UINTN) IsWrite >= 2)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare for ATA command block.
|
||||
//
|
||||
ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
|
||||
Acb.AtaCommand = mAtaCommands[DeviceData->Lba48Bit][IsWrite];
|
||||
Acb.AtaSectorNumber = (UINT8) StartLba;
|
||||
Acb.AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8);
|
||||
Acb.AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16);
|
||||
Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 |
|
||||
(DeviceData->PortMultiplier == 0xFFFF ?
|
||||
0 : (DeviceData->PortMultiplier << 4)));
|
||||
Acb.AtaSectorCount = (UINT8) TransferLength;
|
||||
if (DeviceData->Lba48Bit) {
|
||||
Acb.AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);
|
||||
Acb.AtaCylinderLowExp = (UINT8) RShiftU64 (StartLba, 32);
|
||||
Acb.AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40);
|
||||
Acb.AtaSectorCountExp = (UINT8) (TransferLength >> 8);
|
||||
} else {
|
||||
Acb.AtaDeviceHead = (UINT8) (Acb.AtaDeviceHead | RShiftU64 (StartLba, 24));
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare for ATA pass through packet.
|
||||
//
|
||||
ZeroMem (&Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
|
||||
if (IsWrite) {
|
||||
Packet.OutDataBuffer = Buffer;
|
||||
Packet.OutTransferLength = TransferLength;
|
||||
} else {
|
||||
Packet.InDataBuffer = Buffer;
|
||||
Packet.InTransferLength = TransferLength;
|
||||
}
|
||||
Packet.Asb = NULL;
|
||||
Packet.Acb = &Acb;
|
||||
Packet.Protocol = mAtaPassThruCmdProtocols[IsWrite];
|
||||
Packet.Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
|
||||
//
|
||||
// |------------------------|-----------------|
|
||||
// | ATA PIO Transfer Mode | Transfer Rate |
|
||||
// |------------------------|-----------------|
|
||||
// | PIO Mode 0 | 3.3Mbytes/sec |
|
||||
// |------------------------|-----------------|
|
||||
// | PIO Mode 1 | 5.2Mbytes/sec |
|
||||
// |------------------------|-----------------|
|
||||
// | PIO Mode 2 | 8.3Mbytes/sec |
|
||||
// |------------------------|-----------------|
|
||||
// | PIO Mode 3 | 11.1Mbytes/sec |
|
||||
// |------------------------|-----------------|
|
||||
// | PIO Mode 4 | 16.6Mbytes/sec |
|
||||
// |------------------------|-----------------|
|
||||
//
|
||||
// As AtaBus is used to manage ATA devices, we have to use the lowest transfer
|
||||
// rate to calculate the possible maximum timeout value for each read/write
|
||||
// operation. The timout value is rounded up to nearest integar and here an
|
||||
// additional 30s is added to follow ATA spec in which it mentioned that the
|
||||
// device may take up to 30s to respond commands in the Standby/Idle mode.
|
||||
//
|
||||
// Calculate the maximum timeout value for PIO read/write operation.
|
||||
//
|
||||
Packet.Timeout = TIMER_PERIOD_SECONDS (
|
||||
DivU64x32 (
|
||||
MultU64x32 (TransferLength, DeviceData->Media.BlockSize),
|
||||
3300000
|
||||
) + 31
|
||||
);
|
||||
|
||||
return AtaPassThru->PassThru (
|
||||
AtaPassThru,
|
||||
DeviceData->Port,
|
||||
DeviceData->PortMultiplier,
|
||||
&Packet
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Trust transfer data from/to ATA device.
|
||||
|
||||
|
Reference in New Issue
Block a user