summaryrefslogtreecommitdiff
path: root/Core/EM/Ahci
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/Ahci')
-rw-r--r--Core/EM/Ahci/AInt13.c1366
-rw-r--r--Core/EM/Ahci/AInt13.dxs37
-rw-r--r--Core/EM/Ahci/AInt13.h395
-rw-r--r--Core/EM/Ahci/AhciBus.c4477
-rw-r--r--Core/EM/Ahci/AhciBus.h919
-rw-r--r--Core/EM/Ahci/AhciComponentName.c314
-rw-r--r--Core/EM/Ahci/AhciController.c3403
-rw-r--r--Core/EM/Ahci/AhciController.h633
-rw-r--r--Core/EM/Ahci/AhciInt13Dxe.c412
-rw-r--r--Core/EM/Ahci/AhciInt13Dxe.dxs51
-rw-r--r--Core/EM/Ahci/AhciInt13Smm.c1157
-rw-r--r--Core/EM/Ahci/AhciInt13Smm.cif15
-rw-r--r--Core/EM/Ahci/AhciInt13Smm.dxs65
-rw-r--r--Core/EM/Ahci/AhciInt13Smm.h155
-rw-r--r--Core/EM/Ahci/AhciInt13Smm.mak72
-rw-r--r--Core/EM/Ahci/AhciInt13Smm.sdl58
-rw-r--r--Core/EM/Ahci/AhciSmm/AhciSmm.c2217
-rw-r--r--Core/EM/Ahci/AhciSmm/AhciSmm.cif14
-rw-r--r--Core/EM/Ahci/AhciSmm/AhciSmm.dxs87
-rw-r--r--Core/EM/Ahci/AhciSmm/AhciSmm.h237
-rw-r--r--Core/EM/Ahci/AhciSmm/AhciSmm.mak82
-rw-r--r--Core/EM/Ahci/AhciSmm/AhciSmm.sdl24
-rw-r--r--Core/EM/Ahci/AhciSources.chmbin0 -> 257910 bytes
-rw-r--r--Core/EM/Ahci/AhciSrc.cif19
-rw-r--r--Core/EM/Ahci/AhciSrc.mak102
-rw-r--r--Core/EM/Ahci/AhciSrc.sdl105
-rw-r--r--Core/EM/Ahci/Aint13.cif18
-rw-r--r--Core/EM/Ahci/Aint13.inf5
-rw-r--r--Core/EM/Ahci/Aint13.mak105
-rw-r--r--Core/EM/Ahci/Aint13.sdl67
30 files changed, 16611 insertions, 0 deletions
diff --git a/Core/EM/Ahci/AInt13.c b/Core/EM/Ahci/AInt13.c
new file mode 100644
index 0000000..1df91f1
--- /dev/null
+++ b/Core/EM/Ahci/AInt13.c
@@ -0,0 +1,1366 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AInt13.c 25 11/24/14 11:59p Kapilporwal $
+//
+// $Revision: 25 $
+//
+// $Date: 11/24/14 11:59p $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AInt13.c $
+//
+// 25 11/24/14 11:59p Kapilporwal
+// [TAG] EIP191939
+// [Category] Improvement
+// [Description] Issue about BIG_REAL_MODE_MMIO_ACCESS of AHCI module
+// [Files] AI13.bin
+// AHCIACC.ASM
+// AhciInt13Dxe.c
+// AhciInt13Dxe.dxs
+// AhciInt13Smm.c
+// AhciInt13Smm.cif
+// AhciInt13Smm.dxs
+// AhciInt13Smm.h
+// AhciInt13Smm.mak
+// AhciInt13Smm.sdl
+// AInt13.c
+// Aint13.cif
+// AInt13.h
+// AhciSmm.c
+// AhciSmm.h
+// AhciSmmProtocol.h
+//
+// 24 9/10/12 2:50a Rameshr
+// [TAG] EIP95440
+// [Category] Improvement
+// [Description] Add HddSecurity and HddSmart feature under UEFI Raid
+// driver mode
+// [Files] Ahcibus.c, Pahcibus.h, Aint13.c
+//
+// 23 8/02/12 8:11a Deepthins
+// [TAG] EIP93480
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] AHCI legacy support module is corrupting the memory.
+// [RootCause] AHCI legacy support module is corrupting the memory as it
+// was using wrong offset for storing the base address.
+// [Solution] Properly calculating offset for storing the base address.
+// [Files] AINT13.EQU, AInt13.c, AInt13.h and AHCIACC.ASM
+//
+// 22 6/02/12 2:53a Anandakrishnanl
+// [TAG] EIP91233
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] pBS->CloseEvent(Event) has to be added in function of
+// SetEbdaAddressForPort() asit cabn handle the multiple legacy boot
+// events.
+// [RootCause] CloseEvent not handled properly as SetEbdaAddressForPort
+// will be re executed
+// [Solution] Event should be closed in SetEbdaAddressForPort when the
+// event callback happens
+// [Files] AInt13.c
+//
+// 21 4/24/12 12:53a Deepthins
+// [TAG] EIP86336
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Can't boot from AHCI if SATA_PORT_COUNT=12
+// [RootCause] The controller number was not updated in DEV_INFO_STRUC
+// for all the Hard Disk
+// [Solution] Updated the controller number in the DEV_INFO_STRUC for
+// all the AHCI devices.
+// [Files] AInt13.c, AInt13.h
+//
+// 20 1/13/12 12:15a Deepthins
+// [TAG] EIP78099
+// [Category] Improvement
+// [Description] Handle multiple AHCI controller in legacy.
+// [Files] Aint13.sdl , AInt13.c , AInt13.h , AHCIACC.ASM , AHCI.EQU ,
+// AINT13.bin (AHCIACC.ASM , AINT13.EQU)
+//
+// 19 11/29/11 4:23a Rameshr
+// [TAG] EIP76393
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Any time AHCI is starting when EBDA size is more than 64K,
+// the problem will show as memory corruption.
+// [RootCause] AHCI INT13 code does not use EBDA properly when at the
+// time of EBDA allocation current size of EBDA exceeds 64K
+// [Solution] Modified code to extend the width of EbdaStart offset from
+// 16-bit to 32-bit.
+// [Files] Aint13.asm, Ahcibsp.asm, Aint13.c, Aint13.h, Aint13.bin
+//
+// 18 6/06/11 2:04a Rameshr
+// [TAG]- EIP 57762
+// [Category]-IMPROVEMENT
+// [Description]- Please help to put SATA ODD PxCLB and PxCLBU to E820 and
+// below 1M.
+// [Files]- Aint13.c
+//
+// 17 2/10/11 10:49a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] Aint13.mak
+// AInt13.h
+// AInt13.c
+//
+// 16 6/21/10 5:31a Rameshr
+// AHCI Legacy booting through MMIO reg.
+// EIP 38444
+//
+// 15 4/16/10 4:18p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 14 7/08/09 5:28p Rameshr
+// Bugfix in ConfigureHddParameter function. EIP#23599
+//
+// 13 7/02/09 10:26a Olegi
+// Bugfix in ConfigureHddParameter function. EIP#23599
+//
+// 12 4/28/09 5:33p Rameshr
+//
+// HDD password support in RAID mode
+// EIP:20421
+//
+// 11 11/26/08 12:24p Olegi
+// Added device handle into BBS table.
+//
+// 10 9/09/08 3:20p Michaela
+// Added AHCI_CD_CSM_ID_OFFSET for assigning
+// device numbers for CDs/DVDs in order to
+// avoid a CSM16 conflict with PATA CD devices, which
+// may be present on some systems
+//
+// 9 6/04/08 11:10a Olegi
+// Use externally defined GUIDs instead of redefining them.
+//
+// 8 5/28/08 9:42a Rameshraju
+// Updated the AMI Address.
+//
+// 7 5/13/08 4:31p Olegi
+// Changes related to the latest release of AI13.BIN
+//
+// 6 5/01/08 1:40p Olegi
+// Increase EBDA size by 1KB to be used in runtime for stack.
+//
+// 5 3/28/08 12:16p Michaela
+// updated copyright
+//
+// 4 28/02/08 6:12p Anandakrishnanl
+// Updated for device detection in AHCI mode.
+//
+// 3 2/09/08 4:41p Olegi
+// Modifications related to the changed AllocateEbda interface.
+//
+// 2 19/12/07 4:32p Anandakrishnanl
+// Transition from EDK AHCI driver to AMI AHCI driver.
+//
+// 1 12/07/07 11:17a Olegi
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//**********************************************************************
+//
+// Name: AInt13.c
+// Description: AHCI Int13 structures initialization routines
+//
+//****************************************************************************
+//<AMI_FHDR_END>
+
+#include "Aint13.h"
+#include "AmiDxeLib.h"
+
+#include "Protocol\LegacyBiosExt.h"
+#include "Protocol\LegacyAhci.h"
+#include "Protocol\BlockIo.h"
+#include "Protocol\DevicePath.h"
+#include "AhciBus.h"
+
+EFI_STATUS InitDrivesInformation (VOID*, UINT16);
+
+EFI_AHCI_INT13_INIT_PROTOCOL gAint13;
+UINT32 EbdaStartOffset;
+
+VOID *gLegacyMemoryAddress;
+VOID *gImage;
+LEGACY16_TO_EFI_DATA_TABLE_STRUC *gLegacy16Data = 0;
+EFI_PCI_IO_PROTOCOL *gPciIo = NULL;
+UINT8 *gHddReadData;
+BOOLEAN gAint13InstallationExecuted = FALSE;
+
+EFI_STATUS InitAhciInt13Support();
+UINT8 gController=0;
+CONTROLLER_INFO_STRUC ControllerInfo[AHCI_CONTROLLER_COUNT];
+EFI_LEGACY_BIOS_EXT_PROTOCOL *gBiosExtensions = NULL;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: Ai13EntryPoint
+//
+// Description: Installs gAhciInt13Init protocol
+//
+// Input: IN EFI_HANDLE ImageHandle,
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS Ai13EntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ gAint13.InitAhciInt13Support = InitAhciInt13Support;
+
+ Status = pBS->InstallProtocolInterface(
+ &ImageHandle,
+ &gAint13ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gAint13
+ );
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CountDrives
+//
+// Description: This routine returns the number of connected AHCI drives as well
+// as it fills the optional SATA_DEVICE_INTERFACE* buffer with the
+// device information.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT16
+CountDrives(
+ IN EFI_HANDLE *HandleBuffer,
+ IN UINTN HandleCount,
+ IN VOID *Devices
+)
+{
+ EFI_STATUS Status;
+ DLINK *dlink;
+ SATA_DEVICE_INTERFACE *SataDevInterface = NULL;
+ UINT16 Drives = 0;
+ UINTN n;
+ AHCI_BUS_PROTOCOL *AhciBusInterface;
+
+ //
+ // Go through all controllers, count the number of valid connected drives
+ //
+ for (n = 0; n < HandleCount; n++) {
+ Status = pBS->HandleProtocol(HandleBuffer[n], &gAciBusInitProtocolGuid, &AhciBusInterface);
+ if (EFI_ERROR(Status)) return Drives;
+
+ for (dlink = AhciBusInterface->SataDeviceList.pHead; dlink; dlink = dlink->pNext) {
+ SataDevInterface = OUTTER(dlink, SataDeviceLink, SATA_DEVICE_INTERFACE);
+ if (SataDevInterface->DeviceState == DEVICE_CONFIGURED_SUCCESSFULLY &&
+ (SataDevInterface->DeviceType == ATA || SataDevInterface->DeviceType == ATAPI)) {
+ if (Devices != NULL) {
+ *((UINTN*)Devices)++ = (UINTN)SataDevInterface;
+ }
+ Drives++;
+ }
+ }
+ }
+
+ return Drives;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetEbdaAddressForPort
+//
+// Description: This function will be called when Legacy boot Event Signled
+// This function will set the EBDA address for PxCLB and PxFB
+//
+// Input: IN EFI_EVENT Event - signalled event
+// IN VOID *Context - calling context
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SetEbdaAddressForPort (IN EFI_EVENT Event, IN VOID *Context)
+{
+ AHCI_BUS_PROTOCOL *AhciBusInterface=(AHCI_BUS_PROTOCOL*)Context;
+ UINT32 PortsImplemented;
+ UINT8 i, PortNumber;
+ UINT32 CurrentEbda;
+ UINT32 PortCommandListBaseAddr=0;
+ UINT32 PortFISBaseAddr=0;
+
+ PortsImplemented = AhciBusInterface->HBAPortImplemented;
+ PortNumber = 0;
+
+ //
+ // Find the EBDA Address from the EbdaStartOffset
+ //
+ if (EbdaStartOffset) {
+ CurrentEbda = (UINT32)(UINTN)(*(UINT16*)0x40e << 4);
+ EbdaStartOffset += CurrentEbda;
+ EbdaStartOffset += (1024-1);
+ PortCommandListBaseAddr = EbdaStartOffset & (~(1024-1));
+ PortFISBaseAddr=PortCommandListBaseAddr + 1024;
+ }
+
+ for (i=0; PortsImplemented; PortsImplemented>>=1, PortNumber++){
+ if (PortsImplemented & 1) {
+
+ //
+ // Clear Start
+ //
+ HBA_PORT_REG32_AND (AhciBusInterface->AhciBaseAddress, PortNumber, HBA_PORTS_CMD, ~(HBA_PORTS_CMD_ST));
+
+ //
+ // Program PxCLB and PxFB
+ //
+ HBA_PORT_WRITE_REG32 (AhciBusInterface->AhciBaseAddress,
+ PortNumber,
+ HBA_PORTS_CLB,
+ PortCommandListBaseAddr);
+
+ HBA_PORT_WRITE_REG32 (AhciBusInterface->AhciBaseAddress,
+ PortNumber, 0x0008,
+ PortFISBaseAddr);
+
+ i++;
+ }
+ }
+
+ pBS->CloseEvent(Event);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: InitAhciInt13Support
+//
+// Description: LegacyAhci driver API function. It initializes drive infomation
+// and places it in BBS table as well as in AHCI INT13 runtime area.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitAhciInt13Support()
+{
+ EFI_HANDLE *HandleBuffer = 0;
+ UINTN HandleCount = 0;
+ UINT16 DevCount = 0;
+ VOID *Devices;
+ EFI_STATUS Status;
+ EFI_EVENT LegacyEvent;
+ AHCI_BUS_PROTOCOL *AhciBusInterface;
+ SATA_DEVICE_INTERFACE *Device;
+
+
+ //
+ // First, find out if we have been called already. If yes - do not do anything
+ // since INT13 installation is not intended to be called multiple times.
+ //
+ if (gAint13InstallationExecuted) return EFI_SUCCESS;
+
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,
+ &gAciBusInitProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer);
+
+// ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ DevCount = CountDrives(HandleBuffer, HandleCount, NULL);
+ //
+ // For the 1st time CountDrives was called to get the number of connected
+ // drives; for the 2nd time it will actually return the device information
+ //
+ if (DevCount == 0) return EFI_SUCCESS;
+
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(VOID*)*DevCount, &Devices);
+ ASSERT_EFI_ERROR(Status);
+
+ CountDrives(HandleBuffer, HandleCount, Devices);
+
+ Status = InitDrivesInformation(Devices, DevCount);
+
+ //
+ // Program the EBDA Address on Legacy boot Event.
+ //
+ Device = *((SATA_DEVICE_INTERFACE**)Devices);
+ AhciBusInterface=Device->AhciBusInterface;
+ CreateLegacyBootEvent(TPL_CALLBACK, &SetEbdaAddressForPort, (VOID*)AhciBusInterface, &LegacyEvent);
+
+ pBS->FreePool(Devices);
+
+ gAint13InstallationExecuted = TRUE;
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: GetNumberOfSectors
+//
+// Description: Returns the total number of sectors from IDENTIFY_DATA
+//
+// Input: IdendifyData - ptr to the IDENTIFY_DATA array
+//
+// Output: Total0 - lower DWORD of the total number of blocks
+// Total1 - higher WORD of the total number of blocks
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+GetNumberOfSectors(
+ IN UINT16 *IdentifyData,
+ OUT UINT32 *Total0,
+ OUT UINT16 *Total1
+)
+{
+ UINT32 d0 = 0;
+ UINT16 d1 = 0;
+
+ //
+ // Get total #of sectors
+ // Word-61, Word-60 = Total #of user addressable sectors
+ // Word-103, Word-102, Word-101, Word-100 = Max user LBA for 48bit LBA
+ //
+ d0 = *(UINT32*)((UINTN)IdentifyData+60*2); // get Words 60-61
+
+ //
+ // If 48-bit LBA enabled then get total number of sectors
+ // from words 100..102
+ //
+ if (IdentifyData[86] & 0x400) {
+ d0 = *(UINT32*)((UINTN)IdentifyData+100*2); // get Words 100-101
+ d1 = *(UINT16*)((UINTN)IdentifyData+102*2); // get Word 102
+ }
+
+ *Total0 = d0;
+ *Total1 = d1;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: CalcTranslatedCyl
+//
+// Description: Returns the CHS-translated number of cylinders
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+CalcTranslatedCyl(
+ IN OUT UINT16 *Cyl,
+ IN OUT UINT8 *Heads,
+ IN OUT UINT8 *Sectors,
+ IN UINT32 TotalBlocks
+)
+{
+ UINT8 heads = *Heads;
+ UINT8 sec = *Sectors;
+ UINT16 cyl;
+
+ for (cyl=TotalBlocks/(UINT16)heads*(UINT16)sec; cyl>1024;) {
+ //
+ // Current xlat scheme does not make #of cylinders <= 1024, try next scheme
+ //
+ cyl = 1024;
+ if (heads == 0xFF) {
+ break; // Head limit reached
+ }
+ heads <<= 1; // Double the heads
+ if (heads == 0) heads = 0xFF;
+ }
+ *Heads = heads;
+ *Sectors = sec;
+ *Cyl = cyl;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: TranslateHdSec
+//
+// Description: This function returns the translated max #of heads (1-based),
+// number of cylinders and sectors/track.
+//
+// Input: Heads - Maximum head number (1-based)
+// Sectors - Sectors/track
+// Cyl - Number of cylinders
+// TotalBlocks - Total number of sectors
+//
+// Output: Cyl - Translated number of cylinders
+// Heads - Translated max head number (1-based)
+// Sectors - Translated number of sectors/track
+//
+// Notes: - If total #of sectors < 1032192 (i.e. FC000 hex),
+// translation is not needed.
+// - If total #of sectors <= 2064384 (i.e. 1F8000 hex),
+// use 63 SPT and 32 HD for translation.
+// - If total #of sectors <= 4128768 (i.e. 3F0000 hex),
+// use 63 SPT and 64 HD for translation.
+// - If total #of sectors <= 8257536 (i.e. 7E0000 hex),
+// use 63 SPT and 128 HD for translation, else
+// use 63 SPT and 255 HD for translation.
+// - In any case, check the parameters for maximum values allowed
+// by BIOS and ATA specs (i.e. 1024 cyl, 16 heads, 63 sec/track)
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+TranslateHdSec(
+ IN OUT UINT16 *Cyl,
+ IN OUT UINT8 *Heads,
+ IN OUT UINT8 *Sectors,
+ IN UINT32 TotalBlocks
+)
+{
+ UINT8 heads = *Heads;
+ UINT8 sec = *Sectors;
+ UINT16 cyl = *Cyl;
+
+ if (TotalBlocks >= 0xFC000) {
+ heads = 32; sec = 63;
+ if (TotalBlocks >= 0x1F8000) {
+ heads = 64; sec = 63;
+ if (TotalBlocks >= 0x3F0000) {
+ heads = 128; sec = 63;
+ if (TotalBlocks >= 0x7E0000) {
+ heads = 255; sec = 63;
+ }
+ }
+ }
+ CalcTranslatedCyl(&cyl, &heads, &sec, TotalBlocks);
+ }
+ else {
+ // hd <= 528MB, no translation is needed normally
+ // check maxm value of the parameters
+ if (cyl>1024 || heads>16 || sec>63) {
+ heads = 32; sec = 63;
+ CalcTranslatedCyl(&cyl, &heads, &sec, TotalBlocks);
+ }
+ }
+ *Heads = heads;
+ *Sectors = sec;
+ *Cyl = cyl;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: ConfigureHddParameter
+//
+// Description: This function fills the DEV_PARAM information for the drive.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ConfigureHddParameter(
+ IN EFI_BLOCK_IO_PROTOCOL *BlkIo,
+ IN UINT16 *IdentifyData,
+ IN OUT DEV_PARAM_STRUC *DevParam,
+ IN DEV_INFO_STRUC *DevInfo,
+ IN DEV_PTR_STRUC *DevPtr
+)
+{
+ EFI_STATUS Status;
+ UINT8 PartNo;
+ UINT8 *PartPtr;
+ UINT8 *NonActivePartPtr = NULL;
+ UINT32 OemName;
+ BOOLEAN ValidTable = FALSE;
+ BOOLEAN ValidMBR=FALSE;
+ UINT8 heads, sec;
+ UINT16 cyl;
+ UINT16 SecTimesHeads;
+ UINT32 TotalBlocks;
+
+ //
+ // Check whether the hard disk is already formatted. If already formatted,
+ // find out what mode it was formatted with.
+ //
+ if(BlkIo == NULL ) {
+ return;
+ }
+ Status = BlkIo->ReadBlocks(BlkIo, BlkIo->Media->MediaId, 0, 0x200, gHddReadData);
+ if (!EFI_ERROR(Status) && (*(UINT16*)(gHddReadData+0x1FE) == 0xAA55)) {
+ //
+ // Drive has a partition table, take parameter from 1st bootable partition
+ //
+ PartPtr = gHddReadData+0x1BE;
+
+ for (PartNo=0; PartNo<4; PartNo++, PartPtr+=0x10) {
+ if ((*PartPtr) == 0x80) {
+ ValidTable = TRUE;
+ break;
+ }
+ if (((*(UINT16*)(PartPtr+5)) & 0x3F00) == 0) {
+ // not well formed paritioned table, end sector# = 0
+ continue;
+ }
+ if (NonActivePartPtr == NULL) {
+ NonActivePartPtr = PartPtr;
+ }
+ }
+
+ if (!ValidTable && (NonActivePartPtr != NULL)) {
+ //
+ // No active partition found, use 1st non-active valid partition
+ //
+ PartPtr = NonActivePartPtr;
+ ValidTable = TRUE;
+ }
+
+ if (ValidTable) {
+ //
+ // Either active or first non-active entry found at PartPtr
+ // Read it at gHddReadData + 0xE00
+ //
+ Status = BlkIo->ReadBlocks(BlkIo, BlkIo->Media->MediaId,
+ *(UINT32*)(PartPtr+8), 0x200, gHddReadData+0x800);
+ if (!EFI_ERROR(Status) && (*(UINT16*)(gHddReadData+0x800+0x1FE) == 0xAA55)) {
+ //
+ // Read succeeded so the drive is formatted; check for
+ // valid MSDOS/MSWIN/NTFS boot record
+ //
+ OemName = *(UINT32*)(gHddReadData+0x800+3);
+
+ // 'ODSM' for MSDO
+ // 'IWSM' for MSWI
+ // 'SFTN' for NTFS
+ if((OemName == 0x4F44534D) || (OemName == 0x4957534D) || (OemName == 0x5346544E)) {
+ ValidMBR=TRUE;
+ } else {
+ // Check for valid FAT,FAT16,FAT32 boot records
+ *(gHddReadData+0x800+0x36+3) = 0x20; // Ignore the 4th byte and fill it with space
+ if ((*(UINT32*)(gHddReadData+0x800+0x36) == 0x20544146) // " TAF" for FATx
+ || (*(UINT32*)(gHddReadData+0x800+0x52) == 0x33544146)) // "3TAF" for FAT3
+ {
+ ValidMBR = TRUE;
+ }
+ }
+ }
+ if (ValidMBR) {
+ heads = *(gHddReadData+0x800+0x1A); // number of heads
+ sec = *(gHddReadData+0x800+0x18); // Sectors/track
+ SecTimesHeads = heads * sec;
+ if (SecTimesHeads == 0) {
+ ValidMBR = FALSE;
+ } else {
+ //
+ // Here we have heads/sectors info from partition boot record of known OSes.
+ // NOTE: sectors/track and #of heads is the information with which
+ // the concerned partition was created. This information must be used to
+ // calculate #of cylinders to maintain the current translation scheme.
+ //
+
+ // Find the total #of sectors in the hard disk C * H * S
+ TotalBlocks = DevParam->bMAXHN * DevParam->bMAXSN * DevParam->wMAXCYL;
+ // Calculate #of cylinders using the same translation scheme
+ cyl = TotalBlocks / SecTimesHeads;
+ if (cyl>1024) cyl = 1024;
+ }
+ }
+ }
+ }
+
+ if (!ValidMBR) {
+ //
+ // Hard disk was not formatted OR no valid partition table entry was found;
+ // find the translation scheme which will be used for the hard disk.
+ //
+ cyl = DevParam->wMAXCYL;
+ heads = DevParam->bMAXHN;
+ sec = DevParam->bMAXSN;
+ TotalBlocks = cyl * sec * heads;
+
+ TranslateHdSec(&cyl, &heads, &sec, TotalBlocks);
+ }
+
+
+ DevParam->wLBACYL = DevParam->wMAXCYL;
+ DevParam->bLBAHD = DevParam->bMAXHN;
+ DevParam->bLBASPT = DevParam->bMAXSN;
+
+ DevParam->wMAXCYL = cyl;
+ DevParam->bMAXHN = heads;
+ DevParam->bMAXSN = sec;
+
+ if (heads > 8) {
+ DevParam->bCBYTE = 8; // More than 8 heads indication
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: InitAhciHddDev
+//
+// Description: This function initializes the AHCI HD drive specific information.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InitAhciHddDev (
+ IN SATA_DEVICE_INTERFACE *Dev,
+ IN DEV_PARAM_STRUC *DevParam,
+ IN DEV_INFO_STRUC *DevInfo,
+ IN DEV_PTR_STRUC *DevPtr,
+ AHCI_RT_MISC_DATA *AhciRtMiscData
+)
+{
+ UINT16 *IdentifyData;
+ UINT32 d0;
+ UINT16 d1;
+ UINT8 DevNo;
+ UINT32 SegOfs;
+ UINT16 heads, spt, cyl;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ UINT32 Temp;
+ UINT8 Temp2 = 0;
+
+ IdentifyData = (UINT16*)&Dev->IdentifyData;
+
+ heads = IdentifyData[3];
+ spt = IdentifyData[6];
+ ASSERT((heads<255) && (spt<255)); // Both heads & sectors/track must be 8-bit
+
+ //
+ // Save AHCI HD Mode Information
+ //
+ DevInfo->bPIOInfo = (UINT8)IdentifyData[64];
+ DevInfo->bUDMAInfo = (UINT8)IdentifyData[88];
+
+ cyl = IdentifyData[1];
+
+ DevParam->wMAXCYL = cyl;
+ DevParam->bMAXHN = (UINT8)heads;
+ DevParam->bMAXSN = (UINT8)spt;
+
+ GetNumberOfSectors(IdentifyData, &d0, &d1);
+ DevInfo->dTotalSectorsLo = d0;
+ DevInfo->dTotalSectorsHi = (UINT32)d1;
+
+ DevNo = AhciRtMiscData->NumAhciDevice++;
+ DevInfo->bInt13Num = DevNo | 0x80;
+ DevPtr->bInt13Num = DevNo | 0x80;
+ DevPtr->bPMnum = Dev->PortNumber;
+ DevPtr->bPortNum = Dev->PMPortNumber;
+ //
+ // Update SEG:OFS address for current DevParam and DevInfo
+ //
+ SegOfs = ((UINT32)gLegacyMemoryAddress<<12)+(UINT32)((UINTN)DevParam-(UINTN)gImage);
+ DevPtr->dParamTablePtr = SegOfs;
+
+ SegOfs = ((UINT32)gLegacyMemoryAddress<<12)+(UINT32)((UINTN)DevInfo-(UINTN)gImage);
+ DevPtr->dInfoTablePtr = SegOfs;
+
+ //
+ // Indicate device is LBA capable
+ // Note: Non-LBA device are not supported in this release
+ //
+ DevInfo->bSelector |= SELECTOR_LBA;
+
+ //
+ // Check whether device is 48-bit LBA capable
+ //
+ if (IdentifyData[86] & 0x400) {
+ DevInfo->bInfoFlag |= INFO_LBA_48;
+ }
+ //
+ // Update sector size if necessary
+ //
+ if ( (IdentifyData[106] & 0x4000) && (!(IdentifyData[106] & 0x8000)) && (IdentifyData[106] & 0x1000) ) {
+ Temp = (UINT32)(IdentifyData[117] + (IdentifyData[118] << 16)) * 2;
+ while (Temp > 1) {
+ Temp = Temp >> 1;
+ Temp2++;
+ }
+ DevInfo->bSectorSizeN = Temp2;
+ }
+ //
+ // Note: Interrupt driven mechanism is not supported
+ //
+ DevInfo->bInfoFlag &= ~(INFO_IRQ);
+
+ //
+ // Do the LBA to CHS translation; use BlkIo to read partition/boot record
+ //
+ BlkIo = &Dev->SataBlkIo->BlkIo;
+ ConfigureHddParameter(BlkIo, IdentifyData, DevParam, DevInfo, DevPtr);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: InitAhciCd
+//
+// Description: This function initializes AHCI CD/DVDROM device information.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InitAhciCd(
+ IN SATA_DEVICE_INTERFACE *Dev,
+ IN DEV_PARAM_STRUC *DevParam,
+ IN DEV_INFO_STRUC *DevInfo,
+ IN DEV_PTR_STRUC *DevPtr,
+ AHCI_RT_MISC_DATA *AhciRtMiscData
+)
+{
+ UINT8 DevNo;
+ UINT32 SegOfs;
+
+ DevNo = AhciRtMiscData->NumAhciDevice++;
+ DevInfo->bInt13Num = (DevNo + AHCI_CD_CSM_ID_OFFSET) | BIT7 ;
+ DevPtr->bInt13Num = (DevNo + AHCI_CD_CSM_ID_OFFSET) | BIT7;
+ DevPtr->bPMnum = Dev->PortNumber;
+ DevPtr->bPortNum = Dev->PMPortNumber;
+ //
+ // Update SEG:OFS address for current DevParam and DevInfo
+ //
+ SegOfs = ((UINT32)gLegacyMemoryAddress<<12)+(UINT32)((UINTN)DevParam-(UINTN)gImage);
+ DevPtr->dParamTablePtr = SegOfs;
+
+ SegOfs = ((UINT32)gLegacyMemoryAddress<<12)+(UINT32)((UINTN)DevInfo-(UINTN)gImage);
+ DevPtr->dInfoTablePtr = SegOfs;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: UpdateControllerInfoToLegacy
+//
+// Description: This function will check if the BusDevFunc is existing in
+// the array, if it exist then it returns EFI_SUCCESS and if not then
+// it will add BusDevFunc into the array and returns EFI_NOT_FOUND.
+//
+// Input: Dev - Structure pointing to SATA_DEVICE_INTERFACE
+// DevInfo - Stucture that maintatin device information
+// wBusDevFunc - It contatin the BusDevFunc number for a device
+//
+// Output: EFI_NOT_FOUND - If wBusDevFunc is not present in the array.
+// i.e a new controller is found
+// EFI_SUCCESS - If wBusDevFunc is present in the array
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+UpdateControllerInfoToLegacy(
+ IN SATA_DEVICE_INTERFACE *Dev,
+ IN DEV_INFO_STRUC *DevInfo,
+ IN UINT16 wBusDevFunc
+ )
+{
+ UINT8 i;
+ EFI_STATUS Status;
+ UINT32 Addr16=0;
+ UINT16 *TempAddress;
+
+ for(i=0;i<gController;i++) {
+ if(ControllerInfo[i].BusDevFun == wBusDevFunc) {
+ //
+ // Updatng the respective controller number.
+ //
+ DevInfo->bControllerNo=ControllerInfo[i].ControllerNo;
+ return;
+ }
+ }
+
+ //
+ // A new controller is found so BusDevFunc and ControllerNo is added
+ // into the array of structure.
+ //
+ ControllerInfo[gController].BusDevFun = wBusDevFunc;
+ ControllerInfo[gController].ControllerNo = gController;
+ DevInfo->bControllerNo= gController++;
+
+ //
+ // Store the current controller's PciIO in global variable
+ //
+ gPciIo = Dev->AhciBusInterface->PciIO;
+ Status = gBiosExtensions->Get16BitFuncAddress(
+ CSM16_CSP_AHCI_ACCESSHBA,
+ &Addr16
+ );
+
+ //
+ //At 'Addr16+2' there is a pointer that point to the structure
+ //that maintains index, data and base address for a controller
+ //
+ TempAddress=(UINT16*)(Addr16+2);
+ Addr16=Addr16 + (*TempAddress);
+
+ //
+ // No Addr16 points to ReadWriteRegisterDword routine implemented in
+ // AHCIACC.ASM in CSP module part
+ //
+ if (!EFI_ERROR(Status)) {
+ Status = InitCspData((UINT16)((Addr16>>4) & 0xF000), (UINT16)Addr16, (UINT32)(Dev->AhciBusInterface->AhciBaseAddress),DevInfo->bControllerNo);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: InitAhciDev
+//
+// Description: This function initializes AHCI device specific information.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InitAhciDev(
+ IN SATA_DEVICE_INTERFACE *Dev,
+ IN DEV_PARAM_STRUC *DevParam,
+ IN DEV_INFO_STRUC *DevInfo,
+ IN DEV_PTR_STRUC *DevPtr,
+ AHCI_RT_MISC_DATA *AhciRtMiscData
+)
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN seg, bus, dev, func;
+ UINT8 bIrq;
+ UINT32 dHbaBase;
+ UINT8 bPort;
+ EFI_STATUS Status;
+
+ PciIo = Dev->AhciBusInterface->PciIO;
+
+ bPort = Dev->PortNumber;
+ DevInfo->bPortNum = bPort;
+ DevInfo->bPMNum = Dev->PMPortNumber;
+
+ Status = PciIo->Pci.Read(PciIo, EfiPciIoWidthUint8, 0x3C, 1, &bIrq);
+ ASSERT_EFI_ERROR(Status);
+ DevInfo->bIrq = bIrq;
+
+ Status = PciIo->GetLocation(PciIo, &seg, &bus, &dev, &func);
+ ASSERT_EFI_ERROR(Status);
+ DevInfo->wBusDevFunc = ((UINT16)bus<<8) + ((UINT16)dev<<3) + (UINT16)func;
+
+ //
+ // Pass the Controller Information to Legacy.
+ //
+ UpdateControllerInfoToLegacy(Dev,DevInfo,DevInfo->wBusDevFunc);
+
+ DevInfo->dHbaCap = Dev->AhciBusInterface->HBACapability;
+ DevInfo->bSelector = SELECTOR_NON_LBA;
+ DevInfo->bSectorSizeN = SECTOR_LENGTH_N; // N value of default sector size 2^N;
+ dHbaBase = (UINT32)Dev->AhciBusInterface->AhciBaseAddress;
+ DevInfo->dHbaBase = dHbaBase;
+ DevInfo->dPortBase = dHbaBase + PORT_REGISTER_START + ((UINT32)bPort<<PORT_REGISTER_SET_SIZE_N);
+
+ if (Dev->DeviceType == ATAPI) {
+ DevInfo->bInfoFlag |= INFO_ATAPI;
+ InitAhciCd(Dev, DevParam, DevInfo, DevPtr, AhciRtMiscData);
+ } else {
+ InitAhciHddDev(Dev, DevParam, DevInfo, DevPtr, AhciRtMiscData);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: CreateAhciDriveString
+//
+// Description: This function generates the readable string with the name of
+// device and the SATA port number this device is connected to.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+CreateAhciDriveString(
+ IN OUT UINT8 *DescString,
+ IN UINT16 *IdentifyData,
+ IN UINT8 DevicePortNum,
+ IN UINT8 DevicePortMulNum
+)
+{
+ UINT8 s[MAX_DESCRIPTION_STRLEN] = "xP :";
+ UINT8 i, data8;
+
+ s[0] = DevicePortNum+0x30;
+
+ // Get the drive name out of IdentifyDrive data word 27..46 (upto 40 chars)
+ pBS->CopyMem(&s[4], IdentifyData+27, MAX_DESCRIPTION_STRLEN-5);
+ // Swap the bytes
+ for (i=0; i<MAX_DESCRIPTION_STRLEN; i+=2) {
+ data8=s[i];
+ s[i]=s[i+1];
+ s[i+1]=data8;
+ }
+
+ s[MAX_DESCRIPTION_STRLEN-1] = 0; // terminate with zero
+
+ pBS->CopyMem(DescString, s, MAX_DESCRIPTION_STRLEN);
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: CreateBbsEntry
+//
+// Description: This function creates BBS entry with the device data filled
+// according to the actual device information.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CreateBbsEntry(
+ IN SATA_DEVICE_INTERFACE *Dev,
+ IN OUT DEV_BBS_OUTFIT *DevOutfit,
+ IN OUT BBS_TABLE *BbsEntry,
+ IN UINT8 Int13Handle,
+ IN UINT16 BcvOffset
+)
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN seg, bus, dev, func;
+ EFI_STATUS Status;
+ UINT8 dData[4];
+ UINT8 bDevAndSysType;
+ UINT8 bHandle;
+ UINT8 bMasterSlave = 0;
+ UINT8 bBaidDeviceType;
+
+ pBS->SetMem(BbsEntry, sizeof(BBS_TABLE), 0);
+
+ //
+ // Get PCI location
+ //
+ PciIo = Dev->AhciBusInterface->PciIO;
+ Status = PciIo->GetLocation(PciIo, &seg, &bus, &dev, &func);
+ BbsEntry->Bus = (UINT32)bus;
+ BbsEntry->Device = (UINT32)dev;
+ BbsEntry->Function = (UINT32)func;
+
+ //
+ // Get class/subclass information
+ //
+ Status = PciIo->Pci.Read(
+ PciIo,
+ EfiPciIoWidthUint32,
+ 8, // offset
+ 1, // width
+ &dData);
+ ASSERT_EFI_ERROR(Status);
+
+ BbsEntry->Class = dData[3];
+ BbsEntry->SubClass = dData[2];
+
+ CreateAhciDriveString(
+ DevOutfit->DescString,
+ (UINT16*)&Dev->IdentifyData,
+ Dev->PortNumber,
+ Dev->PMPortNumber
+ );
+
+ BbsEntry->DescStringSegment = (UINT16)((UINTN)gLegacyMemoryAddress >> 4);
+ BbsEntry->DescStringOffset = (UINT16)((UINTN)DevOutfit->DescString-(UINTN)gImage);
+
+ bDevAndSysType = (SYSTYPE_ATA << 4)+DEVTYPE_SYS;
+ bHandle = Int13Handle;
+
+ if (Dev->DeviceType == ATAPI) {
+ bBaidDeviceType = BAID_TYPE_CDROM;
+ BbsEntry->DeviceType = BBS_CDROM;
+ BbsEntry->BootHandlerSegment = 0xF000;
+ BbsEntry->BootHandlerOffset = gLegacy16Data->CdrBevOffset;
+
+ } else {
+ BbsEntry->DeviceType = BBS_HARDDISK;
+ bBaidDeviceType = BAID_TYPE_HDD;
+ BbsEntry->BootHandlerSegment = (UINT16)((UINTN)gLegacyMemoryAddress >> 4);
+ BbsEntry->BootHandlerOffset = BcvOffset + (Int13Handle & 0x7F)*4;
+ }
+
+ BbsEntry->InitPerReserved = ((UINT32)bBaidDeviceType<<24)
+ +((UINT32)bMasterSlave<<16)
+ +((UINT32)bHandle<<8)
+ +(UINT32)bDevAndSysType;
+
+ *(UINTN*)(&BbsEntry->IBV1) = (UINTN)Dev->IdeDeviceHandle;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitDrivesInformation
+//
+// Description: Initialization of data structures and placement of runtime
+// code of AHCI INT13
+//
+// Input: Devices - pointer to the beginning of the instances of
+// SATA_DEVICE_INTERFACE*
+// DeviceCount - number of valid AHCI devices pointed by
+// Devices parameter
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitDrivesInformation(
+ IN VOID *Devices,
+ IN UINT16 DeviceCount
+)
+{
+ EFI_LEGACY_BIOS_PROTOCOL *Bios = NULL;
+ UINTN ImageSize;
+ EFI_STATUS Status;
+ AHCI_I13_RTDATA *Ai13Data;
+ UINTN Count, i;
+ UINT32 EbdaAddress;
+ BBS_TABLE BbsEntry;
+ UINT32 LockUnlockAddr, LockUnlockSize;
+ UINT16 CheckForAhciCdromOffset;
+ UINT32 CheckForAhciCdromAddress;
+ UINT8 *addr;
+ SATA_DEVICE_INTERFACE *Device;
+ UINT8 PciConfig[16];
+
+
+ if (DeviceCount == 0) return EFI_SUCCESS; // No devices connected
+
+ Status = pBS->LocateProtocol(
+ &gEfiLegacyBiosProtocolGuid, NULL, &Bios);
+ if (EFI_ERROR(Status)) return Status;
+
+ //
+ // Get the AHCI INT13 runtime image
+ //
+ Status = pBS->LocateProtocol(
+ &gEfiLegacyBiosExtProtocolGuid, NULL, &gBiosExtensions);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = gBiosExtensions->GetEmbeddedRom(
+ CSM16_MODULEID, CSM16_VENDORID, CSM16_AHCI_RT_DID, &gImage, &ImageSize);
+ if (EFI_ERROR(Status)) return Status;
+
+ //
+ // Instantiate data area
+ //
+ Ai13Data = (AHCI_I13_RTDATA*)gImage;
+
+ //
+ // Fill the data area with the init values
+ //
+ pBS->SetMem(Ai13Data, sizeof (AHCI_I13_RTDATA), 0);
+ pBS->SetMem(Ai13Data->DevPtr, sizeof(DEV_PTR_STRUC)*SATA_PORT_COUNT, 0xFF);
+
+ //
+ // Allocate legacy region in E000 segment; store SEG:OFS of the allocated
+ // memory in global variables
+ //
+ Status = Bios->GetLegacyRegion(Bios, ImageSize, 2, 0x10, &gLegacyMemoryAddress);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) return Status;
+
+ //
+ // Allocate EBDA area for Command List/Command Table/FIS
+ //
+ Status = gBiosExtensions->AllocateEbda(
+ gBiosExtensions,
+ SIZE_CLCTFIS_AREA_K+1, // 1K extra for stack
+ &EbdaAddress,
+ &EbdaStartOffset );
+ ASSERT_EFI_ERROR(Status);
+
+#if AINT13_AVOID_MULTIPLE_SMI
+ Ai13Data->AhciRtMiscData.RunAttribute |= A_INT13_SWSMI_USED;
+ Ai13Data->AhciRtMiscData.AhciSmmRt.MiscInfo = 1;
+ Ai13Data->AhciRtMiscData.AhciSmmRt.SmmAttr = 0;
+ Ai13Data->AhciRtMiscData.AhciSmmRt.SmmPort = SW_SMI_IO_ADDRESS;
+ Ai13Data->AhciRtMiscData.AhciSmmRt.SmmData = AHCI_INT13_SMM_SWSMI_VALUE;
+#endif
+
+ Ai13Data->AhciRtMiscData.AhciEbdaStart = EbdaStartOffset;
+ Ai13Data->AhciRtMiscData.RunAttribute |= A_EBDA_USED;
+
+ gBiosExtensions->UnlockShadow(
+ (UINT8*)gLegacyMemoryAddress, ImageSize,
+ &LockUnlockAddr, &LockUnlockSize);
+
+ gLegacy16Data = (LEGACY16_TO_EFI_DATA_TABLE_STRUC*)(UINTN)(0xF0000 + *(UINT16*)0xFFF4C);
+
+ Status = pBS->AllocatePool(EfiBootServicesData, 0x1000, &gHddReadData);
+ ASSERT_EFI_ERROR(Status)
+
+ //
+ // Here is a tricky part: we will have to convert the data passed by Ahci Bus
+ // driver to the data used by INT13
+ //
+ for (Count=0, i=0; i<DeviceCount; i++, ((UINTN*)Devices)++) {
+ Device = *((SATA_DEVICE_INTERFACE**)Devices);
+ InitAhciDev(Device,
+ &Ai13Data->DevParam[Count],
+ &Ai13Data->DevInfo[Count],
+ &Ai13Data->DevPtr[Count],
+ &Ai13Data->AhciRtMiscData
+ );
+
+ Status = gPciIo->Pci.Read ( gPciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciConfig),
+ PciConfig
+ );
+
+ //
+ //Under Raid mode ATA devices are not added into BBS table.
+ //
+ if((PciConfig [IDE_SUB_CLASS_CODE]!= SCC_RAID_CONTROLLER) || (Device->DeviceType != ATA)) {
+ Status = CreateBbsEntry(Device,
+ &Ai13Data->DevOutfit[Count],
+ &BbsEntry,
+ Ai13Data->DevPtr[Count].bInt13Num,
+ ((AHCI_I13_DATA*)Ai13Data)->AhciBcvOffset
+ );
+
+ ASSERT_EFI_ERROR(Status);
+
+ Status = gBiosExtensions->AddBbsEntry(&BbsEntry);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ Count++;
+ if (Count==SATA_PORT_COUNT) break;
+ }
+
+ //
+ // Patch farReturnCDROMSupportAPIPointer routine with "call farCheckForAHCICdrom"
+ //
+ CheckForAhciCdromOffset = ((AHCI_I13_DATA*)Ai13Data)->CheckForAhciCdromOffset;
+ CheckForAhciCdromAddress =
+ (UINT32)((UINTN)gLegacyMemoryAddress<<12) + (UINT32)CheckForAhciCdromOffset;
+
+ addr = (UINT8*)(UINTN)(0xF0000+gLegacy16Data->CDROMSupportAPIOfs+10);
+ *addr++ = 0x9A; // far call opcode
+ *(UINT32*)addr = CheckForAhciCdromAddress;
+
+ //
+ // Copy the image into the shadow
+ //
+ pBS->CopyMem(gLegacyMemoryAddress, gImage, ImageSize);
+
+ gBiosExtensions->LockShadow(LockUnlockAddr, LockUnlockSize);
+
+ pBS->FreePool(gHddReadData);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitCspData
+//
+// Description: Initialization of chipset specific fields of AHCI runtime
+// (INT 13) code.
+//
+// Input: Seg16, Ofs16 - 16-bit address of chipset specific 16-bit code/data.
+//
+// Output: Status of operation
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitCspData(
+ IN UINT16 Seg16,
+ IN UINT16 Ofs16,
+ IN UINT32 BaseAddress,
+ IN UINT8 ControllerNumber
+
+)
+{
+ UINT16 indx, data;
+ UINT16 *addr;
+ EFI_STATUS Status;
+
+ ASSERT(gPciIo);
+
+ //
+ // Calculate the address according to the segment ,offset and controller
+ // number.
+ addr = (UINT16*)(UINTN)(((UINTN)Seg16<<4)+(UINTN)Ofs16)+ 4*(ControllerNumber);
+
+ //
+ // Update the Ahci Base Address
+ //
+ *(UINT32*)(addr+2)=BaseAddress;
+
+ Status = GetAccessInfo (gPciIo, &indx, &data);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Update the Index and Data Port
+ //
+ *addr++ = indx;
+ *addr = data;
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AInt13.dxs b/Core/EM/Ahci/AInt13.dxs
new file mode 100644
index 0000000..877fea3
--- /dev/null
+++ b/Core/EM/Ahci/AInt13.dxs
@@ -0,0 +1,37 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+#include "token.h"
+#ifdef CSM_SUPPORT
+#include <Protocol/LegacyBios.h>
+#endif
+
+DEPENDENCY_START
+#if CSM_SUPPORT
+ EFI_LEGACY_BIOS_PROTOCOL_GUID
+#endif
+DEPENDENCY_END
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
diff --git a/Core/EM/Ahci/AInt13.h b/Core/EM/Ahci/AInt13.h
new file mode 100644
index 0000000..a55d3d0
--- /dev/null
+++ b/Core/EM/Ahci/AInt13.h
@@ -0,0 +1,395 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AInt13.h 17 11/25/14 12:00a Kapilporwal $
+//
+// $Revision: 17 $
+//
+// $Date: 11/25/14 12:00a $
+//
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AInt13.h $
+//
+// 17 11/25/14 12:00a Kapilporwal
+// [TAG] EIP191939
+// [Category] Improvement
+// [Description] Issue about BIG_REAL_MODE_MMIO_ACCESS of AHCI module
+// [Files] AI13.bin
+// AHCIACC.ASM
+// AhciInt13Dxe.c
+// AhciInt13Dxe.dxs
+// AhciInt13Smm.c
+// AhciInt13Smm.cif
+// AhciInt13Smm.dxs
+// AhciInt13Smm.h
+// AhciInt13Smm.mak
+// AhciInt13Smm.sdl
+// AInt13.c
+// Aint13.cif
+// AInt13.h
+// AhciSmm.c
+// AhciSmm.h
+// AhciSmmProtocol.h
+//
+// 16 11/29/12 12:58a Rameshr
+// [TAG] EIP107365
+// [Category] Improvement
+// [Description] Increase the SATA_PORT_COUNT to 32 to support 32 SATA
+// devices on Legacyboot
+// [Files] Aint13.h, Ahci.sdl ( Ain13.bin)
+//
+// 15 8/02/12 8:12a Deepthins
+// [TAG] EIP93480
+// [Category] Bug Fix
+// [Symptom] AHCI legacy support module is corrupting the memory.
+// [RootCause] AHCI legacy support module is corrupting the memory as it
+// was using wrong offset for storing the base address.
+// [Solution] Properly calculating offset for storing the base address.
+// [Files] AINT13.EQU, AInt13.c, AInt13.h and AHCIACC.ASM
+//
+// 14 7/20/12 6:12a Anandakrishnanl
+// [TAG] EIP88683
+// [Category] New Feature
+// [Description] EFI_ATA_PASS_THRU_PROTOCOL Support for Aptio IDE
+// [Files] AhciBus.c
+// AhciBus.h
+// AInt13.h
+// IdeBus.c
+// IdeBus.h
+// PIDEBus.h
+// PAhciBus.h
+// AtaPassThru.sdl
+// AtaPassThru.mak
+// AtaPassThru.c
+// AtaPassThruSupport.h
+// AtaPassThru.chm
+//
+// 13 4/24/12 12:54a Deepthins
+// [TAG] EIP86336
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Can't boot from AHCI if SATA_PORT_COUNT=12
+// [RootCause] The controller number was not updated in DEV_INFO_STRUC
+// for all the Hard Disk
+// [Solution] Updated the controller number in the DEV_INFO_STRUC for
+// all the AHCI devices.
+// [Files] AInt13.c, AInt13.h
+//
+// 12 1/13/12 12:18a Deepthins
+// [TAG] EIP78099
+// [Category] Improvement
+// [Description] Handle multiple AHCI controller in legacy.
+// [Files] Aint13.sdl , AInt13.c , AInt13.h , AHCIACC.ASM , AHCI.EQU ,
+// AINT13.bin (AHCIACC.ASM , AINT13.EQU)
+//
+// 11 11/29/11 4:27a Rameshr
+// [TAG] EIP76393
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Any time AHCI is starting when EBDA size is more than 64K,
+// the problem will show as memory corruption.
+// [RootCause] AHCI INT13 code does not use EBDA properly when at the
+// time of EBDA allocation current size of EBDA exceeds 64K
+// [Solution] Modified code to extend the width of EbdaStart offset from
+// 16-bit to 32-bit.
+// [Files] Aint13.asm, Ahcibsp.asm, Aint13.c, Aint13.h, Aint13.bin
+//
+// 10 2/10/11 10:49a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] Aint13.mak
+// AInt13.h
+// AInt13.c
+//
+// 9 6/21/10 5:32a Rameshr
+// AHCI Legacy booting through MMIO reg.
+// EIP 38444
+//
+// 8 9/09/08 3:19p Michaela
+// Added AHCI_CD_CSM_ID_OFFSET for assigning
+// device numbers for CDs/DVDs in order to
+// avoid a CSM16 conflict with PATA devices, which
+// may be present on some systems
+//
+// 7 5/28/08 9:41a Rameshraju
+// Updated the AMI Address.
+//
+// 6 5/13/08 4:31p Olegi
+// Modifications in DEV_PARAM_STRUC and DEV_PTR_STRUC to accomodate the
+// new AI13.BIN that is based on the latest AHCI Core8 src.
+//
+// 3 3/28/08 12:16p Michaela
+// updated copyright
+//
+// 2 19/12/07 4:29p Anandakrishnanl
+//
+// 1 12/07/07 11:17a Olegi
+//
+//****************************************************************************
+
+#ifndef __AI13_HEADER__
+#define __AI13_HEADER__
+
+#include "efi.h"
+#include "Protocol\PciIo.h"
+
+#pragma pack(1)
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AINT13.H
+// Description: Definitions and structures for AHCI INT13
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+typedef struct _DEV_INFO_STRUC {
+ UINT8 bDetectType; // Detected Device Type (Details Below)
+ UINT8 bInstalledType; // Device Installed Type (See Below)
+ UINT16 wStatus; // Bit-mapped device Init Status (Details Below)
+ UINT8 bInt13Num; // Device# for INT13 (8xh)
+ UINT8 bPMNum; // Port Multipier Port #
+ UINT8 bPortNum; // SATA Port# (0-Based) where device is present
+ UINT16 wBusDevFunc; // Bus#, Dev#, Func# of Controller
+ UINT8 bControllerNo; // Ahci Controller number
+ UINT32 dHbaBase; // HBA Base Address of Generic Host Control Registers
+ UINT32 dHbaCap; // HBA Capabilities
+ UINT32 dPortBase; // Base Address of SATA port where device is present
+ UINT8 bSelector; // Device selector value
+ UINT8 bIrq; // IRQ used by this device
+ UINT8 bInfoFlag; // Information Flag (details below)
+ UINT8 bSectorSizeN; // N value of Sector size 2^N ;For 512bytes sector, N = 9
+ UINT16 wSmartInfo; // SMART info (details below)
+ UINT32 dTotalSectorsLo;// Total #of sectors in device (1-based)
+ UINT32 dTotalSectorsHi;
+ UINT16 wXferCount; // Device transfer count. Used for ATAPI packer size
+ UINT8 bBlockInfo;
+ UINT8 b32BitInfo;
+ UINT8 bUDMAInfo;
+ UINT8 bPIOInfo;
+} DEV_INFO_STRUC;
+
+typedef struct _CONTROLLER_INFO_STRUC
+{
+ UINT16 BusDevFun; // Bus, Device and Function number for a controller
+ UINT8 ControllerNo; // Controler number for a controller
+}CONTROLLER_INFO_STRUC;
+
+// Details of bDetectType
+
+#define DETECT_NO 0
+#define DETECT_ATA 1
+#define DETECT_ATAPI_CD 2
+#define DETECT_ATAPI_ARMD 3
+
+// Details of bInstalledType
+
+#define INSTALLED_NO 0
+#define INSTALLED_HDD 1
+#define INSTALLED_CDROM 2
+#define INSTALLED_ARMD_FDD 3
+#define INSTALLED_ARMD_HDD 4
+
+// Details of wStatus
+
+// Bit 0 = 1, successful (device is installed in this case)
+// Bit 1 = 1, Identify Device Failed
+// Bit 2 = 1, Invalid Device Geometry
+// Bit 3 = 1, Init device parameter failed
+// Bit 4 = 1, Recalibrate failed
+// Bit 5 = 1, SMART failed
+// Bit 6 = 1, Verify failed
+// Bit 7 = 1, Security Freeze Lock failed
+// Bit 8 = 1, Port Reset failed
+// Bit 9 = 1, SMART Event was found
+// Bit 10 = 1, Device will be supported by RIAD OROM, not AHCI OROM (ex. HDD)
+// Bit 14-11, Reserved for future use
+// Bit 15 = 1, Device not supported
+
+#define ST_SUCCESS 0x0001
+#define ST_ID_DEV_ERR 0x0002
+#define ST_DEV_GEOMETRY_ERR 0x0004
+#define ST_INIT_DEV_PARAM_ERR 0x0008
+#define ST_RECALI_ERR 0x0010
+#define ST_SMART_ERR 0x0020
+#define ST_VERIFY_ERR 0x0040
+#define ST_FREEZE_LOCK_ERR 0x0080
+#define ST_PORT_RESET_ERR 0x0100
+#define ST_SMART_EVENT 0x0200
+#define ST_RAID_SUPPORT_ERR 0x0400
+#define ST_NOT_SUPPORT_ERR 0x8000
+
+
+// Details of bInt13Num
+
+// Bit 7 = 1, this bit must be set for CDs/HDDs
+// AHCI_CD_CSM_ID_OFFSET, PATA CDs/DVDs use the device handle range 0x80-0x8F
+// so this value will be added to ensure AHCI CDs/DVDs
+// are above that range
+
+#define AHCI_CD_CSM_ID_OFFSET 0x10
+
+
+// Details of bInfoFlag, a bit-mapped field
+
+// Bit 0 = 1, Device supports removable media
+// Bit 1 = 1, 48bit LBA enabled
+// Bit 2 = 1, Device uses IRQ; 0, Device uses DRQ
+// Bit 6-2, Reserved
+// Bit 7 = 1, ATAPI Device; 0, ATA Device
+
+#define INFO_REMOVABLE 0x01
+#define INFO_LBA_48 0x02
+#define INFO_IRQ 0x04
+#define INFO_ATAPI 0x80
+
+// Details wSmartInfo
+
+// Bit 0 = 0/1, SMART (Not Supported/Supported)
+// Bit 1 = 0/1, SMART (Disabled/Enabled)
+// Bit 2 = 0/1, Device Status Good/Bad
+// Bit 7 = 0/1, SMART Execution Successful/Error
+// Bit 15-8, Reserved
+
+#define AHCI_SMART_SUPPORT 0x01
+#define AHCI_SMART_ENABLE 0x02
+#define AHCI_SMART_EN 0x02
+#define AHCI_SMART_STATUS 0x04
+#define AHCI_SMART_COMMAND_STATUS 0x80
+
+#define SECTOR_LENGTH_N 9
+#define SELECTOR_NON_LBA 0xA0
+#define SELECTOR_LBA 0xE0
+#define MAX_STND_XFER_SECTOR 0x80
+#define MAX_EXTD_XFER_SECTOR 0x7F
+#define BLOCK_SIZE 0x80
+#define BLOCK_SIZE_N 0xB
+
+typedef struct _DEV_PTR_STRUC {
+ UINT8 bInt13Num; // INT13 Drive# for this Port
+ UINT8 bDetectType; // Detected Device Type
+ UINT8 bPMnum; // Port Multipier port #
+ UINT8 bPortNum; // Port# (0-based) on Controller
+ UINT32 dParamTablePtr; // Ptr to device parameter table
+ UINT32 dInfoTablePtr; // Ptr to device info table
+} DEV_PTR_STRUC;
+
+typedef struct _DEV_PARAM_STRUC {
+ UINT16 wMAXCYL; // maximum no. of cylinders..INT13 interface. (logical)
+ UINT8 bMAXHN; // maximum no. of heads..INT13 interface. (logical)
+ UINT8 bLBASIG; // LBA signature
+ UINT8 bLBASPT; // #of sectors per track drive is configured for. (physical)
+ UINT16 wWPCYL; // start write precomp cyl no.
+ UINT8 bReserved; // reserved
+ UINT8 bCBYTE; // bit 3 for more than 8 heads
+ UINT16 wLBACYL; // #of cylinders drive is configured for. (physical)
+ UINT8 bLBAHD; // #of heads drive is configured for. (physical)
+ UINT16 wLANDZ; // Landing zone
+ UINT8 bMAXSN; // no. of sectors per track..INT13 interface. (logical)
+ UINT8 bLBACHK; // checksum..LBA
+} DEV_PARAM_STRUC;
+
+//
+// The following definitions should be in sync with 16-bit definition
+//
+#define SATA_PORT_COUNT 32
+#define MAX_DESCRIPTION_STRLEN 32
+
+typedef struct _AHCI_SMM_RTS {
+ UINT8 MiscInfo;
+ UINT16 SmmAttr;
+ UINT32 SmmPort;
+ UINT32 SmmData;
+} AHCI_SMM_RTS;
+
+typedef struct _AHCI_RT_MISC_DATA {
+ UINT8 NumAhciDevice; // #of AHCI device installed by BIOS
+ UINT8 RunAttribute; // Bit-mapped information about runtime environment
+ UINT8 AhciEbdaSizeK; // Size of EBDA in unit of 1k that is created by AHCI init
+ UINT32 AhciEbdaStart; // Start offset of AHCI communication area in EBDA
+ AHCI_SMM_RTS AhciSmmRt; // Port and Data information to generate software SMI
+} AHCI_RT_MISC_DATA;
+
+typedef struct _DEV_BBS_OUTFIT {
+ UINT8 DescString[MAX_DESCRIPTION_STRLEN];
+} DEV_BBS_OUTFIT;
+
+typedef struct _AHCI_I13_RTDATA {
+ DEV_PARAM_STRUC DevParam[SATA_PORT_COUNT];
+ DEV_INFO_STRUC DevInfo[SATA_PORT_COUNT+1];
+ DEV_PTR_STRUC DevPtr[SATA_PORT_COUNT];
+ AHCI_RT_MISC_DATA AhciRtMiscData;
+ DEV_BBS_OUTFIT DevOutfit[SATA_PORT_COUNT];
+} AHCI_I13_RTDATA;
+
+typedef struct _AHCI_I13_DATA {
+ AHCI_I13_RTDATA rtdata;
+ UINT16 CheckForAhciCdromOffset;
+ UINT16 AhciBcvOffset;
+} AHCI_I13_DATA;
+
+// Details of bSignature field: A signature Axh indicates that the table is translated.
+#define DPTBL_SIG_MASK 0x0F0
+// A0h signature indicating LBA translation
+#define LBA_SIGNATURE 0x0A0
+
+//-------------------------------------------------------------------------
+// Port registers
+//
+#define PORT_REGISTER_START 0x100
+#define PORT_REGISTER_SET_SIZE 0x80
+#define PORT_REGISTER_SET_SIZE_N 7
+
+#define SIZE_CLCTFIS_AREA_K 4
+#define A_EBDA_USED 1
+#define A_INT13_SWSMI_USED BIT2
+
+#define BAID_TYPE_HDD 1
+#define BAID_TYPE_RMD_HDD 2
+#define BAID_TYPE_CDROM 3
+#define BAID_TYPE_RMD_FDD 4
+#define BAID_TYPE_FDD 5
+
+#define DEFAULT_DEVICE_STATUS 0x50
+#define SYSTYPE_ATA 0
+#define DEVTYPE_SYS 1
+
+EFI_STATUS GetAccessInfo (EFI_PCI_IO_PROTOCOL*, UINT16*, UINT16*);
+EFI_STATUS InitCspData (UINT16, UINT16,UINT32,UINT8);
+UINT16 CountDrives(IN EFI_HANDLE *HandleBuffer,
+ IN UINTN HandleCount,
+ IN VOID *Devices
+ );
+#pragma pack()
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciBus.c b/Core/EM/Ahci/AhciBus.c
new file mode 100644
index 0000000..ae1fd38
--- /dev/null
+++ b/Core/EM/Ahci/AhciBus.c
@@ -0,0 +1,4477 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciBus.c 74 6/25/14 10:01a Anandakrishnanl $
+//
+// $Revision: 74 $
+//
+// $Date: 6/25/14 10:01a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciBus.c $
+//
+// 74 6/25/14 10:01a Anandakrishnanl
+// [TAG] EIP170118
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] MDAT can't program correctly in AHCI module
+// [RootCause] Identify Data Word 76_79 Offset for DiPM Support/Enabled
+// is incorrect for validation
+// [Solution] Changed separating DiPM and Device Sleep into two routines
+// and also modified the tokens to disable both support by default .
+// Corrected Identify data validations.
+// [Files] AhciBus.c
+// AhciBus.h
+// AhciSrc.sdl
+// PAhciBus.h
+// PIDEBus.h
+//
+// 73 6/09/14 9:56a Anbuprakashp
+// [TAG] EIP172443
+// [Category] Improvement
+// [Description] "RaidDriverBlockingStatus" is using
+// gEfiGlobalVariableGuid that violates UEFI 2.4 spec in
+// IdeSecurityBdsCall.c and Runtime attribute set of this variable need to
+// be removed
+// [Files] IdeSecurityBdsCall.c, AhciBus.c
+//
+// 72 1/27/14 4:55a Rameshr
+// [TAG] EIP148180
+// [Category] Improvement
+// [Description] change from EFI_MBR_WRITE_PROTECTION_PROTOCOL to
+// AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL
+// [Files] Ahcibus.c, Ahcibus.h, AhciComponentName.c, AhciController.c
+//
+// 71 1/13/14 4:26a Rameshr
+// [TAG] EIP147909
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Boot devices can not find after resume from s4
+// [RootCause] HddPassword Verification failed because of
+// gHddSecurityEndProtocolGuid is uninstalled on the controller handle
+// [Solution] If the gHddSecurityEndProtocolGuid protocol is already
+// installed , to signel the event Reinstall Protocol interface is done
+// instead of uninstalling the protocol interface.
+// [Files] Ahcibus.c
+//
+// 70 12/20/13 4:06a Rameshr
+// [TAG] EIP126640
+// [Category] Improvement
+// [Description] AHCIBUS driver need to preserve the port settings in
+// GeneratePortReset
+// [Files] Ahcibus.c, AhciController.c
+//
+// 69 12/18/13 3:17a Srikantakumarp
+// [TAG] EIP127356
+// [Category] Improvement
+// [Description] Flash NVRAM seems to cause HDD can't be unlocked when
+// S3 resume.
+// [Files] IdeSecurity.c, IDESMM.c, HddPassword.c, AhciBus.c, AhciBus.h
+//
+// 68 12/02/13 5:46a Anbuprakashp
+// [TAG] EIP138377
+// [Category] Improvement
+// [Description] "CR has Bad Signature" error on AHCI eModule when
+// "disconnect -r" from shell
+// [Files] AhciBus.c
+//
+// 67 9/26/13 2:22a Rameshr
+// [TAG] EIP128963
+// [Category] Improvement
+// [Description] Uninitilized variable cleaned up in AhciBus Stop
+// function.
+// [Files] Ahcibus.c
+//
+// 66 9/26/13 2:10a Rameshr
+// [TAG] EIP125006
+// [Category] Improvement
+// [Description] Dummy Protocol installed for the protocol event
+// signaling is uninstalled. So that Ahcibus driver can signal the event
+// again if the bus driver gets starts again.
+// [Files] Ahcibus.c
+//
+// 65 8/27/13 4:19a Rameshr
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] MbrWriteProtectionProtocol file name changesd to
+// AmiMbrWriteProtectionProtocol.h
+// [Files] AhciController.c, AhciBus.h, Ahcibus.c
+//
+// 64 8/22/13 2:52a Srikantakumarp
+// [TAG] EIP106423
+// [Category] Improvement
+// [Description] Correcting the previous changes.
+// [Files] AhciBus.c
+//
+// 63 7/23/13 11:52p Srikantakumarp
+// [TAG] EIP129989
+// [Category] Improvement
+// [Description] Added DIPM support in Aptio 4.x AHCIBUS driver.
+// [Files] AhciBus.c, AhciBus.h, AhciController.h, AhciSrc.sdl,
+// PAhciBus.h
+//
+// 62 7/22/13 2:05a Rameshr
+// [TAG] EIP129028
+// [Category] Improvement
+// [Description] Implement the POWERUP_IN_STANDBY_MODE support in
+// AHCIBUS driver
+// [Files] Ahcibus.c, Ahcibus.h, Pahcibus.h
+//
+// 61 7/18/13 4:21a Rameshr
+// [TAG] EIP127919
+// [Category] Improvement
+// [Description] "Device is Atapi" bit of PxCMD will be set if the ATAPI
+// device connected on the Port and "Drive LED on ATAPI" Enabled by AHCI
+// platform policy
+// [Files] Pahcibus.h, Ahcibus.c, Ahcibus.h
+//
+// 60 7/01/13 4:31a Kapilporwal
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] Please support Boot Sector Virus Protection for CSM
+// Disabled Mode
+// [Files] VirusProtect.c, VirusProtect.dxs, AhciBus.c,
+// AhciController.c, CsmBlockIo.c, CsmInt13.c, Ata.c, IdeBus.c,
+// SdioBlkIo.c, SdioDriver.c, efiusbmass.c
+//
+// 59 6/06/13 4:22a Rameshr
+// [TAG] EIP106423
+// [Category] Improvement
+// [Description] HddPassword Support in UEFI Raid and Legacy Raid. And
+// also taken care where there is no Conin Device avilable in the post
+// [Files] IdeSecurity.cif,IdeSecurity.sdl,IdeSecurity.mak,IdeSecurityB
+// dsCall.c,HddPassword.c, Ahcibus.c, Pidebus.h
+//
+// 58 6/06/13 2:30a Rameshr
+// [TAG] EIP119759
+// [Category] Improvement
+// [Description] Ahcibus driver should not be stated when the Idebus
+// driver is active on the SATA Controller
+// [Files] Ahcibus.c
+//
+// 57 3/25/13 4:55a Rameshr
+// [TAG] EIP118033
+// [Category] Improvement
+// [Description] If the device is not yet detected in the remaining
+// device path port, proceed for the device detection and configuration.
+//
+// [Files] Ahcibus.c
+//
+// 56 2/11/13 12:35a Rameshr
+// [TAG] EIP114276
+// [Category] Improvement
+// [Description] Error in AHCIBus Driver when Power management and HPA
+// support is turned on. Removed the unused Power mangement and HPA code
+// from Ahcibus driver
+// [Files] Ahcibus.c
+//
+// 55 10/18/12 5:36a Srilathasc
+// [TAG] EIP95446
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Diskinfo Identify function returns the invalid Identify
+// data after post
+// [RootCause] DiskInfoIdentify function copies the identify data from
+// buffer.
+//
+// [Solution] DiskInfoIdentify function should send command and get
+// identify data.
+// [Files] IdeBus.c, AhciBus.c
+//
+// 54 9/17/12 1:49a Anandakrishnanl
+// [TAG] EIP100891
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] PortFISBaseAddr and PortCommandListBaseAddr allocation to
+// support memory allocation above 4gb
+// [RootCause] System hangs in Ahci Mode > 4Gb memory allocation, With
+// Filesystem and UEFI Boot Failing
+// [Solution] Fixed by handling FIS and Command List base Address
+// allocation >4gb allocation
+// [Files] AhciBus.c
+//
+// 53 9/17/12 12:48a Rameshr
+// [TAG] EIP100335
+// [Category] Improvement
+// [Description] Port Multiplier spend long time to connect device.
+// [Files] Ahcibus.c, AhciController.c
+//
+// 52 9/10/12 2:48a Rameshr
+// [TAG] EIP95440
+// [Category] Improvement
+// [Description] Add HddSecurity and HddSmart feature under UEFI Raid
+// driver mode
+// [Files] Ahcibus.c, Pahcibus.h, Aint13.c
+//
+// 51 9/03/12 6:07a Rameshr
+// [TAG] EIP94991
+// [Category] Improvement
+// [Description] If the link is already established before setting up
+// the allowed port speed, current interface speed has not been set based
+// on the port speed allowed. ComReset has been issued to setup the
+// current interface speed according to the port speed allowed.
+// [Files] Ahcibus.c
+//
+// 50 8/21/12 2:13a Rameshr
+// [TAG] EIP98436
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] FISAddress is being set incorrrectly.
+// [RootCause] Before setting the FIS Address, it has been used in
+// GeneratePortReset function.
+// [Solution] Moveed the FIS base address and command list base address
+// programming before GeneratePortReset
+// [Files] Ahcibus.c
+//
+// 49 8/16/12 3:05a Rajeshms
+// [TAG] EIP97048
+// [Category] New Feature
+// [Description] ATAPI PassThru Support using
+// EFI_EXT_SCSI_PASS_THRU_PROTOCOL.
+// [Files] AhciBus.c, AhciController.c, IdeBus.c, Atapi.c, PIDEBus.h,
+// PAhciBus.h, ScsiPassThruAtapi.sdl, ScsiPassThruAtapi.mak,
+// ScsiPassThruAtapi.c, ScsiPassThruAtapiSupport.h, ScsiPassThruAtapi.chm,
+// ScsiPassThruExt.h
+//
+// 48 8/16/12 2:27a Anandakrishnanl
+// [TAG] EIP97113
+// [Category] Improvement
+// [Description] AtaPassThru - Module Enhancement
+// [Files] AtaPassThru.c,
+// AtaPassThruSupport.h,AtaPassThru.mak,IdeBus.c,AhciBus.c
+//
+// 47 7/20/12 6:09a Anandakrishnanl
+// [TAG] EIP88683
+// [Category] New Feature
+// [Description] EFI_ATA_PASS_THRU_PROTOCOL Support for Aptio IDE
+// [Files] AhciBus.c
+// AhciBus.h
+// AInt13.h
+// IdeBus.c
+// IdeBus.h
+// PIDEBus.h
+// PAhciBus.h
+// AtaPassThru.sdl
+// AtaPassThru.mak
+// AtaPassThru.c
+// AtaPassThruSupport.h
+// AtaPassThru.chm
+//
+// 46 11/03/11 5:44a Rajeshms
+// [TAG] EIP73249
+// [Category] Improvement
+// [Description] AHCI Driver Follow the UEFI Driver Model as per the
+// UEFI Spec. and STOP function was Verified.
+// [Files] AhciBus.c
+//
+// 45 10/11/11 2:21a Rameshr
+// [TAG] EIP71410
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] 10 seconds Delay in post if ODD with CD/DVD
+// [RootCause] ATA Specific commands are executed for ATAPI devices
+// also.
+// [Solution] ATA device check added before sending the command.
+// [Files] Ahcibus.c
+//
+// 44 9/19/11 3:03a Lavanyap
+// [TAG] EIP69398
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Function ConfigureController() has a runtime error (NULL
+// pointer dereference)
+// [RootCause] variable SupportedModes has been initialized again in
+// ConfigureController().
+// [Solution] variable SupportedModes is passed as an input parameter
+// for ConfigureController() and ConfigureDevice().
+// [Files] AhciBus.c, AhciBus.h
+//
+// 43 8/02/11 4:34a Rameshr
+// [TAG] - EIP 61076
+// [Category]- IMPROVEMENT
+// [Description]- Setting the Interface Speed Support in CAP.ISS. so that
+// it's get programmed in PxSCT[7:4]. For this programming the link
+// communication should not be established. If it's already established we
+// should use GeneratePortReset function to set the speed
+// [Files] - AhciBus.c
+//
+// 42 7/05/11 2:50a Anandakrishnanl
+// [TAG] EIP56530
+// [Category] Improvement
+// [Description] EFI_IDE_CONTROLLER_INIT_PROTOCOL and
+// EFI_DISK_INFO_PROTOCOL are used accordingly to the PI 1.2 spec
+// [Files] AhciBus.c, IdeControllerInit.h, PDiskInfo.h
+//
+// 41 6/14/11 5:48a Rameshr
+// [TAG]- EIP 59495
+// [Category]-IMPROVEMENT
+// [Description]- Update implementation of EFI_BLOCK_IO_PROTOCOL as
+// described in UEFI specification v 2.3.1, page 12.8
+// [Files]- AhciBus.c
+//
+// 40 5/19/11 3:12a Anandakrishnanl
+// [TAG] EIP53565
+// [Category] New Feature
+// [Description] UEFI2.3+ Specifications defines Storage Security
+// protocol which needs to be implemented.
+// [Files] AhciBus.c,IdeBus.c,AHCIOpalSec.c,IDEOpalSec.c,OpalSecurity.c
+// ,OpalSecurity.chm,OpalSecurity.cif,OpalSecurity.h,OpalSecurity.mak,Opal
+// Security.sdl,PIDEBus.h,StorageSecurityProtocol.CIF,StorageSecurityProto
+// col.h
+//
+// 39 2/18/11 5:04a Rameshr
+// [TAG]- EIP 37975
+// [Category]-IMPROVEMENT
+// [Description]- Klocwork Issues II - IDE/Ahci module
+// [Files]- AhciBus.c, AhciController.c
+//
+// 38 2/11/11 4:22a Rameshr
+// [TAG] EIP53730
+// [Category] Improvement
+// [Description] Add Odd Loading type information into ATAPI_DEVICE
+// structure in AHCI mode
+// [Files] AhciBus.c
+// AhciController.c
+// AhciBus.h
+//
+// 37 2/10/11 10:35a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSrc.mak
+// AhciBus.c
+// AhciController.c
+// AhciComponentName.c
+// AhciBus.h
+// AhciController.h
+//
+// 36 12/30/10 3:48a Rameshr
+// [TAG] - EIP 49229
+// [Category]- BUG FIX
+// [Severity]- Minor
+// [Symptom] - SATA interface setting (SATA speed)
+// [RootCause]- Read the SATA device speed from the Capabilities Register
+// and set it to Port Control speed Register
+// [Solution] - Read the SATA device speed from the Capabilities Register
+// and set it to Port Control speed Register.
+// [Files] - AhciBus.c
+//
+// 35 12/23/10 3:58a Lavanyap
+// [TAG] - EIP41445
+// [Category] - NEW FEATURE
+// [Description] - Created SataPioDataOut and AtaPioDataOut protocol
+// function that can accept additional input parameters.
+// [Files] - AhciBus.h, AhciBus.c, AhciController.c, Ata.c, IdeBus.c,
+// IdeBus.h, IdeBusMaster.c,PAhciBus.h, PIdeBus.h
+//
+// 34 11/25/10 7:09a Rameshr
+//
+// [TAG] - EIP 48045
+// [Category]- BUG FIX
+// [Severity]- Minor
+// [Symptom] - DISABLE_SOFT_SET_PREV sdl token set 1 , throws build error
+// in AHCI driver.
+// [RootCause]- Status Variable not declared
+// [Solution] - Declared the Status variable.
+// [Files] - Ahcibus.c
+//
+// 33 11/02/10 12:03a Rameshr
+// [TAG] - EIP 45266
+// [Category]- BUG FIX
+// [Severity]- Minor
+// [Symptom] - E-SATA card will hang up on post and debug card show "AE
+// [RootCause]- Device doesn't support any of the UDMA mode and function
+// ReturnMsbbit returns incorrect values
+// [Solution] - If any of the bit is not set in Input value, ReturnMsbbit
+// returns 0xFF.
+// [Files] - Ata.c, AhciBus.c
+//
+// 32 10/11/10 6:28p Krishnakumarg
+// [TAG] - EIP 44800
+// [Category] - Defect
+// [Severity] - Major
+// [Symptom] - Side Effect of EIP 40528. HDD security setup option
+// disappear on warn boot in AHCI mode.
+// [RootCause]- When FORCE_HDD_PASSWORD_PROMPT token enabled,Software
+// preservation is disabled only when password is enabled.
+// [Solution] - Software preservation is disabled when HDD can support
+// software preservation.
+// [Files] - AhciBus.c
+//
+// 31 9/24/10 2:40a Rameshr
+// [TAG]- EIP 42817
+// [Category]-IMPROVEMENT
+// [Description]- Ide Smart checks HDDs for errors moved after Idebus
+// Device path has been installed.
+// [Files]- AhciBus.c, IdeBus.c
+//
+// 30 5/26/10 6:21a Rameshr
+// Checked the Device Configuration Overlay feature set supported status
+// before sending the DEV_CONFIG_FREEZE_LOCK
+// EIP 38384
+//
+// 29 5/07/10 11:44a Krishnakumarg
+// Coding standard update
+//
+// 28 4/16/10 4:15p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 27 3/26/10 5:35p Krishnakumarg
+// UEFI2.1 compliance change EIP#34744.
+//
+// 26 2/15/10 5:51p Srinin
+// KlockWork flags "'SupportedModes' is explicitly dereferenced.". Fix
+// added.
+//
+// 25 2/11/10 4:00a Rameshr
+// Atapi devices are handled by AhciBus driver based on
+// SUPPORT_ATAPI_IN_RAID_MODE SDL token.
+// EIP 34583
+//
+// 24 1/11/10 12:12p Krishnakumarg
+// Update for Eip 11835 - To implement Acoustic Management function
+// EIP 30041 - Aptio 4 Device Initiated Power Management (DipM) support
+// for SATA devices
+//
+// 23 10/15/09 11:46p Fasihm
+// EIP#28961: Corrected the Disk Info Protocol installation information,
+// and corrected it from EFI_BLOCK_IO_PROTOCOL to EFI_DISK_INFO_PROTOCOL.
+//
+// 22 9/22/09 10:57a Krishnakumarg
+// Code modified to update SataDevInterface->identifydata in
+// GetIdentifyData function instead of returning in global variable -
+// EIP26411
+//
+// 21 9/04/09 3:32p Krishnakumarg
+// Coding Standard and unwanted code removal in InitAcousticSupport
+// function
+//
+// 20 9/04/09 3:16p Krishnakumarg
+// Acoustic Management function updated to set acoustic level according to
+// setup option EIP:11835
+//
+// 19 8/18/09 2:04p Rameshr
+// AhciBus driver doesn't work for Multi Entry.
+// Ahci Int13 initilization code moved from AhciBus to CsmHwinfo.c
+// EIP: 25369
+//
+// 18 8/17/09 2:55p Rameshr
+// AHCI bus driver doesn't detect the devices other than port 0 when the
+// remaining device path is not null
+// EIP:25368
+//
+// 17 7/13/09 3:37p Rameshr
+// Symptom: After installing the UEFI windows 7 and reboot, system hangs
+// on post.
+// Rootcause: Devicepath created with NULL when the Remainingdevicepath
+// has valid value.
+// Solution: Created the Devicepath even if the RemainingDevicePath has
+// the valid value.
+//
+// 16 6/22/09 11:33a Rameshr
+// Odd Type information Saved in Atapi Device Structure.
+// EIP:21548
+//
+// 15 4/28/09 3:47p Rameshr
+//
+// HDD password support in RAID mode
+// EIP:20421
+//
+// 14 12/31/08 3:05p Rameshraju
+// BugFix- Validate the PIO mode before programming the PIO mode into the
+// device EIP:17885
+//
+// 13 14/08/08 10:47a Anandakrishnanl
+// Compatible Mode AHCI Support Added and Sdl Token Added in IdeBusSrc.sdl
+//
+// 12 5/28/08 9:38a Rameshraju
+// Based on the SDL token index/data or MMIO method used to access the
+// AHCI configuration space.
+//
+// 11 5/14/08 4:42p Rameshraju
+// Error code added if error happens while configuring device or
+// controller.
+//
+// 10 5/09/08 9:59a Rameshraju
+// Cdrom block size initilized.
+//
+// 9 5/02/08 3:41p Rameshraju
+// Insteed of OR, Write the FIS base address.
+//
+// 8 4/23/08 12:30p Srinin
+// Bug fix in CheckDevicePresence()
+//
+// 7 4/18/08 2:58p Srinin
+// If Device SPINUP is enabled, check is added to see whether
+// COMRESET is expected or not.
+//
+// 6 4/14/08 4:58p Rameshraju
+// Security feature stopped when the AHCI bus driver is stopped.
+//
+// 5 3/27/08 11:23a Srinin
+// CreateSataDevicePath() modified to create a devicepath
+// even if Remaining devicepath is not NULL.
+//
+// 4 3/24/08 6:17p Fasihm
+// Fixed the issue that HDD Password prompt is not displayed in POST in
+// AHCI mode when DISABLE_SOFT_SET_PREV is enabled.
+//
+// 3 7/03/08 5:31p Anandakrishnanl
+// Added Smart Support as a seperate Driver and Corresponding changes to
+// invoke Smart Protocols and removed SDL-Token
+//
+// 2 28/02/08 6:21p Anandakrishnanl
+// Cleaned up Code and re Checked - in
+//
+// 1 28/02/08 6:03p Anandakrishnanl
+// AHCI Bus Driver initial check-in.
+//
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AhciBus.c
+//
+// Description: Provides AHCI Block IO protocol
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include "AhciBus.h"
+#include "protocol\legacyahci.h"
+#if SBIDE_SUPPORT
+#include "SBIDE.h"
+#endif
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL *AmiBlkWriteProtection = NULL;
+#endif
+
+EFI_GUID gEfiAhciBusProtocolGuid = AHCI_BUS_INIT_PROTOCOL_GUID;
+EFI_GUID gAhciBusDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+EFI_GUID gEfiIdeControllerProtocolGuid = IDE_CONTROLLER_PROTOCOL_GUID;
+static EFI_GUID gDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID
+EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#else
+EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
+#endif
+
+static EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+EFI_GUID gEfiDiskInfoProtocolGuid = EFI_DISK_INFO_PROTOCOL_GUID;
+EFI_GUID gEfiAhciDiskInfoProtocolGuid = EFI_DISK_INFO_AHCI_INTERFACE_GUID;
+EFI_GUID gSecurityModeProtocolGuid = IDE_SECURITY_INTERFACE_GUID;
+EFI_GUID gSMARTProtocolGuid = IDE_SMART_INTERFACE_GUID;
+EFI_GUID gPowerMgmtProtocolGuid = IDE_POWER_MGMT_INTERFACE_GUID;
+EFI_GUID gHPAProtocolGuid = IDE_HPA_INTERFACE_GUID;
+EFI_GUID gStorageSecurityProtocolGuid = EFI_STORAGE_SECURITY_COMMAND_PROTOCOL_GUID;
+EFI_EVENT gIDEBusEvtBootScript = NULL;
+static EFI_GUID gHddSecurityInitProtocolGuid= HDD_SECURITY_INIT_PROTOCOL_GUID;
+static EFI_GUID gHddSmartInitProtocolGuid = HDD_SMART_INIT_PROTOCOL_GUID;
+static EFI_GUID gHddSecurityEndProtocolGuid = HDD_SECURITY_END_PROTOCOL_GUID;
+static EFI_GUID gOpalSecInitProtocolGuid = OPAL_SEC_INIT_PROTOCOL_GUID;
+static EFI_GUID gAtaPassThruInitProtocolGuid= ATA_PASS_THRU_INIT_PROTOCOL_GUID;
+static EFI_GUID gScsiPassThruAtapiInitProtocolGuid = SCSI_PASS_THRU_ATAPI_INIT_PROTOCOL_GUID;
+static EFI_GUID gEfiIdeBusInitProtocolGuid = IDE_BUS_INIT_PROTOCOL_GUID;
+static EFI_GUID gOnboardRaidControllerGuid = ONBOARD_RAID_CONTROLLER_GUID;
+static EFI_GUID gHddPasswordVerifiedGuid = HDD_PASSWORD_VERIFIED_GUID;
+static EFI_GUID gAmiGlobalVariableGuid = AMI_GLOBAL_VARIABLE_GUID;
+
+
+#if SBIDE_SUPPORT
+EFI_GUID gIdeSetupProtocolguid = IDE_SETUP_PROTOCOL_GUID;
+VOID InitMiscConfig(IN SATA_DEVICE_INTERFACE *SataDevInterface);
+#endif
+
+
+#if INDEX_DATA_PORT_ACCESS
+extern InitilizeIndexDataPortAddress();
+#endif
+
+extern
+EFI_STATUS
+ExecutePacketCommand (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_STRUCTURE *CommandStructure,
+ IN BOOLEAN READWRITE
+);
+
+#if (EFI_SPECIFICATION_VERSION > 0x00020000)
+extern EFI_COMPONENT_NAME2_PROTOCOL gAhciBusControllerDriverName;
+#else
+extern EFI_COMPONENT_NAME_PROTOCOL gAhciBusControllerDriverName;
+#endif
+
+
+AHCI_CONTOLLER_LINKED_LIST AhciControllerLinkedList;
+
+EFI_DRIVER_BINDING_PROTOCOL gAhciBusDriverBinding = {
+ AhciBusSupported,
+ AhciBusStart,
+ AhciBusStop,
+ AHCI_BUS_DRIVER_VERSION, // version
+ NULL, // ImageHandle
+ NULL // DriverBindingHandle
+};
+
+HDD_SECURITY_INIT_PROTOCOL *HddSecurityInitProtocol;
+HDD_SMART_INIT_PROTOCOL *HddSmartInitProtocol;
+OPAL_SECURITY_INIT_PROTOCOL *OpalSecInitProtocol;
+ATA_PASS_THRU_INIT_PROTOCOL *AtaPassThruInitProtocol;
+SCSI_PASS_THRU_ATAPI_INIT_PROTOCOL *gScsiPassThruAtapiInitProtocol;
+AHCI_PLATFORM_POLICY_PROTOCOL *AhciPlatformPolicy = NULL;
+
+//
+// Instantiate AHCI_PLATFORM_POLICY_PROTOCOL with default values
+//
+AHCI_PLATFORM_POLICY_PROTOCOL gDefaultAhciPlatformPolicy = {
+ FALSE, // Legacy Raid option selected
+ TRUE, // Ahcibus driver handles the ATAPI devices
+ FALSE, // Drive LED on ATAPI Enable (DLAE)
+#ifdef POWERUP_IN_STANDBY_SUPPORT
+ POWERUP_IN_STANDBY_SUPPORT, // PowerUpInStandby feature is supported or not
+#else
+ FALSE,
+#endif
+#ifdef POWERUP_IN_STANDBY_MODE
+ POWERUP_IN_STANDBY_MODE, // PowerUpInStandby mode
+#else
+ FALSE,
+#endif
+#ifdef DiPM_SUPPORT
+ DiPM_SUPPORT, // Device Initiated power management
+#else
+ FALSE,
+#endif
+#ifdef ENABLE_DIPM
+ ENABLE_DIPM,
+#else
+ FALSE,
+#endif
+#ifdef DEVICE_SLEEP_SUPPORT
+ DEVICE_SLEEP_SUPPORT,
+#else
+ FALSE,
+#endif
+#ifdef ENABLE_DEVICE_SLEEP
+ ENABLE_DEVICE_SLEEP
+#else
+ FALSE
+#endif
+
+};
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: AhciBusEntryPoint
+//
+// Description: Installs gAhciBusDriverBinding protocol
+//
+// Input:
+// IN EFI_HANDLE ImageHandle,
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitAmiLib InstallMultipleProtocolInterfaces DListInit
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Initialize Ami Lib.
+// 2. Install Driver Binding Protocol
+// 3. Return EFI_SUCCESS.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS AhciBusEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+
+ gAhciBusDriverBinding.DriverBindingHandle=NULL;
+ gAhciBusDriverBinding.ImageHandle=ImageHandle;
+
+ InitAmiLib(ImageHandle, SystemTable);
+ DListInit(&(AhciControllerLinkedList.AhciControllerList));
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &gAhciBusDriverBinding.DriverBindingHandle,
+ &gAhciBusDriverBindingProtocolGuid,&gAhciBusDriverBinding,
+ &gComponentNameProtocolGuid, &gAhciBusControllerDriverName,
+ NULL
+ );
+
+ return Status;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: AhciBusSupported
+//
+// Description: Checks whether EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID
+// is installed on the controller. If 'yes', return SUCCESS else ERROR
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: OpenProtocol CloseProtocol
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If Devicepath is NULL, check "gEfiIdeControllerInitProtocolGuid"
+// is installed by IdeController device driver,if yes, it is the
+// IDE controller that this Bus will manage. Then return Success.
+// 2. If Devicepath is valid, check if it is a SATA device Path. See
+// if gEfiAhciBusProtocolGuid is installed on the device.
+// 3. make sure the the Controller class code is AHCI
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+AhciBusSupported(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+
+ EFI_STATUS Status;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL IdeControllerInterface;
+ SATA_DEVICE_PATH *SataRemainingDevicePath = (SATA_DEVICE_PATH *) RemainingDevicePath;
+ AHCI_BUS_PROTOCOL *AhciBusInterface;
+ SATA_DEVICE_INTERFACE *SataDevInterface = NULL;
+ EFI_PCI_IO_PROTOCOL *PciIO;
+ UINT8 PciConfig[256];
+
+ //
+ // Check for Valid SATA Device Path. If no return UNSUPPORTED
+ //
+ if (!(SataRemainingDevicePath == NULL)) {
+ //
+ // Check if the SataRemainingDevicePath is valid 8.3.4.1
+ //
+ if (SataRemainingDevicePath->Header.Type != MESSAGING_DEVICE_PATH ||
+ SataRemainingDevicePath->Header.SubType != MSG_USB_SATA_DP &&
+ NODE_LENGTH(&SataRemainingDevicePath->Header) != SATA_DEVICE_PATH_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Now check whether it is OK to enumerate the specified device.
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiAhciBusProtocolGuid,
+ (VOID **)&AhciBusInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) {
+ pBS->CloseProtocol (
+ Controller,
+ &gEfiAhciBusProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+
+ SataDevInterface = GetSataDevInterface(
+ AhciBusInterface,
+ (UINT8)SataRemainingDevicePath->PortNumber,
+ (UINT8)SataRemainingDevicePath->MultiplierPortNumber
+ );
+
+ // If the device in the remaining device path Port already detected and configued
+ // return as EFI_ALREADY_STARTED. If the device is not yet detected in the
+ // remaining device path port, proceed for the device detection and configuration
+
+ if (SataDevInterface && (SataDevInterface->DeviceState >= DEVICE_DETECTION_FAILED)) {
+ return EFI_ALREADY_STARTED;
+ }
+ else {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ // Check if the IDEBUS installed on the controller. If it is installed
+ // Idebus driver already handling the Controller. So AHCIBUS driver should not handle
+ // the controller
+
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if (Status == EFI_SUCCESS) {
+
+ // Idebus handling the controller. Return with Error.
+ return EFI_UNSUPPORTED;
+ }
+
+
+ // Check whether IDE_CONTROLLER_PROTOCOL has been installed on
+ // this controller
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ //
+ // IDE_CONTROLLER_PROTOCOL will be opened by each device. So
+ // EFI_ALREADY_STARTED is not an error.
+ //
+ if ( !(Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Close IDE_CONTROLLER_PROTOCOL
+ //
+ pBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Check if Controller is in AHCI mode or not?
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIO,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {return EFI_UNSUPPORTED;}
+
+ Status = PciIO->Pci.Read ( PciIO,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciConfig),
+ PciConfig
+ );
+
+ if (PciConfig [IDE_SUB_CLASS_CODE] == SCC_AHCI_CONTROLLER) {
+#ifdef AHCI_COMPATIBLE_MODE
+ #if !(AHCI_COMPATIBLE_MODE)
+ return EFI_SUCCESS;
+ #endif
+#endif
+ }
+
+#ifdef SUPPORT_ATAPI_IN_RAID_MODE
+#ifdef HDD_PASSWORD_SUPPORT_UNDER_RAIDMODE
+ #if SUPPORT_ATAPI_IN_RAID_MODE || HDD_PASSWORD_SUPPORT_UNDER_RAIDMODE
+ if (PciConfig [IDE_SUB_CLASS_CODE] == SCC_RAID_CONTROLLER) {
+
+ //
+ // Under Raid mode, don't detect the devices again
+ // Check if AHCI_BUS_PROTOCOL installed status. If already installed
+ // Ahcibus started already and device detection done
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiAhciBusProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+
+ if ( EFI_ERROR(Status)) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+ #endif
+#endif
+#endif
+
+ return EFI_UNSUPPORTED;
+
+}
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: AhciBusStart
+//
+// Description: Installs AHCI Block IO Protocol
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: OpenProtocol CloseProtocol InstallProtocolInterface
+// AllocatePool InstallAhciBusProtocol CheckPortImplemented
+// DetectAndConfigureDevice.
+//
+// Notes:
+// 1. Collect the info about the number of devices to detect and configure.
+// 2. Configure the AHCI controller if it is not done yet.
+// 3. Detect the device connected to the port
+// 4. If the device is a Port Multiplier, detect & configure all the
+// devices behind it, else configure the device directly connected
+// to the port.
+// 5. Continue step 3 and 4 for all the ports on the controller.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+AhciBusStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIO;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface;
+ SATA_DEVICE_INTERFACE *SataDevInterface = NULL;
+ AHCI_BUS_PROTOCOL *AhciBusInterface;
+ UINT8 Enumeration_Process = ENUMERATE_ALL;
+ SATA_DEVICE_PATH *SataRemainingDevicePath = (SATA_DEVICE_PATH *)RemainingDevicePath;
+ UINT8 PortEnumeration = 0xFF, PMPortEnumeration = 0xFF; // Bit Map
+ UINT8 CurrentPort = 0, CurrentPMPort = 0xFF;
+ BOOLEAN Enabled = TRUE;
+ UINT8 MaxDevices = 0;
+ UINT8 Data8;
+ EFI_HANDLE SecHandle=NULL;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ VOID *TempProtocolPtr;
+ EFI_STATUS SecurityStatus=EFI_NOT_FOUND;
+ BOOLEAN RaidDriverBlocked=FALSE;
+
+ PROGRESS_CODE(DXE_IDE_BEGIN);
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+ if(AmiBlkWriteProtection == NULL) {
+ Status = pBS->LocateProtocol(&gAmiBlockIoWriteProtectionProtocolGuid, NULL, &AmiBlkWriteProtection);
+ if(EFI_ERROR(Status)) {
+ AmiBlkWriteProtection = NULL;
+ }
+ }
+#endif
+
+ // Open IDE_CONTROLLER_PROTOCOL. If success or Already opened, It is OK to proceed.
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if ( !(Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED)) return EFI_DEVICE_ERROR;
+
+ // Get the PciIO interface
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIO,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ // Check if AHCI_BUS_PROTOCOL installed.
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiAhciBusProtocolGuid,
+ (VOID **)&AhciBusInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+
+ if ( !(Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED)) {
+
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ sizeof(AHCI_BUS_PROTOCOL),
+ (VOID**)&AhciBusInterface
+ );
+
+ if (EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES; //No need to close IDE_CONTROLLER_PROTOCOL
+
+ Status = InstallAhciBusProtocol (Controller, AhciBusInterface, IdeControllerInterface, PciIO);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR; //No need to close the protocol. Will be handled in STOP
+ }
+
+ if (!IdeControllerInterface->EnumAll) {
+ // Check if sataRemainingDevicePath is valid or not
+ if (!(SataRemainingDevicePath == NULL)) {
+ // Check if the SataRemainingDevicePath is valid 8.3.4.1
+ if (SataRemainingDevicePath->Header.Type != MESSAGING_DEVICE_PATH ||
+ SataRemainingDevicePath->Header.SubType != MSG_USB_SATA_DP &&
+ NODE_LENGTH(&SataRemainingDevicePath->Header) != SATA_DEVICE_PATH_LENGTH) {
+ return EFI_DEVICE_ERROR;
+ }
+ // Get the Port# that needs to be processed.
+ PortEnumeration = 1 << SataRemainingDevicePath->PortNumber; //Bit Map
+ PMPortEnumeration = 1 << SataRemainingDevicePath->MultiplierPortNumber; // Bit Map
+ CurrentPMPort = (UINT8) SataRemainingDevicePath->MultiplierPortNumber;
+ }
+ }
+ else {
+ PortEnumeration = AhciBusInterface->HBAPortImplemented;
+ }
+
+ //
+ // Get the Ahci Platform Policy Protocol
+ //
+ Status=pBS->LocateProtocol(&gAciPlatformPolicyProtocolGuid, NULL, &AhciPlatformPolicy);
+ if(EFI_ERROR(Status)) {
+ //
+ // If the Ahci Platform policy protocol not found, initilize with default value
+ //
+ AhciPlatformPolicy=(AHCI_PLATFORM_POLICY_PROTOCOL *)&gDefaultAhciPlatformPolicy;
+ }
+
+
+ TRACE_AHCI((-1,"\nAHCI Driver Detection and Configuratiion starts\n"));
+
+
+ //--------------------------------------------------------------------------
+ // Detection and Configuration starts
+ //--------------------------------------------------------------------------
+ for ( ; PortEnumeration != 0 ; PortEnumeration >>= 1, CurrentPort++, CurrentPMPort = 0xFF) {
+
+ if(!(PortEnumeration & 1)) {
+ continue;
+ }
+
+ // Check if the current port is implemented or not?
+ Status = CheckPortImplemented(AhciBusInterface, CurrentPort);
+ if (EFI_ERROR(Status)) { continue;}
+
+ Status = IdeControllerInterface->NotifyPhase (IdeControllerInterface, EfiIdeBeforeChannelEnumeration, CurrentPort);
+ if (EFI_ERROR(Status)) { continue;}
+
+ Status = IdeControllerInterface->GetChannelInfo(IdeControllerInterface, CurrentPort, &Enabled, &MaxDevices);
+ if (EFI_ERROR(Status) || !Enabled) { goto NextDevice; }
+
+ Status = DetectAndConfigureDevice(This, Controller, RemainingDevicePath, AhciBusInterface, IdeControllerInterface, CurrentPort, CurrentPMPort);
+ SataDevInterface = GetSataDevInterface(AhciBusInterface, CurrentPort, CurrentPMPort);
+
+ if(SataDevInterface != NULL && EFI_ERROR(SecurityStatus)) {
+ // Verify that Security interface has been installed
+ // on atleast one device
+ SecurityStatus = pBS->HandleProtocol(SataDevInterface->IdeDeviceHandle,
+ &gSecurityModeProtocolGuid,
+ &TempProtocolPtr
+ );
+ }
+
+ // Check whether the device detected is PM. Also check whether PM is supported by the Controller
+ // and also MaxDevices should be more than 1 if PM is Supported.
+ if (!EFI_ERROR(Status) && SataDevInterface && SataDevInterface->NumPMPorts &&
+ (SataDevInterface->DeviceType == PMPORT) && MaxDevices > 1){
+
+ Data8 = SataDevInterface->NumPMPorts > MaxDevices ? MaxDevices : SataDevInterface->NumPMPorts;
+ PMPortEnumeration = 1;
+ for (Data8-- ;Data8; Data8-- ){
+ PMPortEnumeration = (PMPortEnumeration << 1) | 1;
+ }
+
+ // Port Multiplier loop
+ for (CurrentPMPort = 0; PMPortEnumeration & 1 ; PMPortEnumeration >>= 1, CurrentPMPort++ ){
+ DetectAndConfigureDevice(This, Controller, RemainingDevicePath, AhciBusInterface, IdeControllerInterface, CurrentPort, CurrentPMPort);
+ }
+
+ }
+
+NextDevice:
+ IdeControllerInterface->NotifyPhase(IdeControllerInterface, EfiIdeAfterChannelEnumeration, CurrentPort);
+
+ }
+
+
+ TRACE_AHCI((-1," AHCI Driver Detection and Configuratiion Ends\n"));
+
+ Status = pBS->LocateProtocol (
+ &gAtaPassThruInitProtocolGuid,
+ NULL,
+ &AtaPassThruInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(AtaPassThruInitProtocol != NULL) {
+ AtaPassThruInitProtocol->InstallAtaPassThru(Controller, TRUE);
+ }
+ }
+
+ // SCSIPassThruAtapi install
+ Status = pBS->LocateProtocol (
+ &gScsiPassThruAtapiInitProtocolGuid,
+ NULL,
+ &gScsiPassThruAtapiInitProtocol
+ );
+
+
+ if(!EFI_ERROR(Status)) {
+ if(gScsiPassThruAtapiInitProtocol != NULL) {
+ gScsiPassThruAtapiInitProtocol->InstallScsiPassThruAtapi(Controller, TRUE);
+ }
+ }
+
+ // Handle the Onboard Raid controller Password Verification
+
+ Status = pBS->HandleProtocol(Controller,
+ &gHddSecurityEndProtocolGuid,
+ & TempProtocolPtr
+ );
+
+ if(Status == EFI_SUCCESS) {
+ //
+ // Protocol already installed on the Controller handle.
+ // Re-Install the protocol interface to Notify the Password verification
+ //
+ Status = pBS->ReinstallProtocolInterface(
+ &Controller,
+ &gHddSecurityEndProtocolGuid, NULL,NULL
+ );
+ } else {
+ //
+ // This will notify AMITSE to invoke the HDD password Screen
+ //
+ Status = pBS->InstallProtocolInterface(
+ &Controller,
+ &gHddSecurityEndProtocolGuid, EFI_NATIVE_INTERFACE,NULL
+ );
+ }
+
+ if(!EFI_ERROR(Status) && !EFI_ERROR(SecurityStatus)) {
+
+ // Handle the Onboard Raid controller Password Verification
+
+ Status = pBS->HandleProtocol(Controller,
+ &gOnboardRaidControllerGuid,
+ &TempProtocolPtr
+ );
+ if(!EFI_ERROR(Status)) {
+
+
+ // Check the Hdd Password verification done. If the password
+ // Verification done, proceed for RAID driver launch. Otherwise
+ // Hold the Raid driver until Password verification finished.
+
+ Status = pBS->HandleProtocol(Controller,
+ &gHddPasswordVerifiedGuid,
+ &TempProtocolPtr
+ );
+
+ if(EFI_ERROR(Status)) {
+
+ // Don't launch the Raid Option rom until password verified
+
+ Status = pBS->OpenProtocol (
+ Controller,
+ &gDevicePathProtocolGuid,
+ (VOID *) &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if(Status == EFI_SUCCESS) {
+ RaidDriverBlocked=TRUE;
+ Status = pRS->SetVariable(L"RaidDriverBlockingStatus",
+ &gAmiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(RaidDriverBlocked),
+ &RaidDriverBlocked );
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DetectAndConfigureDevice
+//
+// Description: Detects and Configures Sata Device
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+// AHCI_BUS_PROTOCOL *AhciBusInterface,
+// EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+// UINT8 Port,
+// UINT8 PMPort
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AhciDetectDevice ConfigureDevice InitSataBlockIO InitSataDiskInfo
+//
+// Notes:
+// 1. Detect whether device is connected to the port. If no device exit.
+// 2. Install SataDevInterface. If PMPort, Configure PMPort and Exit.
+// 3. Configure the SATA device and the controller.
+// 4. Install DevicePath, BlockIO and DiskInfo protocol.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+DetectAndConfigureDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ UINT8 Port,
+ UINT8 PMPort
+)
+{
+
+ EFI_STATUS Status;
+ SATA_DEVICE_INTERFACE *SataDevInterface = NULL;
+ EFI_ATA_COLLECTIVE_MODE *SupportedModes = NULL;
+ UINT16 SecurityStatus = 0;
+
+ SataDevInterface = GetSataDevInterface(AhciBusInterface, Port, PMPort);
+
+ if (SataDevInterface && ((SataDevInterface->DeviceState == DEVICE_DETECTION_FAILED)||
+ (SataDevInterface->DeviceState == DEVICE_CONFIGURED_SUCCESSFULLY))){
+ return EFI_SUCCESS;
+ }
+
+ Status = AhciDetectDevice(AhciBusInterface, IdeControllerInterface, Port, PMPort);
+ SataDevInterface = GetSataDevInterface(AhciBusInterface, Port, PMPort);
+ if (EFI_ERROR(Status)) {
+ if (SataDevInterface) SataDevInterface->DeviceState = DEVICE_DETECTION_FAILED;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (!SataDevInterface) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ SataDevInterface->DeviceState = DEVICE_DETECTED_SUCCESSFULLY;
+
+ //
+ // if this is a Port Multiplier skip the rest
+ //
+ if (SataDevInterface->DeviceType == PMPORT) {
+ SataDevInterface->DeviceState = DEVICE_CONFIGURED_SUCCESSFULLY;
+
+ //
+ //Update Port Multiplier Data
+ //
+ Status = ConfigurePMPort(SataDevInterface);
+ if (!EFI_ERROR(Status)) {
+ TRACE_AHCI((-1,"AHCI: SATA Device type %x detected at Port Number : %x, PM Port Number : %x\n",
+ SataDevInterface->DeviceType, SataDevInterface->PortNumber, SataDevInterface->PMPortNumber));
+ }
+ return Status;
+ }
+
+ Status = ConfigureDevice(SataDevInterface, &SupportedModes);
+ if (EFI_ERROR(Status)) {
+ ERROR_CODE(DXE_IDE_DEVICE_FAILURE, EFI_ERROR_MAJOR);
+ SataDevInterface->DeviceState = DEVICE_DETECTION_FAILED;
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = ConfigureController(SataDevInterface, SupportedModes);
+ if (EFI_ERROR(Status)) {
+ ERROR_CODE(DXE_IDE_DEVICE_FAILURE, EFI_ERROR_MAJOR);
+ SataDevInterface->DeviceState = DEVICE_DETECTION_FAILED;
+ return EFI_DEVICE_ERROR;
+ }
+
+ SataDevInterface->DeviceState = DEVICE_CONFIGURED_SUCCESSFULLY;
+
+ Status = ConfigureSataPort(SataDevInterface);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Create the Devicepath
+ //
+ Status = CreateSataDevicePath (This, Controller, SataDevInterface, RemainingDevicePath);
+ if (EFI_ERROR(Status)) { return EFI_DEVICE_ERROR; }
+
+ //
+ // Initialize Block_IO Protocol
+ //
+ Status = InitSataBlockIO (SataDevInterface);
+ if (EFI_ERROR(Status)){
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Initialize IDE EFI_DISK_INFO_PROTOCOL
+ //
+ Status = InitSataDiskInfo (SataDevInterface);
+ if (EFI_ERROR(Status)){
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Install Devicepath
+ //
+ Status = pBS->InstallMultipleProtocolInterfaces (
+ &(SataDevInterface->IdeDeviceHandle),
+ &gDevicePathProtocolGuid, SataDevInterface->DevicePathProtocol,
+ NULL);
+
+ if(EFI_ERROR(Status)) {
+ SataDevInterface->DeviceState = DEVICE_DETECTION_FAILED;
+ if (EFI_ERROR(Status)){
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Open IdeControllerProtocol
+ //
+ Status = pBS->OpenProtocol(Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ SataDevInterface->IdeDeviceHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+
+ Status = pBS->LocateProtocol (
+ &gHddSecurityInitProtocolGuid,
+ NULL,
+ &HddSecurityInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(HddSecurityInitProtocol != NULL) {
+ HddSecurityInitProtocol->InstallSecurityInterface(SataDevInterface, TRUE);
+ }
+ } else {
+
+ //
+ // If Security Feature support is not enabled, always freeze
+ // lock the security feature
+ //
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_82 & 0x2) {
+ COMMAND_STRUCTURE CommandStructure;
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SECURITY_FREEZE_LOCK;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ //
+ // if Device Configuration Overlay feature set supported then issue the
+ // Dev config Free lock command.
+ //
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_83 & 0x800) {
+ CommandStructure.Command = DEV_CONFIG_FREEZE_LOCK;
+ CommandStructure.Features = DEV_CONFIG_FREEZE_LOCK_FEATURES;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ //
+ // Update the Identify device buffer
+ //
+ Status = GetIdentifyData(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+
+ Status = pBS->LocateProtocol (
+ &gOpalSecInitProtocolGuid,
+ NULL,
+ &OpalSecInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(OpalSecInitProtocol != NULL) {
+ OpalSecInitProtocol->InstallOpalSecurityInterface(SataDevInterface, TRUE);
+ }
+ }
+
+ Status = pBS->LocateProtocol (
+ &gHddSmartInitProtocolGuid,
+ NULL,
+ &HddSmartInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(HddSmartInitProtocol != NULL) {
+ HddSmartInitProtocol->InitSMARTSupport(SataDevInterface, TRUE);
+ //
+ // Update the Idendify Data.
+ //
+ Status = GetIdentifyData(SataDevInterface);
+ if(HddSmartInitProtocol->SmartDiagonasticFlag) {
+ HddSmartInitProtocol->InstallSMARTInterface(SataDevInterface, TRUE);
+ }
+ }
+ }
+
+ //
+ // Check BlockIO has been installed or not.
+ //
+ Status = pBS->OpenProtocol( SataDevInterface->IdeDeviceHandle,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ SataDevInterface->IdeDeviceHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (EFI_ERROR(Status)) {
+ //
+ // BLOCKIO not installed and device has been configured successfully
+ //
+ Status = EFI_UNSUPPORTED;
+ SecurityStatus = 0;
+ }
+
+ if ((Status == EFI_UNSUPPORTED) || (!(SecurityStatus & 4))){
+ //
+ // Either the device doesn't support Security Mode OR Device is not locked
+ //
+ Status = pBS->InstallMultipleProtocolInterfaces (
+ &(SataDevInterface->IdeDeviceHandle),
+ &gEfiDiskInfoProtocolGuid,
+ (EFI_DISK_INFO_PROTOCOL *)(SataDevInterface->SataDiskInfo),
+ NULL);
+
+#if HDD_PASSWORD_SUPPORT_UNDER_RAIDMODE
+ if (!(!(AhciBusInterface->AHCIRAIDMODE) && (SataDevInterface->DeviceType == ATA))) {
+#endif
+
+ //
+ // If it's Raid mode and AHCIBUS handles the ATAPI devices, install the BlockIo
+ // for the ATAPI devices. BlockIo Will be installed for all the ATA and ATAPI device under AHCI mode
+ //
+ if (!(!(AhciBusInterface->AHCIRAIDMODE) && (AhciPlatformPolicy->AhciBusAtapiSupport == FALSE ))) {
+
+ //
+ // Either the device doesn't support Security Mode OR Device is not locked
+ //
+ Status = pBS->InstallMultipleProtocolInterfaces (
+ &(SataDevInterface->IdeDeviceHandle),
+ &gEfiBlockIoProtocolGuid,
+ (EFI_BLOCK_IO_PROTOCOL *)(SataDevInterface->SataBlkIo),
+ NULL);
+ }
+
+#if HDD_PASSWORD_SUPPORT_UNDER_RAIDMODE
+ }
+#endif
+
+ } // Install BLOCKIO
+
+ TRACE_AHCI((-1,"AHCI: SATA Device type %x detected at Port Number : %x, PM Port Number : %x\n",
+ SataDevInterface->DeviceType, SataDevInterface->PortNumber, SataDevInterface->PMPortNumber));
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: AhciBusStop
+//
+// Description: Uninstall all devices installed in start procedure.
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IN UINTN NumberOfChildren,
+// IN EFI_HANDLE *ChildHandleBuffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: OpenProtocol CloseProtocol
+//
+// Notes:
+// 1. Check whether "gEfiAhciBusProtocolGuid" is installed on this
+// controller. If not exit with error.
+// 2. If "NumberOfChildren" is zero, check wether all child devices
+// have been stopped. If not exit with error.If all child devices
+// have been stopped, then close "gEfiAhciBusProtocolGuid" and
+// "gEfiIdeControllerInitProtocolGuid",uninstall
+// "gEfiIdeControllerInitProtocolGuid" and then exit with success.
+// 3. If "NumberOfChildren" is non-zero, close
+// "gEfiIdeControllerInitProtocolGuid" opened by the child device
+// in start function.Uninstall all protocols installed on this
+// child device in start function,free up all resources allocated
+// in start function. Repeat step 3 for all child devices and
+// return success at the end.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+AhciBusStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ AHCI_BUS_PROTOCOL *AhciBusInterface;
+ SATA_DEVICE_INTERFACE *SataDeviceInterface;
+ EFI_STATUS Status;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface;
+ UINT16 Index = 0;
+ UINT16 Port=0;
+ UINT16 PMPort=0;
+ BOOLEAN Flag = TRUE;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ DLINK *dlink;
+
+ //
+ // Check if AHCI_BUS_PROTOCOL is installed on the Controller.
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiAhciBusProtocolGuid,
+ (VOID **)&AhciBusInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check if ChildHandleBuffer is valid
+ //
+ if (NumberOfChildren) {
+ while (NumberOfChildren) {
+
+
+ Status = pBS->CloseProtocol ( Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]);
+
+ Status = pBS->OpenProtocol(
+ ChildHandleBuffer[Index],
+ &gDevicePathProtocolGuid,
+ (VOID **)&DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ //
+ // Lookout for SATA device path ACPI_DEVICE path, PCI
+ // Device path and then ATAPI device path will be the sequence
+ //
+ do {
+ if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_USB_SATA_DP)) {
+ Port = ((SATA_DEVICE_PATH *)DevicePath)->PortNumber;
+ PMPort = ((SATA_DEVICE_PATH *)DevicePath)->MultiplierPortNumber;
+ break;
+ }
+ else {
+ DevicePath = NEXT_NODE(DevicePath);
+ }
+ } while (DevicePath->Type != END_DEVICE_PATH);
+
+ if(DevicePath->Type == END_DEVICE_PATH) {
+ //Unable to find the Messaging device path node.
+ ASSERT(FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+
+ SataDeviceInterface = GetSataDevInterface(AhciBusInterface, (UINT8)Port, (UINT8)PMPort);
+ if (!SataDeviceInterface) return EFI_DEVICE_ERROR;
+
+ //
+ // Before uninstalling DiskInfo check whether it is installed or not
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gEfiDiskInfoProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (Status == EFI_SUCCESS) {
+ Status = pBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiDiskInfoProtocolGuid,
+ (EFI_DISK_INFO_PROTOCOL *)(SataDeviceInterface->SataDiskInfo),
+ NULL);
+ }
+
+ //
+ // Before uninstalling BLOCKIO check whether it is installed or not
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (Status == EFI_SUCCESS) {
+ Status = pBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ (EFI_BLOCK_IO_PROTOCOL *)(SataDeviceInterface->SataBlkIo),
+ NULL);
+ }
+
+ Status = pBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gDevicePathProtocolGuid,
+ SataDeviceInterface->DevicePathProtocol,
+ NULL);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ } else {
+
+ //
+ // Now free up all resources allocated.
+ //
+ if (SataDeviceInterface->AtapiDevice != NULL){
+ pBS->FreePool(SataDeviceInterface->AtapiDevice->PacketBuffer);
+ pBS->FreePool(SataDeviceInterface->AtapiDevice->InquiryData);
+ pBS->FreePool(SataDeviceInterface->AtapiDevice);
+ }
+
+ //
+ // Freeup resources allocated for component names
+ //
+ if (SataDeviceInterface->UDeviceName != NULL) {
+ pBS->FreePool(SataDeviceInterface->UDeviceName->Language);
+ pBS->FreePool(SataDeviceInterface->UDeviceName->UnicodeString);
+ pBS->FreePool(SataDeviceInterface->UDeviceName);
+ }
+
+ //
+ // Before uninstalling HDD security check whether it is installed or not
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gSecurityModeProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (Status == EFI_SUCCESS) {
+ if(HddSecurityInitProtocol != NULL) {
+ HddSecurityInitProtocol->StopSecurityModeSupport(SataDeviceInterface, TRUE);
+ }
+ }
+
+ //
+ // Before uninstalling Hdd Smart check whether it is installed or not
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gSMARTProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (Status == EFI_SUCCESS) {
+ if(HddSmartInitProtocol != NULL) {
+ if(HddSmartInitProtocol->SmartDiagonasticFlag) {
+ HddSmartInitProtocol->UnInstallSMARTInterface(SataDeviceInterface, TRUE);
+ }
+ }
+ }
+
+ //
+ // Before uninstalling OPAL security interface check whether it is installed or not.
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gStorageSecurityProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (Status == EFI_SUCCESS) {
+ if(OpalSecInitProtocol != NULL) {
+ OpalSecInitProtocol->UnInstallOpalSecurityInterface(SataDeviceInterface, TRUE);
+ }
+ }
+
+ pBS->FreePool(SataDeviceInterface->SataBlkIo->BlkIo.Media);
+ pBS->FreePool(SataDeviceInterface->SataBlkIo);
+ pBS->FreePool(SataDeviceInterface->SataDiskInfo);
+ pBS->FreePool (SataDeviceInterface->DevicePathProtocol);
+ DListDelete(&(AhciBusInterface->SataDeviceList), &(SataDeviceInterface->SataDeviceLink));
+ pBS->FreePool (SataDeviceInterface);
+ }
+ NumberOfChildren--;
+ Index++;
+ }
+ } else {
+
+ //
+ // Check if AHCI_BUS_PROTOCOL can be removed. No device other
+ // than Port Multiplier can be present.
+ //
+ dlink = AhciBusInterface->SataDeviceList.pHead;
+ Status = EFI_SUCCESS;
+ if (dlink){
+ do {
+ SataDeviceInterface = OUTTER(dlink, SataDeviceLink, SATA_DEVICE_INTERFACE);
+ if (SataDeviceInterface->DeviceType != PMPORT ||
+ SataDeviceInterface->DeviceState == DEVICE_CONFIGURED_SUCCESSFULLY) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ dlink = dlink-> pNext;
+ }while (dlink);
+ }
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Free PM resources
+ //
+ dlink = AhciBusInterface->SataDeviceList.pHead;
+ Status = EFI_SUCCESS;
+ if (dlink){
+ do {
+ SataDeviceInterface = OUTTER(dlink, SataDeviceLink, SATA_DEVICE_INTERFACE);
+ //
+ // Now free up all resources allocated.
+ //
+ if (SataDeviceInterface->AtapiDevice != NULL){
+ pBS->FreePool(SataDeviceInterface->AtapiDevice->PacketBuffer);
+ pBS->FreePool(SataDeviceInterface->AtapiDevice->InquiryData);
+ pBS->FreePool(SataDeviceInterface->AtapiDevice);
+ }
+
+ //
+ // Freeup resources allocated for component names
+ //
+ if (SataDeviceInterface->UDeviceName != NULL) {
+ pBS->FreePool(SataDeviceInterface->UDeviceName->Language);
+ pBS->FreePool(SataDeviceInterface->UDeviceName->UnicodeString);
+ pBS->FreePool(SataDeviceInterface->UDeviceName);
+ }
+ DListDelete(&(AhciBusInterface->SataDeviceList), &(SataDeviceInterface->SataDeviceLink));
+ dlink = dlink-> pNext;
+ pBS->FreePool (SataDeviceInterface);
+ }while (dlink);
+ }
+
+ //
+ // Close all the protocols opened in Start Function
+ //
+ Status = pBS->CloseProtocol ( Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ //
+ // AtaPass Thru uninstall
+ //
+ Status = pBS->LocateProtocol (
+ &gAtaPassThruInitProtocolGuid,
+ NULL,
+ &AtaPassThruInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(AtaPassThruInitProtocol != NULL) {
+ AtaPassThruInitProtocol->StopAtaPassThruSupport(Controller, TRUE);
+ }
+ }
+
+ //
+ // SCSIPassThruAtapi uninstall
+ //
+ Status = pBS->LocateProtocol (
+ &gScsiPassThruAtapiInitProtocolGuid,
+ NULL,
+ &gScsiPassThruAtapiInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(gScsiPassThruAtapiInitProtocol != NULL) {
+ gScsiPassThruAtapiInitProtocol->StopScsiPassThruAtapiSupport(Controller, TRUE);
+ }
+ }
+
+ Status = pBS->CloseProtocol( Controller,
+ &gEfiAhciBusProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+
+ Status = pBS->UninstallProtocolInterface ( Controller,
+ &gEfiAhciBusProtocolGuid,
+ AhciBusInterface);
+
+ if (EFI_ERROR(Status)) {
+
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiAhciBusProtocolGuid,
+ (VOID **)&AhciBusInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Free the Pages allocated for the FIS and Command List
+ if (AhciBusInterface->Address1) {
+ pBS->FreePages(AhciBusInterface->Address1,
+ EFI_SIZE_TO_PAGES(AhciBusInterface->NumberofPortsImplemented * RECEIVED_FIS_SIZE + 0x100 ));
+ }
+
+ if (AhciBusInterface->Address2) {
+ pBS->FreePages((AhciBusInterface->Address2),EFI_SIZE_TO_PAGES(COMMAND_LIST_SIZE_PORT * 2));
+ }
+
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: InstallAhciBusProtocol
+//
+// Description: Installs BUS Init Protocol on the IDE controller Handle
+//
+// Input:
+// IN EFI_HANDLE Controller,
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface,
+// IDE_CONTROLLER_PROTOCOL *IdeControllerInterface,
+// EFI_PCI_IO_PROTOCOL *PciIO
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AllocatePool, InstallProtocolInterface, AhciInitController
+//
+// Notes:
+// 1. Call AhciInitController
+// 2. Install gEfiAhciBusProtocolGuid protocol
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+InstallAhciBusProtocol (
+ IN EFI_HANDLE Controller,
+ IN OUT AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ IN EFI_PCI_IO_PROTOCOL *PciIO
+ )
+{
+
+ EFI_STATUS Status;
+ UINT8 PciConfig[16];
+#if SBIDE_SUPPORT
+ IDE_SETUP_PROTOCOL *gIdeSetupProtocol;
+#endif
+
+ //
+ // Initialize the default Values
+ //
+ ZeroMemory (AhciBusInterface, sizeof(AHCI_BUS_PROTOCOL));
+
+ AhciBusInterface->ControllerHandle = Controller;
+ AhciBusInterface->IdeControllerInterface = IdeControllerInterface;
+ AhciBusInterface->PciIO = PciIO;
+ DListInit(&(AhciBusInterface->SataDeviceList));
+
+ AhciBusInterface->SataReadWritePio = SataReadWritePio;
+ AhciBusInterface->SataPioDataOut = SataPioDataOut;
+ AhciBusInterface->ExecutePioDataCommand = ExecutePioDataCommand;
+ AhciBusInterface->ExecuteNonDataCommand = ExecuteNonDataCommand;
+ AhciBusInterface->WaitforCommandComplete = WaitforCommandComplete;
+ AhciBusInterface->GeneratePortReset = GeneratePortReset;
+ AhciBusInterface->ExecutePacketCommand = ExecutePacketCommand;
+ AhciBusInterface->AHCIRAIDMODE = TRUE; // Set TRUE when in AHCI mode
+
+ Status = PciIO->Pci.Read ( PciIO,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciConfig),
+ PciConfig
+ );
+
+ if (PciConfig [IDE_SUB_CLASS_CODE]== SCC_RAID_CONTROLLER ){
+ AhciBusInterface->AHCIRAIDMODE = FALSE;
+ }
+
+ //
+ // Using setup question if needed, set Bit 0 to enable/Disable
+ // Acoustic Power Management.
+ // Set bit1 only if HDD Losses power in S3 state. HDD freeze lock
+ // command will be issued during S3 resume when this bit is set
+ // and also if Password is enabled for HDD, it will be unlocked
+ // during S3 resume.
+ //
+
+ AhciBusInterface->Acoustic_Enable = 0; // ACOUSTIC_SUPPORT_DISABLE
+
+#if SBIDE_SUPPORT
+ Status = pBS->LocateProtocol(&gIdeSetupProtocolguid, NULL, &gIdeSetupProtocol);
+
+ #if ACOUSTIC_MANAGEMENT_SUPPORT
+ if (!EFI_ERROR(Status)) {
+ AhciBusInterface->Acoustic_Enable = gIdeSetupProtocol->AcousticPwrMgmt;
+ AhciBusInterface->Acoustic_Management_Level = gIdeSetupProtocol->AcousticLevel;
+ } else {
+ AhciBusInterface->Acoustic_Enable = ACOUSTIC_SUPPORT_DISABLE;
+ AhciBusInterface->Acoustic_Management_Level = ACOUSTIC_LEVEL_BYPASS;
+ }
+ #endif //End of ACOUSTIC_MANAGEMENT_SUPPORT
+#endif // end of if SBIDE_SUPPORT
+
+
+ // Initialize PrevPortNum and PrevPortMultiplierPortNum for AtaPassThru to 0xFFFF
+
+ AhciBusInterface->PrevPortNum = 0xffff;
+ AhciBusInterface->PrevPortMultiplierPortNum = 0xffff;
+
+ //
+ // Init AHCI Controller
+ //
+ Status = AhciInitController(AhciBusInterface);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = pBS->InstallProtocolInterface(
+ &Controller,
+ &gEfiAhciBusProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ AhciBusInterface);
+
+ return Status;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: AhciInitController
+//
+// Description: Initializes AHCI Controller
+//
+// Input:
+// IN OUT AHCI_BUS_PROTOCOL *AhciBusInterface
+//
+// Output:
+// EFI_STATUS
+//
+//
+// Notes:
+// 1. Update internal Data area about the AHCI controller Capabilities.
+// 2. Allocate memory for FIS and CommandList
+// 3. Enable AHCI mode
+// 3. Disable all the ports
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+AhciInitController (
+ IN OUT AHCI_BUS_PROTOCOL *AhciBusInterface
+)
+{
+ EFI_STATUS Status;
+ UINT8 PciConfig[40];
+ UINT32 PortsImplemented;
+ UINT8 i, PortNumber;
+ UINT32 AhciBaseAddr;
+ UINTN AllocatePageSize = 0;
+ UINT32 Data32;
+
+
+ //
+ // Make sure AHCI Base address is programmed Properly
+ //
+ Status = AhciBusInterface->PciIO->Pci.Read (
+ AhciBusInterface->PciIO,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciConfig),
+ PciConfig
+ );
+
+ if (EFI_ERROR(Status)) { return Status;}
+
+ AhciBusInterface->AhciBaseAddress = *(UINT32 *)(PciConfig + PCI_ABAR);
+ if (!AhciBusInterface->AhciBaseAddress) return EFI_DEVICE_ERROR;
+
+ AhciBaseAddr = (UINT32) (AhciBusInterface->AhciBaseAddress);
+
+#if INDEX_DATA_PORT_ACCESS
+ Status = InitilizeIndexDataPortAddress (AhciBusInterface->PciIO);
+#endif
+
+ //
+ // Get AHCI Capability
+ //
+ AhciBusInterface->HBACapability = HBA_REG32(AhciBaseAddr, HBA_CAP);
+ if (AhciBusInterface->HBACapability == 0xFFFFFFFF) return EFI_DEVICE_ERROR; // Not decoded properly
+
+ //
+ // Get # of Ports Implemented (bit map)
+ //
+ AhciBusInterface->HBAPortImplemented = HBA_REG32(AhciBaseAddr, HBA_PI);
+ if (!AhciBusInterface->HBAPortImplemented) return EFI_DEVICE_ERROR;
+
+ //
+ // Cross check whether # of Ports implemented is less or equal to
+ // Max. # of ports supported by the silicon
+ //
+ PortsImplemented = AhciBusInterface->HBAPortImplemented;
+ AhciBusInterface->NumberofPortsImplemented = 0;
+ for ( ;PortsImplemented; PortsImplemented >>= 1){
+ if (PortsImplemented & 1) AhciBusInterface->NumberofPortsImplemented++;
+ }
+ if (((AhciBusInterface->HBACapability & HBA_CAP_NP_MASK) + 1) < AhciBusInterface->NumberofPortsImplemented)
+ { return EFI_DEVICE_ERROR; }
+
+ //
+ // Get the HBA version #
+ //
+ AhciBusInterface->AhciVersion = HBA_REG32(AhciBaseAddr, HBA_VS);
+
+ //
+ // Set AE bit
+ //
+ HBA_REG32_OR(AhciBaseAddr, HBA_GHC, HBA_GHC_AE);
+
+ //
+ // Allocate memory for FIS. Should be aligned on 256 Bytes. Each
+ // Port will have it own FIS data area.
+ //
+
+ AhciBusInterface->PortFISBaseAddr=0xFFFFFFFF;
+ AllocatePageSize = AhciBusInterface->NumberofPortsImplemented * RECEIVED_FIS_SIZE + 0x100;
+
+ Status = pBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES(AllocatePageSize), // Bytes->4KiloBytes conversion
+ (EFI_PHYSICAL_ADDRESS*)&(AhciBusInterface->PortFISBaseAddr));
+
+ ZeroMemory ((VOID *) AhciBusInterface->PortFISBaseAddr,
+ AhciBusInterface->NumberofPortsImplemented * RECEIVED_FIS_SIZE + 0x100);
+ AhciBusInterface->PortFISBaseAddrEnd = AhciBusInterface->PortFISBaseAddr +
+ AhciBusInterface->NumberofPortsImplemented * RECEIVED_FIS_SIZE;
+ AhciBusInterface->Address1 = AhciBusInterface->PortFISBaseAddr; // Will be used to free the memory later
+ AhciBusInterface->PortFISBaseAddr = (AhciBusInterface->PortFISBaseAddr & (~0xFF))+ 0x100;
+
+ //
+ // Allocate memory for Command List (1KB aligned) and Command Table (128KB aligned).
+ // All the ports in the controller will share Command List and Command table data Area.
+ //
+
+ AhciBusInterface->PortCommandListBaseAddr=0xFFFFFFFF;
+ AllocatePageSize = COMMAND_LIST_SIZE_PORT * 2;
+
+ Status = pBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES(AllocatePageSize), // Bytes->4KiloBytes conversion
+ (EFI_PHYSICAL_ADDRESS*)&(AhciBusInterface->PortCommandListBaseAddr));
+
+ ZeroMemory ((VOID *)AhciBusInterface->PortCommandListBaseAddr, COMMAND_LIST_SIZE_PORT * 2);
+ AhciBusInterface->Address2 = AhciBusInterface->PortCommandListBaseAddr;
+
+ AhciBusInterface->PortCommandListBaseAddr = (AhciBusInterface->PortCommandListBaseAddr & (~0x3FF)) + 0x400;
+ AhciBusInterface->PortCommandListLength = 0x20;
+ AhciBusInterface->PortCommandTableBaseAddr = AhciBusInterface->PortCommandListBaseAddr + 0x80;
+ AhciBusInterface->PortCommandTableLength = COMMAND_LIST_SIZE_PORT - 0x80;
+
+ //
+ // Make sure controller is not running
+ //
+ PortsImplemented = AhciBusInterface->HBAPortImplemented;
+ PortNumber = 0;
+ for (i=0; PortsImplemented; PortsImplemented>>=1, PortNumber++){
+ if (PortsImplemented & 1) {
+
+ //
+ // Program PxCLB and PxFB
+ //
+ HBA_PORT_WRITE_REG32 (AhciBaseAddr, PortNumber, HBA_PORTS_CLB,AhciBusInterface->PortCommandListBaseAddr);
+
+ HBA_PORT_WRITE_REG32 (AhciBaseAddr, PortNumber, 0x0008, AhciBusInterface->PortFISBaseAddr +(i * RECEIVED_FIS_SIZE));
+
+ //
+ // Clear Start
+ //
+ HBA_PORT_REG32_AND(AhciBaseAddr, PortNumber, HBA_PORTS_CMD, ~(HBA_PORTS_CMD_ST));
+
+ //
+ // Make sure CR is 0 with in 500msec
+ //
+ Status = WaitForMemClear(AhciBaseAddr, PortNumber, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_CR_CLEAR_TIMEOUT
+ );
+
+ if (EFI_ERROR(Status)) {
+ // Get the Port Speed allowed and Interface Power Management Transitions Allowed
+ // Pass the values for PortReset.
+ Data32 = HBA_PORT_REG32 ((UINT32)(AhciBusInterface->AhciBaseAddress), PortNumber, HBA_PORTS_SCTL);
+ Data32 &= 0xFF0;
+
+ Status = GeneratePortReset(AhciBusInterface, NULL, PortNumber, 0xFF,
+ (UINT8)((Data32 & 0xF0) >> 4), (UINT8)(Data32 >> 8));
+ }
+
+ if (EFI_ERROR(Status)) {
+ HostReset(AhciBusInterface);
+ }
+
+ //
+ // Clear FIS receive enable.
+ //
+ HBA_PORT_REG32_AND (AhciBaseAddr, PortNumber,
+ HBA_PORTS_CMD, ~(HBA_PORTS_CMD_FRE));
+ //
+ // Make sure FR is 0 with in 500msec
+ //
+ Status = WaitForMemClear(AhciBaseAddr, PortNumber, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ HBA_PORT_REG32_OR (AhciBaseAddr, PortNumber,
+ HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR); // Clear Status register
+
+ i++;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckPortImplemented
+//
+// Description: Check if the port is implemented in the AHCI Controller
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN UINT8 Port
+//
+// Output:
+// EFI_STATUS
+//
+// Notes:
+// 1. Check Port Implemented register whether the PORT is
+// implemented in the Controller or not.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+CheckPortImplemented (
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN UINT8 Port
+)
+{
+
+ if (AhciBusInterface->HBAPortImplemented & (1<< Port)) return EFI_SUCCESS;
+
+ return EFI_NOT_FOUND;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciDetectDevice
+//
+// Description: Detects a SATA device connected to given Port and PMPort
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: CheckDevicePresence CheckPMDevicePresence GenerateSoftReset
+//
+// Notes:
+// 1. if CheckDevicePresence fails exit.
+// 2. If Controller supports PM, issue Softreset
+// 3. Check the Device Signature.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+AhciDetectDevice (
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort
+)
+{
+
+ EFI_STATUS Status;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ SATA_DEVICE_INTERFACE *SataDevInterface = NULL;
+
+ PROGRESS_CODE(DXE_IDE_DETECT);
+
+ IdeControllerInterface->NotifyPhase (IdeControllerInterface, EfiIdeBusBeforeDevicePresenceDetection, Port);
+
+ SataDevInterface = GetSataDevInterface(AhciBusInterface, Port, PMPort);
+
+ if (!SataDevInterface){
+
+ //
+ // A device is present.
+ //
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ sizeof(SATA_DEVICE_INTERFACE),
+ (VOID**)&SataDevInterface);
+ if (EFI_ERROR(Status)) return Status;
+
+ ZeroMemory (SataDevInterface, sizeof(SATA_DEVICE_INTERFACE));
+
+ SataDevInterface->PortNumber = Port;
+ SataDevInterface->PMPortNumber = PMPort;
+ SataDevInterface->AhciBusInterface = AhciBusInterface;
+ SataDevInterface->DeviceState = DEVICE_IN_RESET_STATE;
+
+ //
+ // Update Base addresses
+ //
+ SataDevInterface->PortCommandListBaseAddr = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_CLB);
+ SataDevInterface->PortFISBaseAddr = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_FB);
+
+ //
+ // Add to the AhciBusInterface
+ //
+ DListAdd(&(AhciBusInterface->SataDeviceList), &(SataDevInterface->SataDeviceLink));
+
+
+ }
+
+ if (PMPort == 0xFF) {
+ Status = CheckDevicePresence (SataDevInterface, IdeControllerInterface, Port, PMPort);
+ }
+ else {
+ Status = CheckPMDevicePresence (SataDevInterface, IdeControllerInterface, Port, PMPort);
+ }
+
+ if (EFI_ERROR(Status)) {
+ IdeControllerInterface->NotifyPhase (IdeControllerInterface, EfiIdeBusAfterDevicePresenceDetection, Port);
+ if (SataDevInterface->DeviceState == DEVICE_IN_RESET_STATE) {
+ DListDelete(&(AhciBusInterface->SataDeviceList), &(SataDevInterface->SataDeviceLink));
+ pBS->FreePool(SataDevInterface);
+ }
+ return EFI_DEVICE_ERROR;
+ }
+
+ #if PORT_MULTIPLIER_SUPPORT
+ //
+ // Check if PM support is present
+ //
+ if (AhciBusInterface->HBACapability & HBA_CAP_SPM) {
+ Status = GenerateSoftReset(SataDevInterface, PMPort == 0xFF ? CONTROL_PORT : PMPort);
+ if (EFI_ERROR(Status)) {
+
+ //
+ // We know link has been established, meaning device is
+ // present. Maybe we need delay before giving a Soft reset.
+ //
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (!EFI_ERROR(Status)){
+ pBS->Stall(3000000); // 3sec delay
+ Status = GenerateSoftReset(SataDevInterface, PMPort == 0xFF ? CONTROL_PORT : PMPort);
+ }
+ }
+
+ if (EFI_ERROR(Status)) {
+ IdeControllerInterface->NotifyPhase (IdeControllerInterface, EfiIdeBusAfterDevicePresenceDetection, Port);
+ if (SataDevInterface->DeviceState == DEVICE_IN_RESET_STATE) {
+ DListDelete(&(AhciBusInterface->SataDeviceList), &(SataDevInterface->SataDeviceLink));
+ pBS->FreePool(SataDevInterface);
+ }
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ #endif
+
+ if (!(SataDevInterface->PortCommandListBaseAddr) || !(SataDevInterface->PortFISBaseAddr)) {
+ ASSERT_EFI_ERROR(EFI_DEVICE_ERROR);
+ }
+
+ //
+ // Save the Signature
+ //
+ SataDevInterface->Signature = HBA_PORT_REG32(AhciBaseAddr, Port, HBA_PORTS_SIG);
+ switch (SataDevInterface->Signature) {
+ case ATA_SIGNATURE_32:
+ SataDevInterface->DeviceType = ATA;
+ break;
+ case ATAPI_SIGNATURE_32:
+ SataDevInterface->DeviceType = ATAPI;
+ break;
+ case PMPORT_SIGNATURE:
+ SataDevInterface->DeviceType = PMPORT;
+ // 1 sec Delay needed for the next device to be discovered from PM.
+ pBS->Stall(1000000);
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ }
+
+#if !HDD_PASSWORD_SUPPORT_UNDER_RAIDMODE
+ if ((!AhciBusInterface->AHCIRAIDMODE) && (SataDevInterface->DeviceType == ATA)) {
+ DListDelete(&(AhciBusInterface->SataDeviceList), &(SataDevInterface->SataDeviceLink));
+ pBS->FreePool(SataDevInterface);
+ Status = EFI_DEVICE_ERROR;
+ }
+#endif
+
+#if !SUPPORT_ATAPI_IN_RAID_MODE
+
+ //
+ // If the Atapi devices are handled by Raid option rom, then
+ // don't configure the Atapi devices.
+ //
+ if ((!AhciBusInterface->AHCIRAIDMODE) && (SataDevInterface->DeviceType == ATAPI)) {
+ DListDelete(&(AhciBusInterface->SataDeviceList), &(SataDevInterface->SataDeviceLink));
+ pBS->FreePool(SataDevInterface);
+ Status = EFI_DEVICE_ERROR;
+ }
+#endif
+ IdeControllerInterface->NotifyPhase (IdeControllerInterface, EfiIdeBusAfterDevicePresenceDetection, Port);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckDevicePresence
+//
+// Description: Check if any device is connected to the port
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: HandlePortComReset CheckValidDevice GeneratePortReset
+//
+// Notes:
+// 1. If Staggered spin-up is supported, power-up the device.
+// 2. Call CheckValidDevice if success exit. Else generate Softreset.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+CheckDevicePresence (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort
+)
+{
+
+ EFI_STATUS Status;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ UINT8 CapIss;
+ UINT8 PortSpeed=0;
+ UINT8 CurrentPortSpeed=0;
+ UINT32 Data32;
+
+ //
+ // PM disabled
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SCTL, HBA_PORTS_SCTL_IPM_PSD_SSD);
+
+ //
+ // Clear Status register
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ //
+ // Get the Interface Speed Support( Maximum Speed supported)
+ //
+ CapIss = (UINT8)((HBA_REG32(AhciBaseAddr, HBA_CAP) & HBA_CAP_ISS_MASK)>>20);
+
+ //
+ // Get the Speed Allowed (SPD) for the Port. Maximum speed allowed for the Port
+ //
+ PortSpeed = (UINT8)((HBA_PORT_REG32(AhciBaseAddr, Port, HBA_PORTS_SCTL)
+ & HBA_PORTS_SCTL_SPD_MASK)>>4);
+
+ //
+ // If the Maximum speed allowed is programmed for the port, use the Port Speed allowed value
+ //
+ if(PortSpeed != 0 ) {
+ if(PortSpeed > CapIss) {
+ //
+ // Port Speed allowed can't be more than Interface Speed. So limit Port speed to Interface Speed
+ //
+ PortSpeed = CapIss;
+ }
+ } else {
+ //
+ // If there is no Maximum speed allowed for the port, use the Interface Speed
+ //
+ PortSpeed = CapIss;
+ }
+
+ //
+ // Check if Link is already established
+ //
+ if ((HBA_PORT_REG32 (AhciBusInterface->AhciBaseAddress, Port, HBA_PORTS_SSTS)
+ & HBA_PORTS_SSTS_DET_MASK) == HBA_PORTS_SSTS_DET_PCE) {
+
+ //
+ // As the Link is already established, get the negotiated interface
+ // communication speed
+ //
+ CurrentPortSpeed = (UINT8)((HBA_PORT_REG32(AhciBaseAddr, Port, HBA_PORTS_SSTS)
+ & HBA_PORTS_SSTS_SPD_MASK)>>4);
+
+ //
+ // Check the Current Interface Speed with Speed Allowed. If current inerface speed is more than
+ // Speed allowed set, then set the port speed according to the speed allowed
+ //
+ if( CurrentPortSpeed > PortSpeed) {
+
+ Status = GeneratePortReset(AhciBusInterface, SataDevInterface, Port, PMPort,
+ PortSpeed, HBA_PORTS_SCTL_IPM_PSSD);
+ }
+ } else {
+ //
+ // Link Not Established. Set SPD by PortSpeed
+ //
+ CapIss = (UINT8)((HBA_REG32(AhciBaseAddr, HBA_CAP) & HBA_CAP_ISS_MASK)>>20);
+ HBA_PORT_REG32_AND_OR (AhciBaseAddr, Port, HBA_PORTS_SCTL, ~HBA_PORTS_SCTL_SPD_MASK,PortSpeed<<4 );
+ }
+
+ //
+ // Check if Staggered Spinup is supported
+ //
+ if (HBA_REG32 (AhciBaseAddr, HBA_CAP) & HBA_CAP_SSS) {
+
+ //
+ // Check if Link is already established, if yes dodn't expect a COMRESET
+ //
+ if ((HBA_PORT_REG32 (AhciBusInterface->AhciBaseAddress, Port, HBA_PORTS_SSTS)
+ & HBA_PORTS_SSTS_DET_MASK) != HBA_PORTS_SSTS_DET_PCE) {
+ //
+ // Enable FIS Receive Enable
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_FRE);
+
+ //
+ // Wait till FIS is running
+ //
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_SUD); // Spin up the device
+
+ //
+ // Todo Todo delay necessary here after power up?
+ //
+ Status = HandlePortComReset(AhciBusInterface, NULL, Port, 0xFF);
+
+ //
+ // Disable FIS Receive Enable
+ //
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~HBA_PORTS_CMD_FRE);
+
+ IdeControllerInterface->NotifyPhase (IdeControllerInterface, EfiIdeBusAfterDevicePresenceDetection, Port);
+ }
+ else {
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_SUD); // Spin up the device
+ }
+ }
+
+ //
+ // Check if Device detected. And check if Cold Presence logic
+ // is enabled. If yes enable POD
+ //
+ if (((HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_SSTS) & HBA_PORTS_SSTS_DET_MASK) == HBA_PORTS_SSTS_DET_PCE) &&
+ (HBA_PORT_REG32(AhciBaseAddr, Port, HBA_PORTS_CMD) & HBA_PORTS_CMD_CPD)) {
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_POD);
+ }
+
+ Status = CheckValidDevice(AhciBusInterface, Port, PMPort);
+
+#if PORT_MULTIPLIER_SUPPORT
+ // If PORT Multiplier support is enabled, SoftReset generated later will get the signature.
+ // No need for this additional Port Reset here
+ if ((HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_SSTS) & HBA_PORTS_SSTS_DET_MASK) == HBA_PORTS_SSTS_DET_PCE) {
+ return EFI_SUCCESS;
+ }
+#else
+ if (EFI_ERROR(Status)) {
+ IdeControllerInterface->NotifyPhase (
+ IdeControllerInterface,
+ EfiIdeBeforeChannelReset,
+ (UINT8)Port
+ );
+
+ // Get the Port Speed allowed and Interface Power Management Transitions Allowed
+ // Pass the values for PortReset.
+ Data32 = HBA_PORT_REG32 ((UINT32)(AhciBusInterface->AhciBaseAddress), Port, HBA_PORTS_SCTL);
+ Data32 &= 0xFF0;
+
+ Status = GeneratePortReset(
+ AhciBusInterface,
+ SataDevInterface,
+ Port,
+ PMPort,
+ (UINT8)((Data32 & 0xF0) >> 4),
+ (UINT8)(Data32 >> 8)
+ );
+
+ IdeControllerInterface->NotifyPhase (
+ IdeControllerInterface,
+ EfiIdeAfterChannelReset,
+ (UINT8)Port
+ );
+ }
+#endif
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckPMDevicePresence
+//
+// Description: Checks for the presence device behind a Port Multiplier.
+//
+// Input:
+// SATA_DEVICE_INTERFACE *SataDevInterface,
+// EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+// UINT8 Port,
+// UINT8 PMPort
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ReadWritePMPort GeneratePortReset
+//
+// Notes:
+// 1. Check whether communication is established?
+// 2. If yes exit else issues Port Reset
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+CheckPMDevicePresence (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort
+)
+{
+
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ UINT32 Data32 = 0, Init_SStatus = 0;
+
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_0_SSTATUS, &Init_SStatus, FALSE);
+
+ SataDevInterface->SControl = HBA_PORTS_SCTL_IPM_PSD_SSD;
+ if ((Init_SStatus & HBA_PORTS_SSTS_DET_MASK) == HBA_PORTS_SSTS_DET_PCE) {
+ Data32 = HBA_PORTS_SCTL_IPM_PSD_SSD;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_2_SCONTROL, &Data32, TRUE);
+ } else {
+
+ //
+ // Perform Port Reset to bring the communication back
+ //
+ IdeControllerInterface->NotifyPhase (
+ IdeControllerInterface,
+ EfiIdeBeforeChannelReset,
+ (UINT8)Port
+ );
+
+ // Get the Port Speed allowed and Interface Power Management Transitions Allowed
+ // Pass the values for PortReset.
+ Data32 = HBA_PORT_REG32 ((UINT32)(AhciBusInterface->AhciBaseAddress), Port, HBA_PORTS_SCTL);
+ Data32 &= 0xFF0;
+
+ Status = GeneratePortReset(
+ AhciBusInterface,
+ SataDevInterface,
+ Port,
+ PMPort,
+ (UINT8)((Data32 & 0xF0) >> 4),
+ (UINT8)(Data32 >> 8)
+ );
+
+ IdeControllerInterface->NotifyPhase (
+ IdeControllerInterface,
+ EfiIdeAfterChannelReset,
+ (UINT8)Port
+ );
+
+ // Giving a Softreset immediatly after Port Reset doesn't help to detect the
+ // devices behind PM quickly. Add a delay here before Softreset is generated.
+ // Add 1Sec delay
+ pBS->Stall(1000000);
+ }
+
+ //
+ // Clear Status register
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ Data32 = HBA_PORTS_ERR_CLEAR;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_1_SERROR, &Data32, TRUE);
+
+ Data32 = 0;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_0_SSTATUS, &Data32, FALSE);
+
+ if ((Data32 & HBA_PORTS_SSTS_DET_MASK) == HBA_PORTS_SSTS_DET_PCE) Status = EFI_SUCCESS;
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConfigureSataPort
+//
+// Description: Configure Sata Port settings
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// EFI_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ConfigureSataPort (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+
+ // Check for the ATAPI device
+ if (SataDevInterface->DeviceType == ATAPI) {
+ //
+ // Set Device is ATAPI Bit in CMD register
+ //
+ HBA_PORT_REG32_OR (
+ SataDevInterface->AhciBusInterface->AhciBaseAddress,
+ SataDevInterface->PortNumber,
+ HBA_PORTS_CMD,
+ HBA_PORTS_CMD_ATAPI
+ );
+ }
+
+ // Check the AHCI platform policy protocol to set the
+ // Drive LED on ATAPI Enable (DLAE) bit
+
+ if(AhciPlatformPolicy->DriverLedOnAtapiEnable) {
+ //
+ // Set Drive LED on ATAPI Enable (DLAE) Bit in CMD register
+ //
+ HBA_PORT_REG32_OR (
+ SataDevInterface->AhciBusInterface->AhciBaseAddress,
+ SataDevInterface->PortNumber,
+ HBA_PORTS_CMD,
+ HBA_PORTS_CMD_DLAE
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConfigurePMPort
+//
+// Description: Configure Port Multiplier
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+//
+// Modified:
+//
+// Referrals: ReadWritePMPort
+//
+// Notes:
+// 1. Read the number of Ports implemented in the Port Multiplier
+// 2. Update PM attached bit in the AHCI controller.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ConfigurePMPort (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+ EFI_STATUS Status;
+ UINT32 Data;
+
+ //
+ // Read the number of Ports preset in PM
+ //
+ Status = ReadWritePMPort (SataDevInterface, CONTROL_PORT, GSCR_2, &Data, FALSE);
+ SataDevInterface->NumPMPorts = ((UINT8)Data) - 1;
+
+ //
+ // Set PM Attched bit in CMD register
+ //
+ HBA_PORT_REG32_OR (
+ SataDevInterface->AhciBusInterface->AhciBaseAddress,
+ SataDevInterface->PortNumber,
+ HBA_PORTS_CMD,
+ HBA_PORTS_CMD_PMA
+ );
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConfigureDevice
+//
+// Description: Configure the SATA device
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+// IN OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes -
+// Modes collection supported by the device
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: GetIdentifyData, GeneratePortReset, ExecuteNonDataCommand, InitAcousticSupport
+//
+// Notes:
+// 1. Get the Identify data command.
+// 2. From the IdeControllerInit protocol, get the DMA & PIO supported
+// 3. Issue Set feature command to set PIO, DMA and multiple mode
+// 4. Initialize Acoustic, SMART, Power Management features.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ConfigureDevice (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes
+)
+{
+
+ EFI_STATUS Status;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface = AhciBusInterface->IdeControllerInterface;
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 PMPort = SataDevInterface->PMPortNumber;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT8 Data8;
+ UINT32 Data32;
+ UINT8 Index;
+ UINT16 DeviceName[41];
+ CHAR8 Language[] = "Eng";
+ EFI_UNICODE_STRING_TABLE *tempUnicodeTable;
+
+
+ if (SataDevInterface->DeviceType == PMPORT) return EFI_SUCCESS; // This is a Port Multiplier
+
+ Status = GetIdentifyData(SataDevInterface);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+#if !DISABLE_SOFT_SET_PREV
+#if FORCE_HDD_PASSWORD_PROMPT
+ if ((SataDevInterface->DeviceType == ATA) &&
+ (SataDevInterface->IdentifyData.Reserved_76_79[0] != 0xFFFF )&&
+ (SataDevInterface->IdentifyData.Reserved_76_79[2] & 0x0040)&& // Software Preservation support
+ (SataDevInterface->IdentifyData.Reserved_76_79[3] & 0x0040)){ // Software Preservation Enabled
+
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ CommandStructure.Features = DISABLE_SATA2_SOFTPREV; // Disable Software Preservation
+ CommandStructure.SectorCount = 6;
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+
+ // Get the Port Speed allowed and Interface Power Management Transitions Allowed
+ // Pass the values for PortReset.
+ Data32 = HBA_PORT_REG32 ((UINT32)(AhciBusInterface->AhciBaseAddress), Port, HBA_PORTS_SCTL);
+ Data32 &= 0xFF0;
+
+ GeneratePortReset(AhciBusInterface,
+ SataDevInterface,
+ Port,
+ PMPort,
+ (UINT8)((Data32 & 0xF0) >> 4),
+ (UINT8)(Data32 >> 8)
+ );
+
+ CommandStructure.Features = 0x10; // Enable Software Preservation
+ CommandStructure.SectorCount = 6;
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+#endif
+#endif
+
+ //
+ // Check if Device need spin-up
+ //
+ if ((SataDevInterface->IdentifyData.General_Config_0 & 4) &&
+ (SataDevInterface->IdentifyData.Special_Config_2 == SPIN_UP_REQUIRED1 ||
+ SataDevInterface->IdentifyData.Special_Config_2 == SPIN_UP_REQUIRED2 )){
+
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Features = SET_DEVICE_SPINUP;
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+
+ //
+ // Get the Identify Command once more
+ //
+ Status = GetIdentifyData(SataDevInterface);
+ if (EFI_ERROR(Status)){
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ Status = IdeControllerInterface->SubmitData(IdeControllerInterface,
+ Port,
+ PMPort == 0xFF ? 0 : PMPort,
+ (EFI_IDENTIFY_DATA *) &(SataDevInterface->IdentifyData));
+ if (EFI_ERROR(Status))
+ return Status;
+
+ Status = IdeControllerInterface->CalculateMode(IdeControllerInterface,
+ Port,
+ PMPort == 0xFF ? 0 : PMPort,
+ SupportedModes);
+
+ if (EFI_ERROR(Status) || (*SupportedModes == NULL) )
+ return EFI_INVALID_PARAMETER;
+
+ //
+ // Check ExtMode
+ //
+ if ((*SupportedModes)->ExtMode[0].TransferProtocol) { // Not Auto speed
+ Status = GeneratePortReset(AhciBusInterface, SataDevInterface, Port, PMPort,
+ (*SupportedModes)->ExtMode[0].TransferProtocol, HBA_PORTS_SCTL_IPM_PSSD);
+ if (PMPort != 0xFF) {
+ Data32 = HBA_PORTS_ERR_CLEAR;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_1_SERROR, &Data32, TRUE);
+ }
+ }
+
+ Status = IdeControllerInterface->SetTiming(IdeControllerInterface,
+ Port,
+ PMPort == 0xFF ? 0 : PMPort,
+ (*SupportedModes));
+ if (EFI_ERROR(Status)) return Status;
+
+ SataDevInterface->PIOMode = 0xff;
+ SataDevInterface->SWDma = 0xff;
+ SataDevInterface->MWDma = 0xff;
+ SataDevInterface->UDma = 0xff;
+
+ if ((*SupportedModes)->PioMode.Valid)
+ SataDevInterface->PIOMode = (*SupportedModes)->PioMode.Mode;
+
+ if ((*SupportedModes)->SingleWordDmaMode.Valid)
+ SataDevInterface->SWDma = (*SupportedModes)->SingleWordDmaMode.Mode;
+
+ if ((*SupportedModes)->MultiWordDmaMode.Valid)
+ SataDevInterface->MWDma = (*SupportedModes)->MultiWordDmaMode.Mode;
+
+ if ((*SupportedModes)->UdmaMode.Valid)
+ SataDevInterface->UDma = (*SupportedModes)->UdmaMode.Mode;
+
+ SataDevInterface->IORdy = ((EFI_IDENTIFY_DATA *)&(SataDevInterface->IdentifyData))->AtaData.capabilities & 0x800;
+
+ if ((SataDevInterface->IdentifyData.Valid_Bits_53 & 0x2) && ((*SupportedModes)->PioMode.Valid)){
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Features = SET_TRANSFER_MODE;
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.SectorCount = PIO_FLOW_CONTROL | SataDevInterface->PIOMode;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+
+ if (EFI_ERROR(Status))
+ return EFI_DEVICE_ERROR;
+
+ //
+ // Issue Set Multiple Mode Command only for ATA device
+ //
+ if (SataDevInterface->DeviceType == ATA){
+ Data8 = SataDevInterface->IdentifyData.Maximum_Sector_Multiple_Command_47 & 0xff;
+ if (Data8 & 0x2) Data8 = 2;
+ if (Data8 & 0x4) Data8 = 0x4;
+ if (Data8 & 0x8) Data8 = 0x8;
+ if (Data8 & 0x10) Data8 = 0x10;
+ if (Data8 & 0x20) Data8 = 0x20;
+ if (Data8 & 0x40) Data8 = 0x40;
+ if (Data8 & 0x80) Data8 = 0x80;
+
+ if (Data8 > 1) {
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SET_MULTIPLE_MODE;
+ CommandStructure.SectorCount = Data8;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ }
+
+ //
+ // Check if UDMA is supported
+ //
+ if (SataDevInterface->UDma != 0xff){
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Features = SET_TRANSFER_MODE;
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.SectorCount = UDMA_MODE | SataDevInterface->UDma;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ else {
+ if (SataDevInterface->MWDma != 0xff){
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Features = SET_TRANSFER_MODE;
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.SectorCount = MWDMA_MODE | SataDevInterface->MWDma;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ }
+
+ //
+ // Convert the Device string from Engligh to Unicode
+ //
+ SataDevInterface->UDeviceName = NULL;
+ for (Index = 0; Index < 40; Index += 2) {
+ DeviceName[Index] = ((UINT8 *)SataDevInterface->IdentifyData.Model_Number_27)[Index + 1];
+ DeviceName[Index + 1] = ((UINT8 *)SataDevInterface->IdentifyData.Model_Number_27)[Index];
+ }
+ DeviceName[40] = 0; // Word
+
+ tempUnicodeTable = MallocZ(sizeof (EFI_UNICODE_STRING_TABLE) * 2);
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ sizeof (Language),
+ (VOID**)&tempUnicodeTable[0].Language
+ );
+
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ sizeof (DeviceName),
+ (VOID**)&tempUnicodeTable[0].UnicodeString
+ );
+
+ pBS->CopyMem(tempUnicodeTable[0].Language, &Language, sizeof(Language));
+ pBS->CopyMem(tempUnicodeTable[0].UnicodeString, DeviceName, sizeof (DeviceName));
+ tempUnicodeTable[1].Language = NULL;
+ tempUnicodeTable[1].UnicodeString = NULL;
+ SataDevInterface->UDeviceName = tempUnicodeTable;
+
+ #if SBIDE_SUPPORT
+ InitMiscConfig(SataDevInterface);
+ #endif
+
+
+ if( AhciPlatformPolicy->DipmSupport) {
+ // Initialize and Enable Device initiated Power management
+ InitializeDipm(SataDevInterface);
+ }
+
+ if( AhciPlatformPolicy->DeviceSleepSupport) {
+ // Initialize and Enable Device Sleep Support
+ InitializeDeviceSleep(SataDevInterface);
+ }
+
+
+ ConfigurePowerUpInStandby(SataDevInterface);
+
+ Status = GetIdentifyData(SataDevInterface);
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConfigureController
+//
+// Description: Configure the AHCI Controller
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+// IN EFI_ATA_COLLECTIVE_MODE *SupportedModes -
+// Modes collection supported by the device
+//
+// Output:
+// EFI_STATUS
+//
+//
+// Notes:
+// 1. Issue IdeControllerInterface->SetTiming for setting uDMA
+// and PIO mode timings in the controller.
+// 2. Update the Read/Write command for the device
+// 3. Update the Device name used in Component Name protocol
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ConfigureController (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN EFI_ATA_COLLECTIVE_MODE *SupportedModes
+)
+{
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface = AhciBusInterface->IdeControllerInterface;
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 PMPort = SataDevInterface->PMPortNumber;
+
+ //
+ // Check if UDMA and MWDMA are programmed successfully
+ //
+ if (SataDevInterface->UDma != 0xff) {
+ if (!(ReturnMSBset((SataDevInterface->IdentifyData.UDMA_Mode_88 >> 8)) == SataDevInterface->UDma)) {
+ SataDevInterface->UDma = ReturnMSBset((SataDevInterface->IdentifyData.UDMA_Mode_88 >> 8));
+ SupportedModes->UdmaMode.Mode = SataDevInterface->UDma;
+ IdeControllerInterface->SetTiming (IdeControllerInterface, Port,
+ PMPort == 0xFF ? 0 : PMPort, SupportedModes);
+ }
+ }
+ else {
+ if (SataDevInterface->MWDma != 0xff) {
+ if (!(ReturnMSBset(SataDevInterface->IdentifyData.MultiWord_DMA_63 >> 8) == SataDevInterface->MWDma)) {
+ SataDevInterface->MWDma = ReturnMSBset((SataDevInterface->IdentifyData.MultiWord_DMA_63 >> 8));
+ SupportedModes->MultiWordDmaMode.Mode = SataDevInterface->MWDma;
+ IdeControllerInterface->SetTiming (IdeControllerInterface, Port,
+ PMPort == 0xFF ? 0 : PMPort, SupportedModes);
+ }
+ }
+ }
+
+ //
+ // Check for ATA
+ //
+ if (SataDevInterface->DeviceType == ATA) {
+
+ //
+ // Update IDE Read/Write Command
+ //
+ if ((SataDevInterface->IdentifyData.Valid_Bits_59 & 0x100) &&
+ (SataDevInterface->IdentifyData.Valid_Bits_59 & 0xff)) { // Check if Multiple Read/Write
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_83 & 0x400) {
+
+ //
+ // 48Bit LBA supported
+ //
+ SataDevInterface->ReadCommand = READ_MULTIPLE_EXT;
+ SataDevInterface->WriteCommand = WRITE_MULTIPLE_EXT;
+ }
+ else {
+ SataDevInterface->ReadCommand = READ_MULTIPLE;
+ SataDevInterface->WriteCommand = WRITE_MULTIPLE;
+ }
+ } // End of Multiple
+ else { // 1 Block = 1 Sector
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_83 & 0x400) {
+
+ //
+ // 48Bit LBA supported
+ //
+ SataDevInterface->ReadCommand = READ_SECTORS_EXT;
+ SataDevInterface->WriteCommand = WRITE_SECTORS_EXT;
+ }
+ else {
+ SataDevInterface->ReadCommand = READ_SECTORS;
+ SataDevInterface->WriteCommand = WRITE_SECTORS;
+ }
+ }
+ if (DMACapable(SataDevInterface)) {
+ #if IDEBUSMASTER_SUPPORT
+ SataDevInterface->ReadCommand = READ_DMA;
+ SataDevInterface->WriteCommand = WRITE_DMA;
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_83 & 0x400) {
+
+ //
+ // 48Bit LBA supported
+ //
+ SataDevInterface->ReadCommand = READ_DMA_EXT;
+ SataDevInterface->WriteCommand = WRITE_DMA_EXT;
+ }
+ #endif
+ }
+ } // end of ATA
+
+#if DISABLE_SOFT_SET_PREV
+
+ //
+ // Software settings preserved
+ //
+ if ((SataDevInterface->DeviceType == ATA) &&
+ (SataDevInterface->IdentifyData.Reserved_76_79[0] != 0xFFFF )&&
+ (SataDevInterface->IdentifyData.Reserved_76_79[2] & 0x0040)) {
+
+ COMMAND_STRUCTURE CommandStructure;
+ EFI_STATUS Status;
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.Features = DISABLE_SATA2_SOFTPREV;
+ CommandStructure.SectorCount = 6;
+ ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+
+ //
+ // Update the Identify device buffer
+ //
+ Status = GetIdentifyData(SataDevInterface);
+ if (EFI_ERROR(Status)){
+ return EFI_DEVICE_ERROR;
+ }
+ }
+#endif
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitializeDipm
+//
+// Description: Initialize Dipm in the device and controller
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// VOID
+//
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+InitializeDipm (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ COMMAND_STRUCTURE CommandStructure;
+
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.SectorCount = DiPM_SUB_COMMAND; // 0x03 : DiPM
+
+ // Check Host Supports Aggressive Link Power Management
+ // and Check DiPM supported by device
+
+ if((SataDevInterface->AhciBusInterface->HBACapability & HBA_CAP_SALP) &&
+ (SataDevInterface->IdentifyData.Reserved_76_79[0] & IDENTIFY_DiPM_HIIPM_REQUESTS_CAPABLE) &&
+ (SataDevInterface->IdentifyData.Reserved_76_79[2] & IDENTIFY_DiPM__SUPPORT)){
+
+ // Check DiPM needs to be enabled from Platform Policy
+ if(AhciPlatformPolicy->DipmEnable) {
+ // Check DiPM is already enabled via Identify Data Word.
+ if (!(SataDevInterface->IdentifyData.Reserved_76_79[3] & IDENTIFY_DiPM_ENABLED)) {
+ // Enable DiPM and Issue Set Feature command.
+ CommandStructure.Features = DiPM_ENABLE;
+ ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ } else {
+ if (SataDevInterface->IdentifyData.Reserved_76_79[3] & IDENTIFY_DiPM_ENABLED) {
+
+ // Disable DiPM and Issue Set Feature command only if it is enabled already.
+ CommandStructure.Features = DiPM_DISABLE;
+ ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ }
+ }
+ return;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitializeDeviceSleep
+//
+// Description: Initialize Device Sleep in the device and controller
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// VOID
+//
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InitializeDeviceSleep (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ UINT8 PortNumber = SataDevInterface->PortNumber;
+ COMMAND_STRUCTURE CommandStructure;
+ EFI_STATUS Status;
+ UINT8 DevSleep_Exit_TimeOut = DEVSLEEP_EXIT_TIMEOUT;
+ UINT8 Minimum_DevSleep_Assertion_Time = MINIMUM_DEVSLP_ASSERTION_TIME;
+ UINT8 DITO_Multiplier = 0xF;
+ UINT8 *Buffer = NULL;
+ UINT32 PxDevSlp;
+ UINT8 SectorCount = 1;
+
+ // If Aggressive DelSlp is supported then DevSlp also supported. Also check if the port supports DevSlp or not
+ if ((HBA_REG32(AhciBaseAddr, HBA_CAP2) & HBA_CAP2_SADM) &&
+ (HBA_PORT_REG32(AhciBaseAddr, PortNumber, HBA_PORTS_PxDEVSLP) & HBA_PORTS_PxDEVSLP_DSP)) {
+
+ //Clear ADSE
+ HBA_PORT_REG32_AND (AhciBaseAddr, PortNumber, HBA_PORTS_PxDEVSLP, ~(HBA_PORTS_PxDEVSLP_ADSE));
+
+ // Check Word 78 Bit8 and Word 77 Bit7 of Identify Data.
+ if ((SataDevInterface->IdentifyData.Reserved_76_79[2] & IDENTIFY_DEVSLEEP_SUPPORT) &&
+ (SataDevInterface->IdentifyData.Reserved_76_79[1] & IDENTIFY_DEVSLP_TO_REDUCED_PWRSTATE_CAPABLE)) {
+
+ if(AhciPlatformPolicy->DeviceSleepEnable) {
+
+ // DevSlp not enabled in device. Issue Set Feature command.
+ if (!(SataDevInterface->IdentifyData.Reserved_76_79[3] & IDENTIFY_DEVSLEEP_ENABLED)) {
+
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.SectorCount = DEVSLEEP_SUB_COMMAND;
+ CommandStructure.Features = DEVSLEEP_ENABLE;
+ ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+
+ // Allocate Memory for Identify Device Data
+ pBS->AllocatePool(EfiBootServicesData, ATA_SECTOR_BYTES, (VOID**)&Buffer);
+ ZeroMemory(Buffer, ATA_SECTOR_BYTES);
+
+ // Get Identify Device Data Log (log 30h Page 8)
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = READ_LOG_EXT;
+ CommandStructure.SectorCount = SectorCount;
+ CommandStructure.LBAMid = SERIAL_ATA_SETTINGS_PAGE;
+ CommandStructure.LBALow = IDENTIFY_DEVICE_DATA_LOG;
+ CommandStructure.ByteCount = SectorCount * ATA_SECTOR_BYTES;;
+ CommandStructure.Buffer = Buffer;
+
+ Status = ExecutePioDataCommand (SataDevInterface, &CommandStructure, FALSE);
+ if (!EFI_ERROR(Status)){
+
+ // Update the Time out values
+ ///BYTE 30h..37h DEVSLP Timing Variables (Qword) of Identify Device Data log (log 30h page 08h)
+ ///63 Valid
+ ///62:16 Reserved
+ ///15:8 DevSleep Exit Timeout, in ms (DETO)
+ ///5:7 Reserved
+ ///4:0 Minimum DEVSLP Assertion Time, in ms (MDAT)
+
+ DevSleep_Exit_TimeOut = Buffer[DEVSLP_TIMING_VARIABLES_OFFSET + 1] ? Buffer[DEVSLP_TIMING_VARIABLES_OFFSET + 1] : DEVSLEEP_EXIT_TIMEOUT;
+ Minimum_DevSleep_Assertion_Time = (Buffer[DEVSLP_TIMING_VARIABLES_OFFSET] & 0x1F) ? (Buffer[DEVSLP_TIMING_VARIABLES_OFFSET] & 0x1F) : MINIMUM_DEVSLP_ASSERTION_TIME;
+ }
+
+ // Program the Timeouts and Multiplier value in PxDEVSLP Registers
+ PxDevSlp = HBA_PORT_REG32 (AhciBaseAddr, PortNumber, HBA_PORTS_PxDEVSLP);
+ PxDevSlp &= ~(HBA_PORTS_PxDEVSLP_DETO_MASK | HBA_PORTS_PxDEVSLP_DMDAT_MASK | HBA_PORTS_PxDEVSLP_DM_MASK);
+ PxDevSlp |= ((DevSleep_Exit_TimeOut << 2) + (Minimum_DevSleep_Assertion_Time << 10) + (DITO_Multiplier << 25));
+ HBA_PORT_REG32_OR (AhciBaseAddr, PortNumber, HBA_PORTS_PxDEVSLP, PxDevSlp);
+
+ // Enable PxDEVSLP.ADSE
+ HBA_PORT_REG32_OR (AhciBaseAddr, PortNumber, HBA_PORTS_PxDEVSLP, HBA_PORTS_PxDEVSLP_ADSE);
+ pBS->FreePool(Buffer);
+ } else {
+ if (SataDevInterface->IdentifyData.Reserved_76_79[3] & IDENTIFY_DEVSLEEP_ENABLED) {
+
+ // Disable Device Sleep and Issue Set Feature command only if it is enabled already.
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.SectorCount = DEVSLEEP_SUB_COMMAND;
+ CommandStructure.Features = DEVSLEEP_DISABLE;
+ ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetSataDevInterface
+//
+// Description:
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort,
+//
+// Output:
+// SATA_DEVICE_INTERFACE*
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Return the Pointer to the SATA_DEVICE_INTERFACE for the given
+// Port and PM Port
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+SATA_DEVICE_INTERFACE *
+GetSataDevInterface(
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort
+)
+{
+
+ DLINK *dlink = AhciBusInterface->SataDeviceList.pHead;
+ SATA_DEVICE_INTERFACE *SataDevInterface = NULL;
+
+ if (!dlink) return NULL;
+ do {
+ SataDevInterface = OUTTER(dlink, SataDeviceLink, SATA_DEVICE_INTERFACE);
+ if (SataDevInterface->PortNumber == Port &&
+ SataDevInterface->PMPortNumber == PMPort ) break;
+ dlink = dlink-> pNext;
+ SataDevInterface = NULL;
+ }while (dlink);
+
+ return SataDevInterface;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitForMemSet
+//
+// Description: Wait for memory to be set to the test value.
+//
+// Input: MemTestAddr - The memory address to test
+// MaskValue - The mask value of memory
+// TestValue - The test value of memory
+// WaitTimeInMs - The time out value for wait memory set
+//
+// Output: EFI_SUCCESS - HBA reset successfully.
+// EFI_DEVICE_ERROR - HBA failed to complete hardware reset.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitForMemSet (
+ IN UINT32 BaseAddr,
+ IN UINT8 Port,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 TestValue,
+ IN UINT32 WaitTimeInMs
+)
+{
+ UINT8 Delay;
+ while(WaitTimeInMs!=0){
+ for ( Delay = 10; Delay > 0; Delay--) {
+
+ if(((HBA_PORT_REG32(BaseAddr, Port, Register)) & AndMask) == TestValue){
+ return EFI_SUCCESS;
+ }
+
+ pBS->Stall (100); // 100 usec * 10 = 1Msec
+ }
+ WaitTimeInMs--;
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitForMemClear
+//
+// Description: Wait for memory to be set to the test value.
+//
+// Input: MemTestAddr - The memory address to test
+// MaskValue - The mask value of memory
+// WaitTimeInMs - The time out value for wait memory set
+//
+// Output: EFI_SUCCESS - HBA reset successfully.
+// EFI_DEVICE_ERROR - HBA failed to complete hardware reset.
+//
+// Modified:
+//
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitForMemClear (
+ IN UINT32 BaseAddr,
+ IN UINT8 Port,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 WaitTimeInMs
+)
+{
+ UINT8 Delay;
+ while(WaitTimeInMs!=0){
+ for ( Delay = 10; Delay > 0; Delay--) {
+
+ if(!((HBA_PORT_REG32(BaseAddr, Port, Register)) & AndMask)){
+ return EFI_SUCCESS;
+ }
+
+ pBS->Stall (100); // 100 usec * 10 = 1Msec
+ }
+ WaitTimeInMs--;
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: ReturnMSBset
+//
+// Description: Returns the MOST significant Bit set.
+//
+// Input:
+// IN UINT32 Data
+//
+// Output:
+// UINT8
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+UINT8
+ReturnMSBset(
+ IN UINT32 Data
+ )
+{
+ UINT8 Index;
+ UINT8 Value = 0xFF;
+
+ for (Index = 0; Index < 32; Index++) {
+ if ( Data & 1) {
+ Value = Index;
+ }
+ Data >>= 1;
+ }
+
+ return Value;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: InitSataBlockIO
+//
+// Description: Initializes SATA Block IO interface
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AllocatePool, OpenProtocol, DetectAtapiMedia, AtapiInquiryData
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Initialize EFI_BLOCK_IO_PROTOCOL Protocol.
+// 2. In case of Removable devices, detect Media presence.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+InitSataBlockIO (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ SATA_BLOCK_IO *SataBlkIo;
+ EFI_BLOCK_IO_MEDIA *BlkMedia;
+ ATAPI_DEVICE *AtapiDevice;
+ UINT8 *Data, *InquiryData;
+ UINT16 InquiryDataSize;
+ UINT16 OddType=0;
+ UINT8 OddLoadingType=0xFF;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ sizeof(SATA_BLOCK_IO),
+ (VOID**)&SataBlkIo);
+ if (EFI_ERROR(Status)) return Status;
+
+ BlkMedia = MallocZ(sizeof(EFI_BLOCK_IO_MEDIA));
+ if (!BlkMedia) {
+ pBS->FreePool (SataBlkIo);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize the IdeBlkIo pointer in IDE_BUS_PROTOCOL (IdeBusInterface)
+ //
+ SataDevInterface->SataBlkIo = SataBlkIo;
+
+ //
+ // Initialize the fields in IdeBlkIo (SATA_BLOCK_IO)
+ //
+ SataBlkIo->SataDevInterface = SataDevInterface;
+
+ if (SataDevInterface->DeviceType == ATA){
+ // ATA
+ BlkIo = &(SataBlkIo->BlkIo);
+
+#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ BlkIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+ } else {
+ BlkIo->Revision = BLKIO_REVISION;
+ }
+#else
+ BlkIo->Revision = BLKIO_REVISION;
+#endif
+ BlkIo->Media = BlkMedia;
+ BlkIo->Reset = SataReset;
+ BlkIo->ReadBlocks = SataBlkRead;
+ BlkIo->WriteBlocks = SataBlkWrite;
+ BlkIo->FlushBlocks = SataBlkFlush;
+
+ BlkMedia->MediaId = 0;
+ BlkMedia->RemovableMedia = (SataDevInterface->IdentifyData.General_Config_0 & 0x80) == 0x80 ? TRUE : FALSE;
+
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->LogicalPartition = FALSE;
+ BlkMedia->ReadOnly = FALSE;
+ BlkMedia->WriteCaching = FALSE;
+
+ if((SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT14) && // WORD 106 valid? - BIT 14 - 1
+ (!(SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT15)) && // WORD 106 valid? - BIT 15 - 0
+ (SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT12)) { // WORD 106 bit 12 - Sectorsize > 256 words
+ // The sector size is in words 117-118.
+ SectorSize = (UINT32)(SataDevInterface->IdentifyData.Reserved_104_126[13] + \
+ (SataDevInterface->IdentifyData.Reserved_104_126[14] << 16)) * 2;
+ }
+
+ BlkMedia->BlockSize = SectorSize;
+ BlkMedia->IoAlign = 4;
+
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_83 & 0x400) {
+ BlkMedia->LastBlock = SataDevInterface->IdentifyData.LBA_48 - 1;
+ }
+ else {
+ BlkMedia->LastBlock = SataDevInterface->IdentifyData.Addressable_Sector_60 - 1;
+ }
+
+#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a
+ if(pST->Hdr.Revision >= 0x0002001F) {
+
+ BlkMedia->OptimalTransferLengthGranularity=BlkMedia->BlockSize;
+ //
+ // bit 14 of word 106 is set to one and bit 15 of word 106 is cleared to zero,
+ // then the contents of word 106 contain valid information .
+ // Otherwise, information is not valid in this word.
+ //
+ if ( (SataDevInterface->IdentifyData.Reserved_104_126[2] & 0xC000) == 0x4000 ) {
+ //
+ // If bit 13 of word 106 is set to one, then the device has more than one
+ // logical sector per physical sector and bits (3:0) of word 106 are valid
+ //
+ if ( SataDevInterface->IdentifyData.Reserved_104_126[2] & 0x2000 ) {
+
+ BlkMedia->LogicalBlocksPerPhysicalBlock = 1 <<
+ (SataDevInterface->IdentifyData.Reserved_104_126[2] & 0xF);
+
+ //
+ // Bits 13:0 of word 209 indicate the Logical sector offset within the first physical
+ // sector where the first logical sector is placed
+ //
+ BlkMedia->LowestAlignedLba =SataDevInterface->IdentifyData.Reserved_206_254[3] & 0x3FFF;
+
+ } else {
+ //
+ // Default set the 1 logical blocks per PhysicalBlock
+ //
+ BlkMedia->LogicalBlocksPerPhysicalBlock=1;
+
+ //
+ // Default value set to 0 for Lowest Aligned LBA
+ //
+ BlkMedia->LowestAlignedLba=0;
+ }
+ } else {
+ //
+ // Default set the 1 logical blocks per PhysicalBlock
+ //
+ BlkMedia->LogicalBlocksPerPhysicalBlock=1;
+ //
+ // Default value set to 0 for Lowest Aligned LBA
+ //
+ BlkMedia->LowestAlignedLba=0;
+ }
+ }
+#endif
+
+ } else {
+
+ //
+ // If it is an ATAPI device, check whether it is a CDROM or not.
+ // Currently only CDROM/Direct access Devices are supported.
+ //
+ if ((SataDevInterface->IdentifyData.General_Config_0 & 0x1f00) == (CDROM_DEVICE << 8) ||
+ (SataDevInterface->IdentifyData.General_Config_0 & 0x1f00) == (DIRECT_ACCESS_DEVICE << 8) ||
+ (SataDevInterface->IdentifyData.General_Config_0 & 0x1f00) == (OPTICAL_MEMORY_DEVICE << 8)){
+
+ AtapiDevice = MallocZ(sizeof (ATAPI_DEVICE));
+
+ if (!AtapiDevice) return EFI_OUT_OF_RESOURCES;
+
+ SataDevInterface->AtapiDevice = AtapiDevice;
+
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ 16,
+ (VOID**)&Data
+ );
+
+ if (EFI_ERROR(Status)) return Status;
+
+ AtapiDevice->PacketBuffer = Data;
+ AtapiDevice->DeviceType = (SataDevInterface->IdentifyData.General_Config_0 & 0x1f00) >> 8;
+ AtapiDevice->PacketSize = (SataDevInterface->IdentifyData.General_Config_0 & 3) == 1 ? 16 : 12;
+
+ BlkIo = &(SataBlkIo->BlkIo);
+#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ BlkIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+ } else {
+ BlkIo->Revision = BLKIO_REVISION;
+ }
+#else
+ BlkIo->Revision = BLKIO_REVISION;
+#endif
+ BlkIo->Media = BlkMedia;
+ BlkIo->Reset = SataReset;
+ BlkIo->ReadBlocks = SataAtapiBlkRead;
+ BlkIo->WriteBlocks = SataAtapiBlkWrite;
+ BlkIo->FlushBlocks = SataBlkFlush;
+ BlkMedia->BlockSize = CDROM_BLOCK_SIZE;
+
+ //
+ // Update Inquiry Data
+ //
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ INQUIRY_DATA_LENGTH,
+ (VOID**)&InquiryData);
+ if (EFI_ERROR(Status)) return Status;
+ InquiryDataSize = INQUIRY_DATA_LENGTH;
+ SataAtapiInquiryData(SataDevInterface, InquiryData, &InquiryDataSize);
+ AtapiDevice->InquiryData = InquiryData;
+ AtapiDevice->InquiryDataSize = InquiryDataSize;
+
+ //
+ // Get the ATAPI drive type information and save it ATAPI_DEVICE
+ //
+ Status=SataGetOddType(SataDevInterface, &OddType);
+ if(!EFI_ERROR(Status)) {
+ AtapiDevice->OddType=GetEnumOddType(OddType);
+ }
+
+ //
+ // Get the ATAPI drive Loading information and save it ATAPI_DEVICE
+ //
+ Status=SataGetOddLoadingType(SataDevInterface, &OddLoadingType);
+
+ if ( !EFI_ERROR( Status )) {
+ AtapiDevice->OddLoadingType = (ODD_LOADING_TYPE)OddLoadingType;
+ } else {
+ AtapiDevice->OddLoadingType = (ODD_LOADING_TYPE)0xFF;
+ }
+
+ BlkMedia->RemovableMedia = (SataDevInterface->IdentifyData.General_Config_0 & 0x80) == 0x80 ? TRUE : FALSE;
+ BlkMedia->LogicalPartition = FALSE;
+ BlkMedia->WriteCaching = FALSE;
+ BlkMedia->IoAlign = 4;
+#if defined CORE_COMBINED_VERSION && CORE_COMBINED_VERSION > 0x4028a
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ //
+ // For Atapi Devices, Default set the 1 for logical blocks per PhysicalBlock
+ //
+ BlkMedia->LogicalBlocksPerPhysicalBlock=1;
+
+ //
+ // For Atapi Devices, Default value set to 0 for Lowest Aligned LBA
+ //
+ BlkMedia->LowestAlignedLba=0;
+
+ BlkMedia->OptimalTransferLengthGranularity=BlkMedia->BlockSize;
+ }
+#endif
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetEnumOddType
+//
+// Description: Get the Enum value for ODD type found on profile
+//
+// Input:
+//
+// UINT16 Oddtype
+// Output:
+// ODD_TYPE EnumValue
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ODD_TYPE GetEnumOddType(
+ UINT16 OddType
+)
+{
+
+ switch(OddType) {
+ case 1:
+ case 3:
+ case 4:
+ case 5:
+ return Obsolete;
+
+ case 2:
+ return Removabledisk;
+
+ case 8:
+ return CDROM;
+
+ case 9:
+ return CDR;
+
+ case 0xa:
+ return CDRW;
+
+ case 0x10:
+ return DVDROM;
+
+ case 0x11:
+ return DVDRSequentialrecording;
+
+ case 0x12:
+ return DVDRAM;
+
+ case 0x13:
+ return DVDRWRestrictedOverwrite;
+
+ case 0x15:
+ return DVDRWSequentialrecording;
+
+ case 0x16:
+ return DVDRDualLayerJumprecording;
+
+ case 0x17:
+ return DVDRWDualLayer;
+
+ case 0x18:
+ return DVDDownloaddiscrecording;
+
+ case 0x1a:
+ return DVDRW;
+
+ case 0x1b:
+ return DVDR;
+
+ case 0x40:
+ return BDROM;
+
+ case 0x41:
+ return BDRSequentialRecording;
+
+ case 0x42:
+ return BDRRandomRecordingMode;
+
+ case 0x43:
+ return BDRE;
+
+ case 0x50:
+ return HDDVDROM;
+
+ case 0x51:
+ return HDDVDR;
+
+ case 0x52:
+ return HDDVDRAM;
+
+ case 0x53:
+ return HDDVDRW;
+
+ case 0x58:
+ return HDDVDRDualLayer;
+
+ case 0x5a:
+ return HDDVDRWDualLayer;
+
+ default:
+ return UnknownType;
+ }
+
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: InitSataDiskInfo
+//
+// Description: Initializes SATA DiskInfo Interface
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AllocatePool
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+InitSataDiskInfo (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+ )
+{
+ EFI_STATUS Status;
+ SATA_DISK_INFO *SataDiskInfo;
+
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ sizeof(SATA_DISK_INFO),
+ (VOID**)&SataDiskInfo);
+ if (EFI_ERROR(Status)){
+ return Status;
+ }
+
+ //
+ // Initialize the SataBlkIo pointer in SATA_DEVICE_INTERFACE
+ //
+ SataDevInterface->SataDiskInfo = SataDiskInfo;
+
+ // Initialize the fields in SataDiskInfo (SATA_DISK_INFO)
+ SataDiskInfo->SataDevInterface = SataDevInterface;
+
+ pBS->CopyMem (&(SataDiskInfo->DiskInfo.Interface), &gEfiAhciDiskInfoProtocolGuid, sizeof (EFI_GUID));
+ SataDiskInfo->DiskInfo.Inquiry = DiskInfoInquiry;
+ SataDiskInfo->DiskInfo.Identify = DiskInfoIdentify;
+ SataDiskInfo->DiskInfo.SenseData = DiskInfoSenseData;
+ SataDiskInfo->DiskInfo.WhichIde = DiskInfoWhichIDE;
+ return EFI_SUCCESS;
+
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: CreateSataDevicePath
+//
+// Description: Creates a SATA device devicepath and adds it to SataDevInterface
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+// IN OUT EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AllocatePool, OpenProtocol, IdeBusStart
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If Remaining Devicepath is not NULL, we have already verified that it is a
+// valid Atapi device path in IdeBusStart. So nothing to do. Just exit.
+// 2. Build a Atapi devicepath and a End devce path.
+// 3. Get the Devicepath for the IDE controller.
+// 4. Append Atapi devicepath to IDE controller devicepath.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+CreateSataDevicePath (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ SATA_DEVICE_PATH NewDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+
+ NewDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
+ NewDevicePath.Header.SubType = MSG_USB_SATA_DP;
+ SET_NODE_LENGTH(&NewDevicePath.Header,SATA_DEVICE_PATH_LENGTH);
+ NewDevicePath.PortNumber = SataDevInterface->PortNumber;
+ NewDevicePath.MultiplierPortNumber = SataDevInterface->PMPortNumber == 0xFF ? 0xFFFF : SataDevInterface->PMPortNumber;
+ NewDevicePath.LogicalUnitNumber = 0;
+
+ //
+ // Append the Device Path
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gDevicePathProtocolGuid,
+ (VOID **)&TempDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ SataDevInterface->DevicePathProtocol = DPAddNode(TempDevicePath, &NewDevicePath.Header);
+ return Status;
+
+}
+
+#if SBIDE_SUPPORT
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: InitMiscConfig
+//
+// Description: Initialize misc IDE configurations.
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// None
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+VOID InitMiscConfig (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+ IDE_SETUP_PROTOCOL *gIdeSetupProtocol;
+ COMMAND_STRUCTURE CommandStructure;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Status = pBS->LocateProtocol(&gIdeSetupProtocolguid, NULL, &gIdeSetupProtocol);
+ if(EFI_ERROR(Status)){
+ return;
+ }
+
+ #if ACOUSTIC_MANAGEMENT_SUPPORT
+ InitAcousticSupport (SataDevInterface);
+ #endif
+
+}
+#endif
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: ConfigurePowerUpInStandby
+//
+// Description: Configure PowerUpInStandby
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecuteNonDataCommand
+//
+// Notes:
+// 1. Check if the device support PowerUp In Standby.
+// 2. Check the desired state Vs the current state.
+// 3. If both are equal nothing to do, exit else program the desired level
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+ConfigurePowerUpInStandby (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+ )
+{
+ COMMAND_STRUCTURE CommandStructure;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if(AhciPlatformPolicy->PowerUpInStandbySupport) {
+ //
+ // Check if the device supports PowerUpInStandby feature
+ //
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_83 & 0x20){
+ //
+ //Check if the desired state is already present or not
+ //
+ if (!((SataDevInterface->IdentifyData.Command_Set_Enabled_86 & 0x20) ==
+ (AhciPlatformPolicy->PowerUpInStandbyMode))){
+
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+ CommandStructure.Features = (AhciPlatformPolicy->PowerUpInStandbyMode) == 0 ? DISABLE_POWERUP_IN_STANDBY : ENABLE_POWERUP_IN_STANDBY;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+
+ }
+ }
+ }
+
+ return Status;
+}
+
+#if ACOUSTIC_MANAGEMENT_SUPPORT
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: InitAcousticSupport
+//
+// Description: Initialize Acoustic functionality
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecuteNonDataCommand
+//
+// Notes:
+// 1. Check if the device support Acoustic management.
+// 2. Check the desired state Vs the current state.
+// 3. If both are equal nothing to do, exit else program the desired level
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+InitAcousticSupport (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+ )
+{
+
+ UINT8 Data8;
+ COMMAND_STRUCTURE CommandStructure;
+ EFI_STATUS Status;
+
+ ZeroMemory(&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Command = SET_FEATURE_COMMAND;
+
+ //
+ // Check if the device supports Acoustic Management
+ //
+ if (SataDevInterface->IdentifyData.Command_Set_Supported_83 & 0x200){
+
+ //
+ // Check if Acoustic Level need to be enabled or Disabled
+ //
+ if (SataDevInterface->AhciBusInterface->Acoustic_Enable & ACOUSTIC_SUPPORT_ENABLE) {
+ Data8 = SataDevInterface->AhciBusInterface->Acoustic_Management_Level;
+
+ //
+ // Do we need to program the recommended value
+ //
+ if (Data8 == ACOUSTIC_LEVEL_BYPASS) {
+
+ //
+ // Get the rcommended value
+ //
+ Data8 = (UINT8)(SataDevInterface->IdentifyData.Acoustic_Level_94 >> 8);
+ }
+
+ CommandStructure.Features = ACOUSTIC_MANAGEMENT_ENABLE;
+ CommandStructure.SectorCount = Data8;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+
+ } else {
+
+ //
+ // If already disabled, nothing to do
+ //
+ if (SataDevInterface->IdentifyData.Command_Set_Enabled_86 & 0x200) {
+ CommandStructure.Features = ACOUSTIC_MANAGEMENT_DISABLE;
+ CommandStructure.SectorCount = 0;
+ Status = ExecuteNonDataCommand (SataDevInterface, CommandStructure);
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+#endif // ACOUSTIC_MANAGEMENT_SUPPORT ends
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DMACapable
+//
+// Description: Check if DMA is supported
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// TRUE : DMA Capable
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check the Identify Data to check if device supports DMA
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+BOOLEAN
+DMACapable(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+
+ if (SataDevInterface->DeviceType == ATAPI){
+ //For Atapi Devices check Bit 8 in Word 49 = DMA Supported or not
+ if((SataDevInterface->IdentifyData.Capabilities_49 & 0x100) == 0) return FALSE;
+ }
+
+ if ( (SataDevInterface->UDma != 0xff) ||
+ (SataDevInterface->MWDma != 0xff))
+ return TRUE;
+ else
+ return FALSE;
+
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DiskInfoInquiry
+//
+// Description: Return ATAPI Inquiry data
+//
+// Input:
+// IN EFI_DISK_INFO_PROTOCOL *This,
+// IN OUT VOID *InquiryData,
+// IN OUT UINT32 *InquiryDataSize
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitSataDiskInfo
+//
+// Notes:
+// 1. Check for Atapi Device. If not exit
+// 2. COpy the Inquiry Data from AtapiDevice->InquiryData to the input pointer.
+//
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+DiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+)
+{
+
+ SATA_DEVICE_INTERFACE *SataDevInterface = ((SATA_BLOCK_IO *)This)->SataDevInterface;
+ ATAPI_DEVICE *AtapiDevice = SataDevInterface->AtapiDevice;
+
+ //
+ // Check for ATAPI device. If not return EFI_NOT_FOUND
+ //
+ if (SataDevInterface->DeviceType == ATA){
+ return EFI_NOT_FOUND; // ATA device
+ }
+ else {
+ if (*InquiryDataSize < AtapiDevice->InquiryDataSize) {
+ *InquiryDataSize = AtapiDevice->InquiryDataSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ if (AtapiDevice->InquiryData != NULL) {
+ pBS->CopyMem (InquiryData, AtapiDevice->InquiryData, AtapiDevice->InquiryDataSize);
+ *InquiryDataSize = AtapiDevice->InquiryDataSize;
+ return EFI_SUCCESS;
+ }
+ else return EFI_NOT_FOUND;
+ }
+}
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DiskInfoIdentify
+//
+// Description: Return Identify Data
+//
+// Input:
+// EFI_DISK_INFO_PROTOCOL *This,
+// IN OUT VOID *IdentifyData,
+// IN OUT UINT32 *IdentifyDataSize
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitSataDiskInfo
+//
+// Notes:
+// 1. Return the Identify command data.
+//
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+DiskInfoIdentify (
+ EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+{
+
+ SATA_DEVICE_INTERFACE *SataDevInterface = ((SATA_BLOCK_IO *)This)->SataDevInterface;
+
+ if (*IdentifyDataSize < sizeof (IDENTIFY_DATA)) {
+ *IdentifyDataSize = sizeof (IDENTIFY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // ATA devices identify data might be changed because of the SetFeature command,
+ // So read the data from the device again by sending identify command.
+ //
+ if(SataDevInterface->DeviceType == ATA){
+ GetIdentifyData(SataDevInterface);
+ }
+
+ pBS->CopyMem (IdentifyData, &(SataDevInterface->IdentifyData), sizeof (IDENTIFY_DATA));
+ *IdentifyDataSize = sizeof (IDENTIFY_DATA);
+ return EFI_SUCCESS;
+
+}
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DiskInfoSenseData
+//
+// Description: Return InfoSenseData.
+//
+// Input:
+// EFI_DISK_INFO_PROTOCOL *This,
+// VOID *SenseData,
+// UINT32 *SenseDataSize,
+// UINT8 *SenseDataNumber
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitSataDiskInfo
+//
+// Notes:
+// 1. Return the Sense data for the Atapi device.
+//
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+DiskInfoSenseData(
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT VOID *SenseData,
+ OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+
+{
+
+ return EFI_NOT_FOUND;
+
+}
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: DiskInfoWhichIDE
+//
+// Description: Returns info about where the device is connected.
+//
+// Input:
+// IN EFI_DISK_INFO_PROTOCOL *This,
+// OUT UINT32 *IdeChannel,
+// OUT UINT32 *IdeDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitSataDiskInfo
+//
+// Notes:
+// 1. Return Port and PMPort
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+DiskInfoWhichIDE
+(
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+{
+
+ SATA_DEVICE_INTERFACE *SataDevInterface = ((SATA_BLOCK_IO *)This)->SataDevInterface;
+
+ *IdeChannel = SataDevInterface->PortNumber;
+ *IdeDevice = SataDevInterface->PMPortNumber == 0xFF ? 0 : SataDevInterface->PMPortNumber;
+ return EFI_SUCCESS;
+
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciBus.h b/Core/EM/Ahci/AhciBus.h
new file mode 100644
index 0000000..c557262
--- /dev/null
+++ b/Core/EM/Ahci/AhciBus.h
@@ -0,0 +1,919 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciBus.h 18 6/25/14 10:04a Anandakrishnanl $
+//
+// $Revision: 18 $
+//
+// $Date: 6/25/14 10:04a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciBus.h $
+//
+// 18 6/25/14 10:04a Anandakrishnanl
+// [TAG] EIP170118
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] MDAT can't program correctly in AHCI module
+// [RootCause] Identify Data Word 76_79 Offset for DiPM Support/Enabled
+// is incorrect for validation
+// [Solution] Changed separating DiPM and Device Sleep into two routines
+// and also modified the tokens to disable both support by default .
+// Corrected Identify data validations.
+// [Files] AhciBus.c
+// AhciBus.h
+// AhciSrc.sdl
+// PAhciBus.h
+// PIDEBus.h
+//
+// 17 1/27/14 4:56a Rameshr
+// [TAG] EIP148180
+// [Category] Improvement
+// [Description] change from EFI_MBR_WRITE_PROTECTION_PROTOCOL to
+// AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL
+// [Files] Ahcibus.c, Ahcibus.h, AhciComponentName.c, AhciController.c
+//
+// 16 12/18/13 3:21a Srikantakumarp
+// [TAG] EIP127356
+// [Category] Improvement
+// [Description] Flash NVRAM seems to cause HDD can't be unlocked when
+// S3 resume.
+// [Files] IdeSecurity.c, IDESMM.c, HddPassword.c, AhciBus.c, AhciBus.h
+//
+// 15 8/27/13 4:18a Rameshr
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] MbrWriteProtectionProtocol file name changesd to
+// AmiMbrWriteProtectionProtocol.h
+// [Files] AhciController.c, AhciBus.h, Ahcibus.c
+//
+// 14 7/23/13 11:54p Srikantakumarp
+// [TAG] EIP129989
+// [Category] Improvement
+// [Description] Added DIPM support in Aptio 4.x AHCIBUS driver.
+// [Files] AhciBus.c, AhciBus.h, AhciController.h, AhciSrc.sdl,
+// PAhciBus.h
+//
+// 13 7/22/13 2:07a Rameshr
+// [TAG] EIP129028
+// [Category] Improvement
+// [Description] Implement the POWERUP_IN_STANDBY_MODE support in
+// AHCIBUS driver
+// [Files] Ahcibus.c, Ahcibus.h, Pahcibus.h
+//
+// 12 7/18/13 4:22a Rameshr
+// [TAG] EIP127919
+// [Category] Improvement
+// [Description] "Device is Atapi" bit of PxCMD will be set if the ATAPI
+// device connected on the Port and "Drive LED on ATAPI" Enabled by AHCI
+// platform policy
+// [Files] Pahcibus.h, Ahcibus.c, Ahcibus.h
+//
+// 11 7/20/12 6:10a Anandakrishnanl
+// [TAG] EIP88683
+// [Category] New Feature
+// [Description] EFI_ATA_PASS_THRU_PROTOCOL Support for Aptio IDE
+// [Files] AhciBus.c
+// AhciBus.h
+// AInt13.h
+// IdeBus.c
+// IdeBus.h
+// PIDEBus.h
+// PAhciBus.h
+// AtaPassThru.sdl
+// AtaPassThru.mak
+// AtaPassThru.c
+// AtaPassThruSupport.h
+// AtaPassThru.chm
+//
+// 10 9/27/11 3:02a Rajeshms
+// [TAG] EIP69295
+// [Category] Improvement
+// [Description] The Timeout values used by IDE and AHCI drivers are
+// made as SDL tokens, so that the timeout values can be varied.
+// [Files] IdeBusBoard.c, CORE_DXE.sdl, AhciSmm.h, AhciBus.h, IDESMM.h,
+// Ata.c, Atapi.c, IdeBus.c, IdeBus.h, IdeBusMaster.c, IdeBusBoard.h
+//
+// 9 9/19/11 3:05a Lavanyap
+// [TAG] EIP69398
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Function ConfigureController() has a runtime error (NULL
+// pointer dereference)
+// [RootCause] variable SupportedModes has been initialized again in
+// ConfigureController().
+// [Solution] variable SupportedModes is passed as an input parameter
+// for ConfigureController() and ConfigureDevice().
+// [Files] AhciBus.c, AhciBus.h
+//
+// 8 2/11/11 4:23a Rameshr
+// [TAG] EIP53730
+// [Category] Improvement
+// [Description] Add Odd Loading type information into ATAPI_DEVICE
+// structure in AHCI mode
+// [Files] AhciBus.c
+// AhciController.c
+// AhciBus.h
+//
+// 7 2/10/11 10:35a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSrc.mak
+// AhciBus.c
+// AhciController.c
+// AhciComponentName.c
+// AhciBus.h
+// AhciController.h
+//
+// 6 12/23/10 3:59a Lavanyap
+// [TAG] - EIP41445
+// [Category] - NEW FEATURE
+// [Description] - Created SataPioDataOut and AtaPioDataOut protocol
+// function that can accept additional input parameters.
+// [Files] - AhciBus.h, AhciBus.c, AhciController.c, Ata.c, IdeBus.c,
+// IdeBus.h, IdeBusMaster.c,PAhciBus.h, PIdeBus.h
+//
+// 5 5/07/10 11:45a Krishnakumarg
+// Coding standard update
+//
+// 4 6/22/09 11:34a Rameshr
+// Odd Type information Saved in Atapi Device Structure.
+// EIP:21548
+//
+// 3 4/28/09 3:58p Rameshr
+//
+// HDD password support in RAID mode
+// EIP:20421
+//
+// 2 5/28/08 9:39a Rameshraju
+// Based on the SDL token index/data or MMIO method used to access the
+// AHCI configuration space.
+//
+// 1 28/02/08 6:03p Anandakrishnanl
+// AHCI Bus Driver initial check-in.
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AhciBus.h
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifndef _AhciBus_
+#define _AhciBus_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Efi.h>
+#include <Token.h>
+#include <Dxe.h>
+#include <AmiDxeLib.h>
+#include "Protocol\PciIo.h"
+#include "Protocol\DevicePath.h"
+#include "protocol\DriverBinding.h"
+#include "protocol\BlockIo.h"
+#include "Protocol\PDiskInfo.h"
+#include "Protocol\PIDEController.h"
+#include "Protocol\PIDEBus.h"
+#include <Protocol\ComponentName.h>
+#include <Protocol\BootScriptSave.h>
+#include <Protocol\PAhciBus.h>
+#include <protocol\AtaPassThru.h>
+#include <protocol\StorageSecurityCommand.h>
+#include "AhciController.h"
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+#include <Protocol\AmiBlockIoWriteProtection.h>
+#endif
+
+#define TRACE_AHCI_LEVEL2
+#define TRACE_AHCI TRACE
+
+#ifdef Debug_Level_1
+VOID EfiDebugPrint (IN UINTN ErrorLevel,IN CHAR8 *Format,...);
+#endif
+
+#define AHCI_BUS_DRIVER_VERSION 0x01
+#define ONE_MILLISECOND 1000
+
+#define COMMAND_LIST_SIZE_PORT 0x800
+
+#ifndef ATAPI_BUSY_CLEAR_TIMEOUT
+#define ATAPI_BUSY_CLEAR_TIMEOUT 16000 // 16sec
+#endif
+
+#ifndef S3_BUSY_CLEAR_TIMEOUT
+#define S3_BUSY_CLEAR_TIMEOUT 10000 // 10Sec
+#endif
+
+#define BUSY_CLEAR_TIMEOUT 1000 // 1Sec
+#define DRDY_TIMEOUT 1000 // 1Sec
+#define DRQ_TIMEOUT 10 // 10msec
+#define DRQ_CLEAR_TIMEOUT 1000 // 1sec
+#define DRQ_SET_TIMEOUT 10 // 10msec
+#define HP_COMMAND_COMPLETE_TIMEOUT 2000 // 2Sec
+#define COMMAND_COMPLETE_TIMEOUT 5000 // 5Sec
+
+#ifndef DMA_ATA_COMMAND_COMPLETE_TIMEOUT
+#define DMA_ATA_COMMAND_COMPLETE_TIMEOUT 5000 // 5Sec
+#endif
+
+#ifndef DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT
+#define DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT 16000 // 16Sec
+#endif
+
+#ifndef ATAPI_RESET_COMMAND_TIMEOUT
+#define ATAPI_RESET_COMMAND_TIMEOUT 5000
+#endif
+
+#ifndef POWERON_BUSY_CLEAR_TIMEOUT
+#define POWERON_BUSY_CLEAR_TIMEOUT 10000 // 10 Sec
+#endif
+
+#define TIMEOUT_1SEC 1000 // 1sec Serial ATA 1.0 Sec 5.2
+
+
+
+#define BLKIO_REVISION 1
+
+#define DEVICE_DISABLED 0
+#define DEVICE_IN_RESET_STATE 1
+#define DEVICE_DETECTION_FAILED 2
+#define DEVICE_DETECTED_SUCCESSFULLY 3
+#define DEVICE_CONFIGURED_SUCCESSFULLY 4
+#define DEVICE_REMOVED 5
+#define CONTROLLER_NOT_PRESENT 0xff
+
+#define ENUMERATE_ALL 0xff
+#define ENUMERATE_PRIMARY_MASTER 0x0
+#define ENUMERATE_PRIMARY_SLAVE 0x1
+#define ENUMERATE_SECONDARY_MASTER 0x2
+#define ENUMERATE_SECONDARY_SLAVE 0x3
+#define INQUIRY_DATA_LENGTH 0x96
+#define READ_CAPACITY_DATA_LENGTH 0x08
+
+// PCI Config Space equates
+#define PROGRAMMING_INTERFACE_OFFSET 0x09
+#define IDE_SUB_CLASS_CODE 0x0A
+ #define SCC_IDE_CONTROLLER 0x01
+ #define SCC_AHCI_CONTROLLER 0x06
+ #define SCC_RAID_CONTROLLER 0x04
+#define IDE_BASE_CLASS_CODE 0x0B
+ #define BASE_CODE_IDE_CONTROLLER 0x01
+#define PRIMARY_COMMAND_BLOCK_OFFSET 0x10
+#define PRIMARY_CONTROL_BLOCK_OFFSET 0x14
+#define SECONDARY_COMMAND_BLOCK_OFFSET 0x18
+#define SECONDARY_CONTROL_BLOCK_OFFSET 0x1C
+#define LEGACY_BUS_MASTER_OFFSET 0x20
+
+#define EFI_SUCCESS_ACTIVE_SET 0x80000000
+
+
+EFI_STATUS
+CreateIdeDevicePath (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface,
+ IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ UINT8 Current_Channel,
+ UINT8 Current_Device
+);
+
+EFI_STATUS
+InitIdeBlockIO (
+ IDE_BUS_PROTOCOL *IdeBusInterface
+);
+
+EFI_STATUS
+InitIdeDiskInfo (
+ IDE_BUS_PROTOCOL *IdeBusInterface
+);
+
+EFI_STATUS
+InstallAhciBusProtocol (
+ IN EFI_HANDLE Controller,
+ AHCI_BUS_PROTOCOL *IdeBusInitInterface,
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ EFI_PCI_IO_PROTOCOL *PciIO
+);
+
+EFI_STATUS
+AhciInitController (
+ AHCI_BUS_PROTOCOL *AhciBusInterface
+);
+
+EFI_STATUS
+CheckPortImplemented (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ UINT8 Port
+);
+
+EFI_STATUS
+AhciDetectDevice (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ UINT8 Port,
+ UINT8 PMPortNumber
+);
+
+EFI_STATUS
+CheckDevicePresence (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ UINT8 Port,
+ UINT8 PMPort
+);
+
+EFI_STATUS
+CheckPMDevicePresence (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ UINT8 Port,
+ UINT8 PMPort
+);
+
+EFI_STATUS
+ConfigureDevice (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ EFI_ATA_COLLECTIVE_MODE **SupportedModes
+);
+
+EFI_STATUS
+ConfigureController (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ EFI_ATA_COLLECTIVE_MODE *SupportedModes
+);
+
+VOID
+InitializeDipm(
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+VOID
+InitializeDeviceSleep (
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+HostReset (
+ AHCI_BUS_PROTOCOL *AhciBusInterface
+);
+
+
+EFI_STATUS
+GeneratePortReset (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 Port,
+ UINT8 PMPort,
+ UINT8 Speed,
+ UINT8 PowerManagement
+);
+
+EFI_STATUS
+GenerateSoftReset (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 PMPort
+);
+
+EFI_STATUS
+GetIdentifyData (
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+HandlePortComReset(
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 Port,
+ UINT8 PMPort
+);
+
+EFI_STATUS
+CheckValidDevice (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ UINT8 Port,
+ UINT8 PMPort
+);
+
+SATA_DEVICE_INTERFACE*
+GetSataDevInterface(
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ UINT8 Port,
+ UINT8 PMPort
+);
+
+EFI_STATUS
+ExecuteNonDataCommand (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_STRUCTURE CommandStructure
+);
+
+EFI_STATUS
+ExecutePioDataCommand (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_STRUCTURE *CommandStructure,
+ BOOLEAN READWRITE
+);
+
+EFI_STATUS
+ExecuteDmaDataCommand (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_STRUCTURE *CommandStructure,
+ BOOLEAN READWRITE
+);
+
+EFI_STATUS
+SataReadWritePio(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE
+) ;
+
+EFI_STATUS
+SataPioDataOut (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT8 Features,
+ IN UINT8 LBALow,
+ IN UINT8 LBALowExp,
+ IN UINT8 LBAMid,
+ IN UINT8 LBAMidExp,
+ IN UINT8 LBAHigh,
+ IN UINT8 LBAHighExp,
+ IN UINT8 Command,
+ IN BOOLEAN READWRITE
+) ;
+
+EFI_STATUS
+WaitforCommandComplete (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_TYPE CommandType,
+ UINTN TimeOut
+);
+
+UINT8
+ReturnMSBset(
+ UINT32 Data
+);
+
+EFI_STATUS
+StartController (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT32 CIBitMask
+);
+
+EFI_STATUS
+ReadytoAcceptCmd (
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+StopController(
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ BOOLEAN StartOrStop
+) ;
+
+EFI_STATUS
+DetectAndConfigureDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInterface,
+ UINT8 Port,
+ UINT8 PMPort
+);
+
+EFI_STATUS
+ConfigurePMPort (
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+ReadWritePMPort (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 Port,
+ UINT8 RegNum,
+ UINT32 *Data,
+ BOOLEAN READWRITE
+);
+
+UINT32
+ReadSCRRegister (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 Port,
+ UINT8 PMPort,
+ UINT8 Register
+);
+
+EFI_STATUS
+WriteSCRRegister (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 Port,
+ UINT8 PMPort,
+ UINT8 Register,
+ UINT32 Data32
+);
+
+EFI_STATUS
+WritePMPort (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 Port,
+ UINT8 RegNum,
+ UINT32 Data
+);
+
+EFI_STATUS
+BuildCommandList (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ AHCI_COMMAND_LIST *CommandList,
+ UINT32 CommandTableBaseAddr
+);
+
+EFI_STATUS
+BuildCommandFIS (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_STRUCTURE CommandStructure,
+ AHCI_COMMAND_LIST *CommandList,
+ AHCI_COMMAND_TABLE *Commandtable
+);
+
+EFI_STATUS
+BuildAtapiCMD(
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_STRUCTURE CommandStructure,
+ AHCI_COMMAND_LIST *CommandList,
+ AHCI_COMMAND_TABLE *Commandtable
+);
+
+EFI_STATUS
+BuildPRDT
+(
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_STRUCTURE CommandStructure,
+ AHCI_COMMAND_LIST *CommandList,
+ AHCI_COMMAND_TABLE *Commandtable
+);
+
+EFI_STATUS
+WaitForMemSet (
+ IN UINT32 BaseAddr,
+ IN UINT8 Port,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 TestValue,
+ IN UINT32 WaitTimeInMs
+);
+
+EFI_STATUS
+WaitforPMMemSet (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT8 PMPort,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 TestValue,
+ IN UINT32 WaitTimeInMs
+);
+
+EFI_STATUS
+WaitForMemClear (
+ IN UINT32 BaseAddr,
+ IN UINT8 Port,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 WaitTimeInMs
+);
+
+EFI_STATUS
+CreateSataDevicePath (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+);
+
+EFI_STATUS
+InitSataBlockIO (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+InitSataDiskInfo (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+InitAcousticSupport (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+InitSMARTSupport (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+SMARTReturnStatusWrapper(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+ConfigurePowerUpInStandby (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+AhciBusSupported(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+);
+
+EFI_STATUS
+AhciBusStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+);
+
+EFI_STATUS
+AhciBusStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+);
+
+
+EFI_STATUS
+DiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+);
+
+EFI_STATUS
+DiskInfoIdentify (
+ EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+);
+
+EFI_STATUS
+DiskInfoSenseData(
+ EFI_DISK_INFO_PROTOCOL *This,
+ VOID *SenseData,
+ UINT32 *SenseDataSize,
+ UINT8 *SenseDataNumber
+);
+
+EFI_STATUS
+DiskInfoWhichIDE
+(
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+);
+
+#define ZeroMemory(Buffer,Size) pBS->SetMem(Buffer,Size,0)
+
+
+BOOLEAN
+DMACapable(
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+SataBlkRead(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+);
+
+EFI_STATUS
+SataBlkWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+);
+
+EFI_STATUS
+SataAtaBlkReadWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer,
+ BOOLEAN READWRITE
+);
+
+EFI_STATUS
+SataAtapiBlkRead(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+);
+
+EFI_STATUS
+SataAtapiBlkWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+);
+
+EFI_STATUS
+SataReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+);
+
+EFI_STATUS
+SataBlkFlush(
+ IN EFI_BLOCK_IO_PROTOCOL *This
+);
+
+EFI_STATUS
+SataReadWriteBusMaster(
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE
+);
+
+EFI_STATUS
+SataAtapiInquiryData (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 *InquiryData,
+ UINT16 *InquiryDataSize
+);
+
+EFI_STATUS
+DetectAtapiMedia(
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+TestUnitReady(
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+ExecutePacketCommand (
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ COMMAND_STRUCTURE *CommandStructure,
+ BOOLEAN READWRITE
+);
+
+EFI_STATUS
+SataAtapiBlkReadWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer,
+ BOOLEAN READWRITE
+);
+
+EFI_STATUS
+HandleAtapiError (
+ SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+BOOLEAN
+Check48BitCommand (
+ IN UINT8 Command
+);
+
+EFI_STATUS
+InitSMARTSupport (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+SMARTReturnStatusWrapper(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+EFI_STATUS
+SataGetOddType (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT UINT16 *OddType
+);
+
+EFI_STATUS
+SataGetOddLoadingType (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT UINT8 *OddLoadingType
+);
+
+ODD_TYPE
+GetEnumOddType(
+ IN UINT16 OddType
+);
+
+EFI_STATUS
+ConfigureSataPort (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+);
+
+
+#if INDEX_DATA_PORT_ACCESS
+UINT32
+ReadDataDword(
+ IN UINTN BaseAddr,
+ IN UINTN Index
+);
+
+UINT16
+ReadDataWord(
+ IN UINTN BaseAddr,
+ IN UINTN Index
+);
+
+UINT8
+ReadDataByte(
+ IN UINTN BaseAddr,
+ IN UINTN Index
+);
+
+VOID
+WriteDataDword(
+ IN UINTN BaseAddr,
+ IN UINTN Index,
+ IN UINTN Data
+);
+
+VOID
+WriteDataWord(
+ IN UINTN BaseAddr,
+ IN UINTN Index,
+ IN UINTN Data
+);
+
+VOID
+WriteDataByte(
+ IN UINTN BaseAddr,
+ IN UINTN Index,
+ IN UINTN Data
+);
+#endif
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciComponentName.c b/Core/EM/Ahci/AhciComponentName.c
new file mode 100644
index 0000000..1d68ea5
--- /dev/null
+++ b/Core/EM/Ahci/AhciComponentName.c
@@ -0,0 +1,314 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciComponentName.c 7 1/27/14 4:57a Rameshr $
+//
+// $Revision: 7 $
+//
+// $Date: 1/27/14 4:57a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciComponentName.c $
+//
+// 7 1/27/14 4:57a Rameshr
+// [TAG] EIP148180
+// [Category] Improvement
+// [Description] Change from EFI_MBR_WRITE_PROTECTION_PROTOCOL to
+// AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL
+// [Files] Ahcibus.c, Ahcibus.h, AhciComponentName.c, AhciController.c
+//
+// 6 2/10/11 10:35a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSrc.mak
+// AhciBus.c
+// AhciController.c
+// AhciComponentName.c
+// AhciBus.h
+// AhciController.h
+//
+// 5 5/07/10 11:45a Krishnakumarg
+// Coding standard update
+//
+// 4 3/26/10 5:37p Krishnakumarg
+// UEFI2.1 compliance change EIP#34744.
+//
+// 3 4/28/09 3:57p Rameshr
+//
+// HDD password support in RAID mode
+// EIP:20421
+//
+// 2 5/28/08 9:39a Rameshraju
+//
+// 1 28/02/08 6:03p Anandakrishnanl
+// AHCI Bus Driver initial check-in.
+//
+//
+//
+//**********************************************************************
+
+#include "AhciBus.h"
+
+extern EFI_GUID gSecurityModeProtocolGuid;
+static EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+extern EFI_DRIVER_BINDING_PROTOCOL gAhciBusDriverBinding;
+
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#define LANGUAGE_CODE_ENGLISH "eng"
+#define EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL
+#endif
+
+EFI_STATUS AhciBusCtlDriverName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+);
+
+EFI_STATUS
+AhciBusCtlGetControllerName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+);
+
+
+CHAR16 *gAhciBusDriverName = L"AMI AHCI BUS Driver";
+CHAR16 *gAhciBusControllerName = L"AHCI Mass Storage Controller";
+
+//==================================================================================
+EFI_COMPONENT_NAME2_PROTOCOL gAhciBusControllerDriverName = {
+ AhciBusCtlDriverName,
+ AhciBusCtlGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: AhciBusCtlDriverName
+//
+// DESCRIPTION: Retrieves a Unicode string that is the user readable name of
+// the EFI Driver.
+//
+//
+// PARAMETERS:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// Language - A pointer to a three character ISO 639-2 language identifier.
+// This is the language of the driver name that that the caller
+// is requesting, and it must match one of the languages specified
+// in SupportedLanguages. The number of languages supported by a
+// driver is up to the driver writer.
+// DriverName - A pointer to the Unicode string to return. This Unicode string
+// is the name of the driver specified by This in the language
+// specified by Language.
+//
+// RETURN:
+// EFI_SUCCES - The Unicode string for the Driver specified by This
+// and the language specified by Language was returned
+// in DriverName.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - DriverName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciBusCtlDriverName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+)
+{
+ //
+ //Supports only English
+ //
+ if(!Language || !DriverName) return EFI_INVALID_PARAMETER;
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) return EFI_UNSUPPORTED;
+ *DriverName = gAhciBusDriverName;
+ return EFI_SUCCESS;
+}
+
+
+
+//---------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// FUNCTION: AhciBusCtlGetControllerName
+//
+// DESCRIPTION: Retrieves a Unicode string that is the user readable name of
+// the controller that is being managed by an EFI Driver.
+//
+// PARAMETERS:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// ControllerHandle - The handle of a controller that the driver specified by
+// This is managing. This handle specifies the controller
+// whose name is to be returned.
+// ChildHandle - The handle of the child controller to retrieve the name
+// of. This is an optional parameter that may be NULL. It
+// will be NULL for device drivers. It will also be NULL
+// for a bus drivers that wish to retrieve the name of the
+// bus controller. It will not be NULL for a bus driver
+// that wishes to retrieve the name of a child controller.
+// Language - A pointer to a three character ISO 639-2 language
+// identifier. This is the language of the controller name
+// that that the caller is requesting, and it must match one
+// of the languages specified in SupportedLanguages. The
+// number of languages supported by a driver is up to the
+// driver writer.
+// ControllerName - A pointer to the Unicode string to return. This Unicode
+// string is the name of the controller specified by
+// ControllerHandle and ChildHandle in the language
+// specified by Language from the point of view of the
+// driver specified by This.
+//
+// RETURNS:
+// EFI_SUCCESS - The Unicode string for the user readable name in the
+// language specified by Language for the driver
+// specified by This was returned in DriverName.
+// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
+// EFI_HANDLE.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - ControllerName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This is not currently
+// managing the controller specified by
+// ControllerHandle and ChildHandle.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//<AMI_PHDR_END>
+//---------------------------------------------------------------------------
+
+
+EFI_STATUS
+AhciBusCtlGetControllerName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+)
+{
+
+ EFI_STATUS Status;
+ SATA_DEVICE_INTERFACE *SataDevInterface;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ SECURITY_PROTOCOL *AhciSecurityInterface;
+ UINTN j, InfoCount;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *pInfo;
+
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ NULL,
+ gAhciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ //Supports only "eng"
+ //
+ if(!Language || !ControllerName) return EFI_INVALID_PARAMETER;
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) return EFI_UNSUPPORTED;
+
+ if (ChildHandle == NULL) {
+ *ControllerName = gAhciBusControllerName;
+ return EFI_SUCCESS;
+ }
+ else {
+ Status = pBS->OpenProtocolInformation(
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ &pInfo,&InfoCount
+ );
+ if (EFI_ERROR(Status)) return EFI_UNSUPPORTED;
+ for(j=0; j<InfoCount; j++) {
+ if (pInfo[j].Attributes!=EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) continue;
+ if (pInfo[j].ControllerHandle==ChildHandle) break;
+ }
+ if (InfoCount) pBS->FreePool(pInfo);
+ if (j >= InfoCount) return EFI_UNSUPPORTED;
+
+ //
+ // Open the BLOCK_IO protocol installed on the child device.
+ //
+ Status = pBS->OpenProtocol ( ChildHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **)&BlkIo,
+ gAhciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+
+ if (EFI_ERROR(Status)) {
+ //
+ // If BLKIO protocol is not installed, maybe Securitymode
+ // protocol is installed.
+ //
+ Status = pBS->OpenProtocol ( ChildHandle,
+ &gSecurityModeProtocolGuid,
+ (VOID **)&AhciSecurityInterface,
+ gAhciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ //
+ // Return Error.
+ //
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ SataDevInterface = AhciSecurityInterface->BusInterface;
+ }else {
+ SataDevInterface = ((SATA_BLOCK_IO *)BlkIo)->SataDevInterface;
+ }
+ if (SataDevInterface->IdeDeviceHandle != ChildHandle) return EFI_UNSUPPORTED;
+
+ *ControllerName = SataDevInterface->UDeviceName->UnicodeString;
+ return EFI_SUCCESS;
+ }
+
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciController.c b/Core/EM/Ahci/AhciController.c
new file mode 100644
index 0000000..73d6c31
--- /dev/null
+++ b/Core/EM/Ahci/AhciController.c
@@ -0,0 +1,3403 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciController.c 41 1/27/14 4:57a Rameshr $
+//
+// $Revision: 41 $
+//
+// $Date: 1/27/14 4:57a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciController.c $
+//
+// 41 1/27/14 4:57a Rameshr
+// [TAG] EIP148180
+// [Category] Improvement
+// [Description] Change from EFI_MBR_WRITE_PROTECTION_PROTOCOL to
+// AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL
+// [Files] Ahcibus.c, Ahcibus.h, AhciComponentName.c, AhciController.c
+//
+// 40 12/20/13 4:06a Rameshr
+// [TAG] EIP126640
+// [Category] Improvement
+// [Description] AHCIBUS driver need to preserve the port settings in
+// GeneratePortReset
+// [Files] Ahcibus.c, AhciController.c
+//
+// 39 8/27/13 4:16a Rameshr
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] MbrWriteProtectionProtocol file name changesd to
+// AmiMbrWriteProtectionProtocol.h
+// [Files] AhciController.c, AhciBus.h, Ahcibus.c
+//
+// 38 7/01/13 5:32a Kapilporwal
+// [TAG] EIP125560
+// [Category] Improvement
+// [Description] Please support Boot Sector Virus Protection for CSM
+// Disabled Mode
+// [Files] VirusProtect.c, VirusProtect.dxs, AhciBus.c,
+// AhciController.c, CsmBlockIo.c, CsmInt13.c, Ata.c, IdeBus.c,
+// SdioBlkIo.c, SdioDriver.c, efiusbmass.c
+//
+// 37 11/18/12 11:45p Rameshr
+// [TAG] EIP102518
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] SCT failure for ATAPI BlockIO
+// [RootCause] BufferSize and IOAllign checking not added for Atapi
+// BlockIO protocol functions
+// [Solution] Added BufferSize and IOAllign checking for Atapi BlockIO
+// protocol functions
+// [Files] AhciController.c
+//
+// 36 9/17/12 12:52a Rameshr
+// [TAG] EIP100335
+// [Category] Improvement
+// [Description] Port Multiplier spend long time to connect device.
+// [Files] Ahcibus.c , AhciController.c
+//
+// 35 9/17/12 12:43a Anandakrishnanl
+// [TAG] EIP100847
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System hangs when Memory allocation >4Gb in AHCI Mode
+// [RootCause] DBAU not programmed for AhciController
+// [Solution] Fixed by Programming DBAU in PRDT Table
+// [Files] AhciController.c
+//
+// 34 8/21/12 2:28a Rameshr
+// [TAG] EIP98526
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] FIS and CommandList Base address store and restore wont
+// work incase of recursive call
+// [RootCause] FIS and CommandList Base address store and restore wont
+// work incase of recursive call
+// [Solution] FIS and Command List base Address save and restore done
+// properly when the function called recursively.
+// [Files] Ahcicontroller.c
+//
+// 33 8/17/12 3:10a Srikantakumarp
+// [TAG] EIP95863
+// [Category] Bug Fix
+// [Symptom] AhciSmm doesnt save and restore the upper 32bits of FBU and
+// CLBU
+// [RootCause] As Windows uses the 64bit address for FIS Base Address
+// and Command List Base Address, and AHCISMM driver doesn't take care of
+// the upper 32bit value of those which cause the failure in AhciSMM
+// driver.
+// [Solution] Save and Restore the upper 32bits of FBU and CLBU in
+// AhciSmm Driver.
+// [Files] AhciController.c, AhciSmm.c
+//
+// 32 8/16/12 3:06a Rajeshms
+// [TAG] EIP97048
+// [Category] New Feature
+// [Description] ATAPI PassThru Support using
+// EFI_EXT_SCSI_PASS_THRU_PROTOCOL.
+// [Files] AhciBus.c, AhciController.c, IdeBus.c, Atapi.c, PIDEBus.h,
+// PAhciBus.h, ScsiPassThruAtapi.sdl, ScsiPassThruAtapi.mak,
+// ScsiPassThruAtapi.c, ScsiPassThruAtapiSupport.h, ScsiPassThruAtapi.chm,
+// ScsiPassThruExt.h
+//
+// 31 2/03/12 3:23a Rameshr
+// [TAG] EIP82275
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] SataReadWritePio doesn't work if the ReadSector count is
+// more than 256 sectors
+// [RootCause] Buffer Address not incremented for the next Read
+// [Solution] Handled the buffer address properly for the next Pio Read
+// [Files] AhciController.c
+//
+// 30 11/08/11 5:19a Deepthins
+// [TAG] EIP74607
+// [Category] Improvement
+// [Description] Block IO Read/Write function, the alignment should be
+// proper. IoAlign value is 0 or 1 means that the buffer can be placed
+// anywhere in memory. Otherwise, IoAlign must be a power of 2, and the
+// requirement is that the start address of a buffer must be evenly
+// divisible by IoAlign with no remainder.
+// [Files] Ata.c, Atapi.c and AhciController.c
+//
+// 29 11/07/11 4:31a Deepthins
+// [TAG] EIP74607
+// [Category] Improvement
+// [Description] IoAlign value is 0 or 1 means that the buffer can be
+// placed anywhere in memory. Otherwise, IoAlign must be a power of 2, and
+// the requirement is that the start address of a buffer must be
+// evenlydivisible by 2 to the power of IoAlign with no remainder.
+// [Files] AhciController.c
+//
+// 28 11/07/11 2:30a Deepthins
+// [TAG] EIP73941
+// [Category] Improvement
+// [Description] BufferSize is 0, ReadBlock function should return
+// EFI_SUCCESS without actual reading.
+// [Files] AhciController.c
+//
+// 27 5/09/11 6:29a Anandv
+// [TAG] - EIP59552
+// [Category] - BUG FIX
+// [Severity] - Normal
+// [Symptom] -AhciController.c file in Ahci driver needs modification to
+// Support Index/Data Port access method for getting the FIS Address.
+// [RootCause] - FISAddress was Obtained using MMIO method irrespective of
+// "INDEX_DATA_PORT_ACCESS" SDL token.
+// [Solution] - FISAddress is now obtained using Port I/O or MMIO method
+// depending on
+// "INDEX_DATA_PORT_ACCESS" SDL token.
+// [Files] - AhciController.c
+//
+// 26 3/29/11 1:03a Lavanyap
+// [TAG] - EIP53849
+// [Category] - BUG FIX
+// [Severity] - Normal
+// [Symptom] - Ide Bus Sources cannot build in IA32 DEBUG mode.
+// [RootCause] - It happened because of usage of << and * with UINT64
+// values in AtaPioDataOut() and SataPioDataOut().
+// [Solution] - Shl64 and Mul64 functions have been implemented to operate
+// UINT64 values.
+// [Files] - Ata.c, AhciController.c
+//
+// 25 2/21/11 3:38a Rameshr
+// Helpbuilder Issue Resolved
+//
+// 24 2/18/11 5:06a Rameshr
+// [TAG]- EIP 37975
+// [Category]-IMPROVEMENT
+// [Description]- Klocwork Issues II - IDE/Ahci module
+// [Files]- AhciBus.c, AhciController.c
+//
+// 23 2/11/11 4:22a Rameshr
+// [TAG] EIP53730
+// [Category] Improvement
+// [Description] Add Odd Loading type information into ATAPI_DEVICE
+// structure in AHCI mode
+// [Files] AhciBus.c
+// AhciController.c
+// AhciBus.h
+//
+// 22 2/10/11 10:35a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSrc.mak
+// AhciBus.c
+// AhciController.c
+// AhciComponentName.c
+// AhciBus.h
+// AhciController.h
+//
+// 21 12/23/10 3:59a Lavanyap
+// [TAG] - EIP41445
+// [Category] - NEW FEATURE
+// [Description] - Created SataPioDataOut and AtaPioDataOut protocol
+// function that can accept additional input parameters.
+// [Files] - AhciBus.h, AhciBus.c, AhciController.c, Ata.c, IdeBus.c,
+// IdeBus.h, IdeBusMaster.c,PAhciBus.h, PIdeBus.h
+//
+// 20 4/16/10 4:15p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 19 9/22/09 10:53a Krishnakumarg
+// Code modified to update SataDevInterface->identifydata in
+// GetIdentifyData function instead of returning in global variable -
+// EIP26411
+//
+// 18 9/21/09 12:34p Krishnakumarg
+// It takes a long time to detect large size HDD(eg. 500GB, 1TB size)
+// under AHCI mode-EIP26499.
+// Replaced TAB with spaces for AMI code standard
+//
+// 17 8/12/09 5:07p Davidd
+// Corrected command parameter error in all PACKET_COMMAND - EIP 24817
+//
+// 16 6/22/09 11:35a Rameshr
+// Odd Type information Saved in Atapi Device Structure.
+// EIP:21548
+//
+// 15 6/18/09 4:27p Rameshr
+// if the Erase command timeout value is 0 or 255, wait for the Erase
+// command completion without timeout value
+// EIP:20630
+//
+// 14 4/29/09 10:54a Rameshr
+//
+// 13 4/28/09 3:51p Rameshr
+//
+// HDD password support in RAID mode
+// EIP:20421
+//
+// 12 3/29/09 11:08a Rameshr
+// Security Erase command timeout value should be from the Identify packet
+// command word 89
+// EIP 20630
+//
+// 11 12/11/08 1:55p Srinin
+// After COMRESET, wait for shadow status register to get synced up with
+// D2H FIS
+//
+// 10 26/09/08 12:32p Anandakrishnanl
+// Fixed Ahci Block Write Issue Which Exceeds 4MB. Added the Proper Offset
+// of Descriptor and Fixed Valid PRDT_I Bit.
+//
+// 9 13/08/08 2:24p Anandakrishnanl
+// Fixed the Minor error that occured in Previous Checkin for EfiDiag NO
+// Media Issue
+//
+// 8 12/08/08 11:26a Anandakrishnanl
+// Fixed the error reported by EFI Diag r(CD/DVD test) to return
+// EFI_NO_MEDIA.
+//
+// 7 5/28/08 9:38a Rameshraju
+// Based on the SDL token index/data or MMIO method used to access the
+// AHCI configuration space.
+//
+// 6 5/09/08 10:05a Rameshraju
+// Default status initilized.
+//
+// 5 4/10/08 12:52p Srinin
+// PMPort field in Command header and in FIS is set to zero instead of 0xF
+// when PORT 0 is accessed.
+//
+// 4 4/03/08 4:40p Srinin
+// In ReadytoAcceptCmd Status was not initialized. Fixed it.
+//
+// 3 3/24/08 6:19p Fasihm
+// Fixed issue that few HDDs not detected because of PhyRdy Change bit.
+//
+// 2 7/03/08 5:31p Anandakrishnanl
+// Added Smart Support as a seperate Driver and Corresponding changes to
+// invoke Smart Protocols and removed SDL-Token
+//
+// 1 28/02/08 6:03p Anandakrishnanl
+// AHCI Bus Driver initial check-in.
+//
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AhciController.c
+//
+// Description: Provides Access to AHCI Controller
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include "AhciBus.h"
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+extern AMI_BLOCKIO_WRITE_PROTECTION_PROTOCOL *AmiBlkWriteProtection;
+#endif
+
+BOOLEAN gPortReset = FALSE; // Avoid Re-entry
+BOOLEAN gSoftReset = FALSE; // Avoid Re-entry
+UINT32 gCommandListBaseAddress = 0;
+UINT32 gFisBaseAddress;
+UINT32 gCommandListBaseAddress2;
+UINT32 gFisBaseAddress2;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SataBlkRead
+//
+// Description: Read from the Sata ATA Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: SataAtaBlkReadWrite
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataBlkRead(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+
+ EFI_STATUS Status;
+
+ Status = SataAtaBlkReadWrite(This, MediaId, LBA, BufferSize, Buffer, 0);
+
+ TRACE((TRACE_ALWAYS,"AHCI Read: LBA : %lx ByteCount : %lx\n", LBA, BufferSize));
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SataBlkWrite
+//
+// Description: Write to Sata ATA Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: SataAtaBlkReadWrite
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataBlkWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+
+ EFI_STATUS Status;
+
+#if defined CORE_COMBINED_VERSION && (CORE_COMBINED_VERSION > 0x4028E)
+ if(AmiBlkWriteProtection != NULL) {
+ // Get user input
+ Status = AmiBlkWriteProtection->BlockIoWriteProtectionCheck(
+ AmiBlkWriteProtection,
+ This,
+ LBA,
+ BufferSize
+ );
+ // Abort operation if denied
+ if(Status == EFI_ACCESS_DENIED) {
+ return Status;
+ }
+ }
+#endif
+
+ Status = SataAtaBlkReadWrite(This, MediaId, LBA, BufferSize, Buffer, 1);
+
+ TRACE((TRACE_ALWAYS,"AHCI Write: LBA : %lx ByteCount : %lx\n", LBA, BufferSize));
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SataAtaBlkReadWrite
+//
+// Description: Read/Write to/from Sata ATA Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer,
+// BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: SataReadWriteBusMaster, SataReadWritePio
+//
+// Notes:
+// 1. Check for validity of the input
+// 2. Issue DMA or PIO Read/Write call.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataAtaBlkReadWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer,
+ BOOLEAN READWRITE
+)
+{
+
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ SATA_DEVICE_INTERFACE *SataDevInterface = ((SATA_BLOCK_IO *)This)->SataDevInterface;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = This->Media;
+ UINTN DataN;
+ UINTN BufferAddress;
+
+ // Check if Media ID matches
+ if (BlkMedia->MediaId != MediaId) return EFI_MEDIA_CHANGED;
+
+ if (BufferSize == 0) return EFI_SUCCESS;
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((BlkMedia->IoAlign > 1 ) && (BufferAddress % BlkMedia->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check whether the block size is multiple of BlkMedia->BlockSize
+ DataN = BufferSize % BlkMedia->BlockSize;
+ if (DataN) return EFI_BAD_BUFFER_SIZE;
+
+ // Check for Valid start LBA #
+ if (LBA > BlkMedia->LastBlock) return EFI_INVALID_PARAMETER;
+
+ // Check for Valid End LBA #
+ DataN = BufferSize / BlkMedia->BlockSize;
+ if (LBA + DataN > BlkMedia->LastBlock + 1) return EFI_INVALID_PARAMETER;
+
+ #if IDEBUSMASTER_SUPPORT
+ if (DMACapable(SataDevInterface)) {
+ Status = SataReadWriteBusMaster (SataDevInterface, Buffer, BufferSize, LBA,
+ READWRITE ? SataDevInterface->WriteCommand : SataDevInterface->ReadCommand,
+ READWRITE);
+ return Status;
+ }
+ #endif
+
+ Status = SataReadWritePio (SataDevInterface, Buffer, BufferSize, LBA,
+ READWRITE ? SataDevInterface->WriteCommand : SataDevInterface->ReadCommand,
+ READWRITE);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SataAtapiBlkRead
+//
+// Description: Read from the Sata ATAPI Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: SataAtapiBlkReadWrite
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+SataAtapiBlkRead(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+
+ EFI_STATUS Status;
+
+ Status = SataAtapiBlkReadWrite(This, MediaId, LBA, BufferSize, Buffer, 0);
+
+ TRACE((TRACE_ALWAYS,"AHCI ATAPI Read: LBA : %lx ByteCount : %lx\n", LBA, BufferSize));
+
+ return Status;
+
+
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SataAtapiBlkWrite
+//
+// Description: Write to Sata ATAPI Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: SataAtapiBlkReadWrite
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataAtapiBlkWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+
+ EFI_STATUS Status;
+
+ Status = SataAtapiBlkReadWrite(This, MediaId, LBA, BufferSize, Buffer, 1);
+
+ TRACE((TRACE_ALWAYS,"AHCI ATAPI Read: LBA : %lx ByteCount : %lx\n", LBA, BufferSize));
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SataAtapiBlkReadWrite
+//
+// Description: Read/Write to/from Sata ATAPI Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check for validity of Inputs
+// 2. Check whether Media is present or not
+// 3. Issue ATAPi Packet command
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataAtapiBlkReadWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer,
+ BOOLEAN READWRITE
+ )
+{
+
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ SATA_DEVICE_INTERFACE *SataDevInterface = ((SATA_BLOCK_IO *)This)->SataDevInterface;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = This->Media;
+ UINTN DataN;
+ ATAPI_DEVICE *AtapiDevice = SataDevInterface->AtapiDevice;
+ COMMAND_STRUCTURE CommandStructure;
+ INTN TotalNumberofBlocks;
+ INTN TransferLength;
+ UINTN BytesRemainingTobeRead;
+ VOID *TempBuffer = Buffer;
+ UINTN BufferAddress;
+
+
+ // Check if Media Present
+
+ if (BlkMedia->MediaPresent == FALSE) {
+ Status = DetectAtapiMedia(SataDevInterface);
+ if (Status == EFI_SUCCESS) return EFI_MEDIA_CHANGED;
+ if (Status == EFI_NO_MEDIA) return Status;
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Check if Media ID matches
+
+ if (BlkMedia->MediaId != MediaId) return EFI_MEDIA_CHANGED;
+
+ if (BufferSize == 0) return EFI_SUCCESS;
+
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+
+ (VOID *)BufferAddress = Buffer;
+ if((BlkMedia->IoAlign > 1 ) && (BufferAddress % BlkMedia->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check whether the block size is multiple of BlkMedia->BlockSize
+
+ DataN = BufferSize % BlkMedia->BlockSize;
+ if (DataN) return EFI_BAD_BUFFER_SIZE;
+
+ // Check for Valid start LBA #
+
+ if (LBA > BlkMedia->LastBlock) return EFI_INVALID_PARAMETER;
+
+ // Check for Valid End LBA #8
+
+ DataN = BufferSize / BlkMedia->BlockSize;
+ if (LBA + DataN > BlkMedia->LastBlock + 1) return EFI_INVALID_PARAMETER;
+
+
+ TotalNumberofBlocks = BufferSize / AtapiDevice->BlockSize;
+
+ for (; TotalNumberofBlocks > 0; TotalNumberofBlocks -= TransferLength) {
+
+ ZeroMemory (&CommandStructure, sizeof(CommandStructure));
+
+ // Calculate # of blocks to be transferred
+
+ if (TotalNumberofBlocks > 0xffff)
+ TransferLength = 0xffff;
+ else
+ TransferLength = TotalNumberofBlocks;
+
+ BytesRemainingTobeRead = TransferLength * AtapiDevice->BlockSize;
+
+ if (READWRITE) CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = SataDevInterface->WriteCommand;
+ else CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = SataDevInterface->ReadCommand;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = AtapiDevice->Lun << 5;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[2] = (UINT8)(((UINT32) LBA) >> 24);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[3] = (UINT8)(((UINT32) LBA) >> 16);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[4] = (UINT8)(((UINT16) LBA) >> 8);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[5] = (UINT8)(((UINT8) LBA) & 0xff);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[7] = (UINT8) (TransferLength >> 8); // MSB
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[8] = (UINT8) (TransferLength & 0xff); // LSB
+ CommandStructure.Buffer = TempBuffer;
+ CommandStructure.ByteCount = (UINT32)BytesRemainingTobeRead;
+
+ Status = ExecutePacketCommand(SataDevInterface, &CommandStructure, READWRITE);
+
+ if (Status != EFI_SUCCESS) {
+
+ // Some error has occured
+ // Check if Device is getting ready. If yes, wait till it gets ready
+
+ if (AtapiDevice->Atapi_Status == BECOMING_READY) {
+ Status = TestUnitReady(SataDevInterface);
+ }
+
+ if (Status == EFI_MEDIA_CHANGED ) {
+ Status = DetectAtapiMedia(SataDevInterface);
+ if (Status == EFI_SUCCESS) return EFI_MEDIA_CHANGED; // Return Media Change
+ if (Status == EFI_NO_MEDIA) {
+ SataDevInterface->SataBlkIo->BlkIo.Media->MediaPresent = FALSE;
+ return Status;
+ }
+ }
+ return Status;
+ }
+
+ if (CommandStructure.ByteCount != BytesRemainingTobeRead) return EFI_DEVICE_ERROR;
+
+ // Update pointer
+
+ (UINT8 *) TempBuffer += BytesRemainingTobeRead;
+ LBA += TransferLength;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SataReset
+//
+// Description: Reset ATA device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN BOOLEAN ExtendedVerification
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SataBlkFlush
+//
+// Description: Flush the cache
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataBlkFlush(
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SataReadWritePio
+//
+// Description: Issues Read/Write Command and Read/Write the data from/to the ATA device
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// IN OUT VOID *Buffer,
+// UINTN ByteCount,
+// UINT64 LBA
+// IN UINT8 ReadWriteCommand,
+// IN BOOLEAN ReadWrite Read/Write = 0/1
+//
+// Output:
+// *Buffer, EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecutePioDataCommand
+//
+// Notes:
+// 1. Get the Max. number of sectors that can be Read/written in one Read/Write PIO command
+// 2. Update the Command Structure
+// 3. Issue ExecutePioDataCommand.
+// 4. If all the bytes are read exit else goto step 2
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataReadWritePio(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE
+ )
+{
+ EFI_STATUS Status;
+ UINT32 SectorCount;
+ INT64 MaxSectorCount;
+ INT64 Total_Number_Of_Sectors;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+ UINT8 *TempBuffer = Buffer;
+ if (Check48BitCommand(ReadWriteCommand))
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO_48BIT;
+ else
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO;
+
+ //
+ // Calculate Sector Size
+ //
+ if((SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT14) && // WORD 106 valid? - BIT 14 - 1
+ (!(SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT15)) && // WORD 106 valid? - BIT 15 - 0
+ (SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT12)) { // WORD 106 bit 12 - Sectorsize > 256 words
+ // The sector size is in words 117-118.
+ SectorSize = (UINT32)(SataDevInterface->IdentifyData.Reserved_104_126[13] + \
+ (SataDevInterface->IdentifyData.Reserved_104_126[14] << 16)) * 2;
+ }
+
+ if (SectorSize > ByteCount) SectorSize = (UINT32)ByteCount;
+
+ // Calculate the total number of Sectors to be transferred
+ Total_Number_Of_Sectors = ByteCount / SectorSize ;
+
+ for ( ;Total_Number_Of_Sectors > 0; Total_Number_Of_Sectors -= MaxSectorCount) {
+
+ if (Total_Number_Of_Sectors > MaxSectorCount) SectorCount = 0;
+ else SectorCount = (UINT32) Total_Number_Of_Sectors;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ if (Check48BitCommand (ReadWriteCommand)) {
+ CommandStructure.LBALowExp = (UINT8)Shr64(LBA,24);
+ CommandStructure.LBAMidExp = (UINT8)Shr64(LBA,32);
+ CommandStructure.LBAHighExp = (UINT8)Shr64(LBA,40);
+ CommandStructure.Device = 0x40; // 48Bit LBA
+ }
+ else { // 28 Bit LBA
+ CommandStructure.Device = ((UINT8) ((UINT32) LBA >> 24) & 0x0f) | 0x40;
+ }
+
+ CommandStructure.SectorCount = (UINT16) SectorCount;
+ CommandStructure.LBALow = (UINT8)LBA;
+ CommandStructure.LBAMid = (UINT8)(((UINT32)LBA >>8) & 0xff);
+ CommandStructure.LBAHigh = (UINT8)(((UINT32)LBA >>16) & 0xff);
+ CommandStructure.Command = ReadWriteCommand;
+
+ CommandStructure.Buffer = TempBuffer;
+ CommandStructure.ByteCount = (UINT32)(SectorCount == 0 ? MaxSectorCount : Total_Number_Of_Sectors) * SectorSize ;
+
+ Status = ExecutePioDataCommand (SataDevInterface, &CommandStructure, READWRITE); // Returns # of bytes read
+
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ TempBuffer += CommandStructure.ByteCount;
+ SectorCount = CommandStructure.ByteCount / SectorSize ;
+ LBA += SectorCount;
+
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SataPioDataOut
+//
+// Description: Issues Read/Write Command with SubCommand feature
+// and Reads/Writes data to the ATA device.
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN OUT VOID *Buffer,
+// IN UINTN ByteCount,
+// IN UINT8 Features,
+// IN UINT16 LBALow,
+// IN UINT8 LBALowExp,
+// IN UINT8 LBAMid,
+// IN UINT8 LBAMidExp,
+// IN UINT8 LBAHigh,
+// IN UINT8 LBAHighExp,
+// IN UINT8 ReadWriteCommand
+// IN BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecutePioDataCommand
+//
+// Notes:
+// 1. Get the Max. number of sectors that can be transferred in one Read/Write PIO command
+// 2. Update the Command Structure
+// 3. Issue ExecutePioDataCommand.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SataPioDataOut (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT8 Features,
+ IN UINT8 LBALow,
+ IN UINT8 LBALowExp,
+ IN UINT8 LBAMid,
+ IN UINT8 LBAMidExp,
+ IN UINT8 LBAHigh,
+ IN UINT8 LBAHighExp,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE
+ )
+{
+ EFI_STATUS Status;
+ UINT32 SectorCount;
+ INT64 MaxSectorCount;
+ INT64 Total_Number_Of_Sectors;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+ UINT64 LBA = 0;
+ UINT64 LBAHighDword = 0;
+
+ if (Check48BitCommand(ReadWriteCommand)) {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO_48BIT;
+ //
+ // if 48 Bit LBA form Upper Dword
+ //
+ LBAHighDword |= LBAHighExp;
+ LBAHighDword = ( Shl64(( Shl64( LBAHighDword, 8)| LBAMidExp), 8)| LBALowExp);
+ } else {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO;
+ }
+ //
+ // Complete LBA
+ //
+ LBA |= LBAHigh;
+ LBA = (( Shl64(( Shl64( LBA, 8) | LBAMid ), 8)| LBALow)| Shl64( LBAHighDword, 24 ));
+
+ //
+ // Calculate Sector Size
+ //
+ if((SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT14) && // WORD 106 valid? - BIT 14 - 1
+ (!(SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT15)) && // WORD 106 valid? - BIT 15 - 0
+ (SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT12)) { // WORD 106 bit 12 - Sectorsize > 256 words
+ // The sector size is in words 117-118.
+ SectorSize = (UINT32)(SataDevInterface->IdentifyData.Reserved_104_126[13] + \
+ (SataDevInterface->IdentifyData.Reserved_104_126[14] << 16)) * 2;
+ }
+
+ if (SectorSize > ByteCount) SectorSize = (UINT32)ByteCount;
+
+ // Calculate the total number of Sectors to be transferred
+ Total_Number_Of_Sectors = ByteCount / SectorSize ;
+
+ for ( ;Total_Number_Of_Sectors > 0; Total_Number_Of_Sectors -= MaxSectorCount) {
+
+ if ( Total_Number_Of_Sectors > MaxSectorCount ) SectorCount = 0;
+ else SectorCount = (UINT32) Total_Number_Of_Sectors;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ if (Check48BitCommand (ReadWriteCommand)) {
+ //
+ // If 48Bit LBA then form Upper DWord
+ //
+ CommandStructure.LBALowExp = LBALowExp;
+ CommandStructure.LBAMidExp = LBAMidExp;
+ CommandStructure.LBAHighExp = LBAHighExp;
+ CommandStructure.Device = 0x40;
+ }
+ else { // 28 Bit LBA
+ CommandStructure.Device = ((UINT8) LBAHigh & 0x0f) | 0x40;
+ }
+
+ CommandStructure.Features = Features; // SubCommand
+ CommandStructure.SectorCount = (UINT16) SectorCount;
+ CommandStructure.LBALow = LBALow;
+ CommandStructure.LBAMid = LBAMid;
+ CommandStructure.LBAHigh = LBAHigh;
+ CommandStructure.Command = ReadWriteCommand;
+
+ CommandStructure.Buffer = Buffer;
+ CommandStructure.ByteCount = (UINT32)(SectorCount == 0 ? MaxSectorCount : Total_Number_Of_Sectors) * SectorSize ;
+
+ Status = ExecutePioDataCommand (SataDevInterface, &CommandStructure, READWRITE); // Returns # of bytes read
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ SectorCount = CommandStructure.ByteCount / SectorSize ;
+ LBA += SectorCount;
+
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: SataReadWriteBusMaster
+//
+// Description: Issues Read/Write Command and Read/Write the data from/to the ATA device
+// using BusMaster
+//
+// Input:
+// SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN OUT VOID *Buffer,
+// IN UINTN ByteCount,
+// IN UINT64 LBA,
+// IN UINT8 ReadWriteCommand,
+// IN BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecuteDmaDataCommand
+//
+// Notes:
+// 1. Get the Max. number of sectors that can be Read/written in one Read/Write Bus master command
+// 2. Update the Command Structure
+// 3. Issue ExecutePioDataCommand.
+// 4. If all the bytes are read exit else goto step 2
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+EFI_STATUS
+SataReadWriteBusMaster(
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE
+ )
+{
+
+ EFI_STATUS Status;
+ UINTN Total_Number_Of_Sectors,MaxSectorCount;
+ UINTN CurrentSectorCount,CurrentByteCount;
+ UINT8 *TempBuffer = Buffer;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+
+ if (Check48BitCommand(ReadWriteCommand))
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO_48BIT;
+ else
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO;
+
+ //
+ // Calculate Sector Size
+ //
+ if((SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT14) && // WORD 106 valid? - BIT 14 - 1
+ (!(SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT15)) && // WORD 106 valid? - BIT 15 - 0
+ (SataDevInterface->IdentifyData.Reserved_104_126[2] & BIT12)) { // WORD 106 bit 12 - Sectorsize > 256 words
+ // The sector size is in words 117-118.
+ SectorSize = (UINT32)(SataDevInterface->IdentifyData.Reserved_104_126[13] + \
+ (SataDevInterface->IdentifyData.Reserved_104_126[14] << 16)) * 2;
+ }
+ if (SectorSize > ByteCount) SectorSize = (UINT32)ByteCount;
+
+ Total_Number_Of_Sectors = ByteCount / SectorSize ;
+
+ do {
+ if (Total_Number_Of_Sectors > MaxSectorCount) CurrentSectorCount = 0;
+ else CurrentSectorCount = Total_Number_Of_Sectors;
+ CurrentByteCount = (CurrentSectorCount == 0 ? MaxSectorCount : CurrentSectorCount) * SectorSize ;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ CommandStructure.Buffer = TempBuffer;
+ CommandStructure.ByteCount = (UINT32)CurrentByteCount;
+ CommandStructure.Command = ReadWriteCommand;
+
+ if (Check48BitCommand (ReadWriteCommand)) {
+ // 48 Bit LBA
+ // Write the Upper LBA DWORD and Upper byte of Sector Count
+ CommandStructure.LBALowExp = (UINT8)Shr64(LBA,24);
+ CommandStructure.LBAMidExp = (UINT8) Shr64(LBA,32);
+ CommandStructure.LBAHighExp = (UINT8) Shr64(LBA,40);
+ CommandStructure.Device = 0x40; // 48Bit LBA
+ }
+ else { // 28 Bit LBA
+ CommandStructure.Device = ((UINT8) ((UINT32) LBA >> 24) & 0x0f) | 0x40;
+ }
+
+ CommandStructure.SectorCount = (UINT16) CurrentSectorCount;
+ CommandStructure.LBALow = (UINT8)LBA;
+ CommandStructure.LBAMid = (UINT8) (((UINT32)LBA >>8) & 0xff);
+ CommandStructure.LBAHigh = (UINT8) (((UINT32)LBA >>16) & 0xff);
+
+ Status = ExecuteDmaDataCommand (SataDevInterface, &CommandStructure, READWRITE); // Returns # of bytes read
+ if (EFI_ERROR(Status)) return EFI_DEVICE_ERROR;
+
+ CurrentByteCount = CommandStructure.ByteCount;
+ CurrentSectorCount = CurrentByteCount / SectorSize;
+
+ TempBuffer += CurrentByteCount;
+ Total_Number_Of_Sectors -= (CurrentSectorCount == 0 ? MaxSectorCount : CurrentSectorCount);
+ LBA += (CurrentSectorCount == 0 ? MaxSectorCount : CurrentSectorCount);
+
+ } while (Total_Number_Of_Sectors);
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Check48BitCommand
+//
+// Description: Checks if the command is for 48-bit LBA
+//
+// Input:
+// IN UINT8 Command
+//
+// Output:
+// TRUE/FLASE
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+Check48BitCommand (
+ IN UINT8 Command
+ )
+{
+ if ( Command == READ_SECTORS_EXT ||
+ Command == READ_MULTIPLE_EXT ||
+ Command == WRITE_SECTORS_EXT ||
+ Command == WRITE_MULTIPLE_EXT ||
+ Command == READ_DMA_EXT ||
+ Command == WRITE_DMA_EXT )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ExecuteNonDataCommand
+//
+// Description: Issue a Non-Data command to the SATA Device
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, StartController, WaitforCommandComplete
+//
+// Notes:
+// 1. Stop the Controller
+// 2. Check if the device is ready to accept a Command.
+// 3. Build Command list
+// 4. Start the Controller.
+// 5. Wait till command completes. Check for errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ExecuteNonDataCommand (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_STRUCTURE CommandStructure
+)
+{
+ EFI_STATUS Status;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *)(UINTN) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)(UINTN)AhciBusInterface->PortCommandTableBaseAddr;
+
+ Status = StopController(AhciBusInterface, SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+ return Status;
+ }
+
+ BuildCommandList(SataDevInterface, CommandList, AhciBusInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, CommandStructure, CommandList, Commandtable);
+
+ // Data-in
+ CommandList->Ahci_Cmd_W = 0;
+
+ // Update of Command Register
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController(AhciBusInterface, SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, NON_DATA_CMD, ATAPI_BUSY_CLEAR_TIMEOUT );
+
+ // Stop Controller
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ExecutePioDataCommand
+//
+// Description: Ececute PIO Data In/Out command
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN OUT COMMAND_STRUCTURE *CommandStructure
+// IN BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS, CommandStructure->ByteCount
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, BuildCommandList, BuildCommandFIS, BuildAtapiCMD
+// BuildPRDT, StartController, WaitforCommandComplete
+//
+// Notes:
+// 1. Stop the Controller
+// 2. Check if the device is ready to accept a Command.
+// 3. Build Command list
+// 4. Start the Controller.
+// 5. Wait till command completes. Check for errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ExecutePioDataCommand (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT COMMAND_STRUCTURE *CommandStructure,
+ IN BOOLEAN READWRITE
+)
+{
+ EFI_STATUS Status;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *)(UINTN) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)(UINTN)AhciBusInterface->PortCommandTableBaseAddr;
+
+
+ Status = StopController(AhciBusInterface, SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+ return Status;
+ }
+ BuildCommandList(SataDevInterface, CommandList, AhciBusInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildAtapiCMD(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildPRDT(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+
+ if (READWRITE) {
+ CommandList->Ahci_Cmd_W = 1;
+ }
+ else {
+ CommandList->Ahci_Cmd_W = 0;
+ }
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController(AhciBusInterface, SataDevInterface, BIT00);
+
+ // For Security Erase command the time out value comes from Identify Data.
+ if(CommandStructure->Command == SECURITY_ERASE_UNIT ) {
+ UINT32 EraseCommandTimeout;
+ EraseCommandTimeout= (UINT32)(SataDevInterface->IdentifyData.Time_security_Earse_89);
+ if(EraseCommandTimeout <= 254) {
+ EraseCommandTimeout=EraseCommandTimeout * 2 * 1000 * 60; //Value * 2Minitues
+ } else {
+ EraseCommandTimeout= 0; // No timeout
+ }
+ Status = WaitforCommandComplete(SataDevInterface, PIO_DATA_IN_CMD, EraseCommandTimeout);
+ } else {
+ Status = WaitforCommandComplete(SataDevInterface, PIO_DATA_IN_CMD,
+ SataDevInterface->DeviceType == ATA? DMA_ATA_COMMAND_COMPLETE_TIMEOUT \
+ : DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT );
+ }
+
+ CommandStructure->ByteCount = CommandList->Ahci_Cmd_PRDBC;
+
+ // Stop Controller
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ExecuteDmaDataCommand
+//
+// Description:
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE *CommandStructure
+// IN BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, BuildCommandList, BuildCommandFIS, BuildAtapiCMD
+// BuildPRDT, StartController, WaitforCommandComplete
+//
+// Notes:
+// 1. Stop the Controller
+// 2. Check if the device is ready to accept a Command.
+// 3. Build Command list
+// 4. Start the Controller.
+// 5. Wait till command completes. Check for errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ExecuteDmaDataCommand (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_STRUCTURE *CommandStructure,
+ IN BOOLEAN READWRITE
+)
+{
+
+ EFI_STATUS Status;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *)(UINTN) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)(UINTN)AhciBusInterface->PortCommandTableBaseAddr;
+
+
+ Status = StopController(AhciBusInterface, SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+ return Status;
+ }
+ BuildCommandList(SataDevInterface, CommandList, AhciBusInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildAtapiCMD(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildPRDT(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+
+ // Data-in
+ if (READWRITE) {
+ CommandList->Ahci_Cmd_W = 1;
+ }
+ else {
+ CommandList->Ahci_Cmd_W = 0 ;
+ }
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController(AhciBusInterface, SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, DMA_DATA_IN_CMD,
+ SataDevInterface->DeviceType == ATA? DMA_ATA_COMMAND_COMPLETE_TIMEOUT \
+ : DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT );
+
+ if (!EFI_ERROR(Status)){
+ //Check if the required BYTES have been received
+ if (CommandList->Ahci_Cmd_PRDBC != CommandStructure->ByteCount){
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+ // Stop Controller
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+
+ CommandStructure->ByteCount = CommandList->Ahci_Cmd_PRDBC;
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ExecutePacketCommand
+//
+// Description: Execute a Atapi Packet command
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE *CommandStructure
+// IN BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, BuildCommandList, BuildCommandFIS, BuildAtapiCMD
+// BuildPRDT, StartController, WaitforCommandComplete
+//
+// Notes:
+// 1. Stop the Controller
+// 2. Check if the device is ready to accept a Command.
+// 3. Build Command list
+// 4. Start the Controller.
+// 5. Wait till command completes. Check for errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ExecutePacketCommand (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_STRUCTURE *CommandStructure,
+ IN BOOLEAN READWRITE
+ )
+{
+
+ EFI_STATUS Status;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *)(UINTN) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)(UINTN)AhciBusInterface->PortCommandTableBaseAddr;
+ UINT32 AhciBaseAddr = (UINT32)AhciBusInterface->AhciBaseAddress;
+ ATAPI_DEVICE *AtapiDevice = SataDevInterface->AtapiDevice;
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 Data8;
+
+ CommandStructure->LBAMid = (UINT8)(CommandStructure->ByteCount);
+ CommandStructure->LBAHigh = (UINT8)(CommandStructure->ByteCount >> 8);
+ CommandStructure->Command = PACKET_COMMAND;
+
+ Status = StopController(AhciBusInterface, SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+ return Status;
+ }
+ BuildCommandList(SataDevInterface, CommandList, AhciBusInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildAtapiCMD(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildPRDT(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+
+ if (READWRITE) {
+ CommandList->Ahci_Cmd_W = 1;
+ }
+ else {
+ CommandList->Ahci_Cmd_W = 0;
+ }
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController(AhciBusInterface, SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, PIO_DATA_IN_CMD,
+ SataDevInterface->DeviceType == ATA? DMA_ATA_COMMAND_COMPLETE_TIMEOUT \
+ : DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT );
+
+
+ // Handle ATAPI device error
+ if (EFI_ERROR(Status) && SataDevInterface->DeviceType == ATAPI) {
+ Data8 = HBA_PORT_REG8 (AhciBaseAddr, Port, HBA_PORTS_TFD);
+ if (Data8 & CHK ){
+ return HandleAtapiError(SataDevInterface);
+
+ }
+ }
+ AtapiDevice->Atapi_Status = EFI_SUCCESS;
+
+ CommandStructure->ByteCount = CommandList->Ahci_Cmd_PRDBC;
+
+ // Stop Controller
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HandleAtapiError
+//
+// Description: Check for ATAPI Errors
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecutePacketCommand
+//
+// Notes:
+// 1. Execute ATAPI Request Sense command.
+// 2. Check for Device getting ready, Media Change, No Media and other errors. Update AtapiDevice->Atapi_Status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+HandleAtapiError (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+ )
+{
+
+ EFI_STATUS Status;
+ UINT8 Data8 = 0;
+ UINT8 SenseData[256];
+ COMMAND_STRUCTURE CommandStructure;
+ ATAPI_DEVICE *AtapiDevice = SataDevInterface->AtapiDevice;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 AhciBaseAddr = (UINT32)AhciBusInterface->AhciBaseAddress;
+ UINT8 Port = SataDevInterface->PortNumber;
+
+ AtapiDevice->Atapi_Status = DEVICE_ERROR;
+
+ ZeroMemory (SenseData, 256);
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = ATAPI_REQUEST_SENSE;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[4] = 0xff;
+
+ CommandStructure.ByteCount = 256;
+ CommandStructure.Buffer = SenseData;
+
+ Status = ExecutePacketCommand(SataDevInterface, &CommandStructure, 0);
+
+ if (EFI_ERROR(Status)) {
+ Data8 = HBA_PORT_REG8 (AhciBaseAddr, Port, HBA_PORTS_TFD);
+ }
+
+ SataDevInterface->AtapiSenseDataLength = 0;
+
+ // Check for DF and CHK
+ if (Data8 & (DF | CHK)) {
+ goto exit_HandleAtapiError_with_Reset;
+ }
+
+ if (!EFI_ERROR(Status)){
+ //
+ // Store the SenseData whcih would be used by ScsiPassThruAtapi PassThru Interface.
+ //
+ pBS->CopyMem( SataDevInterface->AtapiSenseData, SenseData, 256);
+ SataDevInterface->AtapiSenseDataLength = CommandStructure.ByteCount;
+
+ AtapiDevice->Atapi_Status = DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR; // Default Value
+
+ if (((SenseData[2] & 0xf) == 2) && (SenseData[12] == 0x3a)) {
+ Status = EFI_NO_MEDIA;
+ AtapiDevice->Atapi_Status = MEDIUM_NOT_PRESENT;
+ }
+ if (((SenseData[2] & 0xf) == 2) && (SenseData[12] == 0x04) && (SenseData[13] == 0x01)) {
+ Status = EFI_MEDIA_CHANGED;
+ AtapiDevice->Atapi_Status = BECOMING_READY;
+ }
+
+ if (((SenseData[2] & 0xf) == 6) && (SenseData[12] == 0x28)){
+ Status = EFI_MEDIA_CHANGED;
+ AtapiDevice->Atapi_Status = MEDIA_CHANGED;
+ }
+
+ if (((SenseData[2] & 0xf) == 7) && (SenseData[12] == 0x27)){
+ Status = EFI_WRITE_PROTECTED;
+ AtapiDevice->Atapi_Status = WRITE_PROTECTED_MEDIA;
+ }
+
+ if (((SenseData[2] & 0xf) == 6) && (SenseData[12] == 0x29)){
+ AtapiDevice->Atapi_Status = POWER_ON_OR_DEVICE_RESET;
+ }
+
+ if (((SenseData[2] & 0xf) == 5) && (SenseData[0] == 0x70)){
+ AtapiDevice->Atapi_Status = ILLEGAL_REQUEST;
+ }
+ }
+
+exit_HandleAtapiError_with_Reset:
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadWritePMPort
+//
+// Description: Read/Write routine to PM ports
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 RegNum,
+// IN OUT UINT32 *Data
+// IN BOOLEAN READWRITE // TRUE for Write
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, BuildCommandList, BuildCommandFIS, BuildAtapiCMD
+// BuildPRDT, StartController, WaitforCommandComplete
+//
+// Notes:
+// 1. Update Command Structure for READ/Write Port Multiplier command
+// 2. Issue command
+// 3. Check for errors.
+// 4. Read the out data in case of READ.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ReadWritePMPort (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 RegNum,
+ IN OUT UINT32 *Data,
+ IN BOOLEAN READWRITE
+)
+{
+ EFI_STATUS Status;
+ COMMAND_STRUCTURE CommandStructure;
+ AHCI_RECEIVED_FIS *PortFISBaseAddr = (AHCI_RECEIVED_FIS *)(UINTN)(SataDevInterface->PortFISBaseAddr);
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *)(UINTN) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)(UINTN)AhciBusInterface->PortCommandTableBaseAddr;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ CommandStructure.Command = READ_PORT_MULTIPLIER;
+
+ if (READWRITE) {
+ CommandStructure.SectorCount = (UINT16) (*Data & 0xFF);
+ CommandStructure.LBALow = (UINT8) (*Data >> 8);
+ CommandStructure.LBAMid = (UINT8)(*Data >> 16);
+ CommandStructure.LBAHigh = (UINT8)(*Data >> 24);
+ CommandStructure.Command = WRITE_PORT_MULTIPLIER;
+ }
+
+ CommandStructure.Device = Port;
+ CommandStructure.Features = RegNum;
+
+ Status = StopController(AhciBusInterface, SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+ return Status;
+ }
+
+ BuildCommandList(SataDevInterface, CommandList, AhciBusInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, CommandStructure, CommandList, Commandtable);
+
+ // Data-in
+ CommandList->Ahci_Cmd_W = 0;
+
+ // Update of Command Register
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ // Update the Port Address
+ CommandList->Ahci_Cmd_PMP = CONTROL_PORT;
+ Commandtable->CFis.AHci_CFis_PmPort = CONTROL_PORT;
+
+ StartController(AhciBusInterface, SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, NON_DATA_CMD, TIMEOUT_1SEC);
+
+ // Stop Controller
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+
+ if (!READWRITE) {
+ *Data = 0;
+ if (!EFI_ERROR(Status)) {
+ *Data = PortFISBaseAddr->Ahci_Rfis[12] |
+ (PortFISBaseAddr->Ahci_Rfis[4] << 8) |
+ (PortFISBaseAddr->Ahci_Rfis[5] << 16) |
+ (PortFISBaseAddr->Ahci_Rfis[6] << 24);
+ }
+ }
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetIdentifyData
+//
+// Description: Reaturn Identify data from SATA device
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// gIdentifyDataBuffer
+// EFI_STATUS
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Build CommandStructure.
+// 2. Issue ExecutePioDataCommand
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+GetIdentifyData (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+ EFI_STATUS Status;
+ COMMAND_STRUCTURE CommandStructure;
+ IDENTIFY_DATA tIdentifyData;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ // Read Identifydata
+ CommandStructure.Buffer = &tIdentifyData;
+ CommandStructure.ByteCount = sizeof(IDENTIFY_DATA);
+ CommandStructure.Device = 0;
+ CommandStructure.Command = SataDevInterface->DeviceType == ATA ? IDENTIFY_COMMAND : IDENTIFY_PACKET_COMMAND;
+
+ Status = ExecutePioDataCommand (SataDevInterface, &CommandStructure, FALSE);
+
+ if (CommandStructure.ByteCount != sizeof(IDENTIFY_DATA)) { Status = EFI_DEVICE_ERROR; }
+
+ if(!EFI_ERROR(Status))
+ pBS->CopyMem(&(SataDevInterface->IdentifyData), &tIdentifyData, sizeof(IDENTIFY_DATA));
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SataAtapiInquiryData
+//
+// Description: Return ATAPI Inquiry data
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// OUT UINT8 *InquiryData,
+// IN OUT UINT16 *InquiryDataSize
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecutePioDataCommand
+//
+// Notes:
+// 1. Update CommandStructure
+// 2. Issue ExecutePioDataCommand
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataAtapiInquiryData (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ OUT UINT8 *InquiryData,
+ IN OUT UINT16 *InquiryDataSize
+)
+{
+
+ EFI_STATUS Status;
+ COMMAND_STRUCTURE CommandStructure;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Buffer = InquiryData;
+ CommandStructure.ByteCount = *InquiryDataSize;
+ CommandStructure.Command = PACKET_COMMAND;
+ CommandStructure.LBAMid = (UINT8)*InquiryDataSize;
+ CommandStructure.LBAHigh = (UINT8)(*InquiryDataSize >> 8);
+
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0]=ATAPI_INQUIRY;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[4]=(UINT8)*InquiryDataSize;
+
+ Status = ExecutePioDataCommand (SataDevInterface, &CommandStructure, 0);
+
+ if (!EFI_ERROR(Status)) {
+ *InquiryDataSize = (UINT16)CommandStructure.ByteCount;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: DetectAtapiMedia
+//
+// Description: Detects whether a Media is present in the ATAPI Removable device or not.
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: TestUnitReady, ExecutePacketCommand
+//
+// Notes:
+// 1. Issue Read Capacity command for CDROM or Read Format command for other ATAPI devices.
+// 2. If step 1 is successfull, update last LBA, Block Size, Read/Write capable, Media ID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+DetectAtapiMedia(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+ )
+{
+ UINT8 *InputData, LoopCount;
+ ATAPI_DEVICE *AtapiDevice = SataDevInterface->AtapiDevice;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = SataDevInterface->SataBlkIo->BlkIo.Media;
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ UINT16 ByteCount = 256, Data16;
+ COMMAND_STRUCTURE CommandStructure;
+ BOOLEAN ReadCapacity=FALSE;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+// Default Values
+ BlkMedia->MediaPresent = FALSE;
+ BlkMedia->LastBlock = 0x100; // Dummy value
+ SataDevInterface->ReadCommand = ATAPI_READ_10;
+ SataDevInterface->WriteCommand = ATAPI_WRITE_10;
+
+ Status = TestUnitReady(SataDevInterface);
+ if ((Status != EFI_MEDIA_CHANGED) && (Status != EFI_SUCCESS)) {
+ return Status;
+ }
+
+// Issue Read Capacity command
+ Status = pBS->AllocatePool (EfiBootServicesData, ByteCount, (VOID**)&InputData);
+ if (EFI_ERROR(Status)) return Status;
+
+// For CDROM use Read Capacity command else use Read Format Command
+ if (AtapiDevice->DeviceType == CDROM_DEVICE){
+ BlkMedia->BlockSize = CDROM_BLOCK_SIZE; // Default size
+ AtapiDevice->BlockSize = (UINT16)(BlkMedia->BlockSize);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = ATAPI_READ_CAPACITY;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = AtapiDevice->Lun << 5;
+ Data16 = 8;
+ }
+ else {
+ BlkMedia->BlockSize = LS120_BLOCK_SIZE; // Default Size
+ AtapiDevice->BlockSize = (UINT16)(BlkMedia->BlockSize);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = ATAPI_READ_FORMAT_CAPACITIES;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = AtapiDevice->Lun << 5;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[7] = (UINT8)(ByteCount >> 8);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[8] = (UINT8)(ByteCount & 0xff);
+ Data16 = ByteCount;
+ }
+
+ for (LoopCount = 0; LoopCount < 5; LoopCount++) { // 5sec loop
+ ByteCount = Data16;
+ ZeroMemory (InputData, ByteCount);
+ CommandStructure.Buffer = InputData;
+ CommandStructure.ByteCount = ByteCount;
+ Status = ExecutePacketCommand(SataDevInterface, &CommandStructure, 0);
+ if(CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] == ATAPI_READ_FORMAT_CAPACITIES &&
+ AtapiDevice->Atapi_Status == ILLEGAL_REQUEST) {
+ //
+ //If the Read Format Capacities not supported by device, try
+ //ReadCapacity command
+ //
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ BlkMedia->BlockSize = CDROM_BLOCK_SIZE; // Default size
+ AtapiDevice->BlockSize = (UINT16)(BlkMedia->BlockSize);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = ATAPI_READ_CAPACITY;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = AtapiDevice->Lun << 5;
+ Data16 = 8;
+ ReadCapacity=TRUE;
+ }
+ if (AtapiDevice->Atapi_Status == EFI_SUCCESS) break;
+ if (AtapiDevice->Atapi_Status == MEDIUM_NOT_PRESENT) break;
+ }
+
+ if (Status == EFI_SUCCESS) {
+ if(ReadCapacity == TRUE) {
+ BlkMedia->LastBlock = InputData[0] << 24 | InputData[1] << 16 | InputData[2] << 8 | InputData[3];
+ BlkMedia->LastBlock--;
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->MediaId ++;
+ BlkMedia->BlockSize = InputData[4] << 24 | InputData[5] << 16 | InputData[6] << 8 | InputData[7];
+ AtapiDevice->BlockSize = BlkMedia->BlockSize;
+ BlkMedia->ReadOnly = FALSE;
+ } else if (AtapiDevice->DeviceType == CDROM_DEVICE) {
+ BlkMedia->LastBlock = InputData[0] << 24 | InputData[1] << 16 | InputData[2] << 8 | InputData[3];
+ BlkMedia->LastBlock--;
+ BlkMedia->BlockSize = CDROM_BLOCK_SIZE;
+ AtapiDevice->BlockSize = (UINT16)(BlkMedia->BlockSize);
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->MediaId ++;
+ BlkMedia->ReadOnly = TRUE;
+ } else if (InputData[8] != 3) { // No media present
+ BlkMedia->LastBlock = InputData[4] << 24 | InputData[5] << 16 | InputData[6] << 8 | InputData[7];
+ BlkMedia->LastBlock--;
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->MediaId ++;
+ BlkMedia->BlockSize = InputData[9] << 16 | InputData[10] << 8 | InputData[11];
+ BlkMedia->ReadOnly = FALSE;
+ AtapiDevice->BlockSize = (UINT16)(BlkMedia->BlockSize);
+ }
+
+// Update ReadOnly Status
+ if (AtapiDevice->DeviceType != CDROM_DEVICE) {
+ ByteCount = 256;
+ ZeroMemory (InputData, ByteCount);
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = ATAPI_MODE_SENSE;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[2] = RETURN_ALL_PAGES;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[7] = (UINT8)(ByteCount >> 8);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[8] = (UINT8)(ByteCount & 0xff);
+ CommandStructure.Buffer = InputData;
+ CommandStructure.ByteCount= ByteCount;
+ Status = ExecutePacketCommand(SataDevInterface, &CommandStructure, 0);
+ if ((Status == EFI_SUCCESS) && (ByteCount > 8)) {
+ BlkMedia->ReadOnly = (InputData[3] & 0x80) != 0 ? TRUE : FALSE;
+ }
+ }
+ }
+
+ pBS->FreePool(InputData);
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SataCheckOddType
+//
+// Description: Return ODD type
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecutePioDataCommand
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataGetOddType (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT UINT16 *OddType
+)
+
+{
+
+ EFI_STATUS Status;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT8 *ProfileData;
+
+ Status = pBS->AllocatePool (EfiBootServicesData,16,(VOID**)&ProfileData);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Buffer = ProfileData;
+ CommandStructure.ByteCount = 16;
+ CommandStructure.Command = PACKET_COMMAND;
+ CommandStructure.LBAMid = 16;
+ CommandStructure.LBAHigh = 0;
+
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0]= ATAPI_GET_CONFIGURATION;
+ //
+ // Get the Feature Discriptor.
+ //
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = FEATURE_DISCRIPTOR;
+ //
+ // Get the Profile list
+ //
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[3] = GET_PROFILE_LIST;
+ //
+ // Responce Data Size
+ //
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[8] = 0x10;
+
+ Status = ExecutePioDataCommand (SataDevInterface, &CommandStructure, 0);
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Get the Profile Number
+ //
+ *OddType=(UINT16 )(((ProfileData[sizeof(GET_CONFIGURATION_HEADER)+4]) << 8) + ProfileData[sizeof(GET_CONFIGURATION_HEADER)+5]);
+ }
+
+ pBS->FreePool(ProfileData);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SataGetOddLoadingType
+//
+// Description: Return ODD Loading type information
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecutePioDataCommand
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+SataGetOddLoadingType (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN OUT UINT8 *OddLoadingType
+)
+
+{
+
+ EFI_STATUS Status;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT8 *ProfileData;
+
+ Status = pBS->AllocatePool (EfiBootServicesData,16,(VOID**)&ProfileData);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.Buffer = ProfileData;
+ CommandStructure.ByteCount = 16;
+ CommandStructure.Command = PACKET_COMMAND;
+ CommandStructure.LBAMid = 16;
+ CommandStructure.LBAHigh = 0;
+
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0]= ATAPI_GET_CONFIGURATION;
+ //
+ // Get the Feature Discriptor.
+ //
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = FEATURE_DISCRIPTOR;
+ //
+ // Get the Removable Medium feature
+ //
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[3] = GET_REMOVEABLE_MEDIUM_FEATURE;
+ //
+ // Responce Data Size
+ //
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[8] = 0x10;
+
+ Status = ExecutePioDataCommand (SataDevInterface, &CommandStructure, 0);
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Get the ODD Loading Type
+ //
+ *OddLoadingType=(UINT8 )(((ProfileData[sizeof(GET_CONFIGURATION_HEADER)+4]) & 0xE0) >> 5);
+ }
+
+ pBS->FreePool(ProfileData);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: TestUnitReady
+//
+// Description: Issues Start/Stop unit Command
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// EFI_STATUS EFI_SUCCESS : If Media is accessible
+// EFI_NO_MEDIA
+// EFI_MEDIA_CHANGED
+// EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals: ExecutePacketCommand
+//
+// Notes:
+// 1. Update CommandStructure for ATAPI_TEST_UNIT_READY command
+// 2. Issue ExecutePacketCommand
+// 3. Check if the device is ready to accept command, whether Media is present or not.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+TestUnitReady(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+ )
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ ATAPI_DEVICE *AtapiDevice = SataDevInterface->AtapiDevice;
+ UINT16 LoopCount;
+ COMMAND_STRUCTURE CommandStructure;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = ATAPI_TEST_UNIT_READY;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = AtapiDevice->Lun << 5;
+ CommandStructure.Buffer = NULL;
+ CommandStructure.ByteCount = 0x100;
+
+ for (LoopCount = 0; LoopCount < 1000; LoopCount++) { // 10sec loop ( 1000 * 10 msec = 10Sec)
+ Status = ExecutePacketCommand(SataDevInterface, &CommandStructure, 0);
+ if (Status == EFI_SUCCESS) break;
+ if (AtapiDevice->Atapi_Status == MEDIUM_NOT_PRESENT) break;
+ if (AtapiDevice->Atapi_Status == MEDIA_CHANGED) break;
+ pBS->Stall(10000); // 10msec
+ }
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildCommandList
+//
+// Description: Builds command list
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN UINT32 CommandTableBaseAddr
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Update CommandList bits
+// 2. Not all fields like Ahci_Cmd_A are updated.
+// 3. Port number is set to 0xF (Control port) if PM Port number is 0xFF.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildCommandList (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN UINT32 CommandTableBaseAddr
+)
+{
+
+
+ ZeroMemory (CommandList, sizeof(AHCI_COMMAND_LIST));
+ // CommandList->Ahci_Cmd_A = SataDevInterface->DeviceType == ATAPI ? 1 : 0; // set elsewhere
+ CommandList->Ahci_Cmd_P = 0;
+ CommandList->Ahci_Cmd_R = 0;
+ CommandList->Ahci_Cmd_B = 0;
+ CommandList->Ahci_Cmd_Rsvd1 = 0;
+ CommandList->Ahci_Cmd_PMP = SataDevInterface->PMPortNumber == 0xFF ? 0x0 : SataDevInterface->PMPortNumber;
+ CommandList->Ahci_Cmd_PRDTL = 0;
+ CommandList->Ahci_Cmd_PRDBC = 0;
+ CommandList->Ahci_Cmd_CTBA = CommandTableBaseAddr;
+ CommandList->Ahci_Cmd_CTBAU = 0;
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildCommandFIS
+//
+// Description: Build Command FIS
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure,
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN AHCI_COMMAND_TABLE *Commandtable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Update Command FIS data area.
+// 2. Update the Command FIS lenght in Command List table
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildCommandFIS (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_STRUCTURE CommandStructure,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN AHCI_COMMAND_TABLE *Commandtable
+)
+{
+
+
+ ZeroMemory (Commandtable, sizeof(AHCI_COMMAND_TABLE));
+
+ Commandtable->CFis.Ahci_CFis_Type = FIS_REGISTER_H2D;
+ Commandtable->CFis.AHci_CFis_PmPort = SataDevInterface->PMPortNumber == 0xFF ? 0x0 : SataDevInterface->PMPortNumber;
+// Commandtable->CFis.Ahci_CFis_C = 1; // Set elsewhere
+ Commandtable->CFis.Ahci_CFis_Cmd = CommandStructure.Command;
+
+ Commandtable->CFis.Ahci_CFis_Features = CommandStructure.Features;
+ Commandtable->CFis.Ahci_CFis_FeaturesExp = CommandStructure.FeaturesExp;
+
+ Commandtable->CFis.Ahci_CFis_SecNum = CommandStructure.LBALow;
+ Commandtable->CFis.Ahci_CFis_SecNumExp = CommandStructure.LBALowExp;
+
+ Commandtable->CFis.Ahci_CFis_ClyLow = CommandStructure.LBAMid;
+ Commandtable->CFis.Ahci_CFis_ClyLowExp = CommandStructure.LBAMidExp;
+
+ Commandtable->CFis.Ahci_CFis_ClyHigh = CommandStructure.LBAHigh;
+ Commandtable->CFis.Ahci_CFis_ClyHighExp = CommandStructure.LBAHighExp;
+
+ Commandtable->CFis.Ahci_CFis_SecCount = (UINT8)(CommandStructure.SectorCount);
+ Commandtable->CFis.Ahci_CFis_SecCountExp = (UINT8)(CommandStructure.SectorCount >> 8);
+
+ Commandtable->CFis.Ahci_CFis_DevHead = CommandStructure.Device;
+ Commandtable->CFis.Ahci_CFis_Control = CommandStructure.Control;
+
+ CommandList->Ahci_Cmd_CFL = FIS_REGISTER_H2D_LENGTH / 4;
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildAtapiCMD
+//
+// Description:
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN AHCI_COMMAND_TABLE *Commandtable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Copy Packet data to command table
+// 2. Set Atapi bit in Command List
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildAtapiCMD(
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_STRUCTURE CommandStructure,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN AHCI_COMMAND_TABLE *Commandtable
+)
+{
+
+
+ pBS->CopyMem(&(Commandtable->AtapiCmd),&(CommandStructure.AtapiCmd),sizeof(AHCI_ATAPI_COMMAND));
+
+ if (Commandtable->CFis.Ahci_CFis_Cmd == PACKET_COMMAND){ // Is it a packet command?
+ CommandList->Ahci_Cmd_A = 1;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildPRDT
+//
+// Description: Build PRDT table
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN AHCI_COMMAND_TABLE *Commandtable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Build as many PRDT table entries based on ByteCount.
+// 2. Set the I flag for the lasr PRDT table.
+// 3. Update PRDT table lenght in CommandList
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildPRDT (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_STRUCTURE CommandStructure,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN AHCI_COMMAND_TABLE *Commandtable
+)
+{
+
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 ByteCount = CommandStructure.ByteCount;
+ UINT16 Prdtlength = 0;
+ AHCI_COMMAND_PRDT *PrdtTable = &(Commandtable->PrdtTable);
+
+ for (;ByteCount; (UINT8 *)PrdtTable += sizeof(AHCI_COMMAND_PRDT)){
+ PrdtTable->Ahci_Prdt_DBA = (UINT32)(UINTN)CommandStructure.Buffer;
+ PrdtTable->Ahci_Prdt_DBAU = (UINT32)Shr64((UINTN)CommandStructure.Buffer, 32);
+ PrdtTable->Ahci_Prdt_DBC = ByteCount >= PRD_MAX_DATA_COUNT ? (PRD_MAX_DATA_COUNT - 1) : (ByteCount - 1);
+ ByteCount -= (PrdtTable->Ahci_Prdt_DBC + 1);
+ PrdtTable->Ahci_Prdt_I = 0;
+ Prdtlength+= sizeof(AHCI_COMMAND_PRDT);
+ if ((UINT32)(Prdtlength + 0x80) >= AhciBusInterface->PortCommandTableLength) {
+ //ASSERT_EFI_ERROR(EFI_OUT_OF_RESOURCES);
+ break;
+ }
+ (UINT8 *)CommandStructure.Buffer += PrdtTable->Ahci_Prdt_DBC + 1;
+ }
+ // Set I flag only for the last entry.
+ (UINT8 *)PrdtTable -= sizeof(AHCI_COMMAND_PRDT);
+ PrdtTable->Ahci_Prdt_I = 1;
+ CommandList->Ahci_Cmd_PRDTL = Prdtlength / sizeof(AHCI_COMMAND_PRDT);
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StartController
+//
+// Description:
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT32 CIBitMask
+//
+// Output:
+// EFI_STATUS
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Clear Status register
+// 2. Enable FIS and CR running bit
+// 3. Enable Start bit
+// 4. Update CI bit mask
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+StartController (
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT32 CIBitMask
+)
+{
+
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ UINT8 Port = SataDevInterface->PortNumber;
+
+ // Clear Status
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ // Enable FIS Receive
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_FRE);
+
+ // Wait till FIS is running
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ // Clear FIS Receive area
+ ZeroMemory ((VOID *)(UINTN)SataDevInterface->PortFISBaseAddr, RECEIVED_FIS_SIZE);
+
+ // Enable ST
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_ST);
+
+ // Enable Command Issued
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CI, CIBitMask);
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitforCommandComplete
+//
+// Description: Wait till cmd completes
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_TYPE CommandType,
+// IN UINTN TimeOut
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check for SError bits. If set return error.
+// 2. For PIO IN/Out and Packet IN/OUT command wait till PIO Setup FIS is received
+// 3. If D2H register FIS is received, exit the loop.
+// 4. Check for SError and TFD bits.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitforCommandComplete (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN COMMAND_TYPE CommandType,
+ IN UINTN TimeOut
+)
+{
+
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 AhciBaseAddr = (UINT32)AhciBusInterface->AhciBaseAddress;
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT32 Data32_SERR, Data32_IS, i;
+ BOOLEAN PxSERR_ERROR = FALSE, PIO_SETUP_FIS = FALSE;
+ volatile AHCI_RECEIVED_FIS *FISReceiveAddress = (AHCI_RECEIVED_FIS *)(UINTN)SataDevInterface->PortFISBaseAddr;
+ UINTN TimeOutCount = TimeOut;
+
+ i=0;
+ do {
+ pBS->Stall(500);
+
+ // Check for Error bits
+ Data32_SERR = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_SERR);
+ if (Data32_SERR & HBA_PORTS_ERR_CHK) {
+ PxSERR_ERROR = TRUE;
+ break;
+ }
+
+ // Check for Error bits
+ Data32_IS = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_IS);
+ if (Data32_IS & HBA_PORTS_IS_ERR_CHK) {
+ PxSERR_ERROR = TRUE;
+ break;
+ }
+
+ switch (CommandType) {
+
+ case PIO_DATA_IN_CMD:
+ case PIO_DATA_OUT_CMD:
+ case PACKET_PIO_DATA_IN_CMD:
+ case PACKET_PIO_DATA_OUT_CMD:
+ // check if PIO setup received
+ if(FISReceiveAddress->Ahci_Psfis[0] == FIS_PIO_SETUP) {
+ FISReceiveAddress->Ahci_Psfis[0] = 0;
+ TimeOutCount = TimeOut;
+ PIO_SETUP_FIS = TRUE;
+ }
+ break;
+ default:
+ break;
+
+ }
+
+ // check if D2H register FIS is received
+ if(FISReceiveAddress->Ahci_Rfis[0] == FIS_REGISTER_D2H) break;
+
+ // For PIO Data in D2H register FIS is not received. So rely on BSY bit
+ if ((CommandType == PIO_DATA_IN_CMD) && PIO_SETUP_FIS &&
+ !((HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD) &
+ (HBA_PORTS_TFD_BSY | HBA_PORTS_TFD_DRQ)))){
+ break;
+ }
+ //If the Timeout is 0, Then there is no timeout for command processing
+ if(TimeOut==0) {
+ continue;
+ }
+ i++;
+ } while(i < TimeOutCount * 2);
+
+ if (PxSERR_ERROR) {
+ // clear the status and return error
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+ return EFI_DEVICE_ERROR;
+ }
+
+ // check if CI register is zero
+ if (HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_CI)){
+ return EFI_DEVICE_ERROR;
+ }
+
+ // check for status bits
+ if (HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD) & (HBA_PORTS_TFD_ERR | HBA_PORTS_TFD_DRQ)){
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StopController
+//
+// Description: Stop FIS and CR
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: GeneratePortReset
+//
+// Notes:
+// 1. clear ST bit and wait till CR bits gets reset
+// 2. if not generate Port reset
+// 3. Clear FIS running bit.
+// 4. Clear status register
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+StopController(
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN BOOLEAN StartOrStop
+)
+{
+
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 PMPort = SataDevInterface->PMPortNumber;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ EFI_STATUS Status;
+ UINT32 PortFISBaseAddr = SataDevInterface->PortFISBaseAddr;
+ UINT32 CommandListBaseAddress = SataDevInterface->PortCommandListBaseAddr;
+ UINT32 Data32;
+
+ if(StartOrStop && (HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB) != CommandListBaseAddress)) {
+ gCommandListBaseAddress=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB);
+ gFisBaseAddress=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_FB);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB,CommandListBaseAddress);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FB,PortFISBaseAddr);
+
+ //
+ // Saving the Upper 32 bits of FIS and Command List Registers
+ //
+ gCommandListBaseAddress2=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_CLBU);
+ gFisBaseAddress2=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_FBU);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLBU,0);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FBU,0);
+ }
+
+ // Clear Start
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~(HBA_PORTS_CMD_ST));
+ // Make sure CR is 0 with in 500msec
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_CR_CLEAR_TIMEOUT);
+
+ if (EFI_ERROR(Status)) {
+
+ // Get the Port Speed allowed and Interface Power Management Transitions Allowed
+ // Pass the values for PortReset.
+ Data32 = HBA_PORT_REG32 ((UINT32)(AhciBusInterface->AhciBaseAddress), Port, HBA_PORTS_SCTL);
+ Data32 &= 0xFF0;
+
+ Status = GeneratePortReset(AhciBusInterface, SataDevInterface, Port, PMPort,
+ (UINT8)((Data32 & 0xF0) >> 4), (UINT8)(Data32 >> 8));
+ };
+
+ if (EFI_ERROR(Status)) {
+ goto StopController_ErrorExit;
+ }
+
+ // Clear FIS receive enable.
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port,
+ HBA_PORTS_CMD, ~(HBA_PORTS_CMD_FRE));
+ // Make sure FR is 0 with in 500msec
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+
+StopController_ErrorExit:
+
+ // Clear Status register
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ if(!StartOrStop && gCommandListBaseAddress) {
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB,gCommandListBaseAddress);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FB,gFisBaseAddress);
+ //
+ // Restoring the Upper 32 bits of FIS and Command List Registers
+ //
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLBU,gCommandListBaseAddress2);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FBU,gFisBaseAddress2);
+
+ gCommandListBaseAddress = 0;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadytoAcceptCmd
+//
+// Description: Check if the device is ready to accept cmd.
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: GeneratePortReset, ReadWritePMPort
+//
+// Notes:
+// 1. Check the device is ready to accept the command. BSY and DRQ should be de-asserted.
+// 2. If set, generate Port reset
+// 3. In case Port Multiplier is connected to the port, enable all the ports of the Port Multiplier.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ReadytoAcceptCmd (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 PMPort = SataDevInterface->PMPortNumber;
+ SATA_DEVICE_INTERFACE *SataPMDevInterface, *SataPMPortDevInterface;
+ UINT32 Data32 = 0, Init_SStatus = 0;
+ UINT8 PowerManagement, Speed;
+
+ // Is the Device ready to accept the command
+ if (HBA_PORT_REG8 (AhciBaseAddr, Port, HBA_PORTS_TFD) & (HBA_PORTS_TFD_BSY | HBA_PORTS_TFD_DRQ)){
+ Data32 = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_SCTL);
+ Data32 &= 0xFF0;
+ // make sure the status we read is for the right port
+ Status = GeneratePortReset(AhciBusInterface, SataDevInterface, Port, 0xFF,
+ (UINT8)((Data32 & 0xF0) >> 4), (UINT8)(Data32 >> 8));
+ if (EFI_ERROR(Status)) return Status;
+
+ // If it is a PMPort, Make sure all the Ports are in enabled state.
+ SataPMDevInterface = GetSataDevInterface(AhciBusInterface, Port, 0xFF);
+ if (!SataPMDevInterface) {
+ return EFI_DEVICE_ERROR;
+ }
+ if (SataPMDevInterface->DeviceType == PMPORT) {
+ for (PMPort = 0; PMPort < SataPMDevInterface->NumPMPorts; PMPort++){
+ SataPMPortDevInterface = GetSataDevInterface(AhciBusInterface, Port, PMPort);
+ if (!SataPMPortDevInterface) continue;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_0_SSTATUS, &Init_SStatus, FALSE);
+ if ((Init_SStatus & HBA_PORTS_SSTS_DET_MASK) == HBA_PORTS_SSTS_DET_PCE) {
+ Data32 = SataPMPortDevInterface->SControl;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_2_SCONTROL, &Data32, TRUE);
+ }
+ else {
+ Speed = (UINT8)((SataDevInterface->SControl >> 4) & 0xF);
+ PowerManagement = (UINT8)((SataDevInterface->SControl >> 8) & 0xF);
+ GeneratePortReset(AhciBusInterface, SataDevInterface, Port, PMPort,
+ Speed, PowerManagement);
+ }
+ Data32 = HBA_PORTS_ERR_CLEAR;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_1_SERROR, &Data32, TRUE);
+ }
+ }
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HostReset
+//
+// Description:
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+//
+// Output:
+//
+// Modified:
+//
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+HostReset (
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface
+)
+{
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GeneratePortReset
+//
+// Description: Issue a Port Reset
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 CurrentPort,
+// IN UINT8 Speed,
+// IN UINT8 PowerManagement
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ReadWritePMPort, HandlePortComReset
+//
+// Notes:
+// 1. Issue port reset by setting DET bit in SControl register
+// 2. Call HandlePortComReset to check the status of the reset.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+GeneratePortReset (
+ AHCI_BUS_PROTOCOL *AhciBusInterface,
+ SATA_DEVICE_INTERFACE *SataDevInterface,
+ UINT8 Port,
+ UINT8 PMPort,
+ UINT8 Speed,
+ UINT8 PowerManagement
+)
+{
+
+ EFI_STATUS Status;
+ UINT32 AhciBaseAddr = (UINT32) AhciBusInterface->AhciBaseAddress;
+ volatile AHCI_RECEIVED_FIS *FISAddress = (AHCI_RECEIVED_FIS *)HBA_PORT_REG32(AhciBaseAddr, Port, HBA_PORTS_FB);
+ UINT32 Data32;
+
+ TRACE_AHCI_LEVEL2((-1,"AHCI: PortReset on Port : %x PMPort : %x", Port, PMPort));
+
+ if (!FISAddress) return EFI_DEVICE_ERROR; // FIS receive address is not programmed.
+
+ if (gPortReset) return EFI_SUCCESS;
+ gPortReset = TRUE;
+
+ // Disable Start bit
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~HBA_PORTS_CMD_ST);
+
+ // Wait till CR is cleared
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_CR_CLEAR_TIMEOUT);
+
+ // Clear Status register
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ if (PMPort != 0xFF) {
+ Data32 = HBA_PORTS_ERR_CLEAR;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_1_SERROR, &Data32, TRUE);
+ }
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ // Enable FIS Receive Enable
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_FRE);
+
+ // Wait till FIS is running and then clear the data area
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+
+ FISAddress->Ahci_Rfis[0] = 0;
+
+ if (PMPort == 0xFF) {
+ // Issue Port COMRESET
+ HBA_PORT_REG32_AND_OR (AhciBaseAddr, Port, HBA_PORTS_SCTL, 0xFFFFF000,
+ HBA_PORTS_SCTL_DET_INIT + (Speed << 4) + (PowerManagement << 8));
+ pBS->Stall (1000); // 1msec
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_SCTL, ~HBA_PORTS_SCTL_DET_MASK);
+ }
+ else {
+ Data32 = HBA_PORTS_SCTL_DET_INIT + (Speed << 4) + (PowerManagement << 8);
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_2_SCONTROL, &Data32, TRUE);
+ pBS->Stall (1000); // 1msec
+ Data32 = (Speed << 4) + (PowerManagement << 8);
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_2_SCONTROL, &Data32, TRUE);
+ }
+
+ Status = HandlePortComReset(AhciBusInterface, SataDevInterface, Port, PMPort);
+
+ // Disable FIS Receive Enable
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~HBA_PORTS_CMD_FRE);
+
+ SataDevInterface->SControl = (Speed << 4) + (PowerManagement << 8);
+
+ gPortReset = FALSE;
+
+ if (EFI_ERROR(Status)) {
+ TRACE_AHCI_LEVEL2((-1," Status : %r\n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+
+ TRACE_AHCI_LEVEL2((-1," Status : %r\n", Status));
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GenerateSoftReset
+//
+// Description: Generate Soft Reset
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// In UINT8 PMPort
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, BuildCommandList, BuildCommandFIS, StartController
+//
+// Notes:
+// 1. Issue a Control register update, H2D register FIS with reset bit set.
+// 2. Wait for 100usec
+// 3. Issue a Control register update, H2D register FIS with reset bit reset.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+GenerateSoftReset (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT8 PMPort
+
+)
+{
+
+ EFI_STATUS Status;
+ AHCI_BUS_PROTOCOL *AhciBusInterface = SataDevInterface->AhciBusInterface;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *)(UINTN) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)(UINTN)AhciBusInterface->PortCommandTableBaseAddr;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT32 Data32;
+ UINT8 Port = SataDevInterface->PortNumber;
+
+ TRACE_AHCI_LEVEL2((-1,"AHCI: SoftReset on Port : %x PMPort : %x", Port, PMPort));
+
+ PROGRESS_CODE(DXE_IDE_RESET);
+
+ if (gSoftReset) return EFI_SUCCESS;
+
+ gSoftReset = TRUE;
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ Status = StopController(AhciBusInterface, SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) {
+ goto GenerateSoftReset_Exit;
+ }
+
+
+ // if Command list Override is supported, set CLO bit
+ Data32 = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD) & (HBA_PORTS_TFD_DRQ | HBA_PORTS_TFD_BSY);
+ if ((AhciBusInterface->HBACapability & HBA_CAP_SCLO) && Data32){
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_CLO);
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CLO,
+ BUSY_CLEAR_TIMEOUT);
+ }
+
+ CommandStructure.Control = 4;
+ BuildCommandList(SataDevInterface, CommandList, (UINT32)(UINTN)Commandtable);
+ BuildCommandFIS(SataDevInterface, CommandStructure, CommandList, Commandtable);
+
+ CommandList->Ahci_Cmd_W = 0;
+ // Update of Control Register
+ Commandtable->CFis.Ahci_CFis_C = 0;
+ CommandList->Ahci_Cmd_R = 1;
+ CommandList->Ahci_Cmd_C= 1;
+
+ if (PMPort != 0xFF) Commandtable->CFis.AHci_CFis_PmPort = PMPort;
+
+ StartController(AhciBusInterface, SataDevInterface, BIT00);
+ // Wait till command is processed
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CI,
+ BIT00,
+ ONE_MILLISECOND * 5);
+
+ // Is the command complete?
+ if (EFI_ERROR(Status)){
+ goto GenerateSoftReset_Exit;
+ }
+ pBS->Stall (100); // 100 usec
+
+ ZeroMemory (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+ BuildCommandList(SataDevInterface, CommandList, (UINT32)(UINTN)Commandtable);
+ BuildCommandFIS(SataDevInterface, CommandStructure, CommandList, Commandtable);
+
+ CommandList->Ahci_Cmd_W = 0;
+ // Update of Control Register
+ Commandtable->CFis.Ahci_CFis_C = 0;
+ if (PMPort != 0xFF) Commandtable->CFis.AHci_CFis_PmPort = PMPort;
+
+ StartController(AhciBusInterface, SataDevInterface, BIT00);
+ Status = WaitforCommandComplete(SataDevInterface, NON_DATA_CMD, ATAPI_BUSY_CLEAR_TIMEOUT);
+
+ // Stop Controller
+ StopController(AhciBusInterface, SataDevInterface,FALSE);
+
+GenerateSoftReset_Exit:
+
+ gSoftReset = FALSE;
+ TRACE_AHCI_LEVEL2((-1," Status : %r\n", Status));
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HandlePortComReset
+//
+// Description: Check if COM Reset is successful or not
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ReadSCRRegister, WriteSCRRegister
+//
+// Notes:
+// 1. Check if Link is active. If not return error.
+// 2. If Link is present, wait for PhyRdy Change bit to be set.
+// 3. Clear SError register
+// 4. Wait for D2H register FIS
+// 5. Check the Status register for errors.
+// 6. If COMRESET is success wait for sometime if the device is ATAPI or GEN1
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+HandlePortComReset(
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ BOOLEAN DeviceDetected = FALSE;
+ UINT32 Data32, i, SStatusData;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+ volatile AHCI_RECEIVED_FIS *FISAddress;
+ UINT32 SError = 0;
+ // Check if detection is complete
+ for (i = 0; i < HBA_PRESENCE_DETECT_TIMEOUT; i++){ // Total delay 10msec
+ SStatusData = ReadSCRRegister (AhciBusInterface, SataDevInterface, Port, PMPort, 0); // SStatus
+ SStatusData &= HBA_PORTS_SSTS_DET_MASK;
+ if ((SStatusData == HBA_PORTS_SSTS_DET_PCE) || (SStatusData == HBA_PORTS_SSTS_DET)) {
+ DeviceDetected = TRUE;
+ break;
+ }
+ pBS->Stall (1000); // 1msec
+ }
+
+ if (DeviceDetected) {
+ // Wait till PhyRdy Change bit is set
+ if (PMPort == 0xFF) {
+ Status = WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_SERR,
+ HBA_PORTS_SERR_EX,
+ HBA_PORTS_SERR_EX,
+ ATAPI_BUSY_CLEAR_TIMEOUT);
+ }
+ else {
+ Status = WaitforPMMemSet (SataDevInterface, PMPort, PSCR_1_SERROR,
+ HBA_PORTS_SERR_EX, HBA_PORTS_SERR_EX, ATAPI_BUSY_CLEAR_TIMEOUT);
+ }
+
+ FISAddress = (AHCI_RECEIVED_FIS *)HBA_PORT_REG32(AhciBaseAddr, Port, HBA_PORTS_FB);
+
+ for (i = 0; i < ATAPI_BUSY_CLEAR_TIMEOUT; ) {
+ SError = ReadSCRRegister (AhciBusInterface, SataDevInterface, Port, PMPort, 2); // SError
+ if (SError & HBA_PORTS_ERR_CHK) {
+ WriteSCRRegister (AhciBusInterface, SataDevInterface, Port, PMPort, 1, HBA_PORTS_ERR_CLEAR ); //SError
+ }
+ if(FISAddress->Ahci_Rfis[0] == FIS_REGISTER_D2H) {break;}
+ pBS->Stall (1000); // 1msec Strange. Delay is needed for read to succeed.
+ if (PMPort != 0xFF) {i+= 100;} // For device behind PM Port, there is a delay in writing to the register. So count can be decreased.
+ else { i++; }
+ }
+
+ // Wait till PxTFD gets updated from D2H FIS
+ for (i = 0; i < 100; i++){ // Total delay 10msec
+ WriteSCRRegister (AhciBusInterface, SataDevInterface, Port, PMPort, 1, HBA_PORTS_ERR_CLEAR); //SError
+ if((FISAddress->Ahci_Rfis[2] & HBA_PORTS_TFD_MASK) == (HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD) & HBA_PORTS_TFD_MASK)) break;
+ pBS->Stall (100); // 100usec
+ }
+
+ // check for errors
+ if (FISAddress->Ahci_Rfis[2] & (HBA_PORTS_TFD_BSY | HBA_PORTS_TFD_ERR)) Status = EFI_DEVICE_ERROR;
+
+ Data32 = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_IS);
+ if (Data32 & (BIT30 + BIT29 + BIT28 + BIT27 + BIT26)) Status = EFI_DEVICE_ERROR;
+
+ // Clear the status
+ WriteSCRRegister (AhciBusInterface, SataDevInterface, Port, PMPort, 1, HBA_PORTS_ERR_CLEAR); //SError
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ }
+ else {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadSCRRegister
+//
+// Description:
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort,
+// IN UINT8 Register (0 : SStatus 1: SError 2: SControl)
+//
+// Output:
+// UINT32
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check if the device is connected directly to the port
+// 2. if yes, read to the AHCI Controller else write to the Port Multiplier register.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32
+ReadSCRRegister (
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort,
+ IN UINT8 Register
+)
+{
+
+ UINT32 Data32 = 0;
+ UINT32 Reg = HBA_PORTS_SSTS;
+
+ if (PMPort != 0xFF) {
+ ReadWritePMPort (SataDevInterface, PMPort, Register, &Data32, FALSE);
+ }
+ else {
+ if (Register == 1) Reg = HBA_PORTS_SCTL;
+ if (Register == 2) Reg = HBA_PORTS_SERR;
+ Data32 = HBA_PORT_REG32 (AhciBusInterface->AhciBaseAddress, Port, Reg);
+ }
+
+ return Data32;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WriteSCRRegister
+//
+// Description: Write to SCONTROL/Serror/SStatus register
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort,
+// IN UINT8 Register, (0 : SStatus 1: SError 2: SControl)
+// IN UINT32 Data32
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check if the device is connected directly to the port
+// 2. if yes, write to the AHCI Controller else write to the Port Multiplier register
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WriteSCRRegister (
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort,
+ IN UINT8 Register,
+ IN UINT32 Data32
+)
+{
+
+ UINT32 Reg = HBA_PORTS_SSTS;
+
+ if (PMPort != 0xFF) {
+ ReadWritePMPort (SataDevInterface, PMPort, Register, &Data32, TRUE);
+ }
+ else {
+ if (Register == 2) Reg = HBA_PORTS_SCTL;
+ if (Register == 1) Reg = HBA_PORTS_SERR;
+ HBA_PORT_REG32_OR (AhciBusInterface->AhciBaseAddress, Port, Reg, Data32);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitforPMMemSet
+//
+// Description: Wait for memory to be set to the test value.
+//
+// Input:
+// SATA_DEVICE_INTERFACE *SataDevInterface,
+// PMPort
+// Register
+// MaskValue - The mask value of memory
+// TestValue - The test value of memory
+// WaitTimeInMs - The time out value for wait memory set
+//
+// Output: EFI_SUCCESS - HBA reset successfully.
+// EFI_DEVICE_ERROR - HBA failed to complete hardware reset.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitforPMMemSet (
+ IN SATA_DEVICE_INTERFACE *SataDevInterface,
+ IN UINT8 PMPort,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 TestValue,
+ IN UINT32 WaitTimeInMs
+)
+{
+ UINT32 Data32;
+
+ while(WaitTimeInMs!=0){
+ ReadWritePMPort (SataDevInterface, PMPort, Register, &Data32, FALSE);
+ if((Data32 & AndMask) == TestValue) {return EFI_SUCCESS;}
+ pBS->Stall (1000); // 1Msec
+ WaitTimeInMs--;
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckValidDevice
+//
+// Description: Check for valid ATA/ATAPI/PMPORT signature
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check if Link is active
+// 2. Enable FIS and Command list run bits
+// 3. Check for valid signature
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+CheckValidDevice (
+ IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort
+)
+{
+
+ UINT8 Data8;
+ UINT32 Data32;
+ UINT32 AhciBaseAddr = (UINT32)(AhciBusInterface->AhciBaseAddress);
+
+ // Check if Link is active
+ Data8 = (UINT8)(HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_SSTS) & HBA_PORTS_SSTS_DET_MASK);
+ if (Data8 != HBA_PORTS_SSTS_DET_PCE) return EFI_DEVICE_ERROR;
+
+ // Enable FIS receive and CI so that TFD gets updated properly
+ // Clear out the command slot
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CI, 0);
+
+ // Enable FIS Receive
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_FRE | HBA_PORTS_CMD_ST);
+
+ // Wait till FIS is running
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ // Wait till CR list is running
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_PORTS_CMD_CR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ // Clear Start Bit
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~(HBA_PORTS_CMD_ST));
+ WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_CR_CLEAR_TIMEOUT);
+
+ //Clear FIS Receive enable bit
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~(HBA_PORTS_CMD_FRE));
+ WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+
+ // Check if valid signature is present
+ Data32 = HBA_PORT_REG32(AhciBaseAddr, Port, HBA_PORTS_SIG);
+ if (Data32 != ATA_SIGNATURE_32 && Data32 != ATAPI_SIGNATURE_32 && Data32 != PMPORT_SIGNATURE)
+ return EFI_DEVICE_ERROR;
+
+ Data8 = HBA_PORT_REG8 (AhciBaseAddr, Port, HBA_PORTS_TFD);
+ if (Data8 & (HBA_PORTS_TFD_BSY | HBA_PORTS_TFD_DRQ)) return EFI_DEVICE_ERROR;
+
+ return EFI_SUCCESS;
+
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Ahci/AhciController.h b/Core/EM/Ahci/AhciController.h
new file mode 100644
index 0000000..9ec5e75
--- /dev/null
+++ b/Core/EM/Ahci/AhciController.h
@@ -0,0 +1,633 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciController.h 9 11/13/13 1:52a Divyac $
+//
+// $Revision: 9 $
+//
+// $Date: 11/13/13 1:52a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciController.h $
+//
+// 9 11/13/13 1:52a Divyac
+// [TAG] EIP143018
+// [Category] Improvement
+// [Description] Removed the EIP 128912 changes and checked-in again.
+// EIP 128912 changes creates lot more side effect, so we planed to remove
+// the changes.
+// [Files] AhciController.h
+//
+// 8 7/23/13 11:56p Srikantakumarp
+// [TAG] EIP129989
+// [Category] Improvement
+// [Description] Added DIPM support in Aptio 4.x AHCIBUS driver.
+// [Files] AhciBus.c, AhciBus.h, AhciController.h, AhciSrc.sdl,
+// PAhciBus.h
+//
+// 7 7/18/13 7:35a Rameshr
+// [TAG] EIP128912
+// [Category] Improvement
+// [Description] 10b to 8b decode error is mentioned as Diagnostic error
+// for use by Diagnostic software, So removed this error status checking
+// [Files] AhciController.h
+//
+// 6 7/17/13 10:40a Rameshr
+// [TAG] EIP128912
+// [Category] Improvement
+// [Description] 10b to 8b decode error is mentioned as Diagnostic error
+// for use by Diagnostic software, So removed this error status checking.
+// [Files] AhciController.h
+//
+// 5 2/10/11 10:35a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSrc.mak
+// AhciBus.c
+// AhciController.c
+// AhciComponentName.c
+// AhciBus.h
+// AhciController.h
+//
+// 4 5/07/10 11:45a Krishnakumarg
+// Coding standard update
+//
+// 3 7/09/09 4:50p Fasihm
+// Fixed the Read/Write failure when ALPE is Enabled.
+//
+// 2 5/28/08 9:39a Rameshraju
+// Based on the SDL token index/data or MMIO method used to access the
+// AHCI configuration space.
+//
+// 1 28/02/08 6:03p Anandakrishnanl
+// AHCI Bus Driver initial check-in.
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AhciController.h
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+// Forward reference for pure ANSI compatability
+typedef struct _AHCI_COMMAND_FIS AHCI_COMMAND_FIS;
+typedef struct _AHCI_ATAPI_COMMAND AHCI_ATAPI_COMMAND;
+typedef struct _AHCI_COMMAND_PRDT AHCI_COMMAND_PRDT;
+
+#pragma pack(1)
+
+// Command List Structure
+typedef struct {
+ UINT32 Ahci_Cmd_CFL:5;
+ UINT32 Ahci_Cmd_A:1;
+ UINT32 Ahci_Cmd_W:1;
+ UINT32 Ahci_Cmd_P:1;
+ UINT32 Ahci_Cmd_R:1;
+ UINT32 Ahci_Cmd_B:1;
+ UINT32 Ahci_Cmd_C:1;
+ UINT32 Ahci_Cmd_Rsvd1:1;
+ UINT32 Ahci_Cmd_PMP:4;
+ UINT32 Ahci_Cmd_PRDTL:16;
+ UINT32 Ahci_Cmd_PRDBC;
+ UINT32 Ahci_Cmd_CTBA;
+ UINT32 Ahci_Cmd_CTBAU;
+ UINT32 Ahci_Cmd_Rsvd2[4];
+} AHCI_COMMAND_LIST;
+
+typedef struct {
+ UINT8 Ahci_Dsfis[0x1C]; // DMA Setup Fis
+ UINT8 Ahci_Dsfis_Rsvd[0x04];
+ UINT8 Ahci_Psfis[0x14]; // PIO Setip Fis
+ UINT8 Ahci_Psfis_Rsvd[0x0C];
+ UINT8 Ahci_Rfis[0x14]; // D2H Register Fis
+ UINT8 Ahci_Rfis_Rsvd[0x04];
+ UINT64 Ahci_Sdbfis; // Set Device Bits Fis
+ UINT8 Ahci_Ufis[0x40]; // Unkonw FIS
+ UINT8 Ahci_Ufis_Rsvd[0x60];
+} AHCI_RECEIVED_FIS;
+
+// Register - Host to Device FIS Layout
+typedef struct _AHCI_COMMAND_FIS{
+ UINT8 Ahci_CFis_Type;
+ UINT8 AHci_CFis_PmPort:4;
+ UINT8 Ahci_CFis_Rsvd1:1;
+ UINT8 Ahci_CFis_Rsvd2:1;
+ UINT8 Ahci_CFis_Rsvd3:1;
+ UINT8 Ahci_CFis_C:1;
+ UINT8 Ahci_CFis_Cmd;
+ UINT8 Ahci_CFis_Features;
+ UINT8 Ahci_CFis_SecNum;
+ UINT8 Ahci_CFis_ClyLow;
+ UINT8 Ahci_CFis_ClyHigh;
+ UINT8 Ahci_CFis_DevHead;
+ UINT8 Ahci_CFis_SecNumExp;
+ UINT8 Ahci_CFis_ClyLowExp;
+ UINT8 Ahci_CFis_ClyHighExp;
+ UINT8 Ahci_CFis_FeaturesExp;
+ UINT8 Ahci_CFis_SecCount;
+ UINT8 Ahci_CFis_SecCountExp;
+ UINT8 Ahci_CFis_Rsvd4;
+ UINT8 Ahci_CFis_Control;
+ UINT8 Ahci_CFis_Rsvd5[4];
+ UINT8 Ahci_CFis_Rsvd6[44];
+} AHCI_COMMAND_FIS;
+
+// Physical Region Descriptor Table
+typedef struct _AHCI_COMMAND_PRDT{
+ UINT32 Ahci_Prdt_DBA;
+ UINT32 Ahci_Prdt_DBAU;
+ UINT32 Ahci_Prdt_Rsvd;
+ UINT32 Ahci_Prdt_DBC:22;
+ UINT32 Ahci_Prdt_Rsvd1:9;
+ UINT32 Ahci_Prdt_I:1;
+} AHCI_COMMAND_PRDT;
+
+// Command table
+
+typedef struct _AHCI_COMMAND_TABLE{
+ AHCI_COMMAND_FIS CFis;
+ AHCI_ATAPI_COMMAND AtapiCmd;
+ UINT8 Rsvd[0x30];
+ AHCI_COMMAND_PRDT PrdtTable;
+} AHCI_COMMAND_TABLE;
+
+typedef struct _AHCI_COMMAND_TABLE_NO_PRDT{
+ AHCI_COMMAND_FIS CFis;
+ AHCI_ATAPI_COMMAND AtapiCmd;
+ UINT8 Rsvd[0x30];
+} AHCI_COMMAND_TABLE_NO_PRDT;
+
+#pragma pack()
+
+#define ATA_SIGNATURE_32 0x00000101
+#define ATAPI_SIGNATURE_32 0xEB140101
+#define PMPORT_SIGNATURE 0x96690101
+#define PRD_MAX_DATA_COUNT 0x400000
+
+
+
+#define PCI_ABAR 0x24
+#define RECEIVED_FIS_SIZE 0x100
+
+#define CONTROL_PORT 0x0F
+
+//Generic Host Control Registers
+#define HBA_CAP 0x0000
+#define HBA_CAP_NP_MASK 0x1F
+#define HBA_CAP_EMS BIT06
+#define HBA_CAP_PSC BIT13
+#define HBA_CAP_SSC BIT14
+#define HBA_CAP_PMD BIT15
+#define HBA_CAP_FBSS BIT16
+#define HBA_CAP_SPM BIT17
+#define HBA_CAP_SAM BIT18
+#define HBA_CAP_SNZO BIT19
+#define HBA_CAP_ISS_MASK (BIT20 | BIT21 | BIT22 | BIT23)
+#define HBA_CAP_SCLO BIT24
+#define HBA_CAP_SAL BIT25
+#define HBA_CAP_SALP BIT26
+#define HBA_CAP_SSS BIT27
+#define HBA_CAP_SMPS bit28
+#define HBA_CAP_SSNTF BIT29
+#define HBA_CAP_SCQA BIT30
+#define HBA_CAP_S64A BIT31
+
+#define HBA_GHC 0x0004
+#define HBA_GHC_RESET 0x0001
+#define HBA_GHC_IE 0x0002
+#define HBA_GHC_AE 0x80000000
+#define HBA_GHC_AE_RESET 0x80000001
+#define HBA_IS 0x0008
+#define HBA_PI 0x000C
+#define HBA_VS 0x0010
+#define HBA_CCC_CTL 0x0014
+#define HBA_CCC_PORTS 0x0018
+#define HBA_EM_LOC 0x001C
+#define HBA_EM_CTL 0x0020
+#define HBA_CAP2 0x0024
+#define HBA_CAP2_APST 0x0004
+#define HBA_CAP2_SDS 0x0008
+#define HBA_CAP2_SADM 0x0010
+#define HBA_CAP2_DESO 0x0020
+
+//Port Registers
+#define HBA_PORTS_START 0x0100
+#define HBA_PORTS_REG_WIDTH 0x0080
+#define HBA_PORTS_CLB 0x0000
+#define HBA_PORTS_CLBU 0x0004
+#define HBA_PORTS_FB 0x0008
+#define HBA_PORTS_FBU 0x000C
+#define HBA_PORTS_IS 0x0010
+#define HBA_PORTS_IS_DHRS BIT00
+#define HBA_PORTS_IS_PSS BIT01
+#define HBA_PORTS_IS_SSS BIT02
+#define HBA_PORTS_IS_SDBS BIT03
+#define HBA_PORTS_IS_UFS BIT04
+#define HBA_PORTS_IS_DPS BIT05
+#define HBA_PORTS_IS_PCS BIT06
+#define HBA_PORTS_IS_DIS BIT07
+#define HBA_PORTS_IS_PRCS BIT22
+#define HBA_PORTS_IS_IPMS BIT23
+#define HBA_PORTS_IS_OFS BIT24
+#define HBA_PORTS_IS_INFS BIT26
+#define HBA_PORTS_IS_IFS BIT27
+#define HBA_PORTS_IS_HBDS BIT28
+#define HBA_PORTS_IS_HBFS BIT29
+#define HBA_PORTS_IS_TFES BIT30
+#define HBA_PORTS_IS_CPDS BIT31
+#define HBA_PORTS_IS_CLEAR 0xFFC000FF
+#define HBA_PORTS_IS_FIS_CLEAR 0x0000001F
+#define HBA_PORTS_IS_ERR_CHK BIT04 + BIT06 + BIT23 + BIT24 + BIT27 + \
+ BIT28 + BIT29 + BIT30 + BIT31
+
+#define HBA_PORTS_IE 0x0014
+#define HBA_PORTS_CMD 0x0018
+#define HBA_PORTS_CMD_ST_MASK 0xFFFFFFFE
+#define HBA_PORTS_CMD_ST BIT00
+#define HBA_PORTS_CMD_SUD BIT01
+#define HBA_PORTS_CMD_POD BIT02
+#define HBA_PORTS_CMD_CLO BIT03
+#define HBA_PORTS_CMD_CR BIT15
+#define HBA_PORTS_CMD_FRE BIT04
+#define HBA_PORTS_CMD_FR BIT14
+#define HBA_PORTS_CMD_MASK ~(HBA_PORTS_CMD_ST | HBA_PORTS_CMD_FRE | HBA_PORTS_CMD_CLO)
+#define HBA_PORTS_CMD_PMA BIT17
+#define HBA_PORTS_CMD_HPCP BIT18
+#define HBA_PORTS_CMD_MPSP BIT19
+#define HBA_PORTS_CMD_CPD BIT20
+#define HBA_PORTS_CMD_ESP BIT21
+#define HBA_PORTS_CMD_ATAPI BIT24
+#define HBA_PORTS_CMD_DLAE BIT25
+#define HBA_PORTS_CMD_ALPE BIT26
+#define HBA_PORTS_CMD_ASP BIT27
+#define HBA_PORTS_CMD_ICC_MASK (BIT28 | BIT29 | BIT30 | BIT31)
+#define HBA_PORTS_CMD_ACTIVE (1 << 28 )
+#define HBA_PORTS_TFD 0x0020
+#define HBA_PORTS_TFD_MASK (BIT07 | BIT03 | BIT00)
+#define HBA_PORTS_TFD_BSY BIT07
+#define HBA_PORTS_TFD_DRQ BIT03
+#define HBA_PORTS_TFD_ERR BIT00
+#define HBA_PORTS_TFD_ERR_MASK 0x00FF00 // BIT8 - BIT15
+#define HBA_PORTS_SIG 0x0024
+#define HBA_PORTS_SSTS 0x0028
+#define HBA_PORTS_SSTS_DET_MASK 0x000F
+#define HBA_PORTS_SSTS_DET 0x0001
+#define HBA_PORTS_SSTS_DET_PCE 0x0003
+#define HBA_PORTS_SSTS_SPD_MASK 0x00F0
+#define HBA_PORTS_SCTL 0x002C
+#define HBA_PORTS_SCTL_DET_MASK 0x000F
+#define HBA_PORTS_SCTL_MASK (~HBA_PORTS_SCTL_DET_MASK)
+#define HBA_PORTS_SCTL_DET_INIT 0x0001
+#define HBA_PORTS_SCTL_DET_PHYCOMM 0x0003
+#define HBA_PORTS_SCTL_SPD_MASK 0x00F0
+#define HBA_PORTS_SCTL_SPD_NSNR 0x0
+#define HBA_PORTS_SCTL_SPD_GEN1 0x1
+#define HBA_PORTS_SCTL_SPD_GEN2 0x2
+#define HBA_PORTS_SCTL_SPD_GEN3 0x3
+#define HBA_PORTS_SCTL_IPM_MASK 0x0F00
+#define HBA_PORTS_SCTL_IPM_DIS 0x00
+#define HBA_PORTS_SCTL_IPM_PSD 0x01
+#define HBA_PORTS_SCTL_IPM_SSD 0x02
+#define HBA_PORTS_SCTL_IPM_PSSD 0x03
+#define HBA_PORTS_SCTL_IPM_PSD_SSD 0x0300
+#define HBA_PORTS_SERR 0x0030
+#define HBA_PORTS_SERR_RDIE BIT00
+#define HBA_PORTS_SERR_RCE BIT01
+#define HBA_PORTS_SERR_TDIE BIT08
+#define HBA_PORTS_SERR_PCDIE BIT09
+#define HBA_PORTS_SERR_PE BIT10
+#define HBA_PORTS_SERR_IE BIT11
+#define HBA_PORTS_SERR_PRC BIT16
+#define HBA_PORTS_SERR_PIE BIT17
+#define HBA_PORTS_SERR_CW BIT18
+#define HBA_PORTS_SERR_BDE BIT19
+#define HBA_PORTS_SERR_DE BIT20 // Not used
+#define HBA_PORTS_SERR_CRCE BIT21
+#define HBA_PORTS_SERR_HE BIT22
+#define HBA_PORTS_SERR_LSE BIT23
+#define HBA_PORTS_SERR_TSTE BIT24
+#define HBA_PORTS_SERR_UFT BIT25
+#define HBA_PORTS_SERR_EX BIT26
+#define HBA_PORTS_PxSACT 0x0034
+#define HBA_PORTS_PxCI 0x0038
+#define HBA_PORTS_PxDEVSLP 0x0044
+#define HBA_PORTS_PxDEVSLP_ADSE BIT00
+#define HBA_PORTS_PxDEVSLP_DSP BIT01
+#define HBA_PORTS_PxDEVSLP_DETO_MASK (0x000003FC)
+#define HBA_PORTS_PxDEVSLP_DMDAT_MASK (0x00007C00)
+#define HBA_PORTS_PxDEVSLP_DITO_MASK (0x01FF8000)
+#define HBA_PORTS_PxDEVSLP_DM_MASK (0x1E000000)
+
+#define HBA_PORTS_ERR_CHK (HBA_PORTS_SERR_TDIE + HBA_PORTS_SERR_PCDIE +\
+ HBA_PORTS_SERR_PE + HBA_PORTS_SERR_IE + \
+ HBA_PORTS_SERR_PIE + \
+ HBA_PORTS_SERR_BDE + \
+ HBA_PORTS_SERR_DE + HBA_PORTS_SERR_CRCE + \
+ HBA_PORTS_SERR_HE + HBA_PORTS_SERR_LSE + \
+ HBA_PORTS_SERR_TSTE + HBA_PORTS_SERR_UFT + \
+ HBA_PORTS_SERR_EX)
+
+#define HBA_PORTS_ERR_CLEAR (HBA_PORTS_SERR_RDIE + HBA_PORTS_SERR_RCE +\
+ HBA_PORTS_SERR_TDIE + HBA_PORTS_SERR_PCDIE +\
+ HBA_PORTS_SERR_PE + HBA_PORTS_SERR_IE + \
+ HBA_PORTS_SERR_PRC + HBA_PORTS_SERR_PIE + \
+ HBA_PORTS_SERR_CW + HBA_PORTS_SERR_BDE + \
+ HBA_PORTS_SERR_DE + HBA_PORTS_SERR_CRCE + \
+ HBA_PORTS_SERR_HE + HBA_PORTS_SERR_LSE + \
+ HBA_PORTS_SERR_TSTE + HBA_PORTS_SERR_UFT + \
+ HBA_PORTS_SERR_EX)
+#define HBA_PORTS_SACT 0x0034
+#define HBA_PORTS_CI 0x0038
+#define HBA_PORTS_SNTF 0x003C
+
+//FIS Types
+#define D2H_FIS_OFFSET 0x40
+#define DMA_FIS_OFFSET 0x00
+#define PIO_FIS_OFFSET 0x20
+#define SDB_FIS_OFFSET 0x58
+#define FIS_TYPE_MASK 0xFF
+#define U_FIS_OFFSET 0x60
+
+#define FIS_REGISTER_H2D 0x27 // Host To Device
+#define FIS_REGISTER_H2D_LENGTH 20
+#define FIS_REGISTER_D2H 0x34 // Device To Host
+#define FIS_REGISTER_D2H_LENGTH 20 // Device To Host
+#define FIS_DMA_ACTIVATE 0x39 // Device To Host
+#define FIS_DMA_ACTIVATE_LENGTH 4
+#define FIS_DMA_SETUP 0x41 // Bi-directional
+#define FIS_DMA_SETUP_LENGTH 28
+#define FIS_DATA 0x46 // Bi-directional
+#define FIS_BIST 0x58 // Bi-directional
+#define FIS_BIST_LENGTH 12
+#define FIS_PIO_SETUP 0x5F // Device To Host
+#define FIS_PIO_SETUP_LENGTH 20
+#define FIS_SET_DEVICE 0xA1 // Device To Host
+#define FIS_SET_DEVICE_LENGTH 8
+
+
+#define READ_PORT_MULTIPLIER 0xE4
+#define WRITE_PORT_MULTIPLIER 0xE8
+
+#define GSCR_0 0x00
+#define GSCR_1 0x01
+#define GSCR_2 0x02
+#define GSCR_32 32
+#define GSCR_64 64
+#define GSCR_96 96
+
+#define PSCR_0_SSTATUS 0x00
+#define PSCR_1_SERROR 0x01
+#define PSCR_2_SCONTROL 0x02
+
+
+#define HBA_CR_CLEAR_TIMEOUT 500 // AHCI 1.2 spec 10.1.2
+#define HBA_FR_CLEAR_TIMEOUT 500 // AHCI 1.2 spec 10.1.2
+#define HBA_PRESENCE_DETECT_TIMEOUT 10 // 10msec Serial ATA 1.0 Sec 5.2
+
+#if INDEX_DATA_PORT_ACCESS
+
+ //
+ //Index , Data port access
+ //
+
+#define HBA_PORT_REG_BASE(Port) \
+ (UINTN) (Port * HBA_PORTS_REG_WIDTH + HBA_PORTS_START)
+
+#define HBA_REG32( BaseAddr, Register ) \
+ (ReadDataDword ((BaseAddr), (Register)))
+
+#define HBA_WRITE_REG32( BaseAddr, Register, Data ) \
+ (WriteDataDword( BaseAddr, Register, Data ))
+
+#define HBA_REG16( BaseAddr, Register ) \
+ (ReadDataWord( BaseAddr, Register ))
+
+#define HBA_WRITE_REG16( BaseAddr, Register, Data ) \
+ (WriteDataWord( BaseAddr, Register, Data ))
+
+#define HBA_REG8( BaseAddr, Register ) \
+ (ReadDataByte ((BaseAddr), (Register)))
+
+#define HBA_WRITE_REG8( BaseAddr, Register, Data ) \
+ (WriteDataByte( BaseAddr, Register, Data ))
+
+#define HBA_REG8_OR( BaseAddr, Register, OrData) \
+ HBA_WRITE_REG8(BaseAddr, Register, ((HBA_REG8 ((BaseAddr), (Register))) | ((UINT8) (OrData))))
+
+#define HBA_REG16_OR( BaseAddr, Register, OrData) \
+ HBA_WRITE_REG16(BaseAddr, Register, ((HBA_REG16 ((BaseAddr), (Register))) | ((UINT16) (OrData))))
+
+#define HBA_REG32_OR( BaseAddr, Register, OrData) \
+ HBA_WRITE_REG32(BaseAddr, Register, ((HBA_REG32 ((BaseAddr), (Register))) | ((UINT32) (OrData))))
+
+#define HBA_REG8_AND( BaseAddr, Register, AndData) \
+ HBA_WRITE_REG8(BaseAddr, Register, ((HBA_REG8 ((BaseAddr), (Register))) & ((UINT8) (AndData))))
+
+#define HBA_REG16_AND( BaseAddr, Register, AndData) \
+ HBA_WRITE_REG16(BaseAddr, Register, ((HBA_REG16 ((BaseAddr), (Register))) & ((UINT16) (AndData))))
+
+#define HBA_REG32_AND( BaseAddr, Register, AndData) \
+ HBA_WRITE_REG32(BaseAddr, Register, ((HBA_REG32 ((BaseAddr), (Register))) & ((UINT32) (AndData))))
+
+#define HBA_REG8_AND_OR( BaseAddr, Register, AndData, OrData) \
+ HBA_WRITE_REG8(BaseAddr, Register, ((HBA_REG8 ((BaseAddr), (Register))) & ((UINT8) (AndData)) | ((UINT8) (OrData))))
+
+#define HBA_REG16_AND_OR( BaseAddr, Register, AndData, OrData) \
+ HBA_WRITE_REG16(BaseAddr, Register, ((HBA_REG16 ((BaseAddr), (Register))) & ((UINT16) (AndData)) | ((UINT16) (OrData))))
+
+#define HBA_REG32_AND_OR( BaseAddr, Register,AndData, OrData) \
+ HBA_WRITE_REG32(BaseAddr, Register, ((HBA_REG32 ((BaseAddr), (Register))) & ((UINT32) (AndData)) | ((UINT32) (OrData))))
+
+//Ports
+#define HBA_PORT_REG8(BaseAddr, Port, Register) \
+ (HBA_REG8 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port))))
+
+#define HBA_PORT_REG16(BaseAddr, Port, Register) \
+ (HBA_REG16 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port))))
+
+#define HBA_PORT_REG32(BaseAddr, Port, Register) \
+ (HBA_REG32 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port))))
+
+#define HBA_PORT_WRITE_REG8(BaseAddr, Port, Register, Data) \
+ (HBA_WRITE_REG8 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), Data))
+
+#define HBA_PORT_WRITE_REG16(BaseAddr, Port, Register, Data) \
+ (HBA_WRITE_REG16 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)),Data))
+
+#define HBA_PORT_WRITE_REG32(BaseAddr, Port, Register,Data) \
+ (HBA_WRITE_REG32 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)),Data))
+
+#define HBA_PORT_REG8_OR(BaseAddr, Port, Register, OrData) \
+ (HBA_REG8_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (OrData)))
+
+#define HBA_PORT_REG16_OR(BaseAddr, Port, Register, OrData) \
+ (HBA_REG16_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (OrData)))
+
+#define HBA_PORT_REG32_OR(BaseAddr, Port, Register, OrData) \
+ (HBA_REG32_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (OrData)))
+
+#define HBA_PORT_REG8_AND(BaseAddr, Port, Register, AndData) \
+ (HBA_REG8_AND ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData)))
+
+#define HBA_PORT_REG16_AND(BaseAddr, Port, Register, AndData) \
+ (HBA_REG16_AND ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData)))
+
+#define HBA_PORT_REG32_AND(BaseAddr, Port, Register, AndData) \
+ (HBA_REG32_AND ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData)))
+
+#define HBA_PORT_REG8_AND_OR(BaseAddr, Port, Register, AndData, OrData) \
+ (HBA_REG8_AND_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData), (OrData)))
+
+#define HBA_PORT_REG16_AND_OR(BaseAddr, Port, Register, AndData, OrData) \
+ (HBA_REG16_AND_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData), (OrData)))
+
+#define HBA_PORT_REG32_AND_OR(BaseAddr, Port, Register, AndData, OrData) \
+ (HBA_REG32_AND_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData), (OrData)))
+
+#else
+ //
+ //MMIO Access
+ //
+#define MmAddress( BaseAddr, Register ) \
+ ((UINTN)(BaseAddr) + \
+ (UINTN)(Register) \
+ )
+#define Mm32Ptr( BaseAddr, Register ) \
+ ((volatile UINT32 *)MmAddress (BaseAddr, Register ))
+
+#define Mm16Ptr( BaseAddr, Register ) \
+ ((volatile UINT16 *)MmAddress (BaseAddr, Register ))
+
+#define Mm8Ptr( BaseAddr, Register ) \
+ ((volatile UINT8 *)MmAddress (BaseAddr, Register ))
+
+//HBA Generic
+#define HBA_PORT_REG_BASE(Port) \
+ (UINTN) (Port * HBA_PORTS_REG_WIDTH + HBA_PORTS_START)
+
+#define HBA_REG32( BaseAddr, Register ) \
+ (*Mm32Ptr ((BaseAddr), (Register)))
+
+#define HBA_REG16( BaseAddr, Register ) \
+ (*Mm16Ptr ((BaseAddr), (Register)))
+
+#define HBA_REG8( BaseAddr, Register ) \
+ (*Mm8Ptr ((BaseAddr), (Register)))
+
+#define HBA_WRITE_REG32( BaseAddr, Register, Data ) \
+ (HBA_REG32 ((BaseAddr), (Register))) = ((UINT32) (Data))
+
+#define HBA_WRITE_REG16( BaseAddr, Register, Data ) \
+ (HBA_REG16 ((BaseAddr), (Register))) = ((UINT16) (Data))
+
+#define HBA_WRITE_REG8( BaseAddr, Register, Data ) \
+ (HBA_REG8 ((BaseAddr), (Register))) = ((UINT8) (Data))
+
+#define HBA_REG8_OR( BaseAddr, Register, OrData) \
+ (HBA_REG8 ((BaseAddr), (Register))) |= ((UINT8) (OrData))
+
+#define HBA_REG16_OR( BaseAddr, Register, OrData) \
+ (HBA_REG16 ((BaseAddr), (Register))) |= ((UINT16) (OrData))
+
+#define HBA_REG32_OR( BaseAddr, Register, OrData) \
+ (HBA_REG32 ((BaseAddr), (Register))) = (HBA_REG32 ((BaseAddr), (Register))) | ((UINT32) (OrData))
+
+#define HBA_REG8_AND( BaseAddr, Register, AndData) \
+ (HBA_REG8 ((BaseAddr), (Register))) = (HBA_REG8 ((BaseAddr), (Register))) & ((UINT8) (AndData))
+
+#define HBA_REG16_AND( BaseAddr, Register, AndData) \
+ (HBA_REG16 ((BaseAddr), (Register))) &= ((UINT16) (AndData))
+
+#define HBA_REG32_AND( BaseAddr, Register, AndData) \
+ (HBA_REG32 ((BaseAddr), (Register))) = (HBA_REG32 ((BaseAddr), (Register))) & ((UINT32) (AndData))
+
+#define HBA_REG8_AND_OR( BaseAddr, Register, AndData, OrData) \
+ (HBA_REG8 ((BaseAddr), (Register)) = \
+ (((HBA_REG8 ((BaseAddr), (Register))) & ((UINT8) (AndData))) | ((UINT8) (OrData))))
+
+#define HBA_REG16_AND_OR( BaseAddr, Register, AndData, OrData) \
+ (HBA_REG16 ((BaseAddr), (Register)) = \
+ (((HBA_REG16 ((BaseAddr), (Register))) & ((UINT16) AndData)) | ((UINT16) (OrData))))
+
+#define HBA_REG32_AND_OR( BaseAddr, Register,AndData, OrData) \
+ (HBA_REG32 ((BaseAddr), (Register)) = \
+ (((HBA_REG32 ((BaseAddr), (Register))) & ((UINT32) (AndData))) | ((UINT32) (OrData))))
+
+//Ports
+#define HBA_PORT_REG8(BaseAddr, Port, Register) \
+ (HBA_REG8 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port))))
+
+#define HBA_PORT_REG16(BaseAddr, Port, Register) \
+ (HBA_REG16 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port))))
+
+#define HBA_PORT_REG32(BaseAddr, Port, Register) \
+ (HBA_REG32 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port))))
+
+#define HBA_PORT_WRITE_REG8(BaseAddr, Port, Register, Data) \
+ (HBA_WRITE_REG8 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), Data))
+
+#define HBA_PORT_WRITE_REG16(BaseAddr, Port, Register, Data) \
+ (HBA_WRITE_REG16 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)),Data))
+
+#define HBA_PORT_WRITE_REG32(BaseAddr, Port, Register,Data) \
+ (HBA_WRITE_REG32 ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)),Data))
+
+#define HBA_PORT_REG8_OR(BaseAddr, Port, Register, OrData) \
+ (HBA_REG8_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (OrData)))
+
+#define HBA_PORT_REG16_OR(BaseAddr, Port, Register, OrData) \
+ (HBA_REG16_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (OrData)))
+
+#define HBA_PORT_REG32_OR(BaseAddr, Port, Register, OrData) \
+ (HBA_REG32_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (OrData)))
+
+#define HBA_PORT_REG8_AND(BaseAddr, Port, Register, AndData) \
+ (HBA_REG8_AND ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData)))
+
+#define HBA_PORT_REG16_AND(BaseAddr, Port, Register, AndData) \
+ (HBA_REG16_AND ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData)))
+
+#define HBA_PORT_REG32_AND(BaseAddr, Port, Register, AndData) \
+ (HBA_REG32_AND ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData)))
+
+#define HBA_PORT_REG8_AND_OR(BaseAddr, Port, Register, AndData, OrData) \
+ (HBA_REG8_AND_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData), (OrData)))
+
+#define HBA_PORT_REG16_AND_OR(BaseAddr, Port, Register, AndData, OrData) \
+ (HBA_REG16_AND_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData), (OrData)))
+
+#define HBA_PORT_REG32_AND_OR(BaseAddr, Port, Register, AndData, OrData) \
+ (HBA_REG32_AND_OR ((BaseAddr), ((Register) + HBA_PORT_REG_BASE (Port)), (AndData), (OrData)))
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Ahci/AhciInt13Dxe.c b/Core/EM/Ahci/AhciInt13Dxe.c
new file mode 100644
index 0000000..20724ad
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Dxe.c
@@ -0,0 +1,412 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Dxe.c 1 11/25/14 12:09a Kapilporwal $Revision:
+//
+// $Date: 11/25/14 12:09a $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Dxe.c $
+//
+//
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//****************************************************************************
+//
+// Name: AhciInt13Dxe.c
+//
+// Description:
+// This file will register one CALLBACK function, AmiLegacyBootNotify(),
+// it will collect AHCI Int13 runtime data from gAhciI13Data and
+// send it to SMM for AHCI INT13 SMI handler.
+//****************************************************************************
+//<AMI_FHDR_END>
+
+//---------------------------------------------------------------------------
+#include <Token.h>
+#include <AmiDxeLib.h>
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION>=0x4028B)
+#include <Protocol/SmmCommunication.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/LegacyBiosExt.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/PDiskInfo.h>
+#include <Protocol/PIDEController.h>
+#include <Protocol/PIDEBus.h>
+#include <Protocol/PAhciBus.h>
+#include "AInt13.h"
+#include "AhciInt13Smm.h"
+
+AHCI_I13_RTDATA *gAhciI13Data = NULL;
+extern EFI_GUID gAint13SmmDataGuid;
+EFI_GUID gEfiLegacyBiosProtocolGuid = EFI_LEGACY_BIOS_PROTOCOL_GUID;
+EFI_GUID gEfiDiskInfoProtocolGuid = EFI_DISK_INFO_PROTOCOL_GUID;
+EFI_GUID gEfiEventLegacyBootGuid = EFI_EVENT_LEGACY_BOOT_GUID;
+
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsSataDeviceInAhciMode
+//
+// Description: Check input BBS device is a SATA DEVICE in AHCI mode.
+//
+// Input: BBS_TABLE* - Pointer to an entry in BBS table
+//
+// Output: UINT8 TRUE - It is a SATA device and in AHCI mode
+// FALSE - It is not a SATA device or not in AHCI mode
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+IsSataDeviceInAhciMode (
+ IN BBS_TABLE *BbsEntry
+)
+{
+
+ if((BbsEntry->DeviceType == BBS_HARDDISK || BbsEntry->DeviceType == BBS_CDROM)) {
+ if(BbsEntry->Class == MASS_STORAGE || BbsEntry->SubClass == AHCI_CONTROLLER ){
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: InitializeAhciI13Data
+//
+// Description: It initializes AHCI INT13 runtime data pointer (gAhciI13Data).
+//
+// Input: BBS_TABLE* - Pointer to an entry in BBS table
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+InitializeAhciI13Data (
+ IN BBS_TABLE *BbsEntry
+)
+{
+ UINT16 StrSeg = 0, StrOff = 0;
+ UINT32 DevOutfitAddr = 0, DevOutfitStartAddr = 0;
+ UINT8 AInt13No = 0, DevNo = 0;
+
+ if(!gAhciI13Data) {
+ // INT13 Drive number (0x80~0x8F)
+ AInt13No = (UINT8)(BbsEntry->InitPerReserved >> 8);
+ DevNo = AInt13No & 0x7F; // Drive index
+
+ // Get address of drive description string i.e. AHCI_I13_RTDATA.DevOutfit[DevNo]
+ StrSeg = BbsEntry->DescStringSegment;
+ StrOff = BbsEntry->DescStringOffset;
+ DevOutfitAddr = (UINT32)((UINTN)StrSeg << 4) + (UINT32)StrOff;
+
+ // Now get address of description string of 1st drive i.e. AHCI_I13_RTDATA.DevOutfit[0]
+ DevOutfitStartAddr = DevOutfitAddr - (sizeof(DEV_BBS_OUTFIT)*DevNo);
+ // Now get base address of AHCI_I13_RTDATA structure
+ gAhciI13Data = (AHCI_I13_RTDATA*)(DevOutfitStartAddr - EFI_FIELD_OFFSET(AHCI_I13_RTDATA, DevOutfit));
+ }
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: TransferAhciInt13SmmDataToSmm
+//
+// Description: It uses EFI_SMM_COMMUNICATION_PROTOCOL API to transfer data
+// from Non-SMM mode to SMM mode.
+//
+// Input: VOID* - Pointer to data to be transfered
+// UINTN - size of the data
+// EFI_GUID* - Pointer to GUID identifier for the data
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+TransferAhciInt13SmmDataToSmm (
+ IN VOID *pData,
+ IN UINTN DataSize,
+ IN EFI_GUID *pGuid
+)
+{
+ EFI_SMM_COMMUNICATION_PROTOCOL *gSmmCommunication = NULL;
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
+ UINT8 *CommunicateBuffer = NULL;
+ UINTN CommunicateBufferSize;
+ EFI_STATUS Status;
+
+ if ( pData == NULL || DataSize == 0 || pGuid == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Calculate Size of Communication buffer
+ CommunicateBufferSize = (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) + DataSize; // Header size (without data) + data size
+
+ // Allocate memory for Communication Buffer.
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ CommunicateBufferSize,
+ (VOID**)&CommunicateBuffer );
+ if ( EFI_ERROR( Status )) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ // Copy SMM Communicate Header Here
+ SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicateBuffer;
+
+ // Copy data GUID
+ pBS->CopyMem( &SmmCommunicateHeader->HeaderGuid, pGuid, sizeof( EFI_GUID ) );
+
+ // Updated data length
+ SmmCommunicateHeader->MessageLength = DataSize;
+
+ // Copy Data Here
+ pBS->CopyMem( &SmmCommunicateHeader->Data, pData, DataSize );
+
+ // Locate EFI_SMM_COMMUNICATION_PROTOCOL
+ Status = pBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &gSmmCommunication);
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ // Send data to SMM using protocol API
+ Status = gSmmCommunication->Communicate (gSmmCommunication, CommunicateBuffer, &CommunicateBufferSize);
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ // Free memory allocated for Communication Buffer.
+ Status = pBS->FreePool(CommunicateBuffer);
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AmiLegacyBootNotify
+//
+// Description: This function will be called upon legacy boot event. It
+// collects information about all AHCI devices present in the system and
+// send it to SMM so that AHCI INT13 SMI handler can use it.
+// Operation:
+// 1. Locate EFI_LEGACY_BIOS_PROTOCOL and get All BBS entries and look
+// for entry corresponding to a drive in AHCI mode
+// 2. If a valid entry is found then it will use AHCI INT13 runtime
+// data and AHCI bus interface data to fill data required by AHCI
+// INT13 SMI handler.
+// 3. This newly created data structure will be transfered to SMM using
+// SmmCommunicationProtocol API.
+//
+// Input: EFI_EVENT - Event
+// VOID* - Pointer to Context
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+AmiLegacyBootNotify(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ EFI_STATUS Status;
+ UINT16 HddCount = 0;
+ HDD_INFO *HddInfo = NULL;
+ BBS_TABLE *BbsTable = NULL;
+ UINT16 BbsCount = 0;
+ UINT8 DevNo = 0;
+ UINTN SegNum;
+ UINTN BusNum;
+ UINTN DevNum;
+ UINTN FuncNum;
+ UINT16 i = 0;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_DISK_INFO_PROTOCOL *DiskInfo = NULL;
+ SATA_DEVICE_INTERFACE *SataDevInterface = NULL;
+ SMM_AINT13_DRIVE_INFO *pDriveInfo = NULL;
+ AHCI_INT13_SMM_DATA *AhciInt13SmmData = NULL;
+
+ // Run this function only once
+ pBS->CloseEvent(Event);
+
+ // Locate EFI_LEGACY_BIOS_PROTOCOL
+ Status = pBS->LocateProtocol( &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ &LegacyBios);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ // Get BBS_TABLE
+ Status = LegacyBios->GetBbsInfo( LegacyBios,
+ &HddCount,
+ &HddInfo,
+ &BbsCount,
+ &BbsTable);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ // Allocate Memory for AhciInt13SmmData buffer.
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof(AHCI_INT13_SMM_DATA),
+ (VOID**)&AhciInt13SmmData );
+ if ( EFI_ERROR( Status )) {
+ ASSERT_EFI_ERROR(Status);
+ return;
+ }
+
+ // Initialize drive count to 0
+ AhciInt13SmmData->DriveCount = 0;
+
+ // Loop through all BBS entries
+ for (i = 0; i < BbsCount; i++) {
+
+ // Process if this BDS entry is corresponding to a HDD in AHCI mode
+ if (IsSataDeviceInAhciMode(&BbsTable[i])) {
+
+ // NOTE: We don't need EFI_DISK_INFO_PROTOCOL this is just to get SATA_DEVICE_INTERFACE structure.
+ Status = pBS->HandleProtocol ( (EFI_HANDLE)BbsTable[i].IBV1, &gEfiDiskInfoProtocolGuid, &DiskInfo );
+ if(EFI_ERROR(Status)) {
+ continue; // Goto next BBS entry
+ }
+ SataDevInterface = ((SATA_DISK_INFO *)DiskInfo)->SataDevInterface;
+
+ // Fill data in AhciInt13SmmData
+ pDriveInfo = &(AhciInt13SmmData->DriveInfo[AhciInt13SmmData->DriveCount]);
+ pDriveInfo->DriveNum = (UINT8)(BbsTable[i].InitPerReserved >> 8);
+ pDriveInfo->PMPortNum = SataDevInterface->PMPortNumber;
+ pDriveInfo->PortNum = SataDevInterface->PortNumber;
+ SataDevInterface->AhciBusInterface->PciIO->GetLocation(
+ SataDevInterface->AhciBusInterface->PciIO,
+ &SegNum, &BusNum, &DevNum, &FuncNum
+ );
+ pDriveInfo->BusNo = (UINT8)BusNum;
+ pDriveInfo->DevNo = (UINT8)DevNum;
+ pDriveInfo->FuncNo = (UINT8)FuncNum;
+ pDriveInfo->DeviceType = SataDevInterface->DeviceType;
+ if(pDriveInfo->DeviceType == ATAPI) {
+ pDriveInfo->Lun = SataDevInterface->AtapiDevice->Lun;
+ pDriveInfo->BlockSize = SataDevInterface->AtapiDevice->BlockSize;
+ } else {
+ // Initialize AHCI INT13 runtime data
+ if(!gAhciI13Data) {
+ InitializeAhciI13Data(&BbsTable[i]);
+ }
+ // Get drive index in device parameter array of gAhciI13Data
+ DevNo = pDriveInfo->DriveNum & 0x7F;
+
+ // Fill the information using gAhciI13Data
+ pDriveInfo->wMAXCYL = gAhciI13Data->DevParam[DevNo].wMAXCYL;
+ pDriveInfo->bMAXHN = gAhciI13Data->DevParam[DevNo].bMAXHN;
+ pDriveInfo->bMAXSN = gAhciI13Data->DevParam[DevNo].bMAXSN;
+ pDriveInfo->wLBACYL = gAhciI13Data->DevParam[DevNo].wLBACYL;
+ pDriveInfo->bLBAHD = gAhciI13Data->DevParam[DevNo].bLBAHD;
+ pDriveInfo->bLBASPT = gAhciI13Data->DevParam[DevNo].bLBASPT;
+ }
+ pDriveInfo->RCommand = SataDevInterface->ReadCommand;
+ pDriveInfo->WCommand = SataDevInterface->WriteCommand;
+
+ AhciInt13SmmData->DriveCount += 1; // Update drive count
+ }
+ }
+
+ // Save AhciInt13SmmData in SMM
+ if(AhciInt13SmmData->DriveCount != 0) {
+ Status = TransferAhciInt13SmmDataToSmm ( AhciInt13SmmData, sizeof(AHCI_INT13_SMM_DATA), &gAint13SmmDataGuid );
+ }
+
+ // Free the Memory Allocated for AhciInt13SmmData Buffer.
+ Status = pBS->FreePool(AhciInt13SmmData);
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AhciInt13DxeEntry
+//
+// Description: This is entry point function. It registers a call back function
+// for Legacy boot event.
+//
+// Input: EFI_HANDLE - Standard EFI Image handle
+// EFI_SYSTEM_TABLE* - Pointer to System Table
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciInt13DxeEntry(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ Status = pBS->CreateEventEx (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ AmiLegacyBootNotify,
+ NULL,
+ &gEfiEventLegacyBootGuid,
+ &Event
+ );
+
+ return Status;
+}
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciInt13Dxe.dxs b/Core/EM/Ahci/AhciInt13Dxe.dxs
new file mode 100644
index 0000000..8223f9b
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Dxe.dxs
@@ -0,0 +1,51 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Dxe.dxs 1 11/25/14 12:09a Kapilporwal $Revision:
+//
+// $Date: 11/25/14 12:09a $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Dxe.dxs $
+//
+//
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//****************************************************************************
+//
+// Name: AhciInt13Dxe.dxs
+//
+// Description:
+// Dependency expression for the AhciInt13Dxe component
+//****************************************************************************
+//<AMI_FHDR_END>
+
+#include<Protocol\SmmCommunication.h>
+
+DEPENDENCY_START
+ EFI_SMM_COMMUNICATION_PROTOCOL_GUID
+DEPENDENCY_END
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Ahci/AhciInt13Smm.c b/Core/EM/Ahci/AhciInt13Smm.c
new file mode 100644
index 0000000..8715bce
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Smm.c
@@ -0,0 +1,1157 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.c 2 12/08/14 5:39a Anbuprakashp $Revision:
+//
+// $Date: 12/08/14 5:39a $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.c $
+//
+//
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//****************************************************************************
+//
+// Name: AhciInt13Smm.C
+//
+// Description: This file contains code for SMI handler for AHCI INT13.
+//****************************************************************************
+//<AMI_FHDR_END>
+
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <AmiBufferValidationLib.h>
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION>=0x4028B)
+#include <Protocol/SmmBase2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmCpu.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/PDiskInfo.h>
+#include <Protocol/PIDEController.h>
+#include <Protocol/PIDEBus.h>
+#include <Protocol/AhciSmmProtocol.h>
+#include "AhciInt13Smm.h"
+
+EFI_SMM_CPU_PROTOCOL *gSmmCpuProtocol = NULL;
+AHCI_BUS_SMM_PROTOCOL *gAhciBusSmmProtocol = NULL;
+DLIST gDriveInfoList;
+EFI_GUID gAint13SmmDataGuid = AHCI_INT13_SMM_DATA_GUID;
+EFI_GUID gAhciSmmProtocolGuid = AHCI_SMM_PROTOCOL_GUID;
+EFI_GUID gEfiSmmCpuProtocolGuid = EFI_SMM_CPU_PROTOCOL_GUID;
+EFI_GUID gEfiSmmSwDispatch2ProtocolGuid = EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID;
+UINT64 PciExpressBaseAddress = 0;
+UINT8 *gBuffer = NULL;
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: AhciMmioRead
+//
+// Description: Read from AHCI MMIO address
+//
+// Input: IN UINT32 - AHCI MMIO address
+//
+// Output: OUT UINT32 - Value read from AHCI MMIO address
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciMmioRead (
+ IN UINT32 AhciMmioAddress,
+ OUT UINT32 *ReadValue
+)
+{
+ EFI_STATUS Status;
+ // Validate AhciBaseAddress is valid MMIO address and not reside in SMRAM region
+ Status = AmiValidateMmioBuffer( (VOID*)AhciMmioAddress, 4 );
+ if( EFI_ERROR(Status) ) {
+ return Status;
+ }
+
+ *ReadValue = *(UINT32*)(AhciMmioAddress);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: AhciMmioWrite
+//
+// Description: Write to the AHCI MMIO Address
+//
+// Input: IN UINT32 - AHCI MMIO address
+// IN UINT32 - Value to be written
+//
+// Output: EFI_STATUS - EFI_NOT_FOUND: Invalid address, EFI_SUCCESS: Success
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciMmioWrite (
+ IN UINT32 AhciMmioAddress,
+ IN UINT32 WriteValue
+)
+{
+ EFI_STATUS Status;
+
+ // Validate AhciBaseAddress is valid MMIO address and not reside in SMRAM region
+ Status = AmiValidateMmioBuffer( (VOID*)AhciMmioAddress, 4 );
+ if( EFI_ERROR(Status) ) {
+ return Status;
+ }
+
+ *(UINT32*)(AhciMmioAddress) = WriteValue;
+ return Status;
+}
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION>=0x4028B)
+
+//---------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Is48BitCommand
+//
+// Description: Check if input command is a LBA48 command
+//
+// Input: UINT8 - Command
+//
+// Output: BOOLEAN - TRUE - LBA48 command
+// FALSE - Not a LBA48 command
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+Is48BitCommand (
+ IN UINT8 Command
+ )
+{
+ if ( Command == READ_SECTORS_EXT ||
+ Command == READ_MULTIPLE_EXT ||
+ Command == WRITE_SECTORS_EXT ||
+ Command == WRITE_MULTIPLE_EXT ||
+ Command == READ_DMA_EXT ||
+ Command == WRITE_DMA_EXT )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IsDmaCommand
+//
+// Description: Check if input command is a DMA command
+//
+// Input: UINT8 - Command
+//
+// Output: BOOLEAN - TRUE - DMA command
+// FALSE - Not a DMA command
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+IsDmaCommand (
+ IN UINT8 Command
+ )
+{
+ if ( Command == READ_DMA ||
+ Command == READ_DMA_EXT ||
+ Command == WRITE_DMA ||
+ Command == WRITE_DMA_EXT )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: CheckErrorCode
+//
+// Description: It maps EFI_STATUS code to corresponding INT13 error code
+//
+// Input: EFI_STATUS - Status
+//
+// Output: UINT8 - INT13 error code
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+CheckErrorCode (
+ IN EFI_STATUS Status
+ )
+{
+ switch(Status){
+ case EFI_SUCCESS:
+ return 0x0; // successful completion
+ break;
+ case EFI_INVALID_PARAMETER:
+ return 0x01; // invalid function in AH or invalid parameter
+ break;
+ case EFI_UNSUPPORTED:
+ return 0x01; // invalid function in AH or invalid parameter
+ break;
+ case EFI_NOT_READY:
+ return 0xAA; // drive not ready (hard disk)
+ break;
+ case EFI_DEVICE_ERROR:
+ return 0xE0; // status register error (hard disk)
+ break;
+ case EFI_WRITE_PROTECTED:
+ return 0x03; // disk write-protected
+ break;
+ case EFI_NO_MEDIA:
+ return 0x31; // no media in drive (IBM/MS INT 13 extensions)
+ break;
+ case EFI_MEDIA_CHANGED:
+ return 0x06; // disk changed
+ break;
+ case EFI_NOT_FOUND:
+ return 0x01; // invalid function in AH or invalid parameter
+ break;
+ case EFI_ACCESS_DENIED:
+ return 0xB6; // volume present but read protected (INT 13 extensions)
+ break;
+ case EFI_TIMEOUT:
+ return 0x80; // timeout (not ready)
+ break;
+ case EFI_ABORTED:
+ return 0xBB; // undefined error (hard disk)
+ break;
+ default:
+ break;
+ }
+ return 0xBB;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: GetDriveInfoByDriveNum
+//
+// Description: It returns the drive information corresponding to input drive
+// number, if found.
+//
+// Input: IN UINT8 - INT13 drive number
+// IN OUT VOID** - Pointer to SMM_AINT13_DRIVE_INFO variable
+// It will be filled with corresponding drive
+// information
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - DriveInfo is valid
+// EFI_UNSUPPORTED - Can't find the corresponding data.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetDriveInfoByDriveNum(
+ IN UINT8 DriveNum,
+ IN OUT VOID **DriveInfo
+)
+{
+ DLINK *DriveInfoLink = NULL;
+ SMM_AINT13_DRIVE_INFO *pDriveInfo = NULL;
+
+ // Look for drive information corresponding to DriveNum in gDriveInfoList
+ DriveInfoLink = gDriveInfoList.pHead;
+ for(;DriveInfoLink;DriveInfoLink=DriveInfoLink->pNext){
+ pDriveInfo = OUTTER(DriveInfoLink, dLink, SMM_AINT13_DRIVE_INFO);
+ if(DriveNum == pDriveInfo->DriveNum) {
+ // Return the information if found, also set status as success
+ *DriveInfo = pDriveInfo;
+ return EFI_SUCCESS;
+ }
+ }
+
+ // No drive information corresponding to DriveNum in gDriveInfoList
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ProcessInt13Function
+//
+// Description: Worker function to service AHCI INT13 request. Currently it
+// supports Read/Write function only.
+// Operation:
+// 1. Parse information passed as IA registers to parameter required
+// by AMI_AHCI_BUS_SMM_PROTOCOL APIs.
+// 2. Call appropriate AMI_AHCI_BUS_SMM_PROTOCOL API.
+//
+// Input: EFI_IA32_REGISTER_SET* - Pointer of EFI_IA32_REGISTER_SET
+//
+// Output: EFI_STATUS
+// EFI_SUCCESS - Int13 request complete
+// EFI_UNSUPPORTED - This Int13 request is unsupported
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+ProcessInt13Function(
+ IN EFI_IA32_REGISTER_SET *ExRegs
+)
+{
+ EFI_STATUS Status;
+ BOOLEAN IsSupported = TRUE;
+ VOID *Buffer = NULL;
+ UINT8 *BufferBackup = NULL;
+ UINT32 ByteCount = 0;
+ UINT16 SectorCount = 0;
+ UINT8 Command = 0;
+ EFI_LBA Lba = 0;
+ UINT16 SkipBytesBefore = 0, SkipBytesAfter = 0;
+ UINT16 Header = 0, Cylinder = 0, Sector = 0;
+ UINT8 ReadWrite = 0; // 0 : read, 1: write
+ UINT8 *UserBuf = NULL;
+ UINT64 bAhciBaseAddress = 0;
+ UINTN i = 0;
+ UINT16 BlksPerTransfer;
+ VOID *AhciBuffer;
+ BOOLEAN UnalignedTransfer = FALSE;
+ DISK_ADDRESS_PACKAGE *Package = NULL;
+ SMM_AINT13_DRIVE_INFO *pDriveInfo = NULL;
+ COMMAND_STRUCTURE CommandStructure;
+
+ // Get drive information based on drive number
+ Status = GetDriveInfoByDriveNum(ExRegs->H.DL,&pDriveInfo);
+
+ if(!EFI_ERROR(Status)){
+ if(pDriveInfo->DeviceType == ATA) {
+ // Calculate AHCI parameter to be filled in COMMAND_STRUCTURE based on INT13 function
+ if(ExRegs->H.AH == READ_SECTOR || ExRegs->H.AH == EXT_READ){
+ Command = pDriveInfo->RCommand;
+ ReadWrite = 0; // read
+ }else if(ExRegs->H.AH == WRITE_SECTOR || ExRegs->H.AH == EXT_WRITE){
+ Command = pDriveInfo->WCommand;
+ ReadWrite = 1; // write
+ }
+ switch(ExRegs->H.AH){
+ case READ_SECTOR:
+ case WRITE_SECTOR:
+ Cylinder = ((UINT16)(ExRegs->H.CL & 0xC0 ) << 2) +ExRegs->H.CH; // cylinder: bit 6-7(CL) + CH
+ Header = (UINT16)ExRegs->H.DH; // header : DH
+ Sector = (UINT16)(ExRegs->H.CL & 0x3F); // sector : bit 0-5(CL)
+ Lba = (Cylinder*(pDriveInfo->bMAXHN) + Header) * (pDriveInfo->bMAXSN) + Sector - 1;
+ SectorCount = ExRegs->H.AL;
+ Buffer = (VOID*)(((ExRegs->X.ES) << 4 ) + ExRegs->X.BX);
+ ByteCount = SectorCount*HDD_BLOCK_SIZE;
+ break;
+ case EXT_READ:
+ case EXT_WRITE:
+ Package = (DISK_ADDRESS_PACKAGE*)(((ExRegs->X.DS) << 4 ) + ExRegs->X.SI);
+ Lba = Package->StartLba;
+ SectorCount = Package->XferSector;
+ Buffer = (VOID*)(((Package->Buffer >> 16 & 0xFFFF) << 4) + (UINT16)Package->Buffer);
+ ByteCount = SectorCount*HDD_BLOCK_SIZE;
+ break;
+ default:
+ IsSupported = FALSE;
+ break;
+ }
+ } else if(pDriveInfo->DeviceType == ATAPI){ // Only read command support is required
+ Command = pDriveInfo->RCommand;
+ ReadWrite = 0; // read
+ Buffer = (VOID*)((((ExRegs->E.EDI) >> 16 & 0xFFFF) << 4) + (UINT16)(ExRegs->E.EDI));
+ Lba = ExRegs->E.EAX;
+ SectorCount = ExRegs->X.CX; // CX
+ SkipBytesAfter = ((ExRegs->E.ECX) >> 24) * 512; // CH+ (Higher byte of higher word of ECX)
+ SkipBytesBefore = (((ExRegs->E.ECX) >> 16) & 0xFF) * 512; // CL+ (Lower byte of higher word of ECX)
+ ByteCount = SectorCount * pDriveInfo->BlockSize; // 2048
+ if(SkipBytesBefore || SkipBytesAfter) {
+ Status = pSmst->SmmAllocatePool(EfiRuntimeServicesData, sizeof(UINT8)*(SkipBytesBefore + SkipBytesAfter), &BufferBackup);
+ if (EFI_ERROR(Status)) {
+ ASSERT(TRUE);
+ IsSupported = FALSE;
+ } else {
+ // Backup bytes to be preserved.
+ for(i = 0;i<(SkipBytesBefore + SkipBytesAfter);i++) {
+ BufferBackup[i] = *(((UINT8*)Buffer)+i + (ByteCount - SkipBytesBefore - SkipBytesAfter));
+ }
+ }
+ }
+ } else {
+ IsSupported = FALSE;
+ }
+ } // if(!EFI_ERROR(Status))
+ else {
+ IsSupported = FALSE;
+ }
+
+ if(IsSupported){
+ // Backup AHCI base address from gAhciBusSmmProtocol
+ bAhciBaseAddress = gAhciBusSmmProtocol->AhciBaseAddress;
+
+ // Save current AHCI base address from AHCI controller.
+ gAhciBusSmmProtocol->AhciBaseAddress = *(UINT32*)PCI_CFG_ADDR(pDriveInfo->BusNo, pDriveInfo->DevNo, pDriveInfo->FuncNo, PCI_ABAR);
+
+ BlksPerTransfer = SectorCount;
+ AhciBuffer = Buffer;
+
+ //If Buffer isn't aligned use internal buffer
+ if(((UINT32)Buffer) & 0x1) {
+ BlksPerTransfer = 1;
+ AhciBuffer = gBuffer;
+ UnalignedTransfer = TRUE;
+ }
+
+ if(pDriveInfo->DeviceType == ATA) {
+ ByteCount = BlksPerTransfer * HDD_BLOCK_SIZE;
+ } else if(pDriveInfo->DeviceType == ATAPI){
+ ByteCount = BlksPerTransfer * pDriveInfo->BlockSize;
+ }
+
+ UserBuf = (UINT8*)Buffer;
+
+ for ( ; SectorCount; SectorCount -= BlksPerTransfer){
+
+ if (ReadWrite == 1 && UnalignedTransfer) {
+ for(i = 0; i < ByteCount; i++) {
+ *(((UINT8*)AhciBuffer)+i) = *(((UINT8*)Buffer)+i);
+ }
+ }
+
+ // clear Command structure
+ MemSet (&CommandStructure, sizeof(COMMAND_STRUCTURE), 0);
+
+ // Fill CommandStructure buffer.
+ CommandStructure.Buffer = AhciBuffer;
+ CommandStructure.ByteCount = ByteCount;
+ if(pDriveInfo->DeviceType == ATA) { // ATA
+ CommandStructure.Features = 0;
+ CommandStructure.FeaturesExp = 0;
+ CommandStructure.SectorCount = BlksPerTransfer;
+ CommandStructure.LBALow = (UINT8)Lba;
+ CommandStructure.LBAMid = (UINT8) (((UINT32)Lba >>8) & 0xff);
+ CommandStructure.LBAHigh = (UINT8) (((UINT32)Lba >>16) & 0xff);
+ if(Is48BitCommand(Command)){ // if support LBA48 feature?
+ CommandStructure.LBALowExp = (UINT8) (UINT8)Shr64(Lba,24);
+ CommandStructure.LBAMidExp = (UINT8) (UINT8)Shr64(Lba,32);
+ CommandStructure.LBAHighExp = (UINT8) (UINT8)Shr64(Lba,40);
+ CommandStructure.Device = 0x40; // LBA48
+ }else{
+ CommandStructure.Device = ((UINT8)Shr64(Lba,24) & 0x0f) | 0x40; // LBA28
+ }
+ CommandStructure.Command = Command;
+ CommandStructure.Control = 0;
+ } else if(pDriveInfo->DeviceType == ATAPI) {
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = Command;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[1] = pDriveInfo->Lun << 5;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[2] = (UINT8)(((UINT32) Lba) >> 24);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[3] = (UINT8)(((UINT32) Lba) >> 16);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[4] = (UINT8)(((UINT16) Lba) >> 8);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[5] = (UINT8)(((UINT8) Lba) & 0xff);
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[7] = (UINT8) (BlksPerTransfer >> 8); // MSB
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[8] = (UINT8) (BlksPerTransfer & 0xff); // LSB
+ }
+
+ // Send ATA/ATAPI command in AHCI mode
+ if(pDriveInfo->DeviceType == ATA) { // ATA
+ if(IsDmaCommand(Command)) {
+ Status = gAhciBusSmmProtocol->AhciSmmExecuteDmaDataCommand( gAhciBusSmmProtocol,
+ &CommandStructure,
+ pDriveInfo->PortNum,
+ pDriveInfo->PMPortNum,
+ pDriveInfo->DeviceType,
+ ReadWrite);
+ } else {
+ Status = gAhciBusSmmProtocol->AhciSmmExecutePioDataCommand( gAhciBusSmmProtocol,
+ &CommandStructure,
+ pDriveInfo->PortNum,
+ pDriveInfo->PMPortNum,
+ pDriveInfo->DeviceType,
+ ReadWrite);
+ }
+ } else { // ATAPI
+ Status = gAhciBusSmmProtocol->AhciSmmExecutePacketCommand( gAhciBusSmmProtocol,
+ &CommandStructure,
+ ReadWrite,
+ pDriveInfo->PortNum,
+ pDriveInfo->PMPortNum,
+ pDriveInfo->DeviceType);
+ }
+
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+
+ if (ReadWrite == 0 && UnalignedTransfer) {
+ for(i = 0; i < ByteCount; i++) {
+ *(((UINT8*)Buffer)+i) = *(((UINT8*)AhciBuffer)+i);
+ }
+ }
+
+ (UINTN)Buffer = (UINTN)Buffer + ByteCount;
+ Lba += BlksPerTransfer;
+
+ }
+
+ Buffer = UserBuf;
+
+ // Restore base address to gAhciBusSmmProtocol
+ gAhciBusSmmProtocol->AhciBaseAddress = bAhciBaseAddress;
+
+ if(pDriveInfo->DeviceType == ATAPI){
+ // fill output buffer with requested data only.
+ if(SkipBytesBefore || SkipBytesAfter) {
+ UserBuf = (UINT8*)Buffer;
+ // Move requested data at start of the buffer
+ if(SkipBytesBefore != 0)
+ for(i = 0;i<ByteCount - SkipBytesBefore - SkipBytesAfter;i++) {
+ UserBuf[i] = UserBuf[i+SkipBytesBefore];
+ }
+ // Keep rest of the buffer intact. Restore the backup.
+ for(i = 0;i<SkipBytesBefore + SkipBytesAfter;i++) {
+ UserBuf[i + (ByteCount - SkipBytesBefore - SkipBytesAfter)] = BufferBackup[i];
+ }
+ pSmst->SmmFreePool(BufferBackup);
+ }
+ }
+
+ // update return register data whatever success or error!!
+ if(!EFI_ERROR(Status)){
+ // AHCI success
+ ExRegs->X.Flags.CF = 0x0; // clear if successful
+ ExRegs->H.AH = CheckErrorCode(Status); // successful completion
+ }
+ else{
+ // AHCI error
+ ExRegs->X.Flags.CF = 0x1; // set on error
+ ExRegs->H.AH = CheckErrorCode(Status); // return error code
+ }
+ }
+
+ // return EFI_SUCCESS: Int13 request is complete.
+ // return EFI_UNSUPPORTED: This function isn't supported by this routine.
+ return (IsSupported)? EFI_SUCCESS : EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AhciInt13SmiHandler
+//
+// Description: This is the SWSMI handler to service AHCI INT13 request.
+// Operation:
+// 1. Take INT13 parameters stored on real mode stack from CPU save state.
+// 2. Call a sub-function to process INT13 request.
+// 3. Update output parameters (IA registers) on real mode stack.
+//
+// Input: UINTN - Index of CPU which triggered SW SMI
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciInt13SmiHandler (
+ IN UINTN CpuIndex
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT16 StackSegment = 0;
+ UINT16 StackOffset = 0;
+ EFI_IA32_REGISTER_SET ExRegs;
+ INT13_TO_SMI_EXREGS *Int13ToSmiExRegs = NULL;
+TRACE((-1, "\nKAPIL: AhciInt13SmiHandler."));
+ // Read SS/ESP from CPU save state
+ gSmmCpuProtocol->ReadSaveState ( gSmmCpuProtocol,
+ 2,
+ EFI_SMM_SAVE_STATE_REGISTER_RSP,
+ CpuIndex,
+ &StackOffset );
+
+ gSmmCpuProtocol->ReadSaveState ( gSmmCpuProtocol,
+ 2,
+ EFI_SMM_SAVE_STATE_REGISTER_SS,
+ CpuIndex,
+ &StackSegment );
+
+ // Get base address of real mode stack
+ Int13ToSmiExRegs = (INT13_TO_SMI_EXREGS*)(((StackSegment << 4) + StackOffset) + 2);
+
+ MemSet (&ExRegs, sizeof(EFI_IA32_REGISTER_SET), 0);
+
+ // Initialize the SMM THUNK registers
+ ExRegs.E.EAX = Int13ToSmiExRegs->StackEAX;
+ ExRegs.E.EBX = Int13ToSmiExRegs->StackEBX;
+ ExRegs.E.ECX = Int13ToSmiExRegs->StackECX;
+ ExRegs.E.EDX = Int13ToSmiExRegs->StackEDX;
+ ExRegs.E.EDI = Int13ToSmiExRegs->StackEDI;
+ ExRegs.E.ESI = Int13ToSmiExRegs->StackESI;
+ ExRegs.E.EBP = Int13ToSmiExRegs->StackEBP;
+ ExRegs.E.DS = Int13ToSmiExRegs->StackDS;
+ ExRegs.E.ES = Int13ToSmiExRegs->StackES;
+ ExRegs.E.FS = Int13ToSmiExRegs->StackFS;
+ ExRegs.E.GS = Int13ToSmiExRegs->StackGS;
+ ExRegs.X.Flags = Int13ToSmiExRegs->StackFlags;
+
+ if(gAhciBusSmmProtocol && gDriveInfoList.pHead){
+ // Execute Int13 function by AhciSmmProtocol and update ExRegs for return caller.
+ // Note: Function will return non-EFI_SUCCESS value if Int13 function isn't
+ // supported by ProcessInt13Function().
+ Status = ProcessInt13Function(&ExRegs);
+ }
+
+ // Update the registers before go back caller.
+ Int13ToSmiExRegs->StackEAX = ExRegs.E.EAX;
+ Int13ToSmiExRegs->StackEBX = ExRegs.E.EBX;
+ Int13ToSmiExRegs->StackECX = ExRegs.E.ECX;
+ Int13ToSmiExRegs->StackEDX = ExRegs.E.EDX;
+ Int13ToSmiExRegs->StackEDI = ExRegs.E.EDI;
+ Int13ToSmiExRegs->StackESI = ExRegs.E.ESI;
+ Int13ToSmiExRegs->StackEBP = ExRegs.E.EBP;
+ Int13ToSmiExRegs->StackDS = ExRegs.E.DS;
+ Int13ToSmiExRegs->StackES = ExRegs.E.ES;
+ Int13ToSmiExRegs->StackFS = ExRegs.E.FS;
+ Int13ToSmiExRegs->StackGS = ExRegs.E.GS;
+ Int13ToSmiExRegs->StackFlags = ExRegs.X.Flags;
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: AhciMmioSmiHandler
+//
+// Description: SMI handler for the AHCI_MMIO_SWSMI SW SMI
+//
+// Input: IN UINTN - Index of CPU which triggered SW SMI
+// IN UINT32 - 1/2: Read or Write MMIO operation
+//
+// Output: EFI_STATUS - EFI_SUCCESS
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciMmioSmiHandler (
+ IN UINTN CpuIndex,
+ IN UINT32 FunctionNo
+)
+{
+ EFI_STATUS Status;
+ UINT32 AhciMmioAddress;
+ UINT32 WriteValue;
+ UINT32 ReadValue;
+ UINT32 ReturnStatus = 0x0FF;
+
+ gSmmCpuProtocol->ReadSaveState (gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RSI,
+ CpuIndex,
+ &AhciMmioAddress );
+
+
+ if(FunctionNo == 1) {
+ Status=AhciMmioRead(AhciMmioAddress, &ReadValue);
+
+ if(!EFI_ERROR(Status)) {
+ gSmmCpuProtocol->WriteSaveState(gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RAX,
+ CpuIndex,
+ &ReadValue);
+ ReturnStatus = 0; // Update success
+ }
+
+ gSmmCpuProtocol->WriteSaveState(gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RCX,
+ CpuIndex,
+ &ReturnStatus);
+
+ } else if(FunctionNo == 2) {
+
+ gSmmCpuProtocol->ReadSaveState (gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RBX,
+ CpuIndex,
+ &WriteValue );
+
+ Status = AhciMmioWrite(AhciMmioAddress, WriteValue);
+
+ if(!EFI_ERROR(Status)) {
+ ReturnStatus = 0; // Update success
+ }
+
+ gSmmCpuProtocol->WriteSaveState(gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RCX,
+ CpuIndex,
+ &ReturnStatus);
+ } else {
+ // Invalid function number, return Error(i.e. ReturnStatus==0xFF)
+ gSmmCpuProtocol->WriteSaveState(gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RCX,
+ CpuIndex,
+ &FunctionNo);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: AhciCommonSmmHandler
+//
+// Description: Common SMI handler for AHCI INT13 SMIs
+//
+// Input: IN EFI_HANDLE - EFI Handle
+// IN VOID* - Pointer to the EFI_SMM_SW_REGISTER_CONTEXT
+// IN VOID* - Pointer to Communication data
+// IN UINTN* - Pointer to size of Communication data
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciCommonSmmHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN CpuIndex = (UINTN)-1;
+ UINT32 FunctionNo = 0;
+
+ // Get CPU number of CPU which generated this SWSMI
+ if (CommBuffer != NULL && CommBufferSize != NULL) {
+ CpuIndex = ((EFI_SMM_SW_CONTEXT*)CommBuffer)->SwSmiCpuIndex;
+ }
+
+ // Return if CPU number is invalid
+ if(CpuIndex == (UINTN)-1) return Status;
+
+ // Read ECX from CPU save state
+ gSmmCpuProtocol->ReadSaveState ( gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RCX,
+ CpuIndex,
+ &FunctionNo );
+
+ switch(FunctionNo) {
+ case 0x1:
+ case 0x2:
+ Status = AhciMmioSmiHandler(CpuIndex, FunctionNo);
+ break;
+
+ case 0x3:
+ Status = AhciInt13SmiHandler(CpuIndex);
+ break;
+
+ default:
+ // Invalid Function. Return Error.
+ FunctionNo = 0xFF;
+ gSmmCpuProtocol->WriteSaveState(gSmmCpuProtocol,
+ 4,
+ EFI_SMM_SAVE_STATE_REGISTER_RCX,
+ CpuIndex,
+ &FunctionNo);
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+// Procedure: GetAhciInt13SmmData
+//
+// Description: Saves AINT13 information passed from Non-SMM mode using
+// EFI_SMM_COMMUNICATION_PROTOCOL API. This is required for below reason:
+// 1)AhciSmmProtocol use port number, but Int13 service uses drive number.
+// 2)AhciSmmProtocol use LBA addressing on HDD, but Int13 Read/Write function
+// uses Cylinder, Header and Sector addressing on HDD.
+//
+// Input: IN EFI_HANDLE - EFI Handle
+// IN VOID* - Pointer to the EFI_SMM_SW_REGISTER_CONTEXT
+// IN VOID* - Pointer to Communication data
+// IN UINTN* - Pointer to size of Communication data
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetAhciInt13SmmData (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+)
+{
+ EFI_STATUS Status;
+ UINTN i = 0, j = 0;
+ AHCI_INT13_SMM_DATA *AhciInt13SmmData = NULL;
+ SMM_AINT13_DRIVE_INFO *pDriveInfo = NULL;
+ SMM_AINT13_DRIVE_INFO *pSmmDriveInfo = NULL;
+
+ // Confirm that communication buffer contains required data
+ AhciInt13SmmData = (AHCI_INT13_SMM_DATA *)CommBuffer;
+ if (!AhciInt13SmmData || AhciInt13SmmData->DriveCount == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // Save all information from AhciInt13SmmData to gDriveInfoList
+ for(j=0;j<AhciInt13SmmData->DriveCount;j++){
+
+ // Allocate SMM memory
+ Status = pSmst->SmmAllocatePool(EfiRuntimeServicesData, sizeof(SMM_AINT13_DRIVE_INFO), &pSmmDriveInfo);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ // Copy all data
+ pDriveInfo = &(AhciInt13SmmData->DriveInfo[j]);
+ for(i=0;i<sizeof(SMM_AINT13_DRIVE_INFO);++i){
+ *((UINT8*)pSmmDriveInfo + i) = *((UINT8*)pDriveInfo + i);
+ }
+
+ // Add data to list
+ DListAdd(&gDriveInfoList, &pSmmDriveInfo->dLink);
+ }
+
+ // Locate AMI_AHCI_BUS_SMM_PROTOCOL
+ if(gAhciBusSmmProtocol == NULL) {
+ gAhciBusSmmProtocol = (AHCI_BUS_SMM_PROTOCOL*) GetSmstConfigurationTablePi(&gAhciSmmProtocolGuid);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AhciInt13SmmEntry
+//
+// Description: Driver entry point function. It does following tasks:
+// 1. Initializes global variables (gDriveInfoList, PciExpressBaseAddress etc.)
+// 2. Register SMI handler to get information passed through SmmCommunicationProtocol API.
+// 3. Register SW SMI handler to process AHCI INT13 requests.
+// 4. Locate EFI_SMM_CPU_PROTOCOL for Read/Write from/to CPU save state
+//
+// Input: EFI_HANDLE - Standard EFI Image handle
+// EFI_SYSTEM_TABLE* - Pointer to System Table
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciInt13SmmEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch2;
+ EFI_SMM_SW_REGISTER_CONTEXT AhciInt13SwSmiContext = {AHCI_INT13_SMM_SWSMI_VALUE};
+ EFI_HANDLE AhciInt13SmmHandle;
+ EFI_HANDLE AhciInt13SmmDataHandle;
+
+ InitAmiSmmLibPi(ImageHandle, SystemTable);
+
+ InitAmiBufferValidationLib( ImageHandle, SystemTable );
+
+ // Initialize global drive info list
+ DListInit(&gDriveInfoList);
+
+ // Get the PCI Express Base Address from the PCD
+ PciExpressBaseAddress = PCIEX_BASE_ADDRESS;
+
+ // Return error if PSmstPi is NULL
+ if(pSmmBasePi == NULL || pSmstPi == NULL) {
+ ASSERT(TRUE);
+ return EFI_NOT_FOUND;
+ }
+
+ // Register SMI handler to save AHCI_INT13_SMM_DATA passed from DXE through SmmCommunicationProtocol
+ Status = pSmstPi->SmiHandlerRegister(
+ (VOID *)GetAhciInt13SmmData,
+ &gAint13SmmDataGuid,
+ &AhciInt13SmmDataHandle
+ );
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ // Locate EFI_SMM_SW_DISPATCH2_PROTOCOL
+ Status = pSmstPi->SmmLocateProtocol(
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ &SwDispatch2
+ );
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ // Register SMI handler to handle AHCI INT13 operations
+ Status = SwDispatch2->Register(
+ SwDispatch2,
+ AhciCommonSmmHandler,
+ &AhciInt13SwSmiContext,
+ &AhciInt13SmmHandle
+ );
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ // Locate EFI_SMM_CPU_PROTOCOL for Read/Write from/to CPU save state
+ Status = pSmstPi->SmmLocateProtocol(
+ &gEfiSmmCpuProtocolGuid,
+ NULL,
+ &gSmmCpuProtocol
+ );
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ // Use this buffer for unaligned read or write
+ Status = pBS->AllocatePages (
+ AllocateAnyPages,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES(2048), // 512 for ATA and 2048 for ATAPI, so taking 2048
+ (EFI_PHYSICAL_ADDRESS*)&(gBuffer));
+ if (EFI_ERROR(Status)) {
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AhciInt13SmmEntryPoint
+//
+// Description: Entry point function for both DXE and SMM driver.
+//
+// Input: EFI_HANDLE - Standard EFI Image handle
+// EFI_SYSTEM_TABLE* - Pointer to System Table
+//
+// Output: EFI_STATUS
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciInt13SmmEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ Status = InitSmmHandler(ImageHandle, SystemTable, AhciInt13SmmEntry, AhciInt13DxeEntry);
+
+ return Status;
+}
+
+#else
+#include <Protocol/SmmBase.h>
+#include <Protocol/SmmSwDispatch.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <AmiSmm.h>
+
+EFI_GUID gEfiSmmSwDispatchProtocolGuid = EFI_SMM_SW_DISPATCH_PROTOCOL_GUID;
+EFI_GUID gSwSmiCpuTriggerGuid = SW_SMI_CPU_TRIGGER_GUID;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciMmioSmmSMIHandler
+//
+// Description: Smi handler for the AHCI_MMIO_SWSMI Sw Smi
+//
+// Input: DispatchHandle - EFI Handle
+// DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+AhciMmioSmmSMIHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext
+)
+{
+ UINTN Cpu = (UINTN)-1;
+ UINT32 FunctionNo;
+ UINT32 AhciBaseAddress;
+ UINT32 Value;
+ EFI_SMM_CPU_SAVE_STATE *pCpuSaveState;
+ SW_SMI_CPU_TRIGGER *SwSmiCpuTrigger;
+ UINTN i;
+
+ for (i = 0; i < pSmst->NumberOfTableEntries; ++i) {
+ if (guidcmp(&pSmst->SmmConfigurationTable[i].VendorGuid,&gSwSmiCpuTriggerGuid) == 0) {
+ break;
+ }
+ }
+
+ //If found table, check for the CPU that caused the software Smi.
+ if (i != pSmst->NumberOfTableEntries) {
+ SwSmiCpuTrigger = pSmst->SmmConfigurationTable[i].VendorTable;
+ Cpu = SwSmiCpuTrigger->Cpu;
+ }
+
+ // Found Invalid CPU number, return
+ if(Cpu == (UINTN) -1) {
+ return ;
+ }
+
+ pCpuSaveState = (EFI_SMM_CPU_SAVE_STATE*)pSmst->CpuSaveState;
+
+ FunctionNo = pCpuSaveState[Cpu].Ia32SaveState.ECX;
+ AhciBaseAddress = pCpuSaveState[Cpu].Ia32SaveState.ESI;
+
+ switch(FunctionNo) {
+ case 0x1:
+ Status=AhciMmioRead(AhciBaseAddress, &Value);
+ if( EFI_ERROR(Status) ) {
+ // Return Error.
+ pCpuSaveState[Cpu].Ia32SaveState.ECX = 0xFF;
+ break;
+ }
+ pCpuSaveState[Cpu].Ia32SaveState.EAX = Value;
+ pCpuSaveState[Cpu].Ia32SaveState.ECX = 0;
+ break;
+
+ case 0x2:
+
+ Status = AhciMmioWrite ( AhciBaseAddress, pCpuSaveState[Cpu].Ia32SaveState.EBX );
+ if( EFI_ERROR(Status) ) {
+ // Return Error.
+ pCpuSaveState[Cpu].Ia32SaveState.ECX = 0xFF;
+ break;
+ }
+ pCpuSaveState[Cpu].Ia32SaveState.ECX = 0;
+ break;
+ default:
+ // Invalid Function. Return Error.
+ pCpuSaveState[Cpu].Ia32SaveState.ECX = 0xFF;
+ break;
+ }
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AhciMmioSmmInSmmFunction
+//
+// Description: Regsiter the AHCI_MMIO_SWSMI SMI
+//
+// Input: Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT
+// EFI System Table - Pointer to System Table
+//
+// Output: EFI_STATUS OR EFI_NOT_FOUND
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciMmioSmmInSmmFunction(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ EFI_SMM_SW_DISPATCH_PROTOCOL *pSwDispatch;
+ EFI_SMM_SW_DISPATCH_CONTEXT SwContext;
+
+ InitAmiBufferValidationLib( ImageHandle, SystemTable );
+
+ Status = pBS->LocateProtocol(&gEfiSmmSwDispatchProtocolGuid, NULL, &pSwDispatch);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ SwContext.SwSmiInputValue = AHCI_INT13_SMM_SWSMI_VALUE;
+ Status = pSwDispatch->Register(pSwDispatch, AhciMmioSmmSMIHandler, &SwContext, &Handle);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: AhciMmioSmmEntryPoint
+//
+// Description: Ahci MMIO access module entry Point
+//
+// Input: Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT
+// EFI System Table - Pointer to System Table
+//
+// Output: EFI_STATUS OR EFI_NOT_FOUND
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+AhciInt13SmmEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ InitAmiLib(ImageHandle, SystemTable);
+ return InitSmmHandler(ImageHandle, SystemTable, AhciMmioSmmInSmmFunction, NULL);
+
+}
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciInt13Smm.cif b/Core/EM/Ahci/AhciInt13Smm.cif
new file mode 100644
index 0000000..a06480e
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Smm.cif
@@ -0,0 +1,15 @@
+<component>
+ name = "AhciInt13Smm"
+ category = ModulePart
+ LocalRoot = "Core\eM\Ahci"
+ RefName = "AhciInt13Smm"
+[files]
+"AhciInt13Smm.sdl"
+"AhciInt13Smm.h"
+"AhciInt13Dxe.c"
+"AhciInt13Dxe.dxs"
+"AhciInt13Smm.c"
+"AhciInt13Smm.dxs"
+"AhciInt13Smm.mak"
+<endComponent>
+
diff --git a/Core/EM/Ahci/AhciInt13Smm.dxs b/Core/EM/Ahci/AhciInt13Smm.dxs
new file mode 100644
index 0000000..cb8a532
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Smm.dxs
@@ -0,0 +1,65 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.dxs 1 11/25/14 12:09a Kapilporwal $Revision:
+//
+// $Date: 11/25/14 12:09a $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.dxs $
+//
+//
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//****************************************************************************
+//
+// Name: AhciInt13Smm.dxs
+//
+// Description:
+// Dependency expression for the AhciInt13Smm component
+//****************************************************************************
+//<AMI_FHDR_END>
+
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION>=0x4028B)
+#include<Protocol/SmmBase2.h>
+#include<Protocol/SmmSwDispatch2.h>
+#include<Protocol/SmmCpu.h>
+#else
+#include <Protocol/SmmSwDispatch.h>
+#include <Protocol/SmmBase.h>
+#endif
+
+DEPENDENCY_START
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION>=0x4028B)
+ EFI_SMM_BASE2_PROTOCOL_GUID AND
+ EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID AND
+ EFI_SMM_CPU_PROTOCOL_GUID
+#else
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_SMM_SW_DISPATCH_PROTOCOL_GUID
+#endif
+DEPENDENCY_END
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Ahci/AhciInt13Smm.h b/Core/EM/Ahci/AhciInt13Smm.h
new file mode 100644
index 0000000..efe0fad
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Smm.h
@@ -0,0 +1,155 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.h 1 11/25/14 12:09a Kapilporwal $Revision:
+//
+// $Date: 11/25/14 12:09a $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.h $
+//
+//
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//****************************************************************************
+//
+// Name: AhciInt13Smm.h
+//
+// Description:
+// This file contains the definitions of function prototype, constant and
+// data structure for AhciInt13Smm module.
+//****************************************************************************
+//<AMI_FHDR_END>
+
+#ifndef __AINT13_SMM_HEADER__
+#define __AINT13_SMM_HEADER__
+
+#define AHCI_INT13_SMM_DATA_GUID \
+ { 0xF4F63525, 0x281E, 0x4040, 0xA3, 0x13, 0xC1, 0xD6, 0x76, 0x63, 0x84, 0xBE }
+
+// PciExpressBaseAddress uses PCIEX_BASE_ADDRESS
+#define PCI_CFG_ADDR(bus,dev,func,reg) \
+ ((VOID*)(UINTN) (PciExpressBaseAddress + ((bus) << 20) + ((dev) << 15) + ((func) << 12) + reg))
+
+#define AHCI_CONTROLLER 0x06
+#define MASS_STORAGE 0x01
+#define PCI_ABAR 0x24
+#define HDD_BLOCK_SIZE 512
+
+#define READ_SECTORS 0x20
+#define READ_SECTORS_EXT 0x24
+#define READ_MULTIPLE 0xC4
+#define READ_MULTIPLE_EXT 0x29
+#define WRITE_SECTORS 0x30
+#define WRITE_SECTORS_EXT 0x34
+#define WRITE_MULTIPLE 0xC5
+#define WRITE_MULTIPLE_EXT 0x39
+#define READ_DMA 0xC8
+#define READ_DMA_EXT 0x25
+#define WRITE_DMA 0xCA
+#define WRITE_DMA_EXT 0x35
+
+// Int13 parameter definition
+// function(AH) definition
+#define READ_SECTOR 0x02
+#define WRITE_SECTOR 0x03
+#define EXT_READ 0x42
+#define EXT_WRITE 0x43
+
+#ifndef OFFSET_OF
+#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
+#endif
+
+EFI_STATUS AhciInt13DxeEntry(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+);
+
+EFI_STATUS AhciInt13SmmEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+);
+
+// Prevent compiler from padding the structures
+#pragma pack(1)
+
+typedef struct {
+ DLINK dLink;
+ UINT8 DriveNum; // Int13's Drive Number(dl)
+ UINT8 PMPortNum; // PMPort number on HBA
+ UINT8 PortNum; // Port number on HBA
+ UINT8 BusNo; // Bus# of Controller
+ UINT8 DevNo; // Device# of Controller
+ UINT8 FuncNo; // Function# of Controller
+ UINT8 DeviceType; // 0 ATA, 1 ATAPI
+ UINT8 Lun; // ATAPI LUN
+ UINT16 BlockSize; // ATAPI Block Size
+ UINT16 wMAXCYL; // maximum no. of cylinders..INT13 interface. (logical)
+ UINT8 bMAXHN; // maximum no. of heads..INT13 interface. (logical)
+ UINT8 bMAXSN; // no. of sectors per track..INT13 interface. (logical)
+ UINT16 wLBACYL; // #of cylinders drive is configured for. (physical)
+ UINT8 bLBAHD; // #of heads drive is configured for. (physical)
+ UINT8 bLBASPT; // #of sectors per track drive is configured for. (physical)
+ UINT8 WCommand; // write command
+ UINT8 RCommand; // read command
+} SMM_AINT13_DRIVE_INFO;
+
+typedef struct {
+ UINT8 DriveCount;
+ SMM_AINT13_DRIVE_INFO DriveInfo[32]; // Sync array length with SATA_PORT_COUNT of Aint13.h
+} AHCI_INT13_SMM_DATA;
+
+typedef struct {
+ UINT8 PackageSize; // size of package(10h or 18h)
+ UINT8 Reserved; // reserved
+ UINT16 XferSector; // transfer sectors
+ UINT32 Buffer; // 32 bit address transfer buffer
+ UINT64 StartLba; // Start LBA sectors;
+ UINT64 Buffer64; // 64 bit address transfer buffer(option);
+} DISK_ADDRESS_PACKAGE;
+
+// DO NOT MODIFY BELOW STRUCTURE
+// NOTE: If modified, AINT13.ASM (of AI13.bin) also needs to be modified
+typedef struct {
+ UINT32 StackEDI;
+ UINT32 StackESI;
+ UINT32 StackEBP;
+ UINT32 StackESP;
+ UINT32 StackEBX;
+ UINT32 StackEDX;
+ UINT32 StackECX;
+ UINT32 StackEAX;
+ UINT16 StackDS;
+ UINT16 StackES;
+ UINT16 StackGS;
+ UINT16 StackFS;
+ EFI_FLAGS_REG StackFlags;
+} INT13_TO_SMI_EXREGS;
+
+#pragma pack()
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciInt13Smm.mak b/Core/EM/Ahci/AhciInt13Smm.mak
new file mode 100644
index 0000000..bb6a422
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Smm.mak
@@ -0,0 +1,72 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2014, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.mak 2 12/08/14 5:39a Anbuprakashp $Revision:
+#
+# $Date: 12/08/14 5:39a $Log: /Alaska/SOURCE/Modules/AHCI/INT13/AhciInt13Smm.mak $
+#
+#
+#
+#****************************************************************************
+
+#<AMI_FHDR_START>
+#****************************************************************************
+#
+# Name: AhciInt13Smm.mak
+#
+# Description:
+# MAK file for the AhciInt13Smm component
+#****************************************************************************
+#<AMI_FHDR_END>
+
+all : AhciInt13Smm
+AhciInt13Smm : $(BUILD_DIR)\AhciInt13Smm.mak AhciInt13SmmBin
+
+$(BUILD_DIR)\AhciInt13Smm.mak : $(AHCI_INT13_SMM_DIR)\AhciInt13Smm.cif $(AHCI_INT13_SMM_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(AHCI_INT13_SMM_DIR)\AhciInt13Smm.cif $(CIF2MAK_DEFAULTS)
+
+AHCI_INT13_SMM_INCLUDES = $(AMIDXELIB) \
+ $(BUILD_DIR)\AmiBufferValidationLib.lib
+
+AhciInt13SmmBin : $(AHCI_INT13_SMM_INCLUDES)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\AhciInt13Smm.mak all\
+ GUID=501f30e9-d14f-47da-ae60-b101e4189d07\
+ ENTRY_POINT=AhciInt13SmmEntryPoint\
+!IF $(PI_SPECIFICATION_VERSION) >= 0x1000A && $(CORE_COMBINED_VERSION) >= 0x4028B
+ TYPE=DXESMM_DRIVER PE_TYPE=RT_DRIVER\
+ DEPEX1=$(AHCI_INT13_SMM_DIR)\AhciInt13Smm.dxs \
+ DEPEX1_TYPE=EFI_SECTION_SMM_DEPEX \
+ DEPEX2=$(AHCI_INT13_SMM_DIR)\AhciInt13Dxe.dxs \
+ DEPEX2_TYPE=EFI_SECTION_DXE_DEPEX \
+!ELSE
+ TYPE=BS_DRIVER\
+ DEPEX1=$(AHCI_INT13_SMM_DIR)\AhciInt13Smm.dxs \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+!ENDIF
+ COMPRESS=1
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2014, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Ahci/AhciInt13Smm.sdl b/Core/EM/Ahci/AhciInt13Smm.sdl
new file mode 100644
index 0000000..b5ad133
--- /dev/null
+++ b/Core/EM/Ahci/AhciInt13Smm.sdl
@@ -0,0 +1,58 @@
+TOKEN
+ Name = "AHCI_INT13_SMM_SUPPORT"
+ Value = "0"
+ Help = "Main switch to enable SMM support for AHCI Int13/MMIO operations in Project. Currently only INT13 Read/Write functions are supported."
+ TokenType = Boolean
+ Master = Yes
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+PATH
+ Name = "AHCI_INT13_SMM_DIR"
+End
+
+MODULE
+ Help = "Includes AhciInt13Smm.mak"
+ File = "AhciInt13Smm.mak"
+End
+
+TOKEN
+ Name = "AHCI_INT13_SMM_SWSMI_VALUE"
+ Value = "043h"
+ Help = "Value to write into SMI command register to generate software SMI for AHCI INT13/MMIO operations."
+ TokenType = Integer
+ TargetH = Yes
+ TargetEQU = Yes
+ Range = "0 - 0xff"
+End
+
+TOKEN
+ Name = "AINT13_AVOID_MULTIPLE_SMI"
+ Value = "0"
+ Help = "Execute INT13 Read/Write functions completely in SMM and avoid multiple SMI generation for single AHCI INT13 function/call."
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+ Token = "PI_SPECIFICATION_VERSION" ">=" "0x1000A"
+ Token = "CORE_COMBINED_VERSION" ">=" "0x4028B"
+ Token = "SMM_COMMUNICATE_SUPPORT" "=" "1"
+ Token = "AhciSmm_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "BIG_REAL_MODE_MMIO_ACCESS"
+ Value = "0"
+ Help = "1- Access the MMIO region by switching to big real mode, 0 - Access the MMIO using SMI handler"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\AhciInt13Smm.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End \ No newline at end of file
diff --git a/Core/EM/Ahci/AhciSmm/AhciSmm.c b/Core/EM/Ahci/AhciSmm/AhciSmm.c
new file mode 100644
index 0000000..730c1d1
--- /dev/null
+++ b/Core/EM/Ahci/AhciSmm/AhciSmm.c
@@ -0,0 +1,2217 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.c 12 11/24/14 11:56p Kapilporwal $
+//
+// $Revision: 12 $
+//
+// $Date: 11/24/14 11:56p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.c $
+//
+// 12 11/24/14 11:56p Kapilporwal
+// [TAG] EIP191939
+// [Category] Improvement
+// [Description] Issue about BIG_REAL_MODE_MMIO_ACCESS of AHCI module
+// [Files] AI13.bin
+// AHCIACC.ASM
+// AhciInt13Dxe.c
+// AhciInt13Dxe.dxs
+// AhciInt13Smm.c
+// AhciInt13Smm.cif
+// AhciInt13Smm.dxs
+// AhciInt13Smm.h
+// AhciInt13Smm.mak
+// AhciInt13Smm.sdl
+// AInt13.c
+// Aint13.cif
+// AInt13.h
+// AhciSmm.c
+// AhciSmm.h
+// AhciSmmProtocol.h
+//
+// 11 8/11/14 6:47a Anbuprakashp
+// [TAG] EIP178239
+// [Category] Improvement
+// [Description] S3 Resume fails when HDD password is set where platform
+// have more than one AHCI controller
+// [Files] AhciSmm.c,AhciSmm.sdl,IDESMM.c
+//
+// 10 8/17/12 3:14a Srikantakumarp
+// [TAG] EIP95863
+// [Category] Bug Fix
+// [Symptom] AhciSmm doesnt save and restore the upper 32bits of FBU and
+// CLBU
+// [RootCause] As Windows uses the 64bit address for FIS Base Address
+// and Command List Base Address, and AHCISMM driver doesn't take care of
+// the upper 32bit value of those which cause the failure in AhciSMM
+// driver.
+// [Solution] Save and Restore the upper 32bits of FBU and CLBU in
+// AhciSmm Driver.
+// [Files] AhciController.c, AhciSmm.c
+//
+// 9 11/14/11 3:13a Rameshr
+// [TAG] EIP73137
+// [Category] Improvement
+// [Description] Modified the code to use correct status regsiter and
+// bits to check the device status.
+// [Files] AhciSmm.c
+//
+// 8 3/15/11 4:12a Rameshr
+// [TAG]- EIP 51884
+// [Category]- New Feature
+// [Description]- Added packet command function in AhciSMM for sending
+// command in SMM handler
+// [Files]- AhciSmm.c, AhciSmm.h, AhciSmmProtocols.h
+//
+// 7 2/11/11 4:11a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSmm.mak
+// AhciSmm.dxs
+// AhciSmm.c
+// AhciSmm.h
+//
+// 6 5/07/10 2:32p Krishnakumarg
+// Updated the date in AMI header
+//
+// 5 5/07/10 12:37p Krishnakumarg
+// Update for coding standard
+//
+// 4 11/13/09 6:05a Rameshr
+// AhciBaseAddress initilization moved from entryfunction to
+// AhciSmmInitPortOnS3Resume.
+// EIP: 29827
+//
+// 3 11/02/09 6:15p Davidd
+// Correct S3 resume hanging problem in AHCI mode (EIP 29827).
+//
+// 2 6/05/09 2:45p Rameshr
+// x64 mode compilation error Resolved.
+// Eip:22710
+//
+// 1 4/28/09 6:39p Rameshr
+// Initial Check-in
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//--------------------------------------------------------------------------
+//
+// Name: AHCISmm.c
+//
+// Description: AHCISmm funtion implementation.
+//
+//--------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//---------------------------------------------------------------------------
+// Include files
+//---------------------------------------------------------------------------
+//**********************************************************************
+
+#include <Dxe.h>
+#include <AmiDxeLib.h>
+#include <Token.h>
+#include <Protocol\IdeControllerInit.h>
+#include "Protocol\PciIo.h"
+#include "Protocol\PDiskInfo.h"
+#include "Protocol\PIDEController.h"
+#include "protocol\BlockIo.h"
+#include "Protocol\PIDEBus.h"
+#include <Protocol\AhciSmmProtocol.h>
+#include <Protocol\PAhciBus.h>
+#include "AhciSmm.h"
+#include <Protocol\SmmBase.h>
+#include <AmiSmm.h>
+#include "AhciController.h"
+
+#define SCC_AHCI_CONTROLLER 0x06
+#define SCC_RAID_CONTROLLER 0x04
+#define PCI_SCC 0x000A // Sub Class Code Register
+
+
+EFI_GUID gAhciSmmProtocolGuid=AHCI_SMM_PROTOCOL_GUID;
+UINT32 gCommandListBaseAddress;
+UINT32 gFisBaseAddress;
+UINT32 gCommandListBaseAddress2;
+UINT32 gFisBaseAddress2;
+
+AHCI_BUS_SMM_PROTOCOL AhciSmm;
+BOOLEAN gPortReset = FALSE; // Avoid Re-entry
+UINT8 *SenseData=NULL;
+
+
+#if defined(EFI64) || defined(EFIx64)
+static UINT64
+DivU64x32 (
+ IN UINT64 Dividend,
+ IN UINTN Divisor,
+ OUT UINTN *Remainder OPTIONAL
+ )
+{
+ UINT64 Result = Dividend/Divisor;
+ if (Remainder) *Remainder=Dividend%Divisor;
+ return Result;
+}
+
+#else
+static UINT64
+DivU64x32 (
+ IN UINT64 Dividend,
+ IN UINTN Divisor, //Can only be 31 bits.
+ OUT UINTN *Remainder OPTIONAL
+ )
+{
+ UINT64 Result;
+ UINT32 Rem;
+ _asm
+ {
+ mov eax, dword ptr Dividend[0]
+ mov edx, dword ptr Dividend[4]
+ mov esi, Divisor
+ xor edi, edi ; Remainder
+ mov ecx, 64 ; 64 bits
+Div64_loop:
+ shl eax, 1 ;Shift dividend left. This clears bit 0.
+ rcl edx, 1
+ rcl edi, 1 ;Shift remainder left. Bit 0 = previous dividend bit 63.
+
+ cmp edi, esi ; If Rem >= Divisor, don't adjust
+ cmc ; else adjust dividend and subtract divisor.
+ sbb ebx, ebx ; if Rem >= Divisor, ebx = 0, else ebx = -1.
+ sub eax, ebx ; if adjust, bit 0 of dividend = 1
+ and ebx, esi ; if adjust, ebx = Divisor, else ebx = 0.
+ sub edi, ebx ; if adjust, subtract divisor from remainder.
+ loop Div64_loop
+
+ mov dword ptr Result[0], eax
+ mov dword ptr Result[4], edx
+ mov Rem, edi
+ }
+
+ if (Remainder) *Remainder = Rem;
+
+ return Result;
+}
+
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Stall
+//
+// Description: Stalls for the Required Amount of MicroSeconds
+//
+// Input:
+// UINTN Usec // Number of microseconds to delay
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+SmmStall (
+ UINTN Usec
+ )
+{
+ UINTN Counter, i;
+ UINT32 Data32, PrevData;
+ UINTN Remainder;
+
+ Counter = (UINTN)DivU64x32 ((Usec * 10), 3, &Remainder);
+
+ if (Remainder != 0) {
+ Counter++;
+ }
+
+ //
+ // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
+ // periods, thus attempting to ensure Microseconds of stall time.
+ //
+ if (Counter != 0) {
+
+ PrevData = IoRead32(PM_BASE_ADDRESS + 8);
+ for (i=0; i < Counter; ) {
+ Data32 = IoRead32(PM_BASE_ADDRESS + 8);
+ if (Data32 < PrevData) { // Reset if there is a overlap
+ PrevData=Data32;
+ continue;
+ }
+ i += (Data32 - PrevData);
+ PrevData = Data32;
+ }
+ }
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ZeromemorySmm
+//
+// Description: Clears the buffer
+//
+// Input: void *Buffer,
+// UINTN Size
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+void
+ZeroMemorySmm (
+ void *Buffer,
+ UINTN Size
+ )
+{
+ UINT8 *Ptr;
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = 0;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitforPMMemSet
+//
+// Description: Wait for memory to be set to the test value.
+//
+// Input:
+// SATA_DEVICE_INTERFACE *SataDevInterface,
+// PMPort
+// Register
+// MaskValue - The mask value of memory
+// TestValue - The test value of memory
+// WaitTimeInMs - The time out value for wait memory set
+//
+// Output: EFI_SUCCESS - HBA reset successfully.
+// EFI_DEVICE_ERROR - HBA failed to complete hardware reset.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitforPMMemSet (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT8 PMPort,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 TestValue,
+ IN UINT32 WaitTimeInMs
+)
+{
+ UINT32 Data32;
+
+ while(WaitTimeInMs!=0){
+ ReadWritePMPort (SataDevInterface, PMPort, Register, &Data32, FALSE);
+ if((Data32 & AndMask) == TestValue) {return EFI_SUCCESS;}
+ SmmStall (1000); // 1Msec
+ WaitTimeInMs--;
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitForMemSet
+//
+// Description: Wait for memory to be set to the test value.
+//
+// Input: MemTestAddr - The memory address to test
+// MaskValue - The mask value of memory
+// TestValue - The test value of memory
+// WaitTimeInMs - The time out value for wait memory set
+//
+// Output: EFI_SUCCESS - HBA reset successfully.
+// EFI_DEVICE_ERROR - HBA failed to complete hardware reset.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitForMemSet (
+ IN UINT32 BaseAddr,
+ IN UINT8 Port,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 TestValue,
+ IN UINT32 WaitTimeInMs
+)
+{
+ UINT8 Delay;
+ while(WaitTimeInMs!=0){
+ for ( Delay = 10; Delay > 0; Delay--) {
+ if(((HBA_PORT_REG32(BaseAddr, Port, Register)) & AndMask) == TestValue) {return EFI_SUCCESS;}
+ SmmStall (100); // 100 usec * 10 = 1Msec
+ }
+ WaitTimeInMs--;
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitForMemClear
+//
+// Description: Wait for memory to be set to the test value.
+//
+// Input: MemTestAddr - The memory address to test
+// MaskValue - The mask value of memory
+// WaitTimeInMs - The time out value for wait memory set
+//
+// Output: EFI_SUCCESS - HBA reset successfully.
+// EFI_DEVICE_ERROR - HBA failed to complete hardware reset.
+//
+// Modified:
+//
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitForMemClear (
+ IN UINT32 BaseAddr,
+ IN UINT8 Port,
+ IN UINT8 Register,
+ IN UINT32 AndMask,
+ IN UINT32 WaitTimeInMs
+)
+{
+ UINT8 Delay;
+ while(WaitTimeInMs!=0){
+ for ( Delay = 10; Delay > 0; Delay--) {
+ if(!((HBA_PORT_REG32(BaseAddr, Port, Register)) & AndMask)) {return EFI_SUCCESS;}
+ SmmStall (100); // 100 usec * 10 = 1Msec
+ }
+ WaitTimeInMs--;
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadSCRRegister
+//
+// Description:
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort,
+// IN UINT8 Register (0 : SStatus 1: SError 2: SControl)
+//
+// Output:
+// UINT32
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check if the device is connected directly to the port
+// 2. if yes, read to the AHCI Controller else write to the Port Multiplier register.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32
+ReadSCRRegister (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort,
+ IN UINT8 Register
+)
+{
+
+ UINT32 Data32 = 0;
+ UINT32 Reg = HBA_PORTS_SSTS;
+
+ if (PMPort != 0xFF) {
+ ReadWritePMPort (SataDevInterface, PMPort, Register, &Data32, FALSE);
+ }
+ else {
+ if (Register == 1) Reg = HBA_PORTS_SCTL;
+ if (Register == 2) Reg = HBA_PORTS_SERR;
+ Data32 = HBA_PORT_REG32 (SataDevInterface->AhciBaseAddress, Port, Reg);
+ }
+
+ return Data32;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WriteSCRRegister
+//
+// Description: Write to SCONTROL/Serror/SStatus register
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort,
+// IN UINT8 Register, (0 : SStatus 1: SError 2: SControl)
+// IN UINT32 Data32
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check if the device is connected directly to the port
+// 2. if yes, write to the AHCI Controller else write to the Port Multiplier register
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WriteSCRRegister (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort,
+ IN UINT8 Register,
+ IN UINT32 Data32
+)
+{
+
+ UINT32 Reg = HBA_PORTS_SSTS;
+
+ if (PMPort != 0xFF) {
+ ReadWritePMPort (SataDevInterface, PMPort, Register, &Data32, TRUE);
+ }
+ else {
+ if (Register == 2) Reg = HBA_PORTS_SCTL;
+ if (Register == 1) Reg = HBA_PORTS_SERR;
+ HBA_PORT_REG32_OR (SataDevInterface->AhciBaseAddress, Port, Reg, Data32);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitforCommandComplete
+//
+// Description: Wait till cmd completes
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_TYPE CommandType,
+// IN UINTN TimeOut
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check for SError bits. If set return error.
+// 2. For PIO IN/Out and Packet IN/OUT command wait till PIO Setup FIS is received
+// 3. If D2H register FIS is received, exit the loop.
+// 4. Check for SError and TFD bits.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WaitforCommandComplete (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN COMMAND_TYPE CommandType,
+ IN UINTN TimeOut
+)
+{
+
+ UINT32 AhciBaseAddr = (UINT32)SataDevInterface->AhciBaseAddress;
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT32 Data32_SERR, Data32_IS, i;
+ BOOLEAN PxSERR_ERROR = FALSE, PIO_SETUP_FIS = FALSE;
+ volatile AHCI_RECEIVED_FIS *FISReceiveAddress = (AHCI_RECEIVED_FIS *)SataDevInterface->PortFISBaseAddr;
+ UINTN TimeOutCount = TimeOut;
+
+ for(i = 0; i < TimeOutCount * 2; i++, SmmStall(500)) { // 500usec
+
+ //
+ // Check for Error bits
+ //
+ Data32_SERR = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_SERR);
+ if (Data32_SERR & HBA_PORTS_ERR_CHK) {
+ PxSERR_ERROR = TRUE;
+ break;
+ }
+
+ //
+ // Check for Error bits
+ //
+ Data32_IS = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_IS);
+ if (Data32_IS & HBA_PORTS_IS_ERR_CHK) {
+ PxSERR_ERROR = TRUE;
+ break;
+ }
+
+ switch (CommandType) {
+
+ case PIO_DATA_IN_CMD:
+ case PIO_DATA_OUT_CMD:
+ case PACKET_PIO_DATA_IN_CMD:
+ case PACKET_PIO_DATA_OUT_CMD:
+
+ //
+ // check if PIO setup received
+ //
+ if(FISReceiveAddress->Ahci_Psfis[0] == FIS_PIO_SETUP) {
+ FISReceiveAddress->Ahci_Psfis[0] = 0;
+ TimeOutCount = TimeOut;
+ PIO_SETUP_FIS = TRUE;
+ }
+ break;
+ default:
+ break;
+
+ }
+
+ //
+ // check if D2H register FIS is received
+ //
+ if(FISReceiveAddress->Ahci_Rfis[0] == FIS_REGISTER_D2H) break;
+
+ //
+ // For PIO Data in D2H register FIS is not received. So rely on BSY bit
+ //
+ if ((CommandType == PIO_DATA_IN_CMD) && PIO_SETUP_FIS &&
+ !((HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD) &
+ (HBA_PORTS_TFD_BSY | HBA_PORTS_TFD_DRQ)))){
+ break;
+ }
+ }
+
+ if (PxSERR_ERROR) {
+
+ //
+ // clear the status and return error
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // check if CI register is zero
+ //
+ if (HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_CI)){
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // check for status bits
+ //
+ if (HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD) & (HBA_PORTS_TFD_ERR | HBA_PORTS_TFD_DRQ)){
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StartController
+//
+// Description:
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT32 CIBitMask
+//
+// Output:
+// EFI_STATUS
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Clear Status register
+// 2. Enable FIS and CR running bit
+// 3. Enable Start bit
+// 4. Update CI bit mask
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+StartController (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT32 CIBitMask
+)
+{
+
+ UINT32 AhciBaseAddr = (UINT32)(SataDevInterface->AhciBaseAddress);
+ UINT8 Port = SataDevInterface->PortNumber;
+
+ //
+ // Clear Status
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ //
+ // Enable FIS Receive
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_FRE);
+
+ //
+ // Wait till FIS is running
+ //
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ //
+ // Clear FIS Receive area
+ //
+ ZeroMemorySmm ((VOID *)SataDevInterface->PortFISBaseAddr, RECEIVED_FIS_SIZE);
+
+ //
+ // Enable ST
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_ST);
+
+ //
+ // Enable Command Issued
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CI, CIBitMask);
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HandlePortComReset
+//
+// Description: Check if COM Reset is successful or not
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 PMPort,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ReadSCRRegister, WriteSCRRegister
+//
+// Notes:
+// 1. Check if Link is active. If not return error.
+// 2. If Link is present, wait for PhyRdy Change bit to be set.
+// 3. Clear SError register
+// 4. Wait for D2H register FIS
+// 5. Check the Status register for errors.
+// 6. If COMRESET is success wait for sometime if the device is ATAPI or GEN1
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+HandlePortComReset(
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 PMPort
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ BOOLEAN DeviceDetected = FALSE;
+ UINT32 Data32, i, Delay, SStatusData;
+ UINT32 AhciBaseAddr = (UINT32)(SataDevInterface->AhciBaseAddress);
+ volatile AHCI_RECEIVED_FIS *FISAddress;
+
+ //
+ // Check if detection is complete
+ //
+ for (i = 0; i < HBA_PRESENCE_DETECT_TIMEOUT; i++){ // Total delay 10msec
+ SStatusData = ReadSCRRegister (SataDevInterface, Port, PMPort, 0); // SStatus
+ SStatusData &= HBA_PORTS_SSTS_DET_MASK;
+ if ((SStatusData == HBA_PORTS_SSTS_DET_PCE) || (SStatusData == HBA_PORTS_SSTS_DET)) {
+ DeviceDetected = TRUE;
+ break;
+ }
+ SmmStall (1000); // 1msec
+ }
+
+ if (DeviceDetected) {
+
+ //
+ // Wait till PhyRdy Change bit is set
+ //
+ if (PMPort == 0xFF) {
+ Status = WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_SERR,
+ HBA_PORTS_SERR_EX,
+ HBA_PORTS_SERR_EX,
+ ATAPI_BUSY_CLEAR_TIMEOUT);
+ }
+ else {
+ Status = WaitforPMMemSet (SataDevInterface, PMPort, PSCR_1_SERROR,
+ HBA_PORTS_SERR_EX, HBA_PORTS_SERR_EX, ATAPI_BUSY_CLEAR_TIMEOUT);
+ }
+
+ //
+ // Clear Status register
+ //
+ FISAddress = * ((AHCI_RECEIVED_FIS **)(HBA_PORT_REG_BASE(Port) + AhciBaseAddr + HBA_PORTS_FB));
+ for (i = 0; i < ATAPI_BUSY_CLEAR_TIMEOUT; ) {
+ WriteSCRRegister (SataDevInterface, Port, PMPort, 1, HBA_PORTS_ERR_CLEAR); //SError
+
+ if(FISAddress->Ahci_Rfis[0] == FIS_REGISTER_D2H){
+ break;
+ }
+
+ //
+ // 1msec Strange. Delay is needed for read to succeed.
+ //
+ SmmStall (1000); // 1msec (1000);
+
+ //
+ // For device behind PM Port, there is a delay in
+ // writing to the register. So count can be decreased.
+ //
+ if (PMPort != 0xFF) {i+= 100;}
+ else { i++; }
+ }
+
+
+ for ( Delay = 0; Delay < (ATAPI_BUSY_CLEAR_TIMEOUT * 10); Delay++) {
+ if(!((HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD)) & HBA_PORTS_TFD_BSY)) {break;}
+ if((HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_IS)) & (BIT30 + BIT29 + BIT28 + BIT27 + BIT26)) {break;}
+ SmmStall (1000); // 1msec (100); // 100 usec * 10 = 1Msec
+ }
+
+ //
+ // check for errors
+ //
+ Data32 = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_TFD);
+ if (Data32 & (HBA_PORTS_TFD_BSY | HBA_PORTS_TFD_ERR)) Status = EFI_DEVICE_ERROR;
+
+ Data32 = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_IS);
+ if (Data32 & (BIT30 + BIT29 + BIT28 + BIT27 + BIT26)) Status = EFI_DEVICE_ERROR;
+
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GeneratePortReset
+//
+// Description: Issue a Port Reset
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 CurrentPort,
+// IN UINT8 Speed,
+// IN UINT8 PowerManagement
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ReadWritePMPort, HandlePortComReset
+//
+// Notes:
+// 1. Issue port reset by setting DET bit in SControl register
+// 2. Call HandlePortComReset to check the status of the reset.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+GeneratePortReset (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ UINT8 Port,
+ UINT8 PMPort,
+ UINT8 Speed,
+ UINT8 PowerManagement
+)
+{
+
+ EFI_STATUS Status;
+ UINT32 AhciBaseAddr = (UINT32) SataDevInterface->AhciBaseAddress;
+ volatile AHCI_RECEIVED_FIS *FISAddress = *((AHCI_RECEIVED_FIS **)(HBA_PORT_REG_BASE(Port) + AhciBaseAddr + HBA_PORTS_FB));
+ UINT32 Data32;
+
+ if (!FISAddress){
+ return EFI_DEVICE_ERROR; // FIS receive address is not programmed.
+ }
+
+ if (gPortReset){
+ return EFI_SUCCESS;
+ }
+
+ gPortReset = TRUE;
+
+ //
+ // Disable Start bit
+ //
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~HBA_PORTS_CMD_ST);
+
+ //
+ // Wait till CR is cleared
+ //
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_CR_CLEAR_TIMEOUT);
+
+ //
+ // Clear Status register
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ if (PMPort != 0xFF) {
+ Data32 = HBA_PORTS_ERR_CLEAR;
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_1_SERROR, &Data32, TRUE);
+ }
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ //
+ // Enable FIS Receive Enable
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_FRE);
+
+ //
+ // Wait till FIS is running and then clear the data area
+ //
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+
+ FISAddress->Ahci_Rfis[0] = 0;
+
+ if (PMPort == 0xFF) {
+
+ //
+ // Issue Port COMRESET
+ //
+ HBA_PORT_REG32_AND_OR (AhciBaseAddr, Port, HBA_PORTS_SCTL, 0xFFFFF000,
+ HBA_PORTS_SCTL_DET_INIT + (Speed << 4) + (PowerManagement << 8));
+ SmmStall (1000); // 1msec
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_SCTL, ~HBA_PORTS_SCTL_DET_MASK);
+ }
+ else {
+ Data32 = HBA_PORTS_SCTL_DET_INIT + (Speed << 4) + (PowerManagement << 8);
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_2_SCONTROL, &Data32, TRUE);
+ SmmStall (1000); // 1msec
+ Data32 = (Speed << 4) + (PowerManagement << 8);
+ ReadWritePMPort (SataDevInterface, PMPort, PSCR_2_SCONTROL, &Data32, TRUE);
+ }
+
+ Status = HandlePortComReset(SataDevInterface, Port, PMPort);
+
+ //
+ // Disable FIS Receive Enable
+ //
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~HBA_PORTS_CMD_FRE);
+
+ gPortReset = FALSE;
+
+ if (EFI_ERROR(Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StopController
+//
+// Description: Stop FIS and CR
+//
+// Input:
+// IN AHCI_BUS_PROTOCOL *AhciBusInterface,
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: GeneratePortReset
+//
+// Notes:
+// 1. clear ST bit and wait till CR bits gets reset
+// 2. if not generate Port reset
+// 3. Clear FIS running bit.
+// 4. Clear status register
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+StopController(
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN BOOLEAN StartOrStop
+)
+{
+
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 PMPort = SataDevInterface->PMPortNumber;
+ UINT32 AhciBaseAddr = (UINT32)(SataDevInterface->AhciBaseAddress);
+ EFI_STATUS Status;
+ UINT32 PortFISBaseAddr = SataDevInterface->PortFISBaseAddr;
+ UINT32 CommandListBaseAddress = SataDevInterface->PortCommandListBaseAddr;
+
+ if(StartOrStop) {
+ gCommandListBaseAddress=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB);
+ gFisBaseAddress=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_FB);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB,CommandListBaseAddress);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FB,PortFISBaseAddr);
+
+ //
+ // Saving the Upper 32 bits of FIS and Command List Registers
+ //
+ gCommandListBaseAddress2=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_CLBU);
+ gFisBaseAddress2=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_FBU);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLBU,0);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FBU,0);
+ }
+
+ //
+ // Clear Start
+ //
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port, HBA_PORTS_CMD, ~(HBA_PORTS_CMD_ST));
+
+ //
+ // Make sure CR is 0 with in 500msec
+ //
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_CR_CLEAR_TIMEOUT);
+
+ if (EFI_ERROR(Status)) {
+ Status = GeneratePortReset(SataDevInterface, Port, PMPort,
+ HBA_PORTS_SCTL_SPD_NSNR, HBA_PORTS_SCTL_IPM_DIS);
+ };
+
+ if (EFI_ERROR(Status)) {
+ goto StopController_ErrorExit;
+ }
+
+ if (EFI_ERROR(Status)){
+ return Status;
+ }
+
+ //
+ // Clear FIS receive enable.
+ //
+ HBA_PORT_REG32_AND (AhciBaseAddr, Port,
+ HBA_PORTS_CMD, ~(HBA_PORTS_CMD_FRE));
+ //
+ // Make sure FR is 0 with in 500msec
+ //
+ Status = WaitForMemClear(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ if (EFI_ERROR(Status)) {
+ goto StopController_ErrorExit;
+ }
+
+ //
+ // Clear Status register
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR);
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ if(!StartOrStop) {
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB,gCommandListBaseAddress);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FB,gFisBaseAddress);
+
+ //
+ // Restoring the Upper 32 bits of FIS and Command List Registers
+ //
+
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLBU,gCommandListBaseAddress2);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FBU,gFisBaseAddress2);
+ }
+
+ return EFI_SUCCESS;
+
+StopController_ErrorExit:
+
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLB,gCommandListBaseAddress);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FB,gFisBaseAddress);
+
+ //
+ // Restoring the Upper 32 bits of FIS and Command List Registers
+ //
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_CLBU,gCommandListBaseAddress2);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FBU,gFisBaseAddress2);
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadytoAcceptCmd
+//
+// Description: Check if the device is ready to accept cmd.
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: GeneratePortReset, ReadWritePMPort
+//
+// Notes:
+// 1. Check the device is ready to accept the command. BSY and DRQ
+// should be de-asserted.
+// 2. If set, generate Port reset
+// 3. In case Port Multiplier is connected to the port, enable all
+// the ports of the Port Multiplier.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ReadytoAcceptCmd (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface
+)
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 AhciBaseAddr = (UINT32)(SataDevInterface->AhciBaseAddress);
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 PMPort = SataDevInterface->PMPortNumber;
+ UINT32 Data32 = 0, Init_SStatus = 0;
+
+ //
+ // Is the Device ready to accept the command
+ //
+ if (HBA_PORT_REG8 (AhciBaseAddr, Port, HBA_PORTS_TFD) & (HBA_PORTS_TFD_BSY | HBA_PORTS_TFD_DRQ)){
+ Data32 = HBA_PORT_REG32 (AhciBaseAddr, Port, HBA_PORTS_SCTL);
+ Data32 &= 0xFF0;
+
+ //
+ // make sure the status we read is for the right port
+ //
+ Status = GeneratePortReset(SataDevInterface, Port, 0xFF,
+ (UINT8)((Data32 & 0xF0) >> 4), (UINT8)(Data32 >> 8));
+ if (EFI_ERROR(Status)) return Status;
+
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildCommandList
+//
+// Description: Builds command list
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN UINT32 CommandTableBaseAddr
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Update CommandList bits
+// 2. Not all fields like Ahci_Cmd_A are updated.
+// 3. Port number is set to 0xF (Control port) if PM Port number is 0xFF.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildCommandList (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN UINT32 CommandTableBaseAddr
+)
+{
+ UINT8 PMPort = SataDevInterface->PMPortNumber;
+
+ ZeroMemorySmm (CommandList, sizeof(AHCI_COMMAND_LIST));
+ CommandList->Ahci_Cmd_A = SataDevInterface->DeviceType == ATAPI ? 1 : 0; // set elsewhere
+ CommandList->Ahci_Cmd_P = 0;
+ CommandList->Ahci_Cmd_R = 0;
+ CommandList->Ahci_Cmd_B = 0;
+ CommandList->Ahci_Cmd_Rsvd1 = 0;
+ CommandList->Ahci_Cmd_PMP = PMPort == 0xFF ? 0x0 : SataDevInterface->PMPortNumber;
+ CommandList->Ahci_Cmd_PRDTL = 0;
+ CommandList->Ahci_Cmd_PRDBC = 0;
+ CommandList->Ahci_Cmd_CTBA = CommandTableBaseAddr;
+ CommandList->Ahci_Cmd_CTBAU = 0;
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CopyMemSmm
+//
+// Description: Copy Length bytes from Source to Destination.
+//
+// Input:
+// IN VOID *Destination,
+// IN VOID *Source,
+// IN UINTN Length
+//
+// Output:
+// None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+CopyMemSmm (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+
+ Copy Length bytes from Source to Destination.
+
+Arguments:
+
+ Destination - Target of copy
+
+ Source - Place to copy from
+
+ Length - Number of bytes to copy
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+
+ if (Source < Destination) {
+ Destination8 = (CHAR8 *) Destination + Length - 1;
+ Source8 = (CHAR8 *) Source + Length - 1;
+ while (Length--) {
+ *(Destination8--) = *(Source8--);
+ }
+ } else {
+ Destination8 = (CHAR8 *) Destination;
+ Source8 = (CHAR8 *) Source;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildAtapiCMD
+//
+// Description:
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN AHCI_COMMAND_TABLE *Commandtable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Copy Packet data to command table
+// 2. Set Atapi bit in Command List
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildAtapiCMD(
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN COMMAND_STRUCTURE CommandStructure,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN AHCI_COMMAND_TABLE *Commandtable
+)
+{
+
+ CopyMemSmm(&(Commandtable->AtapiCmd),&(CommandStructure.AtapiCmd),sizeof(AHCI_ATAPI_COMMAND));
+
+ if (Commandtable->CFis.Ahci_CFis_Cmd == PACKET_COMMAND){ // Is it a packet command?
+ CommandList->Ahci_Cmd_A = 1;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildPRDT
+//
+// Description: Build PRDT table
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN AHCI_COMMAND_TABLE *Commandtable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Build as many PRDT table entries based on ByteCount.
+// 2. Set the I flag for the lasr PRDT table.
+// 3. Update PRDT table lenght in CommandList
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildPRDT (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN COMMAND_STRUCTURE CommandStructure,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN AHCI_COMMAND_TABLE *Commandtable
+)
+{
+
+ UINT32 ByteCount = CommandStructure.ByteCount;
+ UINT16 Prdtlength = 0;
+ AHCI_COMMAND_PRDT *PrdtTable = &(Commandtable->PrdtTable);
+
+ for (;ByteCount; (UINT8 *)PrdtTable += sizeof(AHCI_COMMAND_PRDT)){
+ PrdtTable->Ahci_Prdt_DBA = (UINT32)CommandStructure.Buffer;
+ PrdtTable->Ahci_Prdt_DBC = ByteCount >= PRD_MAX_DATA_COUNT ? (PRD_MAX_DATA_COUNT - 1) : (ByteCount - 1);
+ ByteCount -= (PrdtTable->Ahci_Prdt_DBC + 1);
+ PrdtTable->Ahci_Prdt_I = 0;
+ Prdtlength+= sizeof(AHCI_COMMAND_PRDT);
+ (UINT8 *)CommandStructure.Buffer += PrdtTable->Ahci_Prdt_DBC + 1;
+ }
+
+ //
+ // Set I flag only for the last entry.
+ //
+ (UINT8 *)PrdtTable -= sizeof(AHCI_COMMAND_PRDT);
+ PrdtTable->Ahci_Prdt_I = 1;
+ CommandList->Ahci_Cmd_PRDTL = Prdtlength / sizeof(AHCI_COMMAND_PRDT);
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildCommandFIS
+//
+// Description: Build Command FIS
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure,
+// IN AHCI_COMMAND_LIST *CommandList,
+// IN AHCI_COMMAND_TABLE *Commandtable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Update Command FIS data area.
+// 2. Update the Command FIS lenght in Command List table
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BuildCommandFIS (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN COMMAND_STRUCTURE CommandStructure,
+ IN AHCI_COMMAND_LIST *CommandList,
+ IN AHCI_COMMAND_TABLE *Commandtable
+)
+{
+
+ ZeroMemorySmm (Commandtable, sizeof(AHCI_COMMAND_TABLE));
+
+ Commandtable->CFis.Ahci_CFis_Type = FIS_REGISTER_H2D;
+ Commandtable->CFis.AHci_CFis_PmPort = SataDevInterface->PMPortNumber == 0xFF ? 0x0 : SataDevInterface->PMPortNumber;
+
+ Commandtable->CFis.Ahci_CFis_Cmd = CommandStructure.Command;
+
+ Commandtable->CFis.Ahci_CFis_Features = CommandStructure.Features;
+ Commandtable->CFis.Ahci_CFis_FeaturesExp = CommandStructure.FeaturesExp;
+
+ Commandtable->CFis.Ahci_CFis_SecNum = CommandStructure.LBALow;
+ Commandtable->CFis.Ahci_CFis_SecNumExp = CommandStructure.LBALowExp;
+
+ Commandtable->CFis.Ahci_CFis_ClyLow = CommandStructure.LBAMid;
+ Commandtable->CFis.Ahci_CFis_ClyLowExp = CommandStructure.LBAMidExp;
+
+ Commandtable->CFis.Ahci_CFis_ClyHigh = CommandStructure.LBAHigh;
+ Commandtable->CFis.Ahci_CFis_ClyHighExp = CommandStructure.LBAHighExp;
+
+ Commandtable->CFis.Ahci_CFis_SecCount = (UINT8)(CommandStructure.SectorCount);
+ Commandtable->CFis.Ahci_CFis_SecCountExp = (UINT8)(CommandStructure.SectorCount >> 8);
+
+ Commandtable->CFis.Ahci_CFis_DevHead = CommandStructure.Device;
+ Commandtable->CFis.Ahci_CFis_Control = CommandStructure.Control;
+
+ CommandList->Ahci_Cmd_CFL = FIS_REGISTER_H2D_LENGTH / 4;
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadWritePMPort
+//
+// Description: Read/Write routine to PM ports
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN UINT8 Port,
+// IN UINT8 RegNum,
+// IN OUT UINT32 *Data
+// IN BOOLEAN READWRITE // TRUE for Write
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, BuildCommandList, BuildCommandFIS, BuildAtapiCMD
+// BuildPRDT, StartController, WaitforCommandComplete
+//
+// Notes:
+// 1. Update Command Structure for READ/Write Port Multiplier command
+// 2. Issue command
+// 3. Check for errors.
+// 4. Read the out data in case of READ.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ReadWritePMPort (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 RegNum,
+ IN OUT UINT32 *Data,
+ IN BOOLEAN READWRITE
+)
+{
+ EFI_STATUS Status;
+ COMMAND_STRUCTURE CommandStructure;
+ AHCI_RECEIVED_FIS *PortFISBaseAddr = (AHCI_RECEIVED_FIS *)(SataDevInterface->PortFISBaseAddr);
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)SataDevInterface->PortCommandTableBaseAddr;
+
+ ZeroMemorySmm (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ CommandStructure.Command = READ_PORT_MULTIPLIER;
+
+ if (READWRITE) {
+ CommandStructure.SectorCount = (UINT16) (*Data & 0xFF);
+ CommandStructure.LBALow = (UINT8) (*Data >> 8);
+ CommandStructure.LBAMid = (UINT8)(*Data >> 16);
+ CommandStructure.LBAHigh = (UINT8)(*Data >> 24);
+ CommandStructure.Command = WRITE_PORT_MULTIPLIER;
+ }
+
+ CommandStructure.Device = Port;
+ CommandStructure.Features = RegNum;
+
+ Status = StopController(SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(SataDevInterface,FALSE);
+ return Status;
+ }
+
+ BuildCommandList(SataDevInterface, CommandList, SataDevInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, CommandStructure, CommandList, Commandtable);
+
+ //
+ // Data-in
+ //
+ CommandList->Ahci_Cmd_W = 0;
+
+ //
+ // Update of Command Register
+ //
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ //
+ // Update the Port Address
+ //
+ CommandList->Ahci_Cmd_PMP = CONTROL_PORT;
+ Commandtable->CFis.AHci_CFis_PmPort = CONTROL_PORT;
+
+ StartController(SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, NON_DATA_CMD, TIMEOUT_1SEC);
+
+ //
+ // Stop Controller
+ //
+ StopController(SataDevInterface,FALSE);
+
+ if (!READWRITE) {
+ *Data = 0;
+ if (!EFI_ERROR(Status)) {
+ *Data = PortFISBaseAddr->Ahci_Rfis[12] |
+ (PortFISBaseAddr->Ahci_Rfis[4] << 8) |
+ (PortFISBaseAddr->Ahci_Rfis[5] << 16) |
+ (PortFISBaseAddr->Ahci_Rfis[6] << 24);
+ }
+ }
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciSmmExecuteDmaDataCommand
+//
+// Description: Exectue the DMA data command
+//
+// Input:
+// IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure,
+// UINT8 PortNumber,
+// UINT8 PMPortNumber,
+// DEVICE_TYPE DeviceType,
+// BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+AhciSmmExecuteDmaDataCommand (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ COMMAND_STRUCTURE *CommandStructure,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType,
+ BOOLEAN READWRITE
+)
+{
+
+ EFI_STATUS Status;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)SataDevInterface->PortCommandTableBaseAddr;
+
+ SataDevInterface->PortNumber=PortNumber;
+ SataDevInterface->PMPortNumber=PMPortNumber;
+ SataDevInterface->DeviceType=DeviceType;
+
+ Status = StopController(SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(SataDevInterface,FALSE);
+ return Status;
+ }
+ BuildCommandList(SataDevInterface, CommandList, SataDevInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildAtapiCMD(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildPRDT(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+
+ // Data-in
+ if (READWRITE) {
+ CommandList->Ahci_Cmd_W = 1;
+ }
+ else {
+ CommandList->Ahci_Cmd_W = 0;
+ }
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController(SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, DMA_DATA_IN_CMD,
+ SataDevInterface->DeviceType == ATA? DMA_ATA_COMMAND_COMPLETE_TIMEOUT \
+ : DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT );
+
+ if (!EFI_ERROR(Status)){
+ //Check if the required BYTES have been received
+ if (CommandList->Ahci_Cmd_PRDBC != CommandStructure->ByteCount){
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+ // Stop Controller
+ StopController(SataDevInterface,FALSE);
+
+ CommandStructure->ByteCount = CommandList->Ahci_Cmd_PRDBC;
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciSmmExecutePioDataCommand
+//
+// Description: Exectue the PIO data command
+//
+// Input:
+// IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure,
+// UINT8 PortNumber,
+// UINT8 PMPortNumber,
+// DEVICE_TYPE DeviceType,
+// BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+AhciSmmExecutePioDataCommand (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ COMMAND_STRUCTURE *CommandStructure,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType,
+ BOOLEAN READWRITE
+ )
+{
+ EFI_STATUS Status;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)SataDevInterface->PortCommandTableBaseAddr;
+
+ SataDevInterface->PortNumber=PortNumber;
+ SataDevInterface->PMPortNumber=PMPortNumber;
+ SataDevInterface->DeviceType=DeviceType;
+
+ Status = StopController(SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(SataDevInterface,FALSE);
+ return Status;
+ }
+
+ BuildCommandList(SataDevInterface, CommandList, SataDevInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildAtapiCMD(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildPRDT(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+
+ if (READWRITE) {
+ CommandList->Ahci_Cmd_W = 1;
+ } else {
+ CommandList->Ahci_Cmd_W = 0;
+ }
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController(SataDevInterface, BIT00);
+
+
+ Status = WaitforCommandComplete(SataDevInterface, PIO_DATA_IN_CMD,
+ SataDevInterface->DeviceType == ATA? DMA_ATA_COMMAND_COMPLETE_TIMEOUT \
+ : DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT );
+
+ CommandStructure->ByteCount = CommandList->Ahci_Cmd_PRDBC;
+
+ //
+ // Stop Controller
+ //
+ StopController(SataDevInterface,FALSE);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciSmmExecuteNonDataCommand
+//
+// Description: Exectue the Non Data command
+//
+// Input:
+// IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+// IN COMMAND_STRUCTURE CommandStructure,
+// UINT8 PortNumber,
+// UINT8 PMPortNumber,
+// DEVICE_TYPE DeviceType,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+AhciSmmExecuteNonDataCommand (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ COMMAND_STRUCTURE CommandStructure,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType
+)
+{
+
+ EFI_STATUS Status;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)SataDevInterface->PortCommandTableBaseAddr;
+
+ SataDevInterface->PortNumber=PortNumber;
+ SataDevInterface->PMPortNumber=PMPortNumber;
+ SataDevInterface->DeviceType=DeviceType;
+
+ Status = StopController(SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)){
+ return Status;
+ }
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController(SataDevInterface,FALSE);
+ return Status;
+ }
+
+ BuildCommandList(SataDevInterface, CommandList, SataDevInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, CommandStructure, CommandList, Commandtable);
+
+ //
+ // Data-in
+ //
+ CommandList->Ahci_Cmd_W = 0;
+
+ //
+ // Update of Command Register
+ //
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController(SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, NON_DATA_CMD, ATAPI_BUSY_CLEAR_TIMEOUT );
+
+ //
+ // Stop Controller
+ //
+ StopController(SataDevInterface,FALSE);
+
+ return Status;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HandleAtapiError
+//
+// Description: Check for ATAPI Errors
+//
+// Input:
+// IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ExecutePacketCommand
+//
+// Notes:
+// 1. Execute ATAPI Request Sense command.
+// 2. Check for Device getting ready, Media Change, No Media and other errors. Update AtapiDevice->Atapi_Status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+HandleAtapiError (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface
+ )
+{
+
+ EFI_STATUS Status;
+ UINT8 Data8 = 0;
+ COMMAND_STRUCTURE CommandStructure;
+ UINT32 AhciBaseAddr = (UINT32)(SataDevInterface->AhciBaseAddress);
+ UINT8 Port = SataDevInterface->PortNumber;
+ ATAPI_DEVICE *AtapiDevice = &SataDevInterface->AtapiDevice;
+
+ AtapiDevice->Atapi_Status = DEVICE_ERROR;
+
+ ZeroMemorySmm (SenseData, 256);
+ ZeroMemorySmm (&CommandStructure, sizeof(COMMAND_STRUCTURE));
+
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[0] = ATAPI_REQUEST_SENSE;
+ CommandStructure.AtapiCmd.Ahci_Atapi_Command[4] = 0xff;
+
+ CommandStructure.ByteCount = 256;
+ CommandStructure.Buffer = SenseData;
+
+ Status = AhciSmmExecutePacketCommand(SataDevInterface, &CommandStructure, 0,
+ Port,SataDevInterface->PMPortNumber,ATAPI);
+
+ if (EFI_ERROR(Status)) {
+ Data8 = HBA_PORT_REG8 (AhciBaseAddr, Port, HBA_PORTS_TFD);
+ }
+
+ // Check for DF and CHK
+ if (Data8 & (DF | CHK)) {
+ goto exit_HandleAtapiError_with_Reset;
+ }
+
+ if (!EFI_ERROR(Status)){
+
+ AtapiDevice->Atapi_Status = DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR; // Default Value
+
+ if (((SenseData[2] & 0xf) == 2) && (SenseData[12] == 0x3a)) {
+ Status = EFI_NO_MEDIA;
+ AtapiDevice->Atapi_Status = MEDIUM_NOT_PRESENT;
+ }
+ if (((SenseData[2] & 0xf) == 2) && (SenseData[12] == 0x04) && (SenseData[13] == 0x01)) {
+ Status = EFI_MEDIA_CHANGED;
+ AtapiDevice->Atapi_Status = BECOMING_READY;
+ }
+
+ if (((SenseData[2] & 0xf) == 6) && (SenseData[12] == 0x28)){
+ Status = EFI_MEDIA_CHANGED;
+ AtapiDevice->Atapi_Status = MEDIA_CHANGED;
+ }
+
+ if (((SenseData[2] & 0xf) == 7) && (SenseData[12] == 0x27)){
+ Status = EFI_WRITE_PROTECTED;
+ AtapiDevice->Atapi_Status = WRITE_PROTECTED_MEDIA;
+ }
+
+ if (((SenseData[2] & 0xf) == 6) && (SenseData[12] == 0x29)){
+ AtapiDevice->Atapi_Status = POWER_ON_OR_DEVICE_RESET;
+ }
+
+ if (((SenseData[2] & 0xf) == 5) && (SenseData[0] == 0x70)){
+ AtapiDevice->Atapi_Status = ILLEGAL_REQUEST;
+ }
+ }
+
+exit_HandleAtapiError_with_Reset:
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciSmmExecutePacketCommand
+//
+// Description: Execute a Atapi Packet command
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface,
+// IN COMMAND_STRUCTURE *CommandStructure
+// IN BOOLEAN READWRITE
+// UINT8 PortNumber,
+// UINT8 PMPortNumber,
+// DEVICE_TYPE DeviceType
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: StopController, ReadytoAcceptCmd, BuildCommandList, BuildCommandFIS, BuildAtapiCMD
+// BuildPRDT, StartController, WaitforCommandComplete
+//
+// Notes:
+// 1. Stop the Controller
+// 2. Check if the device is ready to accept a Command.
+// 3. Build Command list
+// 4. Start the Controller.
+// 5. Wait till command completes. Check for errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+AhciSmmExecutePacketCommand (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN COMMAND_STRUCTURE *CommandStructure,
+ IN BOOLEAN READWRITE,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType
+ )
+{
+
+ EFI_STATUS Status;
+ AHCI_COMMAND_LIST *CommandList = (AHCI_COMMAND_LIST *) SataDevInterface->PortCommandListBaseAddr;
+ AHCI_COMMAND_TABLE *Commandtable = (AHCI_COMMAND_TABLE *)SataDevInterface->PortCommandTableBaseAddr;
+ UINT32 AhciBaseAddr = (UINT32)(SataDevInterface->AhciBaseAddress);
+ UINT8 Port = SataDevInterface->PortNumber;
+ UINT8 Data8;
+ ATAPI_DEVICE *AtapiDevice = &SataDevInterface->AtapiDevice;
+
+
+ SataDevInterface->PortNumber=PortNumber;
+ SataDevInterface->PMPortNumber=PMPortNumber;
+ SataDevInterface->DeviceType=DeviceType;
+
+ CommandStructure->LBAMid = (UINT8)(CommandStructure->ByteCount);
+ CommandStructure->LBAHigh = (UINT8)(CommandStructure->ByteCount >> 8);
+ CommandStructure->Command = PACKET_COMMAND;
+
+ Status = StopController( SataDevInterface,TRUE);
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = ReadytoAcceptCmd(SataDevInterface);
+ if (EFI_ERROR(Status)) {
+ StopController( SataDevInterface,FALSE);
+ return Status;
+ }
+
+ BuildCommandList(SataDevInterface, CommandList, SataDevInterface->PortCommandTableBaseAddr);
+ BuildCommandFIS(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildAtapiCMD(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+ BuildPRDT(SataDevInterface, *CommandStructure, CommandList, Commandtable);
+
+
+ if (READWRITE) {
+ CommandList->Ahci_Cmd_W = 1;
+ }
+ else {
+ CommandList->Ahci_Cmd_W = 0;
+ }
+ Commandtable->CFis.Ahci_CFis_C = 1;
+
+ StartController( SataDevInterface, BIT00);
+
+ Status = WaitforCommandComplete(SataDevInterface, PIO_DATA_IN_CMD,
+ SataDevInterface->DeviceType == ATA? DMA_ATA_COMMAND_COMPLETE_TIMEOUT \
+ : DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT );
+
+
+ // Handle ATAPI device error
+ if (EFI_ERROR(Status) && SataDevInterface->DeviceType == ATAPI) {
+ Data8 = HBA_PORT_REG8 (AhciBaseAddr, Port, HBA_PORTS_TFD);
+ if (Data8 & CHK ){
+ return HandleAtapiError(SataDevInterface);
+ }
+ }
+
+ AtapiDevice->Atapi_Status = EFI_SUCCESS;
+
+ CommandStructure->ByteCount = CommandList->Ahci_Cmd_PRDBC;
+
+ // Stop Controller
+ StopController(SataDevInterface,FALSE);
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciSmmInitPortOnS3Resume
+//
+// Description: Initilize the Sata port on S3 resume
+//
+// Input:
+// IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+// UINT8 Port,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+AhciSmmInitPortOnS3Resume(
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ UINT8 Port
+ )
+{
+ UINT32 AhciBaseAddr=(UINT32)SataDevInterface->AhciBaseAddress;
+ // Return error if AhciBase Address is invalid
+ if(!AhciBaseAddr) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Set the Spin up device on the port
+ //
+
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_SUD);
+
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_SSTS ,
+ HBA_PORTS_SSTS_DET_MASK ,
+ HBA_PORTS_SSTS_DET_PCE ,
+ HBA_PRESENCE_DETECT_TIMEOUT);
+
+ //
+ //Clear Error Regsiter
+ //
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port,
+ HBA_PORTS_SERR, HBA_PORTS_ERR_CLEAR); // Clear Status register
+
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_IS, HBA_PORTS_IS_CLEAR);
+
+ //
+ //Set the FIS base address
+ //
+ gFisBaseAddress=HBA_PORT_REG32(AhciBaseAddr,Port,HBA_PORTS_FB);
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FB,SataDevInterface->PortFISBaseAddr);
+
+ // Enable FIS Receive Enable
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_FRE);
+
+ // Wait till FIS is running
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_FR,
+ HBA_PORTS_CMD_FR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ // Enable ST
+ HBA_PORT_REG32_OR (AhciBaseAddr, Port, HBA_PORTS_CMD, HBA_PORTS_CMD_ST);
+
+ // Wait till CR list is running
+ WaitForMemSet(AhciBaseAddr, Port, HBA_PORTS_CMD,
+ HBA_PORTS_CMD_CR,
+ HBA_PORTS_CMD_CR,
+ HBA_FR_CLEAR_TIMEOUT);
+
+ //
+ //Restore the FIS base address
+ //
+ HBA_PORT_WRITE_REG32(AhciBaseAddr,Port,HBA_PORTS_FB,gFisBaseAddress);
+
+ return EFI_SUCCESS;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: InSmmFunction
+//
+// Description: This function is called from SMM during SMM registration.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InSmmFunction(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+ UINT32 FisBaseAddress=0;
+ UINT32 PortCommandListBaseAddr=0;
+ EFI_SMM_SYSTEM_TABLE *mSmst;
+
+ //
+ //Initilize the Ahci Base addres to 0
+ //
+ AhciSmm.AhciBaseAddress=0;
+
+ //
+ // Allocate memory for FIS. Should be aligned on 256 Bytes. Each Port will have it own FIS data area.
+ //
+ Status = pBS->AllocatePool (EfiReservedMemoryType,
+ 1 * RECEIVED_FIS_SIZE + 0x100,
+ (VOID**)&FisBaseAddress);
+
+ ZeroMemorySmm ((VOID *)FisBaseAddress,1 * RECEIVED_FIS_SIZE + 0x100);
+ AhciSmm.PortFISBaseAddr =((FisBaseAddress & (~0xFF))+ 0x100);
+
+ //
+ // Allocate memory for Command List (1KB aligned) and Command Table (128KB aligned).
+ // All the ports in the controller will share Command List and Command table data Area.
+ //
+ Status = pBS->AllocatePool (EfiReservedMemoryType,
+ COMMAND_LIST_SIZE_PORT * 2,
+ (VOID**)&PortCommandListBaseAddr);
+
+ ZeroMemorySmm ((VOID *)PortCommandListBaseAddr, COMMAND_LIST_SIZE_PORT * 2);
+
+ //
+ // Allocate memory for Sense Data
+ //
+ Status = pBS->AllocatePool (EfiReservedMemoryType,
+ 256,
+ (VOID**)&SenseData);
+
+ AhciSmm.PortCommandListBaseAddr = (PortCommandListBaseAddr & (~0x3FF)) + 0x400;
+ AhciSmm.PortCommandTableBaseAddr = AhciSmm.PortCommandListBaseAddr + 0x80;
+
+ AhciSmm.AhciSmmInitPortOnS3Resume=AhciSmmInitPortOnS3Resume;
+ AhciSmm.AhciSmmExecutePioDataCommand=AhciSmmExecutePioDataCommand;
+ AhciSmm.AhciSmmExecuteDmaDataCommand=AhciSmmExecuteDmaDataCommand;
+ AhciSmm.AhciSmmExecuteNonDataCommand=AhciSmmExecuteNonDataCommand;
+ AhciSmm.AhciSmmExecutePacketCommand=AhciSmmExecutePacketCommand;
+
+
+ Status = pBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, NULL, &pSmmBase);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ pSmmBase->GetSmstLocation (pSmmBase, &mSmst);
+
+ Status = mSmst->SmmInstallConfigurationTable(
+ mSmst,
+ &gAhciSmmProtocolGuid,
+ &AhciSmm,
+ sizeof(AHCI_BUS_SMM_PROTOCOL)
+ );
+
+
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AhciSmmDriverEntryPoint
+//
+// Description: AHCI Smm driver Entry Point
+//
+// Input: EFI_HANDLE ImageHandle,
+// EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AhciSmmDriverEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ InitAmiLib(ImageHandle, SystemTable);
+ return InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NULL);
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciSmm/AhciSmm.cif b/Core/EM/Ahci/AhciSmm/AhciSmm.cif
new file mode 100644
index 0000000..9ff312d
--- /dev/null
+++ b/Core/EM/Ahci/AhciSmm/AhciSmm.cif
@@ -0,0 +1,14 @@
+<component>
+ name = "AhciSmm"
+ category = ModulePart
+ LocalRoot = "CORE\EM\Ahci\AhciSmm\"
+ RefName = "AhciSmm"
+[files]
+"AhciSmm.sdl"
+"AhciSmm.mak"
+"AhciSmm.dxs"
+"AhciSmm.c"
+"AhciSmm.h"
+[parts]
+"AhciSmmProtocols"
+<endComponent>
diff --git a/Core/EM/Ahci/AhciSmm/AhciSmm.dxs b/Core/EM/Ahci/AhciSmm/AhciSmm.dxs
new file mode 100644
index 0000000..c9cad9c
--- /dev/null
+++ b/Core/EM/Ahci/AhciSmm/AhciSmm.dxs
@@ -0,0 +1,87 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.dxs 6 2/11/11 4:11a Rameshr $
+//
+// $Revision: 6 $
+//
+// $Date: 2/11/11 4:11a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.dxs $
+//
+// 6 2/11/11 4:11a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSmm.mak
+// AhciSmm.dxs
+// AhciSmm.c
+// AhciSmm.h
+//
+// 5 12/13/10 11:15a Krishnakumarg
+// [TAG] EIP48678
+// [Category] Action Item
+// [Description] AHCI module does not build without CSM
+// [Solution] Remove dependecies on CSM that are required for AHCI
+// module
+// [Files]
+// AhciSmm.c
+//
+// 4 5/07/10 12:40p Krishnakumarg
+// Updated the AMI header.
+//
+// 3 12/09/09 12:32p Fasihm
+// EIP#29827: Updated the dependency and added the LegayBoot to the
+// dependents.
+//
+// 2 11/20/09 11:18a Fasihm
+// EIP#29827:HDD Password can not be unlocked on AHCI mode when the system
+// resume from S3.
+//
+// 1 4/28/09 6:39p Rameshr
+// Initial Check-in
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AhciSmm.dxs
+//
+// Description: This file is the dependency file for the AhciSmm driver
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Protocol\SmmBase.h>
+
+DEPENDENCY_START
+ EFI_SMM_BASE_PROTOCOL_GUID
+DEPENDENCY_END
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciSmm/AhciSmm.h b/Core/EM/Ahci/AhciSmm/AhciSmm.h
new file mode 100644
index 0000000..81c3d8b
--- /dev/null
+++ b/Core/EM/Ahci/AhciSmm/AhciSmm.h
@@ -0,0 +1,237 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.h 8 11/24/14 11:56p Kapilporwal $
+//
+// $Revision: 8 $
+//
+// $Date: 11/24/14 11:56p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.h $
+//
+// 8 11/24/14 11:56p Kapilporwal
+// [TAG] EIP191939
+// [Category] Improvement
+// [Description] Issue about BIG_REAL_MODE_MMIO_ACCESS of AHCI module
+// [Files] AI13.bin
+// AHCIACC.ASM
+// AhciInt13Dxe.c
+// AhciInt13Dxe.dxs
+// AhciInt13Smm.c
+// AhciInt13Smm.cif
+// AhciInt13Smm.dxs
+// AhciInt13Smm.h
+// AhciInt13Smm.mak
+// AhciInt13Smm.sdl
+// AInt13.c
+// Aint13.cif
+// AInt13.h
+// AhciSmm.c
+// AhciSmm.h
+// AhciSmmProtocol.h
+//
+// 7 9/27/11 3:00a Rajeshms
+// [TAG] EIP69295
+// [Category] Improvement
+// [Description] The Timeout values used by IDE and AHCI drivers are
+// made as SDL tokens, so that the timeout values can be varied.
+// [Files] IdeBusBoard.c, CORE_DXE.sdl, AhciSmm.h, AhciBus.h, IDESMM.h,
+// Ata.c, Atapi.c, IdeBus.c, IdeBus.h, IdeBusMaster.c, IdeBusBoard.h
+//
+// 6 3/15/11 4:12a Rameshr
+// [TAG]- EIP 51884
+// [Category]- New Feature
+// [Description]- Added packet command function in AhciSMM for sending
+// command in SMM handler
+// [Files]- AhciSmm.c, AhciSmm.h, AhciSmmProtocols.h
+//
+// 5 2/11/11 4:11a Rameshr
+// [TAG] EIP53704
+// [Category] Improvement
+// [Description] AMI headers update for Alaska Ahci Driver
+// [Files] AhciSmm.mak
+// AhciSmm.dxs
+// AhciSmm.c
+// AhciSmm.h
+//
+// 4 9/29/10 1:20p Mirk
+// [TAG] EIP44641
+// [Synopsis] Calpella: Build error when Token INDEX_DATA_PORT_ACCESS = 1
+// in AhciSrc.sdl
+// [Category] Defect
+// [Severity] Normal
+// [Resolution] Updated AhciSmm.h and AhciSmm.mak to resolve build errors.
+// [Files] AhciSmm.h, AhciSmm.mak
+//
+// 3 5/07/10 2:30p Krishnakumarg
+// Updated the date in AMI header
+//
+// 2 5/07/10 12:38p Krishnakumarg
+// Updated the AMI header.
+//
+// 1 4/28/09 6:39p Rameshr
+// Initial Check-in
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//--------------------------------------------------------------------------
+//
+// Name: AHCISmm.h
+//
+// Description: Smm function definition
+//
+//--------------------------------------------------------------------------
+//<AMI_FHDR_END>
+#ifndef _EFI_AHCI_SMM_H_
+#define _EFI_AHCI_SMM_H_
+
+#ifndef ATAPI_BUSY_CLEAR_TIMEOUT
+#define ATAPI_BUSY_CLEAR_TIMEOUT 16000 // 16sec
+#endif
+
+#ifndef DMA_ATA_COMMAND_COMPLETE_TIMEOUT
+#define DMA_ATA_COMMAND_COMPLETE_TIMEOUT 5000 // 5Sec
+#endif
+
+#ifndef DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT
+#define DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT 16000 // 16Sec
+#endif
+
+#define COMMAND_LIST_SIZE_PORT 0x800
+#define TIMEOUT_1SEC 1000 // 1sec Serial ATA 1.0 Sec 5.2
+
+
+#define PCI_CFG_ADDR(bus,dev,func,reg) \
+ ((VOID*)(UINTN) (PCIEX_BASE_ADDRESS + ((bus) << 20) + ((dev) << 15) + ((func) << 12) + reg))
+
+
+EFI_STATUS
+AhciSmmExecuteNonDataCommand (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ COMMAND_STRUCTURE CommandStructure,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType
+);
+
+EFI_STATUS
+AhciSmmExecutePioDataCommand (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ COMMAND_STRUCTURE *CommandStructure,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType,
+ BOOLEAN READWRITE
+ );
+
+EFI_STATUS
+AhciSmmExecuteDmaDataCommand (
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ COMMAND_STRUCTURE *CommandStructure,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType,
+ BOOLEAN READWRITE
+);
+
+EFI_STATUS
+AhciSmmInitPortOnS3Resume(
+ AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ UINT8 Port
+ );
+
+EFI_STATUS
+StartController (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT32 CIBitMask
+);
+
+EFI_STATUS
+ReadWritePMPort (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN UINT8 Port,
+ IN UINT8 RegNum,
+ IN OUT UINT32 *Data,
+ IN BOOLEAN READWRITE
+);
+EFI_STATUS
+AhciSmmExecutePacketCommand (
+ IN AHCI_BUS_SMM_PROTOCOL *SataDevInterface,
+ IN COMMAND_STRUCTURE *CommandStructure,
+ IN BOOLEAN READWRITE,
+ UINT8 PortNumber,
+ UINT8 PMPortNumber,
+ DEVICE_TYPE DeviceType
+ );
+
+#endif
+
+#if INDEX_DATA_PORT_ACCESS
+UINT32
+ReadDataDword(
+ IN UINTN BaseAddr,
+ IN UINTN Index
+);
+
+UINT16
+ReadDataWord(
+ IN UINTN BaseAddr,
+ IN UINTN Index
+);
+
+UINT8
+ReadDataByte(
+ IN UINTN BaseAddr,
+ IN UINTN Index
+);
+
+VOID
+WriteDataDword(
+ IN UINTN BaseAddr,
+ IN UINTN Index,
+ IN UINTN Data
+);
+
+VOID
+WriteDataWord(
+ IN UINTN BaseAddr,
+ IN UINTN Index,
+ IN UINTN Data
+);
+
+VOID
+WriteDataByte(
+ IN UINTN BaseAddr,
+ IN UINTN Index,
+ IN UINTN Data
+);
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Ahci/AhciSmm/AhciSmm.mak b/Core/EM/Ahci/AhciSmm/AhciSmm.mak
new file mode 100644
index 0000000..80ef21a
--- /dev/null
+++ b/Core/EM/Ahci/AhciSmm/AhciSmm.mak
@@ -0,0 +1,82 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.mak 4 2/11/11 4:11a Rameshr $
+#
+# $Revision: 4 $
+#
+# $Date: 2/11/11 4:11a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/AHCI/AhciSmm/AhciSmm.mak $
+#
+# 4 2/11/11 4:11a Rameshr
+# [TAG] EIP53704
+# [Category] Improvement
+# [Description] AMI headers update for Alaska Ahci Driver
+# [Files] AhciSmm.mak
+# AhciSmm.dxs
+# AhciSmm.c
+# AhciSmm.h
+#
+# 3 9/29/10 1:20p Mirk
+# [TAG] EIP44641
+# [Synopsis] Calpella: Build error when Token INDEX_DATA_PORT_ACCESS = 1
+# in AhciSrc.sdl
+# [Category] Defect
+# [Severity] Normal
+# [Resolution] Updated AhciSmm.h and AhciSmm.mak to resolve build errors.
+# [Files] AhciSmm.h, AhciSmm.mak
+#
+# 2 5/07/10 11:59a Krishnakumarg
+# Updated the AMI header.
+#
+# 1 4/28/09 6:39p Rameshr
+# Initial Check-in
+#
+#
+#**********************************************************************
+all : AhciSmm
+
+AhciSmm : $(BUILD_DIR)\AhciSmm.mak AhciSmmBin
+
+$(BUILD_DIR)\AhciSmm.mak : $(AHCI_SMM_DIR)\AhciSmm.cif $(AHCI_SMM_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(AHCI_SMM_DIR)\AhciSmm.cif $(CIF2MAK_DEFAULTS) $(AHCI_CSP_DIR)\AhciAccess.cif
+
+AHCI_SMM_INCLUDES=\
+ /I$(AHCI_DIR)\
+
+AhciSmmBin : $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\AhciSmm.mak all\
+ GUID=BC3245BD-B982-4f55-9F79-056AD7E987C5\
+ ENTRY_POINT=AhciSmmDriverEntryPoint\
+ "MY_INCLUDES=$(AHCI_SMM_INCLUDES)"\
+ TYPE=BS_DRIVER\
+ COMPRESS=1
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/Ahci/AhciSmm/AhciSmm.sdl b/Core/EM/Ahci/AhciSmm/AhciSmm.sdl
new file mode 100644
index 0000000..d187ae4
--- /dev/null
+++ b/Core/EM/Ahci/AhciSmm/AhciSmm.sdl
@@ -0,0 +1,24 @@
+TOKEN
+ Name = "AhciSmm_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable AhciSmm support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "AHCI_SMM_DIR"
+End
+
+MODULE
+ Help = "Includes AhciSmm.mak to Project"
+ File = "AhciSmm.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\AhciSmm.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/Ahci/AhciSources.chm b/Core/EM/Ahci/AhciSources.chm
new file mode 100644
index 0000000..4ae32b0
--- /dev/null
+++ b/Core/EM/Ahci/AhciSources.chm
Binary files differ
diff --git a/Core/EM/Ahci/AhciSrc.cif b/Core/EM/Ahci/AhciSrc.cif
new file mode 100644
index 0000000..9c3053e
--- /dev/null
+++ b/Core/EM/Ahci/AhciSrc.cif
@@ -0,0 +1,19 @@
+<component>
+ name = "AHCI"
+ category = eModule
+ LocalRoot = "Core\em\Ahci\"
+ RefName = "AHCI"
+[files]
+"AhciSrc.sdl"
+"AhciSrc.mak"
+"AhciBus.c"
+"AhciController.c"
+"AhciComponentName.c"
+"AhciBus.h"
+"AhciController.h"
+"AhciSources.chm"
+[parts]
+"AINT13"
+"ACSP"
+"AhciSmm"
+<endComponent>
diff --git a/Core/EM/Ahci/AhciSrc.mak b/Core/EM/Ahci/AhciSrc.mak
new file mode 100644
index 0000000..a22919f
--- /dev/null
+++ b/Core/EM/Ahci/AhciSrc.mak
@@ -0,0 +1,102 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/AHCI/AhciSrc.mak 6 2/10/11 10:35a Rameshr $
+#
+# $Revision: 6 $
+#
+# $$
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/AHCI/AhciSrc.mak $
+#
+# 6 2/10/11 10:35a Rameshr
+# [TAG] EIP53704
+# [Category] Improvement
+# [Description] AMI headers update for Alaska Ahci Driver
+# [Files] AhciSrc.mak
+# AhciBus.c
+# AhciController.c
+# AhciComponentName.c
+# AhciBus.h
+# AhciController.h
+#
+# 5 5/07/10 11:42a Krishnakumarg
+# Coding standard update
+#
+# 4 5/28/08 9:36a Rameshraju
+# Based on the SDL token index/data or MMIO method used to access the
+# AHCI configuration space.
+#
+# 3 3/28/08 12:13p Michaela
+# Fixed build issue related to component name change
+#
+# 2 3/02/08 8:16p Fasihm
+# Removed the code not to build the cod files.
+#
+# 1 28/02/08 6:03p Anandakrishnanl
+# AHCI Bus Driver initial check-in.
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: AhciSrc.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : Ahci
+
+Ahci : $(BUILD_DIR)\AhciSrc.mak AhciBin
+
+!IF "$(INDEX_DATA_PORT_ACCESS)"=="1"
+$(BUILD_DIR)\AhciSrc.mak : $(AHCI_DIR)\$(@B).cif $(AHCI_DIR)\$(@B).mak $(BUILD_RULES) $(AHCI_CSP_DIR)\AhciAccess.cif
+ $(CIF2MAK) $(AHCI_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(AHCI_CSP_DIR)\AhciAccess.cif
+!ELSE
+$(BUILD_DIR)\AhciSrc.mak : $(AHCI_DIR)\$(@B).cif $(AHCI_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(AHCI_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+!ENDIF
+
+
+# "CFLAGS = $(CFLAGS) /FAscu /O1 /Fd$(BUILD_DIR)\ /Zi /Gm" \
+# "LFLAGS = $(LFLAGS) /MAP /DEBUG /PDB:$*.pdb" \
+# "CFLAGS = $(CFLAGS:/O1=) /FAscu /Fd$(BUILD_DIR)\ /Zi /Gm" \
+# "LFLAGS= $(LFLAGS) /MAP /DEBUG /PDB:$(BUILD_DIR)\AhciSrc.pdb "\
+
+AhciBin: $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\AhciSrc.mak all\
+ MAKEFILE=$(BUILD_DIR)\AhciSrc.mak \
+ NAME=AHCI \
+ GUID=8F5A2E02-538C-4D59-B920-C4786ACBC552\
+ ENTRY_POINT=AhciBusEntryPoint \
+ TYPE=BS_DRIVER \
+ COMPRESS=1\
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/Ahci/AhciSrc.sdl b/Core/EM/Ahci/AhciSrc.sdl
new file mode 100644
index 0000000..2fa93d7
--- /dev/null
+++ b/Core/EM/Ahci/AhciSrc.sdl
@@ -0,0 +1,105 @@
+TOKEN
+ Name = "AhciSrc_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable IdeBusSrc support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "AHCI_DIR"
+ Path = "Core\Em\Ahci"
+End
+
+PATH
+ Name = "AHCI_CSP_DIR"
+ Path = "CHIPSET\EM\AHCI"
+End
+
+MODULE
+ Help = "Includes AhciSrc.mak to Project"
+ File = "AhciSrc.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\Ahci.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+TOKEN
+ Name = "PORT_MULTIPLIER_SUPPORT"
+ Value = "0"
+ Help = "Switch to Enable/Disable PM Support"
+ TokenType = Boolean
+ TargetH = Yes
+ TargetEQU = Yes
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INDEX_DATA_PORT_ACCESS"
+ Value = "0"
+ Help = "0-MMIO Access , 1- Index/Port access"
+ TokenType = Boolean
+ TargetH = Yes
+ TargetEQU = Yes
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "HDD_PASSWORD_SUPPORT_UNDER_RAIDMODE"
+ Value = "1"
+ Help = "0-HDD Password not support under Raid mode 1- Enabled"
+ TokenType = Boolean
+ TargetH = Yes
+ TargetEQU = Yes
+End
+
+TOKEN
+ Name = "SUPPORT_ATAPI_IN_RAID_MODE"
+ Value = "1"
+ Help = "1-Under Raid mode , Atapi devices are handled by AhciBus driver. 0 - Raid option rom will handle the Atapi devices."
+ TokenType = Boolean
+ TargetH = Yes
+ TargetEQU = Yes
+End
+
+TOKEN
+ Name = "DiPM_SUPPORT"
+ Value = "0"
+ Help = "Support Device Initiated Power Management"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ENABLE_DIPM"
+ Value = "0"
+ Help = " 0 - Disable Device Initiated Power Management Feature. 1 - Enable DipM Feature"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DEVICE_SLEEP_SUPPORT"
+ Value = "0"
+ Help = "Enable/Disable Token to support Device Sleep"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ENABLE_DEVICE_SLEEP"
+ Value = "0"
+ Help = " 0 - Disable Device Sleep Feature. 1 - Enable Device Sleep Feature"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetH = Yes
+End
diff --git a/Core/EM/Ahci/Aint13.cif b/Core/EM/Ahci/Aint13.cif
new file mode 100644
index 0000000..4c93b5b
--- /dev/null
+++ b/Core/EM/Ahci/Aint13.cif
@@ -0,0 +1,18 @@
+<component>
+ name = "AHCI Int13"
+ category = ModulePart
+ LocalRoot = "Core\eM\Ahci"
+ RefName = "AINT13"
+[files]
+"Aint13.sdl"
+"Aint13.mak"
+"Aint13.inf"
+"AInt13.h"
+"AInt13.c"
+"AInt13.dxs"
+[parts]
+"AHCI_INT13INIT_PROTOCOL"
+"AHCI_BINARY"
+"AHCI_INT13_CSP"
+"AhciInt13Smm"
+<endComponent>
diff --git a/Core/EM/Ahci/Aint13.inf b/Core/EM/Ahci/Aint13.inf
new file mode 100644
index 0000000..79226bb
--- /dev/null
+++ b/Core/EM/Ahci/Aint13.inf
@@ -0,0 +1,5 @@
+[MODULE]
+ModuleID = 1
+VendorID = 0
+DeviceID = 1
+File = Addon\AI13.BIN
diff --git a/Core/EM/Ahci/Aint13.mak b/Core/EM/Ahci/Aint13.mak
new file mode 100644
index 0000000..a6988fe
--- /dev/null
+++ b/Core/EM/Ahci/Aint13.mak
@@ -0,0 +1,105 @@
+#//**********************************************************************//
+#//**********************************************************************//
+#//** **//
+#//** (C)Copyright 1985-2013, American Megatrends, Inc. **//
+#//** **//
+#//** All Rights Reserved. **//
+#//** **//
+#//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **//
+#//** **//
+#//** Phone: (770)-246-8600 **//
+#//** **//
+#//**********************************************************************//
+#//**********************************************************************//
+
+#************************************************************************//
+# $Header: /Alaska/SOURCE/Modules/AHCI/INT13/Aint13.mak 7 8/28/13 12:38a Rameshr $
+#
+# $Revision: 7 $
+#
+# $Date: 8/28/13 12:38a $
+#************************************************************************//
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/AHCI/INT13/Aint13.mak $
+#
+# 7 8/28/13 12:38a Rameshr
+# [TAG] EIP134204
+# [Category] Improvement
+# [Description] Build Error resolved if token INDEX_DATA_PORT_ACCESS is
+# enabled.
+# [Files] Aint13.mak
+#
+# 6 6/07/11 12:02p Olegi
+# [TAG] EIP61801
+# [Category] Improvement
+# [Description] Added dependency on LegacyBios protocol.
+#
+# 5 2/10/11 10:49a Rameshr
+# [TAG] EIP53704
+# [Category] Improvement
+# [Description] AMI headers update for Alaska Ahci Driver
+# [Files] Aint13.mak
+# AInt13.h
+# AInt13.c
+#
+# 4 5/28/08 9:41a Rameshraju
+# Updated the AMI Address.
+#
+# 3 3/28/08 12:14p Michaela
+# updated copyright
+#
+# 2 28/02/08 6:12p Anandakrishnanl
+# Added the flags in the Build process.
+#
+# 1 12/07/07 11:17a Olegi
+#
+#************************************************************************//
+
+all: AHCIINT13 AHCIINT13CSP
+
+!IF "$(INDEX_DATA_PORT_ACCESS)"=="1"
+$(BUILD_DIR)\aint13.mak : $(AINT13_DIR)\aint13.cif $(AHCI_CSP_DIR)\ahcicsp.cif $(AHCI_CSP_DIR)\AhciAccess.cif $(AINT13_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CIF2MAK_DEFAULTS) $(AINT13_DIR)\aint13.cif $(AHCI_CSP_DIR)\ahcicsp.cif $(AHCI_CSP_DIR)\AhciAccess.cif
+!ELSE
+$(BUILD_DIR)\aint13.mak: $(AINT13_DIR)\aint13.cif $(AHCI_CSP_DIR)\ahcicsp.cif $(AINT13_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CIF2MAK_DEFAULTS) $(AINT13_DIR)\aint13.cif $(AHCI_CSP_DIR)\ahcicsp.cif
+!ENDIF
+
+AHCIINT13: $(BUILD_DIR)\aint13.mak AHCIINT13BIN
+
+AHCI_OBJECTS = \
+$(BUILD_DIR)\$(AINT13_DIR)\aint13.obj \
+!IF "$(INDEX_DATA_PORT_ACCESS)"=="1"
+$(BUILD_DIR)\$(AHCI_CSP_DIR)\AhciAccess.obj \
+!ENDIF
+$(BUILD_DIR)\$(AHCI_CSP_DIR)\aint13csp.obj
+
+AHCIINT13BIN: $(AMIDXELIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\aint13.mak all\
+ GUID=67820532-7613-4dd3-9ED7-3D9BE3A7DA63\
+ "OBJECTS=$(AHCI_OBJECTS)"\
+ ENTRY_POINT=Ai13EntryPoint\
+ TYPE=BS_DRIVER\
+ COMPRESS=1\
+ DEPEX1=$(AINT13_DIR)\aint13.dxs \
+
+AHCIINT13CSP: $(BUILD_DIR)\ahciacc.obj
+
+$(BUILD_DIR)\ahciacc.obj: $(AHCI_CSP_DIR)\ahciacc.asm
+ $(ASM) /c /nologo /Fo$(BUILD_DIR)\ /Fl$(BUILD_DIR)\ $(AHCI_CSP_DIR)\ahciacc.asm
+
+#//**********************************************************************//
+#//**********************************************************************//
+#//** **//
+#//** (C)Copyright 1985-2013, American Megatrends, Inc. **//
+#//** **//
+#//** All Rights Reserved. **//
+#//** **//
+#//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **//
+#//** **//
+#//** Phone: (770)-246-8600 **//
+#//** **//
+#//**********************************************************************//
+#//**********************************************************************//
diff --git a/Core/EM/Ahci/Aint13.sdl b/Core/EM/Ahci/Aint13.sdl
new file mode 100644
index 0000000..4a51110
--- /dev/null
+++ b/Core/EM/Ahci/Aint13.sdl
@@ -0,0 +1,67 @@
+TOKEN
+ Name = "AINT13_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable AHCI Int13 support in the project."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+ Token = "CSM_SUPPORT" "=" "1"
+End
+
+
+TOKEN
+ Name = "AHCI_CONTROLLER_COUNT"
+ Value = "1"
+ Help = "The controller count can range from 1-6"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Range = "1-6"
+End
+
+TOKEN
+ Name = "AI13_BINARY_VERSION"
+ Value = "5714"
+ Help = "Version of AI13.bin. Higher 2 digits represent CSM version and lower 2 digits represent AI13.bin build number"
+ TokenType = Integer
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+PATH
+ Name = "AINT13_DIR"
+End
+
+MODULE
+ Help = "Includes Aint13.mak"
+ File = "Aint13.mak"
+End
+
+ELINK
+ Name = "AhciApiModuleStart"
+ Parent = "CsmOem16Functions"
+ ProcID = 07h
+ SrcFile = "$(AHCI_CSP_DIR)\ahciacc.asm"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(AINT13_DIR)\aint13.inf"
+ Parent = "CSM_CUSTOM_INFS"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\ahciacc.obj"
+ Parent = "CSM_OEM16_OBJS"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\aint13.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End