From: Feng Tian Date: Fri, 22 May 2015 06:53:44 +0000 (+0000) Subject: MdeModulePkg/AtaAtapiPassThruDxe: Support 4K bytes block size HDDs X-Git-Tag: edk2-stable201903~9761 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=e7401ee1af263ff946a57f047124241fa4f01cd5;ds=sidebyside 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 --- 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; }