MdeModulePkg/AtaAtapiPassThruDxe: Support 4K bytes block size HDDs

The original code hard-codes block size to 512. But after ATA 7 spec,
the non-512 block size is also supported. The code is updated to
dynamically calculate the block size according to IDENTIFY data.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17495 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Feng Tian 2015-05-22 06:53:44 +00:00 committed by erictian
parent cbbc454b2a
commit e7401ee1af
1 changed files with 31 additions and 20 deletions

View File

@ -2,7 +2,7 @@
This file implements ATA_PASSTHRU_PROCTOCOL and EXT_SCSI_PASSTHRU_PROTOCOL interfaces
for managed ATA controllers.
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
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
@ -1255,6 +1255,7 @@ AtaPassThruPassThru (
UINT32 MaxSectorCount;
ATA_NONBLOCK_TASK *Task;
EFI_TPL OldTpl;
UINT32 BlockSize;
Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
@ -1279,22 +1280,6 @@ AtaPassThruPassThru (
}
}
//
// convert the transfer length from sector count to byte.
//
if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
(Packet->InTransferLength != 0)) {
Packet->InTransferLength = Packet->InTransferLength * 0x200;
}
//
// convert the transfer length from sector count to byte.
//
if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
(Packet->OutTransferLength != 0)) {
Packet->OutTransferLength = Packet->OutTransferLength * 0x200;
}
//
// Check whether this device needs 48-bit addressing (ATAPI-6 ata device).
// Per ATA-6 spec, word83: bit15 is zero and bit14 is one.
@ -1314,13 +1299,39 @@ AtaPassThruPassThru (
}
}
BlockSize = 0x200;
if ((IdentifyData->AtaData.phy_logic_sector_support & (BIT14 | BIT15)) == BIT14) {
//
// Check logical block size
//
if ((IdentifyData->AtaData.phy_logic_sector_support & BIT12) != 0) {
BlockSize = (UINT32) (((IdentifyData->AtaData.logic_sector_size_hi << 16) | IdentifyData->AtaData.logic_sector_size_lo) * sizeof (UINT16));
}
}
//
// convert the transfer length from sector count to byte.
//
if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
(Packet->InTransferLength != 0)) {
Packet->InTransferLength = Packet->InTransferLength * BlockSize;
}
//
// convert the transfer length from sector count to byte.
//
if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
(Packet->OutTransferLength != 0)) {
Packet->OutTransferLength = Packet->OutTransferLength * BlockSize;
}
//
// If the data buffer described by InDataBuffer/OutDataBuffer and InTransferLength/OutTransferLength
// is too big to be transferred in a single command, then no data is transferred and EFI_BAD_BUFFER_SIZE
// is returned.
//
if (((Packet->InTransferLength != 0) && (Packet->InTransferLength > MaxSectorCount * 0x200)) ||
((Packet->OutTransferLength != 0) && (Packet->OutTransferLength > MaxSectorCount * 0x200))) {
if (((Packet->InTransferLength != 0) && (Packet->InTransferLength > MaxSectorCount * BlockSize)) ||
((Packet->OutTransferLength != 0) && (Packet->OutTransferLength > MaxSectorCount * BlockSize))) {
return EFI_BAD_BUFFER_SIZE;
}
@ -2074,7 +2085,7 @@ ExtScsiPassThruPassThru (
// no more sense key or number of sense keys exceeds predefined,
// skip the loop.
//
if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) ||
if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) ||
(SenseDataLen + sizeof (EFI_SCSI_SENSE_DATA) > Packet->SenseDataLength)) {
SenseReq = FALSE;
}