From e7401ee1af263ff946a57f047124241fa4f01cd5 Mon Sep 17 00:00:00 2001 From: Feng Tian Date: Fri, 22 May 2015 06:53:44 +0000 Subject: 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 Reviewed-by: Star Zeng git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17495 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c | 51 +++++++++++++--------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c index 6ccf0a3f01..870900f106 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c @@ -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.
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
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; } -- cgit v1.2.3