summaryrefslogtreecommitdiff
path: root/Core/EM/IdeBus/IdeBus.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/IdeBus/IdeBus.c')
-rw-r--r--Core/EM/IdeBus/IdeBus.c3607
1 files changed, 3607 insertions, 0 deletions
diff --git a/Core/EM/IdeBus/IdeBus.c b/Core/EM/IdeBus/IdeBus.c
new file mode 100644
index 0000000..9a91cc7
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBus.c
@@ -0,0 +1,3607 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/IdeBus/IdeBus.c 65 8/16/12 3:01a Rajeshms $
+//
+// $Revision: 65 $
+//
+// $Date: 8/16/12 3:01a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/IdeBus.c $
+//
+// 65 8/16/12 3:01a 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
+//
+// 64 8/16/12 2:25a Anandakrishnanl
+// [TAG] EIP97113
+// [Category] Improvement
+// [Description] AtaPassThru - Module Enhancement
+// [Files] AtaPassThru.c,
+// AtaPassThruSupport.h,AtaPassThru.mak,IdeBus.c,AhciBus.c
+//
+// 63 8/13/12 10:19a Artems
+// [TAG] EIP97928
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System doesn't detect drives in IDE mode
+// [RootCause] Ide driver returns EFI_ERROR if AtaPassThru protocol is
+// absent
+// [Solution] Make driver to return EFI_SUCCESS as long as there are no
+// IDE-related errors
+// [Files] Idebus.c
+//
+// 62 7/20/12 6:13a 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
+//
+// 61 6/13/12 8:49a Anandakrishnanl
+// [TAG] EIP92381
+// [Category] Improvement
+// [Description] A slip of pen in function IdeBusStart
+// [Files] IdeBus.c
+//
+// 60 12/05/11 6:12p Rajkumarkc
+// [TAG] EIP77142
+// [Category] Improvement
+// [Description] Added the function 'IdeNonDataCommandExp' in the
+// 'IDE_BUS_PROTOCOL' and removed
+// the existing function 'IdeNonDataCommand' for supporting
+// the upper 24bits of LBA.
+// [Files]
+// Ata.c
+// IdeBus.c
+// Idebus.h
+// PIDEBus.h
+//
+// 59 11/16/11 12:35a Rameshr
+// [TAG] EIP74970
+// [Category] Improvement
+// [Description] Generic GUID variables should be defined as static, or
+// not used at all
+// [Files] Idebus.c
+//
+// 57 11/04/11 5:45a Rameshr
+// [TAG] EIP73035
+// [Category] Improvement
+// [Description] Status used on line 2561, conditionally not set.
+// Initilized to EFI_SUCCESS to avoid Junk values.
+// [Files] Idebus.c
+//
+// 56 11/03/11 6:07a Rajeshms
+// [TAG] EIP73260
+// [Category] Improvement
+// [Description] IDE Driver Follow the UEFI Driver Model as per the UEFI
+// Spec. and STOP function was Verified.
+// [Files] IdeBus.c
+//
+// 55 9/27/11 3:13a 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
+//
+// 54 8/22/11 2:56a Anandakrishnanl
+// [TAG] EIP62912
+// [Category] Improvement
+// [Description] Opal Security Definitions Should be Moved to PIDEBUS.h
+// from StorageSecurityProtocol.h
+// StorageSecurityProtocol.h included in OPAL security driver module will
+// give build error when disabled without sdl token #if
+// OpalSecurity_SUPPORT properly placed in Ahcibus and IdeBus drivers. But
+// Bus driver should not depend on any tokens. For this reason need to
+// move OPAL_SEC_INIT_PROTOCOL_GUID in Pidebus.h
+// [Files] IdeBus.c
+// Pidebus.h
+// OpalSecurity.cif
+// OpalSecurity.h
+// IdeOpalSec.c
+// AhciOpalSec.c
+//
+// 53 7/07/11 2:04a Lavanyap
+// [TAG] EIP60503
+// [Description] Added proper comment in InitAcousticSupport() function
+// header
+// [Files] IdeBus.c
+//
+// 52 7/07/11 1:56a Lavanyap
+// [TAG] EIP55207
+// [Category] Improvement
+// [Description] Ide Bus Drive Component Name does not remove trailing
+// spaces from drive name
+// [Files] IdeBus.c
+//
+// 51 6/13/11 1:27p Artems
+// Made file build when OpalSecurity module is absent
+//
+// 50 5/19/11 3:10a 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
+//
+// 49 5/02/11 12:38a Rameshr
+// [TAG]- EIP 58703
+// [Category]-IMPROVEMENT
+// [Description]- Implement correct behavior when RemainingDevicePath
+// passed to Supported() function consist only of end node, as described
+// in UEFI specification Version 2.3.1, page 10.1
+// EFI_DRIVER_BINDING_PROTOCOL.Supported() and Start()
+// [Files]- Idebus.c
+//
+// 48 5/02/11 12:23a Rameshr
+// [TAG]- EIP 58686
+// [Category]-IMPROVEMENT
+// [Description]- Update implementation of EFI_BLOCK_IO_PROTOCOL as
+// described in UEFI specification Version 2.3.1, page 12.8
+// [Files]- Idebus.c, Atapi.c
+//
+// 47 4/12/11 4:05a Rameshr
+// [TAG]- EIP 53710
+// [Category]- New Feature
+// [Description]- ATAPI ODD loading type information added into ATAPI
+// device structure
+// [Files]- Atapi.c, Idebus.c, IdeBus.h
+//
+// 46 12/23/10 3:54a 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
+//
+// 45 9/24/10 2:43a 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
+//
+// 44 8/25/10 4:16a Rameshr
+// New Feature: EIP 37748
+// Description: Move all the IDEBus Source driver SDL token into IdeBus
+// Bin Driver.
+// FilesModified: Ata.c, Atapi.c, idebus.c, IdeBus.h,
+// IdebuscomponentName.c, IdeBusmaster.c IdeBusSrc.mak IdebusSrc.sdl
+// IdeHpa.c, IdePowerManagement.c
+//
+// 43 7/20/10 4:18p Pats
+// EIP 38384: Sytem will get halt with the P-ATA to S-ATA transfer card on
+// APTIO 4.6.4.
+// Problem: Feature and Sector Count values are reversed in the invocation
+// of IdeNonDataCommand to set DEV_CONFIG_FREEZE_LOCK.
+// Solution: Fixed Feature and Sector Count values.
+//
+// 42 5/26/10 6:02a Rameshr
+// Checked the Device Configuration Overlay feature set supported status
+// before sending the DEV_CONFIG_FREEZE_LOCK
+// EIP 38384
+//
+// 41 4/16/10 4:05p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 40 1/11/10 12:10p Krishnakumarg
+// Update for Eip 11835 - To implement Acoustic Management function
+// Eip 30041 - Aptio 4 Device Initiated Power Management (DipM) support
+// for SATA devices
+//
+// 39 9/04/09 3:29p Krishnakumarg
+// Acoustic Management function updated to set acoustic level according to
+// setup option EIP:11835
+// CreateIdeDevicePath will now use EFI_OPEN_PROTOCOL_GET_PROTOCOL instead
+// of EFI_OPEN_PROTOCOL_BY_DRIVER in openprotocol function.
+//
+// 38 8/28/09 11:21a Felixp
+// Component Name protocol implementation is upadted to support both
+// ComponentName and ComponentName2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 37 7/01/09 12:23p Rameshr
+// Coding Standard and File header updated.
+//
+// 36 6/22/09 11:38a Rameshr
+// Odd Type information Saved in Atapi Device Structure.
+// EIP:21548
+//
+// 35 5/01/09 11:01a Rameshr
+// Symptom: Disconnect the IDE controller, make system to hang on debug
+// mode
+// Solution: IdeBlockIoDev pointer has wrong address, that make Freepool
+// to hang the system. Corrected the IdeBlockIoDev address
+//
+// 34 4/28/09 7:17p Rameshr
+// HDD password support in RAID mode
+// EIP:20421
+//
+// 33 4/14/09 1:01p Rameshr
+// When INTEL_IDE_PROTOCOL = 1, the IdeBus driver does not check if modes
+// are valid in the SupportedModes data before assigning them to
+// IdeBusInterface
+// EIP 21195
+//
+// 32 11/02/09 11:16a Anandakrishnanl
+// BUGFIX: Removed ASSERT Since AhciBus Driver presence may return Status
+// Other than Success
+//
+// 31 12/31/08 3:07p Rameshraju
+// BugFix- Validate the PIO mode before programming the PIO mode into the
+// device EIP:17885
+//
+// 30 14/08/08 10:52a Anandakrishnanl
+// Compatible Mode AHCI Support Added and Sdl Token Added in IdeBusSrc.sdl
+//
+// 29 8/06/08 10:37a Rameshraju
+// Corrected problem in debug info print.
+//
+// 28 5/14/08 4:43p Rameshraju
+// Error code added if error happens while configuring device or
+// controller.
+//
+// 27 4/22/08 2:02p Felixp
+// DXE_IDE_DETECT progress code moved from ATA.c to IdeBus.c
+// DXE_IDE_ENABLE progress code added
+//
+// 26 3/27/08 11:21a Srinin
+// CreateIdeDevicePath() modified to create a devicepath
+// even if Remaining devicepath is not NULL.
+//
+// 25 7/03/08 5:45p Anandakrishnanl
+// Added Smart related Changes since Smart is a seperate driver now and
+// smart calls are now made protocol driven. Removed Sdl tokens that are
+// used previously
+//
+// 24 3/06/08 5:20p Ambikas
+//
+// 23 3/06/08 4:41p Ambikas
+//
+// 22 3/04/08 7:51p Felixp
+//
+// 20 28/02/08 7:07p Anandakrishnanl
+// Added HddSecurity Protocol to support security module as a separate
+// driver.
+//
+// 19 10/23/07 4:17p Felixp
+// IDE Security support moved from Sources to Binary
+//
+// 18 22/06/07 12:40p Anandakrishnanl
+// HardDisk Security Support Module Added.
+// Need ACPI Module and SB Module and under Core\Include we updated
+// Setup.h.
+// Also New IdeBus bin module.
+//
+// 17 5/04/07 12:53p Srinin
+// In AHCI and RAID mode, PI reg is ignored. Always controller is in
+// Native mode.
+//
+// 16 4/19/07 12:55p Felixp
+// - Minor bug fix: initialize block size by default with
+// CDROM_BLOCK_SIZE for ATAPI devices (along with DiskIo.c changes
+// resolves SCT failure)
+// - File reformatted to comply with AMI coding standards
+//
+// 13 4/16/07 6:29p Felixp
+// Minor bug fix: initialize block size by default with CDROM_BLOCK_SIZE
+// for ATAPI devices
+//
+// 12 13/04/07 3:01p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 11 12/19/06 6:12p Srinin
+// Software setting Preserve bit set for SATA devices.
+//
+// 10 11/17/06 3:05p Ambikas
+//
+// 9 10/27/06 4:20p Felixp
+// enable IDE interrupts at the exit boot services event handler
+// (required to boot EFI vista)
+//
+// 8 8/09/06 3:34p Pavell
+//
+// 7 5/19/06 10:30p Felixp
+// Device Path code updated to use NODE_LENGTH macros to remove direct
+// access to the Length field
+//
+// 6 3/21/06 4:42p Srinin
+// Build error Fixed.
+//
+// 5 3/13/06 2:20a Felixp
+//
+// 4 1/09/06 11:36a Felixp
+//
+// 2 12/14/05 3:04p Srinin
+// CallBack added to support HDD password support during S3 Resume.
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 16 11/03/05 10:55a Srinin
+// For Busmaster transfer, Buffer should be DWORD aligned.
+//
+// 15 10/21/05 1:39p Srinin
+// Removed Media detection for Atapi devices during Detection process.
+//
+// 14 8/22/05 4:31p Srinin
+// ATA/ATAPI identification changed.
+//
+// 13 2/11/05 6:16p Felixp
+// - Cleanup (duplication of library functions removed)
+// - Code optimized by using DPAddNode instead of DPAdd
+// - AllocatePool + ZeroMem replaced with MallocZ
+//
+// 12 2/01/05 12:58p Srinin
+// IDE HotPlug Support added.
+//
+// 11 1/31/05 11:14a Srinin
+// Fixed ComponentName display issue for IDE devices.
+//
+// 10 1/28/05 1:19p Felixp
+// IdeBus is linked together with CORE_DXE
+//
+// 9 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 8 1/13/05 4:23p Srinin
+// Host Protection Area Support added.
+//
+// 7 1/11/05 2:26p Srinin
+// IDE Power Management Support added.
+//
+// 5 1/10/05 11:29a Srinin
+// SMART Support added.
+//
+// 4 1/05/05 3:55p Srinin
+// Acoustic management Support added.
+//
+// 3 1/05/05 11:21a Srinin
+// BusMaster and Password Support added.
+//
+// 2 12/21/04 4:57p Markw
+// Modified device path defines for consistency.
+//
+// 1 12/10/04 1:01p Srinin
+// Initial Checkin of IdeBus Driver.
+//
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: IdeBus.c
+//
+// Description: Provides IDE Block IO protocol
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#include "IdeBus.h"
+#include <Protocol\IdeBusBoard.h>
+
+static EFI_GUID gEfiIdeBusInitProtocolGuid = IDE_BUS_INIT_PROTOCOL_GUID;
+static EFI_GUID gIdeBusDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+static EFI_GUID gEfiDiskInfoProtocolGuid = EFI_DISK_INFO_PROTOCOL_GUID;
+static EFI_GUID gEfiIdeDiskInfoProtocolGuid = EFI_DISK_INFO_IDE_INTERFACE_GUID;
+static EFI_GUID gIdeSetupProtocolguid = IDE_SETUP_PROTOCOL_GUID;
+static EFI_GUID gEfiBootScriptSaveGuid = EFI_BOOT_SCRIPT_SAVE_GUID;
+static EFI_GUID gDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+static EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+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 gPlatformIdeProtocolGuid = PLATFORM_IDE_PROTOCOL_GUID;
+static EFI_GUID gOpalSecInitProtocolGuid = OPAL_SEC_INIT_PROTOCOL_GUID;
+static EFI_GUID gSMARTProtocolGuid = IDE_SMART_INTERFACE_GUID;
+static EFI_GUID gAtaPassThruInitProtocolGuid = ATA_PASS_THRU_INIT_PROTOCOL_GUID;
+static EFI_GUID gScsiPassThruAtapiInitProtocolGuid = SCSI_PASS_THRU_ATAPI_INIT_PROTOCOL_GUID;
+
+EFI_GUID gSecurityModeProtocolGuid = IDE_SECURITY_INTERFACE_GUID;
+EFI_GUID gPowerMgmtProtocolGuid = IDE_POWER_MGMT_INTERFACE_GUID;
+EFI_GUID gHPAProtocolGuid = IDE_HPA_INTERFACE_GUID;
+
+
+EFI_EVENT gIDEBusEvtBootScript = NULL;
+EFI_EVENT gIDEBusEvtMiscSmmFeatures = NULL;
+
+SCSI_PASS_THRU_ATAPI_INIT_PROTOCOL *gScsiPassThruAtapiInitProtocol;
+ATA_PASS_THRU_INIT_PROTOCOL *AtaPassThruInitProtocol;
+OPAL_SECURITY_INIT_PROTOCOL *OpalSecInitProtocol;
+HDD_SECURITY_INIT_PROTOCOL *HddSecurityInitProtocol;
+HDD_SMART_INIT_PROTOCOL *HddSmartInitProtocol;
+IDE_SETUP_PROTOCOL *gIdeSetupProtocol;
+PLATFORM_IDE_PROTOCOL *gPlatformIdeProtocol;
+
+extern EFI_COMPONENT_NAME_PROTOCOL gIdeBusControllerDriverName;
+
+//
+// Instantiate PLATFORM_IDE_PROTOCOL with default SDL Token values
+//
+
+PLATFORM_IDE_PROTOCOL gPlatformIdeProtocolInstance = {
+ 2, //Protocol Revision
+ 1, //MasterSlaveEnumeration
+ 1, //IdeBusMasterSupport
+ 1, //AtapiBusMasterSupport
+ 1, //AcousticManagementSupport
+ 0, //IdePowerManagementSupport
+ 5, //StandbyTimeout
+ 0, //AdvPowerManagementSupport
+ 1, //AdvPowerManagementLevel
+ 0, //PowerupInStandbySupport
+ 0, //PowerupInStandbyMode
+ 0, //IdePwrManagementInterfaceSupport
+ 0, //HostProtectedAreaSupport
+ 0, //IdeHPSupport
+ 1, //EfiIdeProtocol
+ 0, //AhciCompatibleMode
+ 0, //SBIdeSupport
+ 1, //HddPowerLossInS3
+ 0, //DiPMSupport
+ 0, //DisableSoftSetPrev
+ 0, //ForceHddPasswordPrompt
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID, //gIdeControllerProtocolGuid
+ EFI_COMPONENT_NAME_PROTOCOL_GUID, //gComponentNameProtocolGuid
+ 10000, //S3BusyClearTimeout
+ 5000, //DmaAtaCompleteCommandTimeout
+ 16000, //DmaAtaPiCompleteCommandTimeout
+ 5000, //AtaPiResetCommandTimeout
+ 16000, //AtaPiBusyClearTimeout
+ 10000 //PoweonBusyClearTimeout
+};
+
+EFI_DRIVER_BINDING_PROTOCOL gIdeBusDriverBinding = {
+ IdeBusSupported,
+ IdeBusStart,
+ IdeBusStop,
+ IDE_BUS_DRIVER_VERSION, // version
+ NULL, // ImageHandle
+ NULL // DriverBindingHandle
+};
+
+// Global Buffer pointer used for Bus Mastering
+VOID *gDescriptorBuffer = NULL;
+
+VOID InitMiscConfig (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface
+);
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IdeBusExitBootServices
+//
+// Description: Enables IDE controller interrupt on ExitBootServices
+//
+// Input:
+// Event - The Event that is being processed
+// Context - Event Context
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID EFIAPI IdeBusExitBootServices(
+ IN EFI_EVENT Event,
+ IN VOID *Context )
+{
+ EFI_STATUS Status;
+ UINTN Count;
+ EFI_HANDLE Buffer[0x100];
+ UINTN BufferSize = sizeof(Buffer);
+ UINT8 i;
+ UINT8 j;
+ UINT8 k;
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitProtocol;
+ IDE_BUS_PROTOCOL *pIdeBusProtocol;
+ UINT64 IdeDevControlReg;
+ UINT64 IdeDevReg;
+ UINT8 Data8 = 0;
+
+ Status = pBS->LocateHandle(
+ ByProtocol,
+ &gEfiIdeBusInitProtocolGuid,
+ NULL,
+ &BufferSize,
+ Buffer
+ );
+
+ if ( !EFI_ERROR( Status )) {
+ Count = BufferSize / sizeof(EFI_HANDLE);
+
+ for ( i = 0; i < Count; i++ )
+ {
+ Status = pBS->HandleProtocol( Buffer[i], &gEfiIdeBusInitProtocolGuid, &IdeBusInitProtocol );
+
+ if ( !Status ) {
+ for ( j = 0; j < 2; j++ )
+ {
+ for ( k = 0; k < 2; k++ )
+ {
+ if ( IdeBusInitProtocol->pIdeBusProtocol[j][k] ) {
+ if ( IdeBusInitProtocol->IdeBusInitData[j][k] == DEVICE_CONFIGURED_SUCCESSFULLY ) {
+ pIdeBusProtocol = IdeBusInitProtocol->pIdeBusProtocol[j][k];
+
+ //
+ //Dev select
+ //
+ Data8 = pIdeBusProtocol->IdeDevice.Device << 4;
+ IdeDevReg = (UINT64)pIdeBusProtocol->IdeDevice.Regs.CommandBlock.DeviceReg;
+ pIdeBusProtocol->PciIO->Io.Write(
+ pIdeBusProtocol->PciIO,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IdeDevReg,
+ 1,
+ &Data8
+ );
+
+
+ Data8 = 0;
+ //
+ //Enable IDE Controller interrupt
+ //
+ IdeDevControlReg = (UINT64)pIdeBusProtocol->IdeDevice.Regs.ControlBlock.AlternateStatusReg;
+ pIdeBusProtocol->PciIO->Io.Write(
+ pIdeBusProtocol->PciIO,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IdeDevControlReg,
+ 1,
+ &Data8
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IdeBusEntryPoint
+//
+// Description: Installs gIdeBusDriverBinding protocol
+//
+// Input:
+// IN EFI_HANDLE ImageHandle,
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitAmiLib InstallMultipleProtocolInterfaces
+//
+// 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 IdeBusEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ExitBootServicesNotifyEvent;
+
+ gIdeBusDriverBinding.DriverBindingHandle = NULL;
+ gIdeBusDriverBinding.ImageHandle = ImageHandle;
+
+ InitAmiLib( ImageHandle, SystemTable );
+ //
+ //Register our ExitBootServices () callback function
+ //
+ Status = pBS->CreateEvent(
+ EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK,
+ IdeBusExitBootServices,
+ NULL,
+ &ExitBootServicesNotifyEvent
+ );
+ ASSERT_EFI_ERROR( Status );
+
+ Status = pBS->LocateProtocol(
+ &gPlatformIdeProtocolGuid,
+ NULL,
+ &gPlatformIdeProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // if EFI_ERROR then Assign Default values Instance to gPlatformIdeProtocol.
+ //
+ gPlatformIdeProtocol = (PLATFORM_IDE_PROTOCOL *)&gPlatformIdeProtocolInstance;
+ }
+ //
+ // Assert when PLATFORM_IDE_PROTOCOL's revision is not supported
+ //
+ ASSERT(!(gPlatformIdeProtocol->Revision > PLATFORM_IDE_PROTOCOL_SUPPORTED_REVISION))
+
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &gIdeBusDriverBinding.DriverBindingHandle,
+ &gIdeBusDriverBindingProtocolGuid, &gIdeBusDriverBinding,
+ &(gPlatformIdeProtocol->gComponentNameProtocolGuid), &gIdeBusControllerDriverName,
+ NULL
+ );
+
+#ifdef Debug_Level_1
+ EfiDebugPrint( -1, "IdeBusEntryPoint Exit Status %x\n", Status );
+#endif
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IdeBusSupported
+//
+// Description: Checks whether IDE_PROTOCOL_INTERFACE 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 "gEfiIdeControllerProtocolGuid" 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 "gEfiIdeBusInitProtocolGuid" is already installed by this BUS driver,
+// if yes, check whether it is OK to configure this device. if not installed goto step 1.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeBusSupported(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+ EFI_STATUS Status;
+
+ VOID *IdeControllerInterface = NULL ;
+ ATAPI_DEVICE_PATH *AtapiRemainingDevicePath = (ATAPI_DEVICE_PATH*) RemainingDevicePath;
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface;
+ EFI_PCI_IO_PROTOCOL *PciIO;
+ UINT8 PciConfig[256];
+
+#ifdef Debug_Level_1
+ EfiDebugPrint( -1, "IdeBusSupported Entry\n" );
+#endif
+
+ //
+ //Check for Valid ATAPI Device Path. If no return UNSUPPORTED
+ //
+ if ( !(AtapiRemainingDevicePath == NULL)) {
+
+ //
+ // RemainingDevicePath is not NULL and begins with the End of Device Path node,
+ // then the driver must not enumerate any of the children of Controller nor create any child device handle.
+ // Only the controller initialization should be performed. UEFI specification V 2.3.1, P. 10.1
+ //
+ if(isEndNode(RemainingDevicePath)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check if the AtapiRemainingDevicePath is valid 8.3.4.1
+ //
+ if ( AtapiRemainingDevicePath->Header.Type != MESSAGING_DEVICE_PATH
+ || AtapiRemainingDevicePath->Header.SubType != MSG_ATAPI_DP
+ && NODE_LENGTH( &AtapiRemainingDevicePath->Header ) != ATAPI_DEVICE_PATH_LENGTH ) {
+#ifdef Debug_Level_3
+ EfiDebugPrint( -1, "AtapiRemainingDevicePath not Valid\n" );
+#endif
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ //Now check whether it is OK to enumerate the specified device.
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ (VOID**)&IdeBusInitInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if ( Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED ) {
+ pBS->CloseProtocol(
+ Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == PRIMARY_CHANNEL && AtapiRemainingDevicePath->SlaveMaster == MASTER_DRIVE ) {
+ if ( IdeBusInitInterface->IdeBusInitData[PRIMARY_CHANNEL][MASTER_DRIVE] >= DEVICE_DETECTION_FAILED ) {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == PRIMARY_CHANNEL && AtapiRemainingDevicePath->SlaveMaster == SLAVE_DRIVE ) {
+ if ( IdeBusInitInterface->IdeBusInitData[PRIMARY_CHANNEL][SLAVE_DRIVE] >= DEVICE_DETECTION_FAILED ) {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == SECONDARY_CHANNEL && AtapiRemainingDevicePath->SlaveMaster == MASTER_DRIVE ) {
+ if ( IdeBusInitInterface->IdeBusInitData[SECONDARY_CHANNEL][MASTER_DRIVE] >= DEVICE_DETECTION_FAILED ) {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == SECONDARY_CHANNEL && AtapiRemainingDevicePath->SlaveMaster == SLAVE_DRIVE ) {
+ if ( IdeBusInitInterface->IdeBusInitData[SECONDARY_CHANNEL][SLAVE_DRIVE] >= DEVICE_DETECTION_FAILED ) {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+ }
+ }
+
+ //
+ //Check whether IDE_CONTROLLER_PROTOCOL has been installed on this controller
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ (VOID**)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+#ifdef Debug_Level_3
+
+ if ( EFI_ERROR( Status )) {
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ EfiDebugPrint( -1, "Error opening gEfiIdeControllerInitProtocolGuid\n" );
+ else
+ EfiDebugPrint( -1, "Error opening gEfiIdeControllerProtocolGuid\n" );
+ }
+#endif
+
+ //
+ //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,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ This->DriverBindingHandle,
+ Controller
+ );
+
+#ifdef Debug_Level_1
+ EfiDebugPrint( -1, "IdeBusSupported Exit Success\n" );
+#endif
+ //
+ // 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) || (PciConfig [IDE_SUB_CLASS_CODE] == SCC_RAID_CONTROLLER)) {
+ if ( !(gPlatformIdeProtocol->AhciCompatibleMode) )
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IdeBusStart
+//
+// Description: Installs IDE 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
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Check if "gEfiIdeBusInitProtocolGuid" is already installed. If not, install it "InstallBusInitProtocol".
+// 2. If Devicepath is valid, initialize so that only particular device will be detected and
+// confgiured, else all devices will be detected and configured.
+// 3. check whether the device has not been already detected. If yes, skip it and go for next device
+// 4. IdeBusInterface is initialized for this device. Update Base address.
+// 5. Do the detection "DetectIdeDevice". Update the status in "IdeBusInitProtocol". If failure undo the process "IdeBusInterface".
+// 6. Repeat for all devices from step 3.
+// 7. Start the configuration process for devices which are detected successfully "DEVICE_DETECTED_SUCCESSFULLY".
+// 8. "ConfigureIdeDeviceAndController" will do the configuration.
+// 9. If above step is success, build Devicepath "CreateIdeDevicePath"
+// 10. Create the Block_io_Protocol"InitIdeBlockIO". Install it only if Device is not Password protected.
+// 11. Create the DISK_INFO_PROTOCOL "InitIdeDiskInfo". Install it only if Device is not Password protected.
+// 12. Install a child device with the above three protocols.
+// 13. Open "gEfiIdeControllerProtocolGuid" with the child handle.
+// 14. Repeat from step 8 for the remaining devices.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeBusStart(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIO;
+
+ IDE_BLK_IO_DEV *IdeBlockIoDev = NULL;
+ VOID *IdeControllerInterface = NULL ;
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface;
+ IDE_BUS_PROTOCOL *IdeBusInterface;
+ UINT8 Enumeration_Process = ENUMERATE_ALL;
+ ATAPI_DEVICE_PATH *AtapiRemainingDevicePath = (ATAPI_DEVICE_PATH*)RemainingDevicePath;
+
+ UINT8 Start_Channel = PRIMARY_CHANNEL;
+ UINT8 End_Channel = SECONDARY_CHANNEL;
+ UINT8 Start_Device = MASTER_DRIVE;
+ UINT8 End_Device = SLAVE_DRIVE;
+
+ INT8 TotalDevice = 0;
+ INT8 Current_Channel;
+ INT8 Current_Device;
+ UINT16 SecurityStatus = 0;
+
+#ifdef Debug_Level_1
+ EfiDebugPrint( -1, "IdeBusStart Entry\n" );
+#endif
+
+ PROGRESS_CODE( DXE_IDE_BEGIN );
+
+ //
+ //Open IDE_CONTROLLER_PROTOCOL. If success or Already opened, It is OK to proceed.
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ (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 );
+
+
+ //
+ //Check if IDE_BUS_INIT_PROTOCOL installed.
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ (VOID**)&IdeBusInitInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+
+ if ( !(Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED)) {
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof(IDE_BUS_INIT_PROTOCOL),
+ (VOID**)&IdeBusInitInterface
+ );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = InstallBusInitProtocol( Controller, IdeBusInitInterface, IdeControllerInterface );
+
+ if ( EFI_ERROR( Status )) {
+ if ( Status == EFI_OUT_OF_RESOURCES) {
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+
+ //
+ // Check if AtapiRemainingDevicePath is valid or not
+ //
+ if ( !(AtapiRemainingDevicePath == NULL)) {
+
+ //
+ // RemainingDevicePath is not NULL and begins with the End of Device Path node,
+ // then the driver must not enumerate any of the children of Controller nor create any child device handle.
+ // Only the controller initialization should be performed. UEFI specification V 2.3.1, P. 10.1
+ //
+ if(isEndNode(RemainingDevicePath)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check if the AtapiRemainingDevicePath is valid 8.3.4.1
+ //
+ if ( AtapiRemainingDevicePath->Header.Type != MESSAGING_DEVICE_PATH
+ || AtapiRemainingDevicePath->Header.SubType != MSG_ATAPI_DP
+ && NODE_LENGTH( &AtapiRemainingDevicePath->Header ) != ATAPI_DEVICE_PATH_LENGTH ) {
+#ifdef Debug_Level_3
+ EfiDebugPrint( -1, "AtapiRemainingDevicePath not Valid\n" );
+#endif
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == PRIMARY_CHANNEL
+ && AtapiRemainingDevicePath->SlaveMaster == MASTER_DRIVE ) {
+ Enumeration_Process = ENUMERATE_PRIMARY_MASTER;
+ }
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == PRIMARY_CHANNEL
+ && AtapiRemainingDevicePath->SlaveMaster == SLAVE_DRIVE ) {
+ Enumeration_Process = ENUMERATE_PRIMARY_SLAVE;
+ }
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == SECONDARY_CHANNEL
+ && AtapiRemainingDevicePath->SlaveMaster == MASTER_DRIVE ) {
+ Enumeration_Process = ENUMERATE_SECONDARY_MASTER;
+ }
+
+ if ( AtapiRemainingDevicePath->PrimarySecondary == SECONDARY_CHANNEL
+ && AtapiRemainingDevicePath->SlaveMaster == SLAVE_DRIVE ) {
+ Enumeration_Process = ENUMERATE_SECONDARY_SLAVE;
+ }
+
+ switch ( Enumeration_Process )
+ {
+ case ENUMERATE_PRIMARY_MASTER:
+ Start_Channel = PRIMARY_CHANNEL;
+ End_Channel = PRIMARY_CHANNEL;
+ Start_Device = MASTER_DRIVE;
+ End_Device = MASTER_DRIVE;
+ break;
+ case ENUMERATE_PRIMARY_SLAVE:
+ Start_Channel = PRIMARY_CHANNEL;
+ End_Channel = PRIMARY_CHANNEL;
+ Start_Device = SLAVE_DRIVE;
+ End_Device = SLAVE_DRIVE;
+ break;
+ case ENUMERATE_SECONDARY_MASTER:
+ Start_Channel = SECONDARY_CHANNEL;
+ End_Channel = SECONDARY_CHANNEL;
+ Start_Device = MASTER_DRIVE;
+ End_Device = MASTER_DRIVE;
+ break;
+ case ENUMERATE_SECONDARY_SLAVE:
+ Start_Channel = SECONDARY_CHANNEL;
+ End_Channel = SECONDARY_CHANNEL;
+ Start_Device = SLAVE_DRIVE;
+ End_Device = SLAVE_DRIVE;
+ break;
+ default:
+ break;
+ }
+ }
+
+
+#ifdef Debug_Level_3
+ EfiDebugPrint( -1, "Enumerate = %x\n", Enumeration_Process );
+#endif
+
+ //---------------------------------------------------------------------------------------------------------
+ // Device Detection Begins
+ //---------------------------------------------------------------------------------------------------------
+ PROGRESS_CODE( DXE_IDE_DETECT );
+
+ for ( Current_Channel = Start_Channel; Current_Channel <= End_Channel; Current_Channel++ )
+ {
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ ( (EFI_IDE_CONTROLLER_INIT_PROTOCOL*)IdeControllerInterface )->NotifyPhase( (EFI_IDE_CONTROLLER_INIT_PROTOCOL*)IdeControllerInterface, EfiIdeBeforeChannelEnumeration, Current_Channel );
+ }
+ //
+ // Calculate the Number of Devices to be detected in single Channel
+ //
+ TotalDevice = ( End_Device - Start_Device ) + 1;
+
+ if ( gPlatformIdeProtocol->MasterSlaveEnumeration ) {
+ Current_Device = Start_Device;
+ } else {
+ Current_Device = End_Device;
+ }
+
+ while ( TotalDevice )
+ {
+ //
+ // Check whether the given device is disabled by USER OR already processed
+ //
+ if ( IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_DISABLED
+ || IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_DETECTED_SUCCESSFULLY
+ || IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_CONFIGURED_SUCCESSFULLY
+ || IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_DETECTION_FAILED
+ || IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_REMOVED ) {
+
+ if ( gPlatformIdeProtocol->MasterSlaveEnumeration ) {
+ Current_Device++;
+ } else {
+ Current_Device--;
+ }
+ TotalDevice--;
+ continue;
+ }
+
+ //
+ // Allocate memory for IDE_BUS_PROTOCOL
+ //
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ IdeBlockIoDev = MallocZ( sizeof(IDE_BLK_IO_DEV));
+
+ if ( !IdeBlockIoDev ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ IdeBlockIoDev->Signature = IDE_BLK_IO_DEV_SIGNATURE;
+ IdeBusInterface = (IDE_BUS_PROTOCOL*)&(IdeBlockIoDev->BlkIo);
+ } else {
+ IdeBusInterface = MallocZ( sizeof(IDE_BUS_PROTOCOL));
+
+ if ( !IdeBusInterface ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // Initialize the fields
+ //
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ IdeBusInterface->EfiIdeControllerInterface =(EFI_IDE_CONTROLLER_INIT_PROTOCOL*) IdeControllerInterface;
+ IdeBusInterface->IdeControllerInterfaceHandle = Controller;
+ } else {
+ IdeBusInterface->IdeControllerInterface =(IDE_CONTROLLER_PROTOCOL*) IdeControllerInterface;
+ }
+ IdeBusInterface->IdeBusInitInterface = IdeBusInitInterface;
+ IdeBusInterface->PciIO = PciIO;
+ IdeBusInterface->IdeDevice.PciIO = PciIO;
+ IdeBusInterface->IdeDevice.Channel = Current_Channel;
+ IdeBusInterface->IdeDevice.Device = Current_Device;
+ IdeBusInterface->AtaReadWritePio = AtaReadWritePio;
+ IdeBusInterface->AtaPioDataIn = AtaPioDataIn;
+ IdeBusInterface->AtaPioDataOut = AtaPioDataOut;
+ IdeBusInterface->IdeNonDataCommand = IdeNonDataCommandExp;
+ IdeBusInterface->WaitForCmdCompletion = WaitForCmdCompletion;
+ IdeBusInterface->GeneralAtapiCommandAndData = GeneralAtapiCommandAndData;
+ Status = UpdateBaseAddress( IdeBusInterface );
+
+ if ( Status == EFI_SUCCESS ) {
+ Status = DetectIdeDevice( IdeBusInterface );
+ }
+
+ if ( EFI_ERROR( Status ) ) {
+ //
+ // Update IdeBusInitInterface
+ //
+ IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] = DEVICE_DETECTION_FAILED;
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+
+ if ( gPlatformIdeProtocol->MasterSlaveEnumeration ) {
+ Current_Device++;
+ } else {
+ Current_Device--;
+ }
+ TotalDevice--;
+ continue;
+ } else {
+ IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] = DEVICE_DETECTED_SUCCESSFULLY;
+ IdeBusInitInterface->pIdeBusProtocol[Current_Channel][Current_Device] = IdeBusInterface; // Save the Pointer
+ }
+
+ if ( gPlatformIdeProtocol->MasterSlaveEnumeration ) {
+ Current_Device++;
+ } else {
+ Current_Device--;
+ }
+ TotalDevice--;
+ } // Loop for Master/Slave
+ } // Loop for Primary/Secondary
+
+ //---------------------------------------------------------------------------------------------------------
+ // Device Detection Ends
+ //---------------------------------------------------------------------------------------------------------
+ // Configuration Starts
+ //---------------------------------------------------------------------------------------------------------
+ PROGRESS_CODE( DXE_IDE_ENABLE );
+
+ for ( Current_Channel = Start_Channel; Current_Channel <= End_Channel; Current_Channel++ )
+ {
+ for ( Current_Device = Start_Device; Current_Device <= End_Device; Current_Device++ )
+ {
+
+ //
+ //Check whether the given device is detected successfully
+ //
+ if ( IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_DETECTED_SUCCESSFULLY ) {
+ IdeBusInterface = IdeBusInitInterface->pIdeBusProtocol[Current_Channel][Current_Device];
+
+ Status = ConfigureIdeDeviceAndController( IdeBusInterface, IdeControllerInterface, IdeBusInitInterface );
+
+ if ( EFI_ERROR( Status )) {
+ ERROR_CODE( DXE_IDE_DEVICE_FAILURE, EFI_ERROR_MAJOR );
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+
+ IdeBusInitInterface->pIdeBusProtocol[Current_Channel][Current_Device] = NULL;
+ continue;
+ }
+
+ //
+ //Device has been successfully detected and configured.
+ //
+
+ //
+ //Create the Devicepath
+ //
+ Status = CreateIdeDevicePath( This, Controller, IdeBusInitInterface, IdeBusInterface, RemainingDevicePath, Current_Channel, Current_Device );
+
+ if ( EFI_ERROR( Status )) {
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+ continue;
+ }
+
+ //
+ //Initialize Block_IO Protocol
+ //
+ Status = InitIdeBlockIO( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+ continue;
+ }
+
+ //
+ //Initialize IDE EFI_DISK_INFO_PROTOCOL
+ //
+ Status = InitIdeDiskInfo( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+ continue;
+ }
+
+ //
+ //Install Devicepath
+ //
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &(IdeBusInterface->IdeDeviceHandle),
+ &gDevicePathProtocolGuid, IdeBusInterface->DevicePathProtocol,
+ NULL );
+
+ if ( EFI_ERROR( Status )) {
+ IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] = DEVICE_DETECTION_FAILED;
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+ continue;
+ }
+
+ //
+ //Open IdeControllerProtocol
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ (VOID**)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ IdeBusInterface->IdeDeviceHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+
+
+ //
+ //Install other optional Protocols - Hdd Security
+ //
+ Status = pBS->LocateProtocol(
+ &gHddSecurityInitProtocolGuid,
+ NULL,
+ &HddSecurityInitProtocol
+ );
+
+ if ( !EFI_ERROR( Status )) {
+ if ( HddSecurityInitProtocol != NULL ) {
+ HddSecurityInitProtocol->InstallSecurityInterface( IdeBusInterface, FALSE );
+ }
+ } else {
+ //
+ // If Security Feature support is not enabled, always freeze lock the security feature
+ //
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_82 & 0x2 ) {
+ Status = IdeNonDataCommand( IdeBusInterface, 0, 0,
+ 0, 0, 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ SECURITY_FREEZE_LOCK );
+ //
+ // if Device Configuration Overlay feature set supported then issue the
+ // Dev config Free lock command.
+ //
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x800 ) {
+ Status = IdeNonDataCommand( IdeBusInterface, DEV_CONFIG_FREEZE_LOCK_FEATURES, 0,
+ 0, 0, 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ DEV_CONFIG_FREEZE_LOCK );
+ }
+ // Update the Identify device buffer
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+ }
+ }
+
+ //
+ // Install other optional Protocols - OpalSecurity
+ //
+
+ Status = pBS->LocateProtocol (
+ &gOpalSecInitProtocolGuid,
+ NULL,
+ &OpalSecInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(OpalSecInitProtocol != NULL) {
+ OpalSecInitProtocol->InstallOpalSecurityInterface(IdeBusInterface, FALSE);
+ }
+ }
+
+ //
+ //Install other optional Protocols - SMART
+ //
+ Status = pBS->LocateProtocol(
+ &gHddSmartInitProtocolGuid,
+ NULL,
+ &HddSmartInitProtocol
+ );
+
+ if ( !EFI_ERROR( Status )) {
+ if ( HddSmartInitProtocol != NULL ) {
+ HddSmartInitProtocol->InitSMARTSupport( IdeBusInterface, FALSE );
+ //
+ //Get the updated IdentifyData
+ //
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+ if ( HddSmartInitProtocol->SmartDiagonasticFlag ) {
+ HddSmartInitProtocol->InstallSMARTInterface( IdeBusInterface, FALSE );
+ }
+ }
+ }
+
+ if ( gPlatformIdeProtocol->IdePwrManagementInterfaceSupport ) {
+ InstallIDEPowerMgmtInterface( IdeBusInterface );
+ }
+
+ if ( gPlatformIdeProtocol->HostProtectedAreaSupport ) {
+ InstallHPAInterface( IdeBusInterface );
+ }
+
+#ifdef Debug_Level_3
+ PrintIdeDeviceInfo( IdeBusInterface );
+#endif
+ } // DEVICE_CONFIGURED_SUCCESSFULLY
+
+ //Before installing BlockIO and DiskInfo protocol, check whether the device has been
+ //password protected. If yes, BlockIO and DiskInfo will not be installed.
+ IdeBusInterface = IdeBusInitInterface->pIdeBusProtocol[Current_Channel][Current_Device];
+
+ if ( IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_CONFIGURED_SUCCESSFULLY ) {
+ //
+ //Check BlockIO has been installed or not.
+ //
+ Status = pBS->OpenProtocol( IdeBusInterface->IdeDeviceHandle,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ IdeBusInterface->IdeDeviceHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if ( EFI_ERROR( Status )) {
+ //
+ //BLOCKIO not installed and device has been configured successfully
+ //
+ Status = EFI_UNSUPPORTED;
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &(IdeBusInterface->IdeDeviceHandle),
+ &gEfiBlockIoProtocolGuid, (EFI_BLOCK_IO_PROTOCOL*)(IdeBusInterface->IdeBlkIo),
+ &gEfiDiskInfoProtocolGuid, (EFI_DISK_INFO_PROTOCOL*)(IdeBusInterface->IdeDiskInfo),
+ NULL );
+ } // If BlockIO not Installed
+ } // End of installing BlockIO and DiskInfo
+ } // Loop for Master/Slave
+ } // Loop for Primary/Secondary
+
+ //---------------------------------------------------------------------------------------------------------
+ // Configuration Ends
+ //---------------------------------------------------------------------------------------------------------
+
+ // Check HP Support and Ide Controller protocol to create an HP event
+ if ( gPlatformIdeProtocol->IdeHPSupport == 1 && gPlatformIdeProtocol->EfiIdeProtocol == 0 ) {
+
+ //
+ // Check whether already HP Event has been created and also HP is supported
+ //
+ if ( IdeBusInitInterface->HPEvent == NULL && IdeBusInitInterface->HPMask ) {
+ //
+ // Create and Event
+ //
+ Status = pBS->CreateEvent( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ IdeHPTimer,
+ IdeBusInitInterface,
+ &(IdeBusInitInterface->HPEvent));
+
+ if ( Status == EFI_SUCCESS ) {
+ pBS->SetTimer( IdeBusInitInterface->HPEvent, TimerPeriodic, 20000000 ); // 2sec
+ }
+ }
+ }
+
+ Status = pBS->LocateProtocol (
+ &gAtaPassThruInitProtocolGuid,
+ NULL,
+ &AtaPassThruInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(AtaPassThruInitProtocol != NULL) {
+ AtaPassThruInitProtocol->InstallAtaPassThru(Controller, FALSE);
+ }
+ }
+
+ // SCSIPassThruAtapi install
+ Status = pBS->LocateProtocol (
+ &gScsiPassThruAtapiInitProtocolGuid,
+ NULL,
+ &gScsiPassThruAtapiInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(gScsiPassThruAtapiInitProtocol != NULL) {
+ gScsiPassThruAtapiInitProtocol->InstallScsiPassThruAtapi(Controller, FALSE);
+ }
+ }
+
+ //
+ // This will notify AMITSE to invoke the HDD password Screen
+ //
+ Status = pBS->InstallProtocolInterface(
+ &Controller,
+ &gHddSecurityEndProtocolGuid, EFI_NATIVE_INTERFACE, NULL
+ );
+
+#ifdef Debug_Level_1
+ EfiDebugPrint( -1, "IdeBusStart Exit Success\n" );
+#endif
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IdeBusStop
+//
+// Description: Uninstall all devices installed in start procedure.
+//
+// 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. Check whether "gEfiIdeBusInitProtocolGuid" 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 "gEfiIdeControllerProtocolGuid" and "gEfiIdeBusInitProtocolGuid",
+// uninstall "gEfiIdeBusInitProtocolGuid" and then exit with success.
+// 3. If "NumberOfChildren" is non-zero, close "gEfiIdeControllerProtocolGuid" 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 IdeBusStop(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer )
+{
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface;
+ IDE_BUS_PROTOCOL *IdeBusInterface = NULL;
+ EFI_STATUS Status;
+ IDE_BLK_IO_DEV *IdeBlockIoDev = NULL;
+ VOID *IdeControllerInterface = NULL ;
+
+ UINT8 Current_Channel = 0xff;
+ UINT8 Current_Device = 0xff;
+ UINT8 Index = 0;
+ BOOLEAN Flag = TRUE;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ //
+ //Check if IDE_BUS_INIT_PROTOCOL is installed on the Controller.
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ (VOID**)&IdeBusInitInterface,
+ 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->OpenProtocol(
+ ChildHandleBuffer[Index],
+ &gDevicePathProtocolGuid,
+ (VOID**)&DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+
+ //Lookout for ATAPI 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_ATAPI_DP)) {
+ Current_Channel = ((ATAPI_DEVICE_PATH*)DevicePath)->PrimarySecondary;
+ Current_Device = ((ATAPI_DEVICE_PATH*)DevicePath)->SlaveMaster;
+ break;
+ } else {
+ DevicePath = NEXT_NODE( DevicePath );
+ }
+ } while ( DevicePath->Type != END_DEVICE_PATH );
+
+ if ( Current_Channel == 0xff || Current_Device == 0xff ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Get the pointer to IDE_BUS_PROTOCOL
+ //
+ IdeBusInterface = IdeBusInitInterface->pIdeBusProtocol[Current_Channel][Current_Device];
+
+ //
+ //Close all the protocols opened by this Child Device
+ //
+ pBS->CloseProtocol(
+ Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index] );
+
+ //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*)(IdeBusInterface->IdeBlkIo),
+ &gEfiDiskInfoProtocolGuid, (EFI_DISK_INFO_PROTOCOL*)(IdeBusInterface->IdeDiskInfo),
+ NULL );
+ }
+
+ Status = pBS-> UninstallMultipleProtocolInterfaces(
+ ChildHandleBuffer[Index],
+ &gDevicePathProtocolGuid, IdeBusInterface->DevicePathProtocol,
+ NULL );
+
+ if ( EFI_ERROR( Status )) {
+ pBS->OpenProtocol( Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ (VOID**)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ //Now free up all resources allocated.
+ //
+ if ( IdeBusInterface->IdeDevice.AtapiDevice != NULL ) {
+ pBS->FreePool( IdeBusInterface->IdeDevice.AtapiDevice->PacketBuffer );
+ pBS->FreePool( IdeBusInterface->IdeDevice.AtapiDevice->InquiryData );
+ pBS->FreePool( IdeBusInterface->IdeDevice.AtapiDevice );
+ }
+
+ //
+ //Freeup resources allocated for component names
+ //
+ if ( IdeBusInterface->IdeDevice.UDeviceName != NULL ) {
+ pBS->FreePool( IdeBusInterface->IdeDevice.UDeviceName->Language );
+ pBS->FreePool( IdeBusInterface->IdeDevice.UDeviceName->UnicodeString );
+ pBS->FreePool( IdeBusInterface->IdeDevice.UDeviceName );
+ }
+
+ // Uninstall optional protocols
+
+ //
+ //Before uninstalling HDD security check whether it is installed or not
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gHddSecurityInitProtocolGuid,
+ (VOID**)&HddSecurityInitProtocol,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if ( !EFI_ERROR( Status )) {
+ if ( HddSecurityInitProtocol != NULL ) {
+ HddSecurityInitProtocol->StopSecurityModeSupport( IdeBusInterface, FALSE );
+ }
+ }
+
+ //
+ //Before uninstalling Hdd Smart check whether it is installed or not
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gHddSmartInitProtocolGuid,
+ (VOID**)&HddSmartInitProtocol,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if ( !EFI_ERROR( Status )) {
+ if ( HddSmartInitProtocol != NULL ) {
+ if ( HddSmartInitProtocol->SmartDiagonasticFlag ) {
+ HddSmartInitProtocol->UnInstallSMARTInterface( IdeBusInterface, FALSE );
+ }
+ }
+ }
+
+ //
+ //Before uninstalling OPAL security Interface check whether it is installed or not.
+ //
+ Status = pBS->OpenProtocol( ChildHandleBuffer[Index],
+ &gOpalSecInitProtocolGuid,
+ (VOID**)&OpalSecInitProtocol,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if ( !EFI_ERROR( Status )) {
+ if ( OpalSecInitProtocol != NULL ) {
+ OpalSecInitProtocol->UnInstallOpalSecurityInterface( IdeBusInterface, FALSE );
+ }
+ }
+
+ if ( gPlatformIdeProtocol->IdePwrManagementInterfaceSupport ) {
+ StopIDEPowerMgmtInterface( IdeBusInterface );
+ }
+
+ if ( gPlatformIdeProtocol->HostProtectedAreaSupport ) {
+ StopHPAInterface( IdeBusInterface );
+ }
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ IdeBlockIoDev = IDE_BLOCK_IO_DEV_FROM_THIS( &(IdeBusInterface->IdeBlkIo));
+ }
+ pBS->FreePool( IdeBusInterface->IdeBlkIo->BlkIo.Media );
+ pBS->FreePool( IdeBusInterface->IdeBlkIo );
+ pBS->FreePool( IdeBusInterface->IdeDiskInfo );
+ Current_Channel = IdeBusInterface->IdeDevice.Channel;
+ Current_Device = IdeBusInterface->IdeDevice.Device;
+ IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] = DEVICE_IN_RESET_STATE;
+ pBS->FreePool( IdeBusInterface->DevicePathProtocol );
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+ }
+ NumberOfChildren--;
+ Index++;
+ }
+
+ return EFI_SUCCESS;
+ } else {
+ //
+ //Check if IDE_BUS_INIT_PROTOCOL can be removed
+ //
+ for ( Current_Channel = PRIMARY_CHANNEL; Current_Channel <= SECONDARY_CHANNEL; Current_Channel++ )
+ {
+ for ( Current_Device = MASTER_DRIVE; Current_Device <= SLAVE_DRIVE; Current_Device++ )
+ {
+ if ( IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] == DEVICE_CONFIGURED_SUCCESSFULLY ) {
+ Flag = FALSE;
+ }
+ }
+ }
+
+ //
+ // Can't uninstall IDE_BUS_INIT_PROTOCOL if any one of the IDE devices are in "CONFIGURED" state.
+ //
+ if ( Flag == TRUE ) {
+ if ( gPlatformIdeProtocol->IdeHPSupport ) {
+
+ //
+ // Check whether already HP Event has been created and also HP is supported
+ //
+ if ( IdeBusInitInterface->HPEvent != NULL ) {
+ pBS->CloseEvent( IdeBusInitInterface->HPEvent );
+ }
+ }
+ //
+ //Close all the protocols opened in Start Function
+ //
+ Status = pBS->CloseProtocol( Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ This->DriverBindingHandle,
+ Controller );
+ //
+ // AtaPass Thru uninstall
+ //
+ Status = pBS->LocateProtocol (
+ &gAtaPassThruInitProtocolGuid,
+ NULL,
+ &AtaPassThruInitProtocol
+ );
+
+ if(!EFI_ERROR(Status)) {
+ if(AtaPassThruInitProtocol != NULL) {
+ AtaPassThruInitProtocol->StopAtaPassThruSupport(Controller, FALSE);
+ }
+ }
+ //
+ // ScsiPassThruAtapi uninstall
+ //
+ Status = pBS->LocateProtocol (
+ &gScsiPassThruAtapiInitProtocolGuid,
+ NULL,
+ &gScsiPassThruAtapiInitProtocol);
+
+ if(!EFI_ERROR(Status)) {
+ if(gScsiPassThruAtapiInitProtocol != NULL) {
+ gScsiPassThruAtapiInitProtocol->StopScsiPassThruAtapiSupport(Controller, FALSE);
+ }
+ }
+
+
+ Status = pBS->CloseProtocol( Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller );
+
+ Status = pBS->UninstallProtocolInterface( Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ IdeBusInitInterface );
+
+ if ( EFI_ERROR( Status )) {
+ Status = pBS->OpenProtocol( Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ (VOID**)&IdeBusInitInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ Status = pBS->OpenProtocol( Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ (VOID**)&IdeControllerInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ pBS->FreePool( IdeBlockIoDev );
+ else
+ pBS->FreePool( IdeBusInterface );
+
+ if ( gDescriptorBuffer != NULL ) {
+ pBS->FreePool( gDescriptorBuffer );
+ }
+ gDescriptorBuffer = NULL;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InstallBusInitProtocol
+//
+// Description: Installs BUS Init Protocol on the IDE controller Handle
+//
+// Input:
+// IN EFI_HANDLE Controller,
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface;
+// IDE_CONTROLLER_PROTOCOL *IdeControllerInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AllocatePool, InstallProtocolInterface, IdeGetControllerInfo
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Call "IdeGetControllerInfo", to get channel information from IdeController driver.
+// 2. Install "gEfiIdeBusInitProtocolGuid" on the IDE controller.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS InstallBusInitProtocol(
+ IN EFI_HANDLE Controller,
+ IN OUT IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface,
+ IN VOID *IdeControllerInterfaceIn
+ )
+{
+ CONTROLLER_INFO *ControllerInfo;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *EfiIdeControllerInterface = NULL ;
+ IDE_CONTROLLER_PROTOCOL *IdeControllerInterface = NULL ;
+ EFI_STATUS Status;
+
+ //
+ // Initialize IdeControllerInterface
+ //
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ EfiIdeControllerInterface = ( EFI_IDE_CONTROLLER_INIT_PROTOCOL *) IdeControllerInterfaceIn;
+ else
+ IdeControllerInterface = ( IDE_CONTROLLER_PROTOCOL *) IdeControllerInterfaceIn;
+
+ //
+ //Initialize the default Values
+ //
+ ZeroMemory( IdeBusInitInterface, sizeof(IDE_BUS_INIT_PROTOCOL));
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof(CONTROLLER_INFO),
+ (VOID**)&ControllerInfo
+ );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ ZeroMemory( ControllerInfo, sizeof(CONTROLLER_INFO));
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ ControllerInfo->Flags = 0; // ACOUSTIC_SUPPORT_DISABLE
+
+ if ( gPlatformIdeProtocol->SBIdeSupport ) {
+ Status = pBS->LocateProtocol(&gIdeSetupProtocolguid, NULL, &gIdeSetupProtocol);
+
+ if ( gPlatformIdeProtocol->AcousticManagementSupport ) {
+
+ if (!EFI_ERROR(Status)) {
+
+ if(gIdeSetupProtocol->AcousticPwrMgmt)
+ ControllerInfo->Flags |= ACOUSTIC_SUPPORT_ENABLE;
+ else
+ ControllerInfo->Flags &= ~ACOUSTIC_SUPPORT_ENABLE;
+ ControllerInfo->Acoustic_Management_Level = gIdeSetupProtocol->AcousticLevel;
+ } else {
+ ControllerInfo->Flags &= ~ACOUSTIC_SUPPORT_ENABLE ;
+ ControllerInfo->Acoustic_Management_Level = ACOUSTIC_LEVEL_BYPASS;
+ }
+ } //End of ACOUSTIC_MANAGEMENT_SUPPORT
+ } //End of SBIDE_SUPPORT
+
+ if ( gPlatformIdeProtocol->HddPowerLossInS3 ) {
+ ControllerInfo->Flags |= S3_RESUME_UNLOCK_HDD_PASSWORD;
+ }
+
+ ControllerInfo->PrimaryChannel = PRIMARY_CHANNEL_ENABLE;
+ ControllerInfo->PrimaryMasterDevice = PRIMARY_MASTER_DRIVE_ENABLE;
+ ControllerInfo->PrimarySlaveDevice = PRIMARY_SLAVE_DRIVE_ENABLE;
+ ControllerInfo->SecondaryChannel = SECONDARY_CHANNEL_ENABLE;
+ ControllerInfo->SecondaryMasterDevice = SECONDARY_MASTER_DRIVE_ENABLE;
+ ControllerInfo->SecondarySlaveDevice = SECONDARY_SLAVE_DRIVE_ENABLE;
+ ControllerInfo->BusMasterEnable = BUSMASTER_ENABLE;
+ ControllerInfo->HPMask = 0; // Hot Plug Mask
+
+ } else {
+ IdeControllerInterface->IdeGetControllerInfo( Controller, ControllerInfo );
+ }
+
+ if ( ControllerInfo->PrimaryChannel == DEVICE_DISABLED ) {
+ IdeBusInitInterface->IdeBusInitData[PRIMARY_CHANNEL][MASTER_DRIVE] = DEVICE_DISABLED;
+ IdeBusInitInterface->IdeBusInitData[PRIMARY_CHANNEL][SLAVE_DRIVE] = DEVICE_DISABLED;
+ } else {
+ IdeBusInitInterface->IdeBusInitData[PRIMARY_CHANNEL][MASTER_DRIVE] = ControllerInfo->PrimaryMasterDevice;
+ IdeBusInitInterface->IdeBusInitData[PRIMARY_CHANNEL][SLAVE_DRIVE] = ControllerInfo->PrimarySlaveDevice;
+ }
+
+ if ( ControllerInfo->SecondaryChannel == DEVICE_DISABLED ) {
+ IdeBusInitInterface->IdeBusInitData[SECONDARY_CHANNEL][MASTER_DRIVE] = DEVICE_DISABLED;
+ IdeBusInitInterface->IdeBusInitData[SECONDARY_CHANNEL][SLAVE_DRIVE] = DEVICE_DISABLED;
+ } else {
+ IdeBusInitInterface->IdeBusInitData[SECONDARY_CHANNEL][MASTER_DRIVE] = ControllerInfo->SecondaryMasterDevice;
+ IdeBusInitInterface->IdeBusInitData[SECONDARY_CHANNEL][SLAVE_DRIVE] = ControllerInfo->SecondarySlaveDevice;
+ }
+
+ IdeBusInitInterface->BusMasterSelection = ControllerInfo->BusMasterEnable;
+ IdeBusInitInterface->HPMask = ControllerInfo->HPMask;
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ IdeBusInitInterface->EfiIdeControllerInterface = EfiIdeControllerInterface;
+ else
+ IdeBusInitInterface->IdeControllerInterface = IdeControllerInterface;
+
+ IdeBusInitInterface->Flags = ControllerInfo->Flags;
+ IdeBusInitInterface->Acoustic_Management_Level = ControllerInfo->Acoustic_Management_Level;
+
+ Status = pBS->FreePool( ControllerInfo );
+
+ // Initialize PrevPortNum and PrevPortMultiplierPortNum for AtaPassThru to 0xFFFF
+
+ IdeBusInitInterface->PrevPortNum = 0xffff;
+ IdeBusInitInterface->PrevPortMultiplierPortNum = 0xffff;
+
+ Status = pBS->InstallProtocolInterface(
+ &Controller,
+ &gEfiIdeBusInitProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ IdeBusInitInterface );
+
+ if ((IdeBusInitInterface->BusMasterSelection) && gDescriptorBuffer == NULL ) {
+ //Since the PRD table need to be aligned at 64KB to create maximum # of tables
+ //allocate 128KB and use the 64KB aligned address,
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ 2 * 64 * 1024,
+ (VOID**)&gDescriptorBuffer
+ );
+
+ if ( EFI_ERROR( Status )) {
+ IdeBusInitInterface->BusMasterSelection = 0;
+ }
+ }
+
+#ifdef Debug_Level_3
+ EfiDebugPrint( -1, "Installed IDE_BUS_INIT_PROTOCOL\n" );
+#endif
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ConfigureIdeDeviceAndController
+//
+// Description: PIO and DMA mode programming both on the Controller as well as on the Device is done
+//
+// Input:
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface
+// IDE_CONTROLLER_PROTOCOL *IdeControllerInterface
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ConfigureIdeDevice, GetIdentifyData
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Get the Best PIO and DMA mode supported by the device from Identify Data
+// 2. Set the PIO and DMA mode in the IDE controller.
+// 3. Configure the IDE device with the PIO and DMA mode.
+// 4. Update the Identify Data.
+// 5. Based on the IDE device select the proper Read/Write commands.
+// 6. Construct a unicode string for the IDE device.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ConfigureIdeDeviceAndController(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN VOID *IdeControllerInterfaceIn,
+ IN IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface )
+{
+ EFI_STATUS Status;
+ UINT8 Current_Channel = IdeBusInterface->IdeDevice.Channel;
+ UINT8 Current_Device = IdeBusInterface->IdeDevice.Device;
+
+ EFI_ATA_COLLECTIVE_MODE *SupportedModes = NULL;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *EfiIdeControllerInterface = NULL ;
+ IDE_CONTROLLER_PROTOCOL *IdeControllerInterface = NULL ;
+
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol )
+ EfiIdeControllerInterface = (EFI_IDE_CONTROLLER_INIT_PROTOCOL*) IdeControllerInterfaceIn;
+ else
+ IdeControllerInterface = (IDE_CONTROLLER_PROTOCOL *) IdeControllerInterfaceIn;
+
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+ Status = EfiIdeControllerInterface->SubmitData( EfiIdeControllerInterface, IdeBusInterface->IdeDevice.Channel,
+ IdeBusInterface->IdeDevice.Device, (EFI_IDENTIFY_DATA*)&(IdeBusInterface->IdeDevice.IdentifyData));
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ Status = EfiIdeControllerInterface->CalculateMode( EfiIdeControllerInterface, IdeBusInterface->IdeDevice.Channel,
+ IdeBusInterface->IdeDevice.Device, &SupportedModes );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ Status = EfiIdeControllerInterface->SetTiming( EfiIdeControllerInterface, IdeBusInterface->IdeDevice.Channel,
+ IdeBusInterface->IdeDevice.Device, SupportedModes );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ IdeBusInterface->IdeDevice.PIOMode = 0xff;
+ IdeBusInterface->IdeDevice.SWDma = 0xff;
+ IdeBusInterface->IdeDevice.MWDma = 0xff;
+ IdeBusInterface->IdeDevice.UDma = 0xff;
+
+ if ( SupportedModes->PioMode.Valid ) {
+ IdeBusInterface->IdeDevice.PIOMode = SupportedModes->PioMode.Mode;
+ }
+
+ if ( SupportedModes->SingleWordDmaMode.Valid ) {
+ IdeBusInterface->IdeDevice.SWDma = SupportedModes->SingleWordDmaMode.Mode;
+ }
+
+ if ( SupportedModes->MultiWordDmaMode.Valid ) {
+ IdeBusInterface->IdeDevice.MWDma = SupportedModes->MultiWordDmaMode.Mode;
+ }
+
+ if ( SupportedModes->UdmaMode.Valid ) {
+ IdeBusInterface->IdeDevice.UDma = SupportedModes->UdmaMode.Mode;
+ }
+
+ IdeBusInterface->IdeDevice.IORdy = ((EFI_IDENTIFY_DATA*)&(IdeBusInterface->IdeDevice.IdentifyData))->AtaData.capabilities & 0x800;
+
+ } else {
+ //
+ // Get the best PIO and DMA mode from the IDE device
+ //
+ IdeControllerInterface->GetbestPioDmaMode( &(IdeBusInterface->IdeDevice));
+
+ //
+ // Program PIO mode Timing in the controller
+ //
+ IdeControllerInterface->IdeSetPioMode( &(IdeBusInterface->IdeDevice));
+
+ // See if Bus Master has been enabled
+ IdeControllerInterface->IdeSetDmaMode( &(IdeBusInterface->IdeDevice));
+ }
+
+ // Issue SET feature command to set the PIO and DMA mode
+ Status = ConfigureIdeDevice( IdeBusInterface, IdeBusInitInterface );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ } else {
+ //
+ //Get the updated IdentifyData
+ //
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+
+ //
+ //Check if UDMA and MWDMA are programmed successfully
+ //
+ if ( IdeBusInterface->IdeDevice.UDma != 0xff ) {
+ if ( !(ReturnMSBset((IdeBusInterface->IdeDevice.IdentifyData.UDMA_Mode_88 >> 8)) == IdeBusInterface->IdeDevice.UDma)) {
+ IdeBusInterface->IdeDevice.UDma = ReturnMSBset((IdeBusInterface->IdeDevice.IdentifyData.UDMA_Mode_88 >> 8));
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ SupportedModes->UdmaMode.Mode = IdeBusInterface->IdeDevice.UDma;
+ EfiIdeControllerInterface->SetTiming( EfiIdeControllerInterface, IdeBusInterface->IdeDevice.Channel,
+ IdeBusInterface->IdeDevice.Device, SupportedModes );
+ } else {
+ IdeControllerInterface->IdeSetDmaMode( &(IdeBusInterface->IdeDevice));
+ }
+ }
+ } else {
+ if ( IdeBusInterface->IdeDevice.MWDma != 0xff ) {
+ if ( !(ReturnMSBset( IdeBusInterface->IdeDevice.IdentifyData.MultiWord_DMA_63 >> 8 ) == IdeBusInterface->IdeDevice.MWDma)) {
+ IdeBusInterface->IdeDevice.MWDma = ReturnMSBset( (IdeBusInterface->IdeDevice.IdentifyData.MultiWord_DMA_63 >> 8));
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ SupportedModes->MultiWordDmaMode.Mode = IdeBusInterface->IdeDevice.MWDma;
+ EfiIdeControllerInterface-> SetTiming( EfiIdeControllerInterface, IdeBusInterface->IdeDevice.Channel,
+ IdeBusInterface->IdeDevice.Device, SupportedModes );
+ } else {
+ IdeControllerInterface->IdeSetDmaMode( &(IdeBusInterface->IdeDevice));
+ }
+ }
+ }
+ }
+
+ // Check for ATA
+ if ( IdeBusInterface->IdeDevice.DeviceType == ATA ) {
+ // Update IDE Read/Write Command
+ if ((IdeBusInterface->IdeDevice.IdentifyData.Valid_Bits_59 & 0x100)
+ && (IdeBusInterface->IdeDevice.IdentifyData.Valid_Bits_59 & 0xff)) { // Check if Multiple Read/Write
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ // 48Bit LBA supported
+ IdeBusInterface->IdeDevice.ReadCommand = READ_MULTIPLE_EXT;
+ IdeBusInterface->IdeDevice.WriteCommand = WRITE_MULTIPLE_EXT;
+ } else {
+ IdeBusInterface->IdeDevice.ReadCommand = READ_MULTIPLE;
+ IdeBusInterface->IdeDevice.WriteCommand = WRITE_MULTIPLE;
+ }
+ } else { // 1 Block = 1 Sector
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ // 48Bit LBA supported
+ IdeBusInterface->IdeDevice.ReadCommand = READ_SECTORS_EXT;
+ IdeBusInterface->IdeDevice.WriteCommand = WRITE_SECTORS_EXT;
+ } else {
+ IdeBusInterface->IdeDevice.ReadCommand = READ_SECTORS;
+ IdeBusInterface->IdeDevice.WriteCommand = WRITE_SECTORS;
+ }
+ }
+
+ if ( DMACapable( IdeBusInterface )) {
+ if ( gPlatformIdeProtocol->IdeBusMasterSupport ) {
+ IdeBusInterface->IdeDevice.ReadCommand = READ_DMA;
+ IdeBusInterface->IdeDevice.WriteCommand = WRITE_DMA;
+
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ //
+ // 48Bit LBA supported
+ //
+ IdeBusInterface->IdeDevice.ReadCommand = READ_DMA_EXT;
+ IdeBusInterface->IdeDevice.WriteCommand = WRITE_DMA_EXT;
+ }
+ }
+ }
+ }
+ IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] = DEVICE_CONFIGURED_SUCCESSFULLY;
+ }
+
+ if ( gPlatformIdeProtocol->DisableSoftSetPrev || gPlatformIdeProtocol->ForceHddPasswordPrompt ) {
+
+ //
+ // Software settings preserved
+ //
+ if ((IdeBusInterface->IdeDevice.IdentifyData.Reserved_76_79[0] != 0xFFFF)
+ && (IdeBusInterface->IdeDevice.IdentifyData.Reserved_76_79[2] & 0x0040)) {
+ Status = IdeSetFeatureCommand( IdeBusInterface, DISABLE_SATA2_SOFTPREV, 6 );
+ //
+ // Get the updated IdentifyData
+ //
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitIdeBlockIO
+//
+// Description: Initializes IDE Block IO interface
+//
+// Input:
+//
+// IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// 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 InitIdeBlockIO(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ IDE_BLOCK_IO *IdeBlkIo;
+ EFI_BLOCK_IO_MEDIA *BlkMedia;
+ ATAPI_DEVICE *AtapiDevice;
+ UINT8 *Data;
+ UINT8 *InquiryData;
+ UINT16 InquiryDataSize;
+ UINT8 Current_Channel;
+ UINT8 Current_Device;
+ UINT8 bTemp;
+ UINT16 OddType = 0;
+ UINT8 OddLoadingType =0xFF;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof(IDE_BLOCK_IO),
+ (VOID**)&IdeBlkIo );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+
+ BlkMedia = MallocZ( sizeof(EFI_BLOCK_IO_MEDIA));
+
+ if ( !BlkMedia ) {
+ pBS->FreePool( IdeBlkIo );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ //Initialize the IdeBlkIo pointer in IDE_BUS_PROTOCOL (IdeBusInterface)
+ //
+ IdeBusInterface->IdeBlkIo = IdeBlkIo;
+
+ //
+ //Initialize the fields in IdeBlkIo (IDE_BLOCK_IO)
+ //
+ IdeBlkIo->IdeBusInterface = IdeBusInterface;
+
+ if ( IdeBusInterface->IdeDevice.DeviceType == ATA ) {
+ //
+ //ATA
+ //
+ BlkIo = &(IdeBlkIo->BlkIo);
+ //
+ // UEFI2.3.1 Supports the BlockIo Revision 3
+ //
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ BlkIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+ } else {
+ BlkIo->Revision = BLKIO_REVISION;
+ }
+ BlkIo->Media = BlkMedia;
+ BlkIo->Reset = AtaReset;
+ BlkIo->ReadBlocks = AtaBlkRead;
+ BlkIo->WriteBlocks = AtaBlkWrite;
+ BlkIo->FlushBlocks = AtaBlkFlush;
+
+ BlkMedia->MediaId = 0;
+ BlkMedia->RemovableMedia = (IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 0x80) == 0x80 ? TRUE : FALSE;
+
+ //Check if Hot plug supported for this device
+ Current_Channel = IdeBusInterface->IdeDevice.Channel;
+ Current_Device = IdeBusInterface->IdeDevice.Device;
+ bTemp = Current_Channel == 0 ? 1 : 4; // BIT MASK
+
+ if ( Current_Device ) {
+ bTemp <<= 1;
+ }
+
+ if ( bTemp & IdeBusInterface->IdeBusInitInterface->HPMask ) {
+ BlkMedia->RemovableMedia = TRUE;
+ }
+
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->LogicalPartition = FALSE;
+ BlkMedia->ReadOnly = FALSE;
+ BlkMedia->WriteCaching = FALSE;
+
+
+ if((IdeBusInterface->IdeDevice.IdentifyData.Reserved_104_126[2] & BIT14) && // WORD 106 valid? - BIT 14 - 1
+ (!(IdeBusInterface->IdeDevice.IdentifyData.Reserved_104_126[2] & BIT15)) && // WORD 106 valid? - BIT 15 - 0
+ (IdeBusInterface->IdeDevice.IdentifyData.Reserved_104_126[2] & BIT12)) { // WORD 106 bit 12 - Sectorsize > 256 words
+ // The sector size is in words 117-118.
+ SectorSize = (UINT32)(IdeBusInterface->IdeDevice.IdentifyData.Reserved_104_126[13] + \
+ (IdeBusInterface->IdeDevice.IdentifyData.Reserved_104_126[14] << 16)) * 2;
+ }
+
+ BlkMedia->BlockSize = SectorSize;
+
+ //If BusMaster Support is Enabled for the device, IO Alignment should be DWORD
+
+ if ( DMACapable( IdeBusInterface )) {
+ BlkMedia->IoAlign = 4;
+ } else {
+ BlkMedia->IoAlign = 0;
+ }
+
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ BlkMedia->LastBlock = IdeBusInterface->IdeDevice.IdentifyData.LBA_48 - 1;
+ } else {
+ BlkMedia->LastBlock = IdeBusInterface->IdeDevice.IdentifyData.Addressable_Sector_60 - 1;
+ }
+
+ 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 ( (IdeBusInterface->IdeDevice.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 ( IdeBusInterface->IdeDevice.IdentifyData.Reserved_104_126[2] & 0x2000 ) {
+
+ BlkMedia->LogicalBlocksPerPhysicalBlock = 1 <<
+ (IdeBusInterface->IdeDevice.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 =IdeBusInterface->IdeDevice.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;
+ }
+ }
+ } else {
+ //
+ //If it is an ATAPI device, check whether it is a CDROM or not. Currently only CDROM/Direct access Devices are supported.
+ //
+ if ((IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 0x1f00) == (CDROM_DEVICE << 8)
+ || (IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 0x1f00) == (DIRECT_ACCESS_DEVICE << 8)
+ || (IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 0x1f00) == (OPTICAL_MEMORY_DEVICE << 8)) {
+ AtapiDevice = MallocZ( sizeof (ATAPI_DEVICE));
+
+ if ( !AtapiDevice ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ IdeBusInterface->IdeDevice.AtapiDevice = AtapiDevice;
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ 16,
+ (VOID**)&Data
+ );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ AtapiDevice->PacketBuffer = Data;
+ AtapiDevice->DeviceType = (IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 0x1f00) >> 8;
+ AtapiDevice->PacketSize = (IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 3) == 1 ? 16 : 12;
+
+ BlkIo = &(IdeBlkIo->BlkIo);
+ //
+ // UEFI2.3.1 Supports the BlockIo Revision 3
+ //
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ BlkIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
+ } else {
+ BlkIo->Revision = BLKIO_REVISION;
+ }
+ BlkIo->Media = BlkMedia;
+ BlkIo->Reset = AtapiReset;
+ BlkIo->ReadBlocks = AtapiBlkRead;
+ BlkIo->WriteBlocks = AtapiBlkWrite;
+ BlkIo->FlushBlocks = AtapiBlkFlush;
+ //
+ //Initialize with default value. Later on it will be updated if needed.
+ //
+ 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;
+ AtapiInquiryData( IdeBusInterface, InquiryData, &InquiryDataSize );
+ AtapiDevice->InquiryData = InquiryData;
+ AtapiDevice->InquiryDataSize = InquiryDataSize;
+
+ //
+ // Get the ATAPI drive Type information and save it ATAPI_DEVICE
+ //
+ Status = GetOddType( IdeBusInterface, &OddType );
+
+ if ( !EFI_ERROR( Status )) {
+ AtapiDevice->OddType = GetEnumOddType( OddType );
+ }
+
+ //
+ // Get the ATAPI drive Loading information and save it ATAPI_DEVICE
+ //
+ Status = GetOddLoadingType( IdeBusInterface, &OddLoadingType );
+
+ if ( !EFI_ERROR( Status )) {
+ AtapiDevice->OddLoadingType = (ODD_LOADING_TYPE)OddLoadingType;
+ } else {
+ AtapiDevice->OddLoadingType = (ODD_LOADING_TYPE)0xFF;
+ }
+
+ BlkMedia->RemovableMedia = (IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 0x80) == 0x80 ? TRUE : FALSE;
+ BlkMedia->LogicalPartition = FALSE;
+ BlkMedia->WriteCaching = FALSE;
+
+ //
+ //If BusMaster Support is Enabled for the device, IO Alignment should be DWORD
+ //
+ if ( DMACapable( IdeBusInterface )) {
+ BlkMedia->IoAlign = 4;
+ } else {
+ BlkMedia->IoAlign = 0;
+ }
+ }
+ }
+ 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: InitIdeDiskInfo
+//
+// Description: Initializes IDE DiskInfo Interface
+//
+// Input:
+//
+// IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AllocatePool OpenProtocol
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InitIdeDiskInfo(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status;
+ IDE_DISK_INFO *IdeDiskInfo;
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof(IDE_DISK_INFO),
+ (VOID**)&IdeDiskInfo );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ //Initialize the IdeBlkIo pointer in IDE_BUS_PROTOCOL (IdeBusInterface)
+ //
+ IdeBusInterface->IdeDiskInfo = IdeDiskInfo;
+
+ //
+ //Initialize the fields in IdeDiskInfo (IDE_DISK_INFO)
+ //
+ IdeDiskInfo->IdeBusInterface = IdeBusInterface;
+
+ pBS->CopyMem( &(IdeDiskInfo->DiskInfo.Interface), &gEfiIdeDiskInfoProtocolGuid, sizeof (EFI_GUID));
+ IdeDiskInfo->DiskInfo.Inquiry = DiskInfoInquiry;
+ IdeDiskInfo->DiskInfo.Identify = DiskInfoIdentify;
+ IdeDiskInfo->DiskInfo.SenseData = DiskInfoSenseData;
+ IdeDiskInfo->DiskInfo.WhichIde = DiskInfoWhichIDE;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CreateIdeDevicePath
+//
+// Description: Creates a IDE device devicepath and adds it to IdeBusInterface
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This,
+// IN EFI_HANDLE Controller,
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface;
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+// UINT8 Current_Channel
+// UINT8 Current_Device
+//
+// 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.
+// 3. Append Atapi devicepath to IDE controller devicepath.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CreateIdeDevicePath(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface,
+ IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN UINT8 Current_Channel,
+ IN UINT8 Current_Device )
+{
+ EFI_STATUS Status;
+ ATAPI_DEVICE_PATH NewDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+
+ NewDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
+ NewDevicePath.Header.SubType = MSG_ATAPI_DP;
+ SET_NODE_LENGTH( &NewDevicePath.Header, ATAPI_DEVICE_PATH_LENGTH );
+ NewDevicePath.PrimarySecondary = Current_Channel;
+ NewDevicePath.SlaveMaster = Current_Device;
+ NewDevicePath.Lun = 0;
+
+ //
+ //Append the Device Path
+ //
+ Status = pBS->OpenProtocol( Controller,
+ &gDevicePathProtocolGuid,
+ (VOID**)&TempDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+
+ IdeBusInterface->DevicePathProtocol = DPAddNode( TempDevicePath, &NewDevicePath.Header );
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ConfigureIdeDevice
+//
+// Description: Issues SET FEATURE Command
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface,
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ConfigureIdeDeviceAndController, IdeSetFeatureCommand
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Issue Set feature commend to set PIO mode if needed.
+// 2. Set Multiple Mode command for ATA devices if needed.
+// 3. Issue Set feature commend to set UDMA/MWDMA. If it fails, disable Busmaster support.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS ConfigureIdeDevice(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface )
+{
+ EFI_STATUS Status= EFI_SUCCESS;
+ UINT8 DMACapability;
+ UINT8 Data8;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT16 DeviceName[41];
+ UINT16 Index;
+
+ EFI_UNICODE_STRING_TABLE *tempUnicodeTable;
+ CHAR8 Language[] = "Eng";
+
+ //
+ //Check if Device need spin-up
+ //
+ if ((IdeBusInterface->IdeDevice.IdentifyData.General_Config_0 & 4)
+ && (IdeBusInterface->IdeDevice.IdentifyData.Special_Config_2 == SPIN_UP_REQUIRED1
+ || IdeBusInterface->IdeDevice.IdentifyData.Special_Config_2 == SPIN_UP_REQUIRED2)) {
+ Status = IdeSetFeatureCommand( IdeBusInterface, SET_DEVICE_SPINUP, 0 );
+
+ if ( EFI_ERROR( Status )) {
+ //
+ //Some HDD may take a long time to spin up. Wait for additional time
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO, Regs.ControlBlock.AlternateStatusReg, BSY | DRQ, gPlatformIdeProtocol->PoweonBusyClearTimeout );
+ }
+ //
+ //Get the Identify Command once more
+ //
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+ }
+
+ //
+ // Check if PIO mode needs to be programmed
+ //
+ if ((IdeBusInterface->IdeDevice.IdentifyData.Valid_Bits_53 & 0x2) && (IdeBusInterface->IdeDevice.PIOMode != 0xff)) {
+ Status = IdeSetFeatureCommand( IdeBusInterface, SET_TRANSFER_MODE, PIO_FLOW_CONTROL | IdeBusInterface->IdeDevice.PIOMode );
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Issue Set Multiple Mode Command only for ATA device
+ //
+ if ( IdeBusInterface->IdeDevice.DeviceType == ATA ) {
+ Data8 = IdeBusInterface->IdeDevice.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 ) {
+ Status = IdeNonDataCommand(
+ IdeBusInterface,
+ 0, // Features
+ Data8, // Sector Count
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ SET_MULTIPLE_MODE ); // Command
+ }
+ }
+
+ //Check if Busmaster Enabled
+ //Status = EFI_NOT_FOUND;
+ //Check if UDMA is supported
+ if ( IdeBusInterface->IdeDevice.UDma != 0xff ) {
+ Status = IdeSetFeatureCommand( IdeBusInterface, SET_TRANSFER_MODE, UDMA_MODE | IdeBusInterface->IdeDevice.UDma );
+ } else {
+ if ( IdeBusInterface->IdeDevice.MWDma != 0xff ) {
+ Status = IdeSetFeatureCommand( IdeBusInterface, SET_TRANSFER_MODE, MWDMA_MODE | IdeBusInterface->IdeDevice.MWDma );
+ }
+ }
+
+ if ( EFI_ERROR( Status )) {
+ //
+ //No DMA support
+ //
+ IdeBusInterface->IdeDevice.UDma = 0xff;
+ IdeBusInterface->IdeDevice.MWDma = 0xff;
+ } else {
+ //
+ //Enable DMA capable bit
+ //
+ DMACapability = 0x20;
+
+ if ( IdeBusInterface->IdeDevice.Device ) {
+ DMACapability = 0x40;
+ }
+
+ if ( DMACapable( IdeBusInterface )) {
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMStatusRegister,
+ &Data8 );
+ Data8 |= DMACapability;
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMStatusRegister,
+ Data8 );
+ }
+ }
+
+ //
+ //Convert the Device string from Engligh to Unicode
+ //
+ IdeBusInterface->IdeDevice.UDeviceName = NULL;
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ IdeBusInterface->ControllerNameTable = IdeBusInterface->IdeDevice.UDeviceName;
+ }
+
+ for ( Index = 0; Index < 40; Index += 2 ) {
+
+ DeviceName[Index] = ((UINT8*)IdeBusInterface->IdeDevice.IdentifyData.Model_Number_27)[Index + 1];
+ DeviceName[Index + 1] = ((UINT8*)IdeBusInterface->IdeDevice.IdentifyData.Model_Number_27)[Index];
+ }
+
+ for ( Index = 39; Index >= 0; Index-- ) {
+ if ( DeviceName[Index] == 0x20 )
+ continue;
+ else
+ break;
+ }
+
+ DeviceName[Index + 1] = 0; // Terminate string
+ Index += 2;
+
+ //
+ //This is a patch to make it work for both in Aptio and Alaska
+ //
+ tempUnicodeTable = MallocZ( sizeof (EFI_UNICODE_STRING_TABLE) * 2 );
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof (Language),
+ (VOID**)&tempUnicodeTable[0].Language
+ );
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ Index * (sizeof (UINT16)),
+ (VOID**)&tempUnicodeTable[0].UnicodeString
+ );
+
+
+ pBS->CopyMem( tempUnicodeTable[0].Language, &Language, sizeof(Language));
+ pBS->CopyMem( tempUnicodeTable[0].UnicodeString, DeviceName, Index * (sizeof (UINT16)));
+ tempUnicodeTable[1].Language = NULL;
+ tempUnicodeTable[1].UnicodeString = NULL;
+ IdeBusInterface->IdeDevice.UDeviceName = tempUnicodeTable;
+ if ( gPlatformIdeProtocol->EfiIdeProtocol ) {
+ IdeBusInterface->ControllerNameTable = IdeBusInterface->IdeDevice.UDeviceName;
+ }
+ if ( gPlatformIdeProtocol->SBIdeSupport ) {
+ InitMiscConfig(IdeBusInterface);
+ }
+
+ if ( gPlatformIdeProtocol->IdePowerManagementSupport ) {
+ Status = InitIDEPowerManagement( IdeBusInterface );
+ }
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: InitMiscConfig
+//
+// Description: Initialize misc IDE configurations.
+//
+// Input:
+// IN SATA_DEVICE_INTERFACE *SataDevInterface
+//
+// Output:
+// None
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+VOID InitMiscConfig (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface
+)
+{
+ if ( gPlatformIdeProtocol->DiPMSupport ) {
+
+ if(IdeBusInterface->IdeDevice.IdentifyData.Reserved_76_79[2] & \
+ IDENTIFY_DiPM__SUPPORT) { // DiPM supported?
+ //
+ // Always disable DiPM in IDE mode
+ //
+ IdeSetFeatureCommand (IdeBusInterface, DiPM_DISABLE, DiPM_SUB_COMMAND);
+ }
+ }
+ if ( gPlatformIdeProtocol->AcousticManagementSupport ) {
+ InitAcousticSupport (IdeBusInterface);
+ }
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitAcousticSupport
+//
+// Description: Initializes Acoustic Management Support functionality
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IdeSetFeatureCommand
+//
+// 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 IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ UINT8 Data8;
+
+ //
+ // Check if the device supports Acoustic Management
+ //
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x200 ) {
+ //
+ //Check if Acoustic Level need to be enabled or Disabled
+ //
+ if ( IdeBusInterface->IdeBusInitInterface->Flags & ACOUSTIC_SUPPORT_ENABLE ) {
+ Data8 = IdeBusInterface->IdeBusInitInterface->Acoustic_Management_Level;
+
+ //
+ // Do we need to program the recommended value
+ //
+ if ( Data8 == ACOUSTIC_LEVEL_BYPASS ) {
+ //
+ // Get the rcommended value
+ //
+ Data8 = (UINT8)(IdeBusInterface->IdeDevice.IdentifyData.Acoustic_Level_94 >> 8);
+ }
+
+ IdeSetFeatureCommand (IdeBusInterface, ACOUSTIC_MANAGEMENT_ENABLE, Data8);
+ } else {
+ //
+ // If already disabled, nothing to do
+ //
+ if (IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Enabled_86 & 0x200)
+ IdeSetFeatureCommand (IdeBusInterface, ACOUSTIC_MANAGEMENT_DISABLE, 0);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: UpdateBaseAddress
+//
+// Description: Updates Command and Control reg address.
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IdeBusStart
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Using PCI_IO_PROTOCOL, update the Command, control and Busmaster reg address.
+// Make use of Channel number while updating. Also check whether controller is running in Legacy/Native mode
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS UpdateBaseAddress(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_PCI_IO_PROTOCOL *PciIO;
+ UINT8 PciConfig[0x40];
+ UINT16 CommandReg;
+ UINT16 ControlReg;
+ UINT16 BusMasterReg;
+
+
+ PciIO = IdeBusInterface->PciIO;
+ PciIO->Pci.Read(
+ PciIO,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciConfig),
+ PciConfig );
+
+ if ((PciConfig [PROGRAMMING_INTERFACE_OFFSET] & (IdeBusInterface->IdeDevice.Channel == 0 ? 1 : 4))
+ || (PciConfig [IDE_SUB_CLASS_CODE] == SCC_AHCI_CONTROLLER)
+ || (PciConfig [IDE_SUB_CLASS_CODE] == SCC_RAID_CONTROLLER)) {
+ //
+ //Native Mode Secondary
+ //
+ if ( IdeBusInterface->IdeDevice.Channel ) {
+ CommandReg = (*(UINT16*)(PciConfig + SECONDARY_COMMAND_BLOCK_OFFSET)) & 0xfffe;
+ ControlReg = ((*(UINT16*)(PciConfig + SECONDARY_CONTROL_BLOCK_OFFSET)) & 0xfffe) + 2;
+ BusMasterReg = ((*(UINT16*)(PciConfig + LEGACY_BUS_MASTER_OFFSET)) & 0xfffe) + 8;
+ } else {
+ //
+ // Native mode Primary
+ //
+ CommandReg = (*(UINT16*)(PciConfig + PRIMARY_COMMAND_BLOCK_OFFSET)) & 0xfffe;
+ ControlReg = ((*(UINT16*)(PciConfig + PRIMARY_CONTROL_BLOCK_OFFSET)) & 0xfffe) + 2;
+ BusMasterReg = (*(UINT16*)(PciConfig + LEGACY_BUS_MASTER_OFFSET)) & 0xfffe;
+ }
+ } else {
+ //
+ //Legacy Mode Secondary
+ //
+ if ( IdeBusInterface->IdeDevice.Channel ) {
+ CommandReg = SECONDARY_COMMAND_BLOCK;
+ ControlReg = SECONDARY_CONTROL_BLOCK;
+ BusMasterReg = (*(UINT16*)(PciConfig + LEGACY_BUS_MASTER_OFFSET) & 0xfffe) + 8;
+ } else {
+ //
+ //Legacy mode Primary
+ //
+ CommandReg = PRIMARY_COMMAND_BLOCK;
+ ControlReg = PRIMARY_CONTROL_BLOCK;
+ BusMasterReg = (*(UINT16*)(PciConfig + LEGACY_BUS_MASTER_OFFSET) & 0xfffe);
+ }
+ }
+
+ //
+ // Validate the Address
+ //
+ if ( CommandReg == 0 || ControlReg == 0 ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( CommandReg == 0xfffe || ControlReg == 0xfffe ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Update the Command block registers
+ //
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.DataReg = CommandReg;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.FeatureReg = CommandReg + 1;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.ErrorReg = CommandReg + 1;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.SectorCountReg = CommandReg + 2;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBALowReg = CommandReg + 3;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAMidReg = CommandReg + 4;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAHighReg = CommandReg + 5;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.DeviceReg = CommandReg + 6;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.CommandReg = CommandReg + 7;
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.StatusReg = CommandReg + 7;
+
+ //
+ //Update the Control Block Register address
+ //
+ IdeBusInterface->IdeDevice.Regs.ControlBlock.DeviceControlReg = ControlReg;
+ IdeBusInterface->IdeDevice.Regs.ControlBlock.AlternateStatusReg = ControlReg;
+
+
+ //
+ //Update the Bus Master register address
+ //
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMCommandRegister = BusMasterReg;
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMStatusRegister = BusMasterReg + 2;
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMDescriptorTablePointerReg = BusMasterReg + 4;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: DMACapable
+//
+// Description: Check if DMA is supported
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// TRUE : DMA Capable
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN DMACapable(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ if ( IdeBusInterface->IdeDevice.DeviceType == ATAPI ) {
+ //
+ // For Atapi Devices check Bit 8 in Word 49 = DMA Supported or not
+ //
+ if ((IdeBusInterface->IdeDevice.IdentifyData.Capabilities_49 & 0x100) == 0 ) {
+ return FALSE;
+ }
+ }
+
+ if ((IdeBusInterface->IdeDevice.UDma != 0xff)
+ || (IdeBusInterface->IdeDevice.MWDma != 0xff)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: DiskInfoInquiry
+//
+// Description:
+//
+// Input:
+// IN EFI_DISK_INFO_PROTOCOL *This,
+// IN OUT VOID *InquiryData,
+// IN OUT UINT32 *InquiryDataSize
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeDiskInfo
+//
+// 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 )
+{
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((IDE_BLOCK_IO*)This)->IdeBusInterface;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+
+
+ //
+ // Check for ATAPI device. If not return EFI_NOT_FOUND
+ //
+ if ( IdeBusInterface->IdeDevice.DeviceType == ATA ) {
+ return EFI_NOT_FOUND;
+ } 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: InitIdeDiskInfo
+//
+// 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 )
+{
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((IDE_BLOCK_IO*)This)->IdeBusInterface;
+
+ if ( *IdentifyDataSize < sizeof (IDENTIFY_DATA)) {
+ *IdentifyDataSize = sizeof (IDENTIFY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ pBS->CopyMem( IdentifyData, &(IdeBusInterface->IdeDevice.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: InitIdeDiskInfo
+//
+// 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 whether the device is PM/PS/SM/SS
+//
+// Input:
+// IN EFI_DISK_INFO_PROTOCOL *This,
+// OUT UINT32 *IdeChannel,
+// OUT UINT32 *IdeDevice
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeDiskInfo
+//
+// Notes:
+// 1. Return information about the Primary/Secondary channel and Master/Slave information.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS DiskInfoWhichIDE(
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice )
+{
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((IDE_BLOCK_IO*)This)->IdeBusInterface;
+
+ *IdeChannel = IdeBusInterface->IdeDevice.Channel;
+ *IdeDevice = IdeBusInterface->IdeDevice.Device;
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IdeHPTimer
+//
+// Description: Checks for any HP IDE device
+//
+// Input:
+// IN EFI_EVENT Event,
+// IN VOID *Context
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID IdeHPTimer(
+ IN EFI_EVENT Event,
+ IN VOID *Context )
+{
+ EFI_STATUS Status;
+ UINT8 DeviceStatus;
+ UINT8 CurrentState;
+ UINT8 Current_Channel;
+ UINT8 Current_Device;
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface = (IDE_BUS_INIT_PROTOCOL*)Context;
+
+ IDE_BUS_PROTOCOL *IdeBusInterface;
+ IN IDE_CONTROLLER_PROTOCOL *IdeControllerInterface = IdeBusInitInterface->IdeControllerInterface;
+
+ IdeControllerInterface->HPCheckForDeviceChange( IdeControllerInterface->PciIO,
+ IdeBusInitInterface->HPMask,
+ &DeviceStatus );
+
+ for ( Current_Channel = PRIMARY_CHANNEL; Current_Channel <= SECONDARY_CHANNEL; Current_Channel++ )
+ {
+ for ( Current_Device = MASTER_DRIVE; Current_Device <= SLAVE_DRIVE; Current_Device++ )
+ {
+ CurrentState = IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device];
+ IdeBusInterface = IdeBusInitInterface->pIdeBusProtocol[Current_Channel][Current_Device];
+
+ if ((CurrentState == DEVICE_CONFIGURED_SUCCESSFULLY) && ((DeviceStatus & 01) == 0)) {
+ //
+ //Handle Device Removal
+ //
+ Status = pBS->DisconnectController( IdeControllerInterface->ControllerHandle, NULL, IdeBusInterface->IdeDeviceHandle );
+
+
+ if ( Status == EFI_SUCCESS ) {
+ IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] = DEVICE_IN_RESET_STATE;
+ }
+ }
+
+ if ((CurrentState != DEVICE_CONFIGURED_SUCCESSFULLY) && ((DeviceStatus & 01) == 1)) {
+ //Handle device insertion
+ //Force IdeBusStart to Enumerate this device.
+ IdeBusInitInterface->IdeBusInitData[Current_Channel][Current_Device] = DEVICE_IN_RESET_STATE;
+
+ pBS->ConnectController( IdeControllerInterface->ControllerHandle, NULL, NULL, TRUE );
+ }
+ DeviceStatus >>= 1;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CheckHPControllerPresence
+//
+// Description: A quick check to see if ports are still decoded.
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckHPControllerPresence(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ UINT8 Device = IdeBusInterface->IdeDevice.Device;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.DeviceReg, Device << 4 );
+
+ //
+ //Read the status Register
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.StatusReg, &Data8 );
+
+ if ( Data8 == 0xff ) {
+ return EFI_NOT_FOUND;
+ }
+
+ if ( Data8 == 0x7f ) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+ // IDE_HP_SUPPORT
+//---------------------------------------------------------------------------
+
+#ifdef Debug_Level_3
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: PrintIdeDeviceInfo
+//
+// Description: Prints Debug Level 3 Trace Messages
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+void PrintIdeDeviceInfo(
+ IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ UINT16 Data8;
+ UINT16 *pIdentifyData;
+
+ // Print the Channel and Device Number
+ EfiDebugPrint( -1, "-----------------IDE Device Info Start-----------------\n" );
+ EfiDebugPrint( -1, "Channel : %x Device : %x\n", IdeBusInterface->IdeDevice.Channel, IdeBusInterface->IdeDevice.Device );
+ EfiDebugPrint( -1, "PIOMode : %x UDMAMode : %x\n", IdeBusInterface->IdeDevice.PIOMode, IdeBusInterface->IdeDevice.UDma );
+ EfiDebugPrint( -1, "SWDMAMode : %x MWDMAMode : %x\n", IdeBusInterface->IdeDevice.SWDma, IdeBusInterface->IdeDevice.MWDma );
+ EfiDebugPrint( -1, "IORDY : %x \n", IdeBusInterface->IdeDevice.IORdy );
+ pIdentifyData = (UINT16*) &(IdeBusInterface->IdeDevice.IdentifyData);
+
+ for ( Data8 = 0; Data8 < 0xff; Data8 += 4 )
+ {
+ EfiDebugPrint( -1, "%X %X %X %X\n", pIdentifyData[Data8 + 0], pIdentifyData[Data8 + 1], pIdentifyData[Data8 + 2], pIdentifyData[Data8 + 3] );
+ }
+ EfiDebugPrint( -1, "-----------------IDE Device Info End-------------------\n" );
+}
+
+#endif /* Debug_Level_3 */
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CheckAhciMode
+//
+// Description: Checks If the controller is in AHCI MODE.
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// BOOLEAN TRUE - AHCI Mode
+// FALSE - IDE Mode
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN CheckAhciMode(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_PCI_IO_PROTOCOL *PciIO;
+ UINT8 PciConfig[0x40];
+ BOOLEAN AhciFlag = FALSE;
+
+ PciIO = IdeBusInterface->PciIO;
+ PciIO->Pci.Read(
+ PciIO,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciConfig),
+ PciConfig );
+
+ AhciFlag = (BOOLEAN)((PciConfig [IDE_SUB_CLASS_CODE] & SCC_AHCI_CONTROLLER) ? TRUE : FALSE );
+
+ return AhciFlag;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IssueFreezeLockCommand
+//
+// Description: Issue the Freeze lock command.
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IssueFreezeLockCommand(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_82 & 0x2 ) {
+ Status = IdeNonDataCommand( IdeBusInterface, 0, 0,
+ 0, 0, 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ SECURITY_FREEZE_LOCK );
+ //
+ //Update the Identify device buffer
+ //
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+ }
+ return Status;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************