From nobody Mon Feb 9 19:07:31 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1527831565590323.9186098991803; Thu, 31 May 2018 22:39:25 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 405A721CAD998; Thu, 31 May 2018 22:39:16 -0700 (PDT) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 03AE4210E2A6D for ; Thu, 31 May 2018 22:39:14 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 31 May 2018 22:39:14 -0700 Received: from ray-dev.ccr.corp.intel.com ([10.239.9.4]) by orsmga003.jf.intel.com with ESMTP; 31 May 2018 22:39:13 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.43; helo=mga05.intel.com; envelope-from=ruiyu.ni@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,464,1520924400"; d="scan'208";a="55664537" From: Ruiyu Ni To: edk2-devel@lists.01.org Date: Fri, 1 Jun 2018 13:39:21 +0800 Message-Id: <20180601053921.34724-5-ruiyu.ni@intel.com> X-Mailer: git-send-email 2.16.1.windows.1 In-Reply-To: <20180601053921.34724-1-ruiyu.ni@intel.com> References: <20180601053921.34724-1-ruiyu.ni@intel.com> Subject: [edk2] [PATCH 4/4] MdeModulePkg/Ata/AtaAtapiPassThru: Enable/disable DEVSLP per policy X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hao A Wu MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni Cc: Chasel Chiu Cc: Hao A Wu Reviewed-by: Chasel Chiu --- MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c | 214 +++++++++++++++++++= ++++ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h | 23 ++- 2 files changed, 235 insertions(+), 2 deletions(-) diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/MdeModulePk= g/Bus/Ata/AtaAtapiPassThru/AhciMode.c index 46d5c68996..3741e3b782 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c @@ -2217,6 +2217,213 @@ Error6: return Status; } =20 +/** + Read logs from SATA device. + + @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 timeout value of stop. + @param Buffer The data buffer to store IDENTIFY PACKET dat= a. + + @retval EFI_DEVICE_ERROR The cmd abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for executing. + @retval EFI_SUCCESS The cmd executes successfully. + +**/ +EFI_STATUS +AhciReadLogExt ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_AHCI_REGISTERS *AhciRegisters, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN OUT UINT8 *Buffer, + IN UINT8 LogNumber, + IN UINT8 PageNumber + ) +{ + EFI_ATA_COMMAND_BLOCK AtaCommandBlock; + EFI_ATA_STATUS_BLOCK AtaStatusBlock; + + if (PciIo =3D=3D NULL || AhciRegisters =3D=3D NULL || Buffer =3D=3D NULL= ) { + return EFI_INVALID_PARAMETER; + } + + /// + /// Read log from device + /// + ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK)); + ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK)); + ZeroMem (Buffer, 512); + + AtaCommandBlock.AtaCommand =3D ATA_CMD_READ_LOG_EXT; + AtaCommandBlock.AtaSectorCount =3D 1; + AtaCommandBlock.AtaSectorNumber =3D LogNumber; + AtaCommandBlock.AtaCylinderLow =3D PageNumber; + + return AhciPioTransfer ( + PciIo, + AhciRegisters, + Port, + PortMultiplier, + NULL, + 0, + TRUE, + &AtaCommandBlock, + &AtaStatusBlock, + Buffer, + 512, + ATA_ATAPI_TIMEOUT, + NULL + ); +} + +/** + Enable DEVSLP command of the disk if supported. + Support for S3 resume to be added later + + @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 co= ntain IDENTIFY data. + +**/ +EFI_STATUS +AhciEnableDevSlp ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_AHCI_REGISTERS *AhciRegisters, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN EFI_IDENTIFY_DATA *IdentifyData + ) +{ + EFI_STATUS Status; + UINT32 Offset; + UINT32 Capability2; + UINT8 LogData[512]; + DEVSLP_TIMING_VARIABLES DevSlpTiming; + UINT32 PortCmd; + UINT32 PortDevSlp; + + if (mAtaAtapiPolicy->DeviceSleepEnable =3D=3D 0) { + return EFI_SUCCESS; + } + + // + // Do not enable DevSlp if DevSlp is not supported. + // + Capability2 =3D AhciReadReg (PciIo, AHCI_CAPABILITY2_OFFSET); + DEBUG ((DEBUG_INFO, "AHCI CAPABILITY2 =3D %08x\n", Capability2)); + if ((Capability2 & AHCI_CAP2_SDS) =3D=3D 0) { + return EFI_UNSUPPORTED; + } + + // + // Do not enable DevSlp if DevSlp is not present + // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is sup= ported + // + Offset =3D EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH; + PortCmd =3D AhciReadReg (PciIo, Offset + EFI_AHCI_PORT_CMD); + PortDevSlp =3D AhciReadReg (PciIo, Offset + AHCI_PORT_DEVSLP); + DEBUG ((DEBUG_ERROR, "Port CMD/DEVSLP =3D %08x / %08x\n", PortCmd, PortD= evSlp)); + if (((PortDevSlp & AHCI_PORT_DEVSLP_DSP) =3D=3D 0) || + ((PortCmd & (EFI_AHCI_PORT_CMD_HPCP | EFI_AHCI_PORT_CMD_MPSP)) !=3D = 0) + ) { + return EFI_UNSUPPORTED; + } + + // + // Do not enable DevSlp if the device doesn't support DevSlp + // + DEBUG ((DEBUG_INFO, "IDENTIFY DEVICE: [77] =3D %04x, [78] =3D %04x, [79]= =3D %04x\n", + IdentifyData->AtaData.reserved_77, + IdentifyData->AtaData.serial_ata_features_supported, IdentifyDat= a->AtaData.serial_ata_features_enabled)); + if ((IdentifyData->AtaData.serial_ata_features_supported & BIT8) =3D=3D = 0) { + DEBUG ((DEBUG_INFO, "DevSlp feature is not supported for device at por= t [%d] PortMultiplier [%d]!\n", + Port, PortMultiplier)); + return EFI_UNSUPPORTED; + } + + // + // Enable DevSlp when it is not enabled. + // + if ((IdentifyData->AtaData.serial_ata_features_enabled & BIT8) !=3D 0) { + Status =3D AhciDeviceSetFeature ( + PciIo, AhciRegisters, Port, 0, ATA_SUB_CMD_ENABLE_SATA_FEATURE, 0x09= , ATA_ATAPI_TIMEOUT + ); + DEBUG ((DEBUG_INFO, "DevSlp set feature for device at port [%d] PortMu= ltiplier [%d] - %r\n", + Port, PortMultiplier, Status)); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Status =3D AhciReadLogExt(PciIo, AhciRegisters, Port, PortMultiplier, Lo= gData, 0x30, 0x08); + + // + // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and Px= DEVSLP.MDAT. + // + AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd & ~EFI_AHCI_POR= T_CMD_ST); + PortDevSlp &=3D ~AHCI_PORT_DEVSLP_ADSE; + AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp); + + // + // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0. + // + PortDevSlp &=3D ~AHCI_PORT_DEVSLP_DETO_MASK; + PortDevSlp &=3D ~AHCI_PORT_DEVSLP_MDAT_MASK; + AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp); + DEBUG ((DEBUG_INFO, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\= n", Port, PortMultiplier, Status)); + if (EFI_ERROR (Status)) { + // + // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Dev= ice Data log (30h, 8) fails + // + DevSlpTiming.Supported =3D 0; + } else { + CopyMem (&DevSlpTiming, &LogData[48], sizeof (DevSlpTiming)); + DEBUG ((DEBUG_INFO, "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n= ", + DevSlpTiming.Supported, DevSlpTiming.Deto, DevSlpTiming.Madt)); + } + + // + // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supporte= d or the DETO is 0. + // + if ((DevSlpTiming.Supported =3D=3D 0) || (DevSlpTiming.Deto =3D=3D 0)) { + DevSlpTiming.Deto =3D 20; + } + + // + // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supporte= d or the MADT is 0. + // + if ((DevSlpTiming.Supported =3D=3D 0) || (DevSlpTiming.Madt =3D=3D 0)) { + DevSlpTiming.Madt =3D 10; + } + + PortDevSlp |=3D DevSlpTiming.Deto << 2; + PortDevSlp |=3D DevSlpTiming.Madt << 10; + AhciOrReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp); + + if (mAtaAtapiPolicy->AggressiveDeviceSleepEnable =3D=3D 1) { + if ((Capability2 & AHCI_CAP2_SADM) !=3D 0) { + PortDevSlp &=3D ~AHCI_PORT_DEVSLP_DITO_MASK; + PortDevSlp |=3D (625 << 15); + AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp); + + PortDevSlp |=3D AHCI_PORT_DEVSLP_ADSE; + AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp); + } + } + + + AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd); + + DEBUG ((DEBUG_INFO, "Enabled DevSlp feature at port [%d] PortMultiplier = [%d], Port CMD/DEVSLP =3D %08x / %08x\n", + Port, PortMultiplier, PortCmd, PortDevSlp)); + + return EFI_SUCCESS; +} =20 /** Spin-up disk if IDD was incomplete or PUIS feature is enabled @@ -2688,6 +2895,13 @@ AhciModeInitialization ( CreateNewDeviceInfo (Instance, Port, 0xFFFF, DeviceType, &Buffer); if (DeviceType =3D=3D EfiIdeHarddisk) { REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA= | EFI_P_PC_ENABLE)); + AhciEnableDevSlp ( + PciIo, + AhciRegisters, + Port, + 0, + &Buffer + ); } =20 // diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h b/MdeModulePk= g/Bus/Ata/AtaAtapiPassThru/AhciMode.h index 809bcc307f..0ef749b4c7 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h @@ -1,7 +1,7 @@ /** @file Header file for AHCI mode of ATA host controller. =20 - Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials =20 are licensed and made available under the terms and conditions of the BS= D License =20 which accompanies this distribution. The full text of the license may b= e found at =20 @@ -29,6 +29,10 @@ =20 #define EFI_AHCI_MAX_PORTS 32 =20 +#define AHCI_CAPABILITY2_OFFSET 0x0024 +#define AHCI_CAP2_SDS BIT3 +#define AHCI_CAP2_SADM BIT4 + typedef struct { UINT32 Lower32; UINT32 Upper32; @@ -182,7 +186,13 @@ typedef union { #define EFI_AHCI_PORT_SACT 0x0034 #define EFI_AHCI_PORT_CI 0x0038 #define EFI_AHCI_PORT_SNTF 0x003C - +#define AHCI_PORT_DEVSLP 0x0044 +#define AHCI_PORT_DEVSLP_ADSE BIT0 +#define AHCI_PORT_DEVSLP_DSP BIT1 +#define AHCI_PORT_DEVSLP_DETO_MASK 0x000003FC +#define AHCI_PORT_DEVSLP_MDAT_MASK 0x00007C00 +#define AHCI_PORT_DEVSLP_DITO_MASK 0x01FF8000 +#define AHCI_PORT_DEVSLP_DM_MASK 0x1E000000 =20 #pragma pack(1) // @@ -283,6 +293,15 @@ typedef struct { UINT8 AhciUnknownFisRsvd[0x60]; =20 } EFI_AHCI_RECEIVED_FIS;=20 =20 +typedef struct { + UINT8 Madt : 5; + UINT8 Reserved_5 : 3; + UINT8 Deto; + UINT16 Reserved_16; + UINT32 Reserved_32 : 31; + UINT32 Supported : 1; +} DEVSLP_TIMING_VARIABLES; + #pragma pack() =20 typedef struct { --=20 2.16.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel