summaryrefslogtreecommitdiff
path: root/Core/EM/IdeBus
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/IdeBus')
-rw-r--r--Core/EM/IdeBus/Ata.c2986
-rw-r--r--Core/EM/IdeBus/Atapi.c1811
-rw-r--r--Core/EM/IdeBus/IDEBusComponentName.c374
-rw-r--r--Core/EM/IdeBus/IdeBus.c3607
-rw-r--r--Core/EM/IdeBus/IdeBus.chmbin0 -> 151925 bytes
-rw-r--r--Core/EM/IdeBus/IdeBus.cif13
-rw-r--r--Core/EM/IdeBus/IdeBus.h821
-rw-r--r--Core/EM/IdeBus/IdeBus.mak114
-rw-r--r--Core/EM/IdeBus/IdeBus.sdl195
-rw-r--r--Core/EM/IdeBus/IdeBusMaster.c836
-rw-r--r--Core/EM/IdeBus/IdeBusSrc.chmbin0 -> 152056 bytes
-rw-r--r--Core/EM/IdeBus/IdeBusSrc.cif18
-rw-r--r--Core/EM/IdeBus/IdeBusSrc.mak98
-rw-r--r--Core/EM/IdeBus/IdeBusSrc.sdl22
-rw-r--r--Core/EM/IdeBus/IdeHPA.c792
-rw-r--r--Core/EM/IdeBus/IdePowerManagement.c546
16 files changed, 12233 insertions, 0 deletions
diff --git a/Core/EM/IdeBus/Ata.c b/Core/EM/IdeBus/Ata.c
new file mode 100644
index 0000000..00cabb0
--- /dev/null
+++ b/Core/EM/IdeBus/Ata.c
@@ -0,0 +1,2986 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/IdeBus/Ata.c 34 1/03/12 11:22p Rajkumarkc $
+//
+// $Revision: 34 $
+//
+// $Date: 1/03/12 11:22p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/Ata.c $
+//
+// 34 1/03/12 11:22p Rajkumarkc
+// // [TAG] EIP 79612 & 80003
+// // [Category] Bug Fix
+// // [Description]System hangs with Blue screen during Win8 installation
+// // in IDE Mode (AMD Platforms)
+// // Use PLATFORM_IDE_PROTOCOL data instead of hard coded
+// // macro POWERON_BUSY_CLEAR_TIMEOUT in Ata.c file
+// // [Files] Ata.c
+//
+// 33 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
+//
+// 32 11/08/11 5:15a Deepthins
+// [TAG] EIP74607
+// [Category] Improvement
+// [Description] Block IO Read/Write function, the allignment should be
+// proper. IoAlign value is 0 or 1 means that the buffer can be placed
+// anywhere in memory. Otherwise, IoAlign must be a power of 2, and the
+// requirement is that the start address of a buffer must be evenly
+// divisible by IoAlign with no remainder.
+// [Files] Ata.c, Atapi.c, AhciController.c
+//
+// 31 11/07/11 4:25a Deepthins
+// [TAG] EIP74607
+// [Category] Improvement
+// [Description] IoAlign values is 0 or 1 means that the buffer can be
+// placed anywhere in memory. Otherwise, IoAlign must be a power of 2, and
+// the requirement is that the start address of a buffer must be evenly
+// divisible by 2 to the power of IoAlign with no remainder.
+// [Files] Ata.c
+//
+// 30 11/07/11 12:37a Deepthins
+// [TAG] EIP73941
+// [Category] Improvement
+// [Description] BufferSize is 0 , ReadBlock function should return
+// EFI_SUCCESS without actual reading.
+// [Files] Ata.c
+//
+// 29 9/27/11 3:10a 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
+//
+// 28 8/12/11 4:12a Lavanyap
+// [TAG] EIP66476
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] AtaPioDataOut fails for data write commands
+// [RootCause] TempBuffer pointer has been assigned for both data read
+// and write commands.
+// [Solution] TempBuffer pointer has to be assigned only for data read
+// commands.
+// [Files] Ata.c
+//
+// 27 3/28/11 4:44p Artems
+// EIP 53849: fixed bug with build error in 32-bit debug mode
+//
+// 26 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
+//
+// 25 11/02/10 12:01a Rameshr
+// [TAG] - EIP 45266
+// [Category]- BUG FIX
+// [Severity]- Minor
+// [Symptom] - E-SATA card will hang up on post and debug card show "AE
+// [RootCause]- Device doesn't support any of the UDMA mode and function
+// ReturnMsbbit returns incorrect values
+// [Solution] - If any of the bit is not set in Input value, ReturnMsbbit
+// returns 0xFF.
+// [Files] - Ata.c, AhciBus.c
+//
+// 24 10/11/10 11:27a Krishnakumarg
+// [TAG] - EIP 43249
+// [Category] - IMPROVEMENT
+// [Severity] - Minor
+// [Symptom] - Non-Ascii character in comments causing build problem in
+// japanese XP
+// [RootCause]- Presence of Non-Ascii character
+// [Solution] - Remove Non-Ascii character present in the file
+// [Files] - IdeSecurity.c,IDESMM.c, InstallIdeSmi, Ata.c, Atapi.c,
+// IDEBusComponentName.c, IdeBusMaster.c, IdeHPA.c, IdePowerManagement.c
+//
+// 23 9/24/10 12:47a Rameshr
+// [TAG] - EIP 44713
+// [Category]- BUG FIX
+// [Severity]- Major
+// [Symptom] - SECURITY_ERASE_UNIT command is not working
+// [RootCause] - Security Erase unit command timeout value is not proper.
+// So getting Timeout error for this command.
+// [Solution] - Security Erase command timeout value should be from the
+// Identify packet command word 89
+// [Files] - Ata.c
+//
+// 22 8/25/10 4:07a Rameshr
+// New Feature: EIP 37748
+// Description: Move all the IDEBus Source driver SDL token into IdeBus
+// Bin Driver.
+// FilesModified: All.
+//
+// 21 4/16/10 4:05p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 20 7/01/09 12:23p Rameshr
+// Coding Standard and File header updated.
+//
+// 19 6/16/09 10:13a Rameshr
+// if the Erase command timeout value is 0 or 255, wait for the Erase
+// command completion without timeout value
+// EIP:20630
+//
+// 18 3/29/09 11:13a Rameshr
+// Security Erase command timeout value should be from the Identify packet
+// command word 89
+// EIP 20630
+//
+// 17 4/22/08 2:02p Felixp
+// DXE_IDE_DETECT progress code moved from ATA.c to IdeBus.c
+// DXE_IDE_ENABLE progress code added
+//
+// 16 3/06/08 4:42p Ambikas
+//
+// 15 3/04/08 7:51p Felixp
+//
+// 13 28/02/08 7:06p Anandakrishnanl
+// Changed timeout values and DMA capability logic for DisableIdeInterrupt
+// routine.
+//
+// 12 13/04/07 2:59p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 11 5/03/07 11:40a Anandakrishnanl
+// Fix in Check Controller presence to detect Hard disk above 400 GB.
+//
+// 10 2/12/07 3:41p Pats
+// Eliminated Check Drive Ready to reduce boot time on reset.
+//
+// 9 10/27/06 4:20p Felixp
+// Reverted back to the previous version
+//
+// 7 10/12/06 2:02p Srinin
+// Fixed problem in multiple read/Write word in PIO mode.
+//
+// 6 8/24/06 9:30a Felixp
+// x64 support (bug fixes)
+//
+// 5 3/13/06 2:20a Felixp
+//
+// 4 1/09/06 11:36a Felixp
+//
+// 2 12/14/05 3:06p Srinin
+// Idedevice detection logic modified.
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 11 9/27/05 4:41p Olegi
+// DisableIdeInterrupt is modified, added code to clear interrupt request.
+//
+// 10 8/22/05 4:31p Srinin
+// ATA/ATAPI identification changed.
+//
+// 9 7/18/05 4:31p Felixp
+// 64-bit compatibility warnings removed
+//
+// 8 4/25/05 9:55a Felixp
+// bug fix in IssueAtaReadWriteCommand
+//
+// 7 3/04/05 11:33a Mandal
+//
+// 6 2/24/05 12:21p Felixp
+// bug fix in AtaBlkRead and AtaBlkWrite functions:
+// EFI_INVALID_PARAMETER was returned when last block is read or written
+// to
+//
+// 5 2/01/05 12:59p Srinin
+// IDE HotPlug Support added.
+//
+// 4 1/28/05 1:19p Felixp
+// IdeBus is linked together with CORE_DXE
+//
+// 3 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 2 1/05/05 11:21a Srinin
+// BusMaster and Password Support added.
+//
+// 1 12/10/04 1:01p Srinin
+// Initial Checkin of IdeBus Driver.
+//
+//
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: Ata.c
+//
+// Description: ATA Services
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#include "IdeBus.h"
+#include <Protocol\IdeBusBoard.h>
+
+extern PLATFORM_IDE_PROTOCOL *gPlatformIdeProtocol;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: DetectIdeDevice
+//
+// Description: Detects the ATA/ATAPI device
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IdeBusStart
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If controller not present return EFI_NOT_FOUND
+// 2. If BSY bit not clear and DRDY not set, return EFI_DEVICE_ERROR
+// 3. If Identify command fails, return EFI_NOT_FOUND
+// 4. Else return Success
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DetectIdeDevice(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+
+ //
+ // Check if the controller is present
+ //
+ Status = ControllerPresence( IdeBusInterface );
+
+ if ( Status == EFI_NOT_FOUND ) {
+ //
+ // Status Reg is 0xff
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ if ( Status == EFI_DEVICE_ERROR ) {
+ IdeSoftReset( IdeBusInterface );
+
+ //
+ //3 Sec loop
+ //
+ for ( Index = 0; Index < 300; Index++ ) {
+ //
+ //check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ BSY,
+ 1 ); // 1 msec
+
+ if ( Status == EFI_SUCCESS ) {
+ break;
+ }
+ pBS->Stall( 10000 ); // 10Msec
+ }
+
+ Status = ControllerPresence( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ //
+ // Device couldn't be detected
+ //
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ //
+ //Disable Interrupt
+ //
+ DisableIdeInterrupt( IdeBusInterface );
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ IdeBusInterface->IdeDevice.Device << 4 );
+
+ //
+ //Check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ BSY,
+ gPlatformIdeProtocol->PoweonBusyClearTimeout ); // 10 sec
+
+ //
+ //Check Drive ready. ATAPI devices will not set DRDY bit after reset
+ //
+ Status = CheckDriveReady( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ Status = AtapiIdentifyCommand( IdeBusInterface,
+ &(IdeBusInterface->IdeDevice.IdentifyData));
+ IdeBusInterface->IdeDevice.DeviceType = ATAPI;
+ return Status;
+ }
+
+ //
+ //Detect ATA device
+ //
+ Status = AtaIdentifyCommand( IdeBusInterface,
+ &(IdeBusInterface->IdeDevice.IdentifyData));
+ IdeBusInterface->IdeDevice.DeviceType = ATA;
+
+ if ( Status == EFI_SUCCESS ) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ //Detect ATAPI Device. After failing the ATA Identify command, ATAPI device if present,
+ //should have the signature EB14h
+ //
+ Status = EFI_NOT_FOUND;
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAMidReg,
+ &Data8 );
+
+ if ( Data8 == (ATAPI_SIGNATURE & 0xff)) {
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAHighReg,
+ &Data8 );
+
+ if ( Data8 == (ATAPI_SIGNATURE >> 8)) {
+ IdeBusInterface->IdeDevice.DeviceType = ATAPI;
+ Status = AtapiIdentifyCommand( IdeBusInterface,
+ &(IdeBusInterface->IdeDevice.
+ IdentifyData));
+ }
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ControllerPresence
+//
+// Description: Detects the ATA/ATAPI Controller
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: DetectIdeDevice
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Select the drive
+// 2. Read status Register
+// 3. If Status_Reg = 0xff, return Not_Found
+// 4. Check if Busy bit is clear, return Found
+// 5. If the BUS is not floating return EFI_DEVICE_ERROR
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ControllerPresence(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ UINT8 Device = IdeBusInterface->IdeDevice.Device;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+ UINT8 Temp;
+ UINT16 Index;
+
+ //
+ //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;
+ }
+
+ Index = 0;
+
+ do
+ {
+ //
+ // Status Register is not 0xff.
+ //
+ Temp = Data8;
+
+ //60 usec delay
+ pBS->Stall( 60 );
+
+ //
+ //Read the status Register
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ &Data8 );
+
+ //
+ //Return Success if controller present
+ //
+ if ( !(Data8 & 0x80)) {
+ return EFI_SUCCESS;
+ }
+
+ Data8 |= Temp;
+ //
+ //Keep bits 7,6,3 and 0
+ //
+ Data8 &= 0xc9;
+
+ if ( Data8 == 0xc9 ) {
+ //Check for Bus Floating
+ //Select the drive
+ Data8 = (Device & 1) ? 0xA0 : 0xB0;
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ Data8 );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.SectorCountReg,
+ 0xff );
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ &Temp );
+ //Decide Controller Present or Not
+ return (Temp == Data8) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+ }
+ Index++;
+ } while ( Index < 350 );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaReset
+//
+// Description: Reset ATA device
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeBlockIO
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaReset(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification )
+{
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaBlkRead
+//
+// Description: Read from ATA device
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeBlockIO, AtaReadWritePio
+//
+// Notes:
+// 1. Check for error conditions.
+// 2. Call AtaReadWritePio.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaBlkRead(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer )
+{
+ UINTN DataN;
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((IDE_BLOCK_IO*)This)->IdeBusInterface;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = This->Media;
+ UINT32 BlockSize = BlkMedia->BlockSize;
+ UINTN BufferAddress;
+
+ //
+ //Check if Media ID matches
+ //
+ if ( BlkMedia->MediaId != MediaId ) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if ( BlkMedia->MediaPresent == FALSE ) {
+ return EFI_NO_MEDIA;
+ }
+
+ if ( BufferSize == 0 ) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((BlkMedia->IoAlign > 1 ) && (BufferAddress % BlkMedia->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check whether the block size is multiple of BlkMedia->BlockSize
+ //
+ DataN = BufferSize % BlkMedia->BlockSize;
+
+ if ( DataN ) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //
+ //Check for Valid start LBA #
+ //
+ if ( LBA > BlkMedia->LastBlock ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check for Valid End LBA #
+ //
+ DataN = BufferSize / BlkMedia->BlockSize;
+
+ if ( LBA + DataN > BlkMedia->LastBlock + 1 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( gPlatformIdeProtocol->IdeBusMasterSupport ) {
+ if ( DMACapable( IdeBusInterface )) {
+ Status = AtaReadWriteBusMaster( IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.ReadCommand,
+ 0 );
+ return Status;
+ }
+ }
+
+
+ Status = AtaReadWritePio( IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.ReadCommand,
+ 0 );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaBlkWrite
+//
+// Description: Write to ATA device
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeBlockIO, AtaReadWritePio
+//
+// Notes:
+// 1. Check for error conditions.
+// 2. Call AtaReadWritePio.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaBlkWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer )
+{
+ UINTN DataN;
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((IDE_BLOCK_IO*)This)->IdeBusInterface;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = This->Media;
+ UINT32 BlockSize = BlkMedia->BlockSize;
+ UINTN BufferAddress;
+
+ //
+ //Check if Media ID matches
+ //
+ if ( BlkMedia->MediaId != MediaId ) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if ( BufferSize == 0 ) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((BlkMedia->IoAlign > 1 ) && (BufferAddress % BlkMedia->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check whether the block size is multiple of BlkMedia->BlockSize
+ //
+ DataN = BufferSize % BlkMedia->BlockSize;
+
+ if ( DataN ) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //
+ //Check for Valid start LBA #
+ //
+ if ( LBA > BlkMedia->LastBlock ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check for Valid End LBA #
+ //
+ DataN = BufferSize / BlkMedia->BlockSize;
+
+ if ( LBA + DataN > BlkMedia->LastBlock + 1 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( gPlatformIdeProtocol->IdeBusMasterSupport ) {
+ if ( DMACapable( IdeBusInterface )) {
+ Status = AtaReadWriteBusMaster( IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.WriteCommand,
+ 1 );
+ return Status;
+ }
+ }
+
+ Status = AtaReadWritePio( IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.WriteCommand,
+ 1 );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaBlkFlush
+//
+// Description: Flush the cache
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeBlockIO
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaBlkFlush(
+ IN EFI_BLOCK_IO_PROTOCOL *This )
+{
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaReadWritePio
+//
+// Description: Issues Read/Write Command and Read/Write the data from/to the ATA device
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINTN ByteCount,
+// UINT64 LBA
+// IN UINT8 ReadWriteCommand,
+// IN BOOLEAN ReadWrite Read/Write = 0/1
+//
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals: AtaBlkWrite, AtaBlkRead
+//
+// Notes:
+// 1. Check if Multiple sectors can be read/written to the ATA device.
+// 2. Check for 48-bit LBA support.
+// 3. Issue the command based on step 1 and step 2 results.
+// 4. check for errors.
+// 5. If success read/write data.
+// 6. Based on step 1 results, complete the read/write sequence
+// 7. If all sectors are not completed, goto step 3.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaReadWritePio(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN ReadWrite )
+{
+ EFI_STATUS Status;
+ INT32 WordCount;
+ UINT32 SectorCount;
+ UINTN Remainder;
+ UINT8 Data8;
+ IDE_DEVICE_INTERFACE *IdeDevice = &(IdeBusInterface->IdeDevice);
+ UINT8 BlockSize = 1; // 1 sector Default
+ VOID *TempBuffer;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ INT64 LoopCount;
+ INT64 MaxSectorCount;
+ INT64 Total_Number_Of_Sectors;
+ UINT32 EraseCommandTimeout = 0;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+ BOOLEAN SectorGTBytes = FALSE;
+
+ //
+ //Check if the device supports Multiple sector Read/Write
+ //
+ if ( IdeDevice->IdentifyData.Valid_Bits_59 & 0x100 ) {
+ BlockSize = (UINT8) IdeDevice->IdentifyData.Valid_Bits_59;
+ }
+
+ //
+ // Error Checking
+ //
+ if ( BlockSize == 0 ) {
+ BlockSize = 1;
+ }
+
+ 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;
+ }
+ //
+ // Disable Interrupt
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+
+ if ( Check48BitCommand( ReadWriteCommand )) {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO_48BIT;
+ }
+ else {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO;
+ }
+
+ //
+ //Calculate the total number of Sectors to be transferred
+ //
+ Total_Number_Of_Sectors = ByteCount / SectorSize; //512
+ // If the caller is requesting less bytes than one sector, we need to
+ // allocate space for one sector.
+ if ((ByteCount < SectorSize) && (ByteCount > 0)) {
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ SectorSize,
+ (VOID**)&TempBuffer );
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SectorGTBytes = TRUE;
+ Total_Number_Of_Sectors = 1;
+ } else {
+ TempBuffer = Buffer;
+ }
+
+ for (;
+ Total_Number_Of_Sectors > 0;
+ Total_Number_Of_Sectors -= MaxSectorCount )
+ {
+ if ( Total_Number_Of_Sectors > MaxSectorCount ) {
+ SectorCount = 0;
+ } else {
+ SectorCount = (UINT32) Total_Number_Of_Sectors;
+ }
+
+ Status = IssueAtaReadWriteCommand( IdeBusInterface,
+ LBA,
+ SectorCount,
+ ReadWriteCommand,
+ NULL );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Update LBA for next loop
+ //
+ if ( SectorCount ) {
+ LBA += SectorCount;
+ LoopCount = (SectorCount / BlockSize);
+ LoopCount += ((SectorCount % BlockSize) > 0 ? 1 : 0);
+ }
+ else {
+ LBA += MaxSectorCount;
+ LoopCount = Div64( MaxSectorCount, BlockSize, &Remainder );
+ LoopCount += (Remainder > 0 ? 1 : 0);
+ }
+
+ //
+ //For Security Erase command the time out value comes from Identify Data.
+ //
+ if ( ReadWriteCommand == SECURITY_ERASE_UNIT ) {
+ EraseCommandTimeout = (UINT32)( IdeBusInterface->IdeDevice.IdentifyData.Time_security_Earse_89 );
+
+ if ( EraseCommandTimeout <= 254 ) {
+ EraseCommandTimeout = EraseCommandTimeout * 2 * 1000 * 60; //Value * 2Minitues
+ }
+ else {
+ EraseCommandTimeout = 0; // No Timeout Value
+ }
+ }
+
+ //
+ //Read Data
+ //
+ for (; LoopCount > 0; LoopCount -= 1 ) {
+ //
+ //Wait for Command completion
+ //
+ if ( ReadWriteCommand == SECURITY_ERASE_UNIT ) {
+ Status = WaitForCmdCompletionWithTimeOutValue( IdeBusInterface,
+ EraseCommandTimeout );
+ }
+ else {
+ Status = WaitForCmdCompletion( IdeBusInterface );
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for DRQ
+ //
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ DRQ,
+ DRQ_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Caluculate # of Words to be read/written
+ //
+ if ( SectorCount ) {
+ if ( SectorCount >= BlockSize ) {
+ WordCount = (BlockSize * SectorSize) / 2;
+ }
+ else {
+ WordCount = (SectorCount * SectorSize) / 2; // Partial Block will be transferred
+ }
+ }
+ else {
+ WordCount = (BlockSize * SectorSize) / 2;
+ }
+
+ if ( BlockSize == 1 ) {
+ WordCount = (SectorSize) / 2;
+ }
+
+ if ( ReadWrite ) {
+ Status = IdeWriteMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ WordCount,
+ TempBuffer );
+ } else {
+ Status = IdeReadMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ WordCount,
+ TempBuffer );
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for errors.
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ &Data8 );
+
+ if ( Data8 & 0x21 ) { // ERR OR DF bit set ?
+ return EFI_DEVICE_ERROR;
+ }
+
+ ((UINT8*)TempBuffer) += (WordCount * 2);
+
+ if ( SectorCount ) {
+ SectorCount -= (WordCount * 2) / SectorSize;
+ }
+ else {
+ SectorCount = (UINT32) ( MaxSectorCount - ((WordCount * 2) / SectorSize));
+ }
+ }
+ }
+ if (SectorGTBytes) {
+ pBS->CopyMem( Buffer, TempBuffer, ByteCount);
+ pBS->FreePool( TempBuffer );
+ }
+
+ //
+ // Check for errors
+ //
+ if ( ReadWriteCommand == SECURITY_ERASE_UNIT ) {
+ Status = WaitForCmdCompletionWithTimeOutValue( IdeBusInterface,
+ EraseCommandTimeout );
+ } else {
+ Status = WaitForCmdCompletion( IdeBusInterface );
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaPioDataIn
+//
+// Description: Issues command which require data to be read
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINT32 ByteCount,
+// UINT8 SectorCount,
+// UINT8 LBALow,
+// UINT8 LBAMid,
+// UINT8 LBAHigh,
+// UINT8 Device,
+// UINT8 Command,
+// BOOLEAN Multiple // to determine the block size
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// Used to get Identify command data etc.
+// 1. Issue the command
+// 2. Check for errors.
+// 3. Check if Data is ready. If yes, read it else return error.
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaPioDataIn(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 Features,
+ IN UINT8 SectorCount,
+ IN UINT8 LBALow,
+ IN UINT8 LBAMid,
+ IN UINT8 LBAHigh,
+ IN UINT8 Device,
+ IN UINT8 Command,
+ IN BOOLEAN Multiple )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ EFI_STATUS Status;
+ UINT8 Data8;
+ UINT32 BlockSize;
+ VOID *TempBuffer = Buffer;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+ INT64 TempByteCount;
+
+
+ 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;
+ }
+
+ if ( Multiple ) {
+ BlockSize = SectorSize * (IdeBusInterface->IdeDevice.IdentifyData.Valid_Bits_59 & 0x0f);
+ }
+ else {
+ //
+ // Only one block of data to read
+ //
+ BlockSize = SectorSize;
+ }
+
+ if (ByteCount < SectorSize) BlockSize = ByteCount;
+
+ // Make the byte count a signed number.
+ TempByteCount = (INT64)ByteCount;
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ Device );
+
+ //
+ // Issue the Command
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.FeatureReg,
+ Features );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.SectorCountReg,
+ SectorCount );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBALowReg,
+ LBALow );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAMidReg,
+ LBAMid );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAHighReg,
+ LBAHigh );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.CommandReg,
+ Command );
+
+ for (; TempByteCount > 0; TempByteCount -= BlockSize ) {
+
+ //
+ //Wait for 400nsec before reading the status. To accomplish it, read ATL_STATUS and ignore the result
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ //
+ //Check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY,
+ COMMAND_COMPLETE_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check if DRQ is set else it is an error
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ &Data8 );
+
+ //
+ // DRQ bit set ?
+ //
+ if ( !(Data8 & 0x08)) {
+ //
+ // Handle Error condition
+ //
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( Data8 & 0x21 ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = IdeReadMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ BlockSize / 2,
+ TempBuffer );
+ //
+ // Wait for DRQ to go low
+ //
+ WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ DRQ,
+ DRQ_CLEAR_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+ ((UINT8*)TempBuffer) += BlockSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaPioDataOut
+//
+// Description: Issues Read/Write Command and Read/Write the data from/to the ATA device
+// with SubCommand Support.
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINTN ByteCount,
+// UINT8 Features,
+// UINT32 SectorCountIn,
+// UINT8 LBALow,
+// UINT8 LBALowExp,
+// UINT8 LBAMid,
+// UINT8 LBAMidExp,
+// UINT8 LBAHigh,
+// UINT8 LBAHighExp,
+// UINT8 Device,
+// UINT8 Command,
+// BOOLEAN ReadWrite, // Read/Write = 0/1
+// BOOLEAN Multiple // to determine the block size
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check if Multiple sectors can be read/written to the ATA device.
+// 2. Check for 48-bit LBA support.
+// 3. Issue the command based on step 1 and step 2 results.
+// 4. check for errors.
+// 5. If success read/write data.
+// 6. Based on step 1 results, complete the read/write sequence
+// 7. If all sectors are not completed, goto step 3.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtaPioDataOut(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT8 Features,
+ IN UINT32 SectorCountIn,
+ IN UINT8 LBALow,
+ IN UINT8 LBALowExp,
+ IN UINT8 LBAMid,
+ IN UINT8 LBAMidExp,
+ IN UINT8 LBAHigh,
+ IN UINT8 LBAHighExp,
+ IN UINT8 Device,
+ IN UINT8 Command,
+ IN BOOLEAN ReadWrite,
+ IN BOOLEAN Multiple )
+{
+ EFI_STATUS Status;
+ INT32 WordCount;
+ UINT32 SectorCount;
+ UINTN Remainder;
+ UINT8 Data8;
+ IDE_DEVICE_INTERFACE *IdeDevice = &(IdeBusInterface->IdeDevice);
+ UINT8 BlockSize = 1; // 1 sector Default
+ VOID *TempBuffer;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ INT64 LoopCount;
+ INT64 MaxSectorCount;
+ INT64 Total_Number_Of_Sectors;
+ UINT32 EraseCommandTimeout = 0;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+ BOOLEAN SectorGTBytes = FALSE;
+ UINT64 LBA = 0;
+ UINT64 LBAHighDword = 0;
+ INT64 i;
+
+ //
+ // Check if the device supports Multiple sector Read/Write
+ //
+ if ( IdeDevice->IdentifyData.Valid_Bits_59 & 0x100 ) {
+ BlockSize = (UINT8) IdeDevice->IdentifyData.Valid_Bits_59;
+ }
+
+ //
+ // Error Checking
+ //
+ if ( BlockSize == 0 ) {
+ BlockSize = 1;
+ }
+
+ 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;
+ }
+ //
+ // Disable Interrupt
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+
+ if ( Check48BitCommand( Command )) {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO_48BIT;
+ //
+ // if 48 Bit LBA form Upper Dword
+ //
+ LBAHighDword |= LBAHighExp;
+ LBAHighDword = ( Shl64(( Shl64( LBAHighDword, 8)| LBAMidExp), 8)| LBALowExp);
+ }
+ else {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO;
+ }
+ //
+ // Complete LBA
+ //
+ LBA |= LBAHigh;
+ LBA = (( Shl64(( Shl64( LBA, 8) | LBAMid ), 8)| LBALow)| Shl64( LBAHighDword, 24 ));
+
+ //
+ //Calculate the total number of Sectors to be transferred
+ //
+ Total_Number_Of_Sectors = ByteCount / SectorSize; //512
+ // If the caller is requesting less bytes than one sector, we need to
+ // allocate space for one sector.
+ if (!ReadWrite && ((ByteCount < SectorSize) && (ByteCount > 0))) {
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ SectorSize,
+ (VOID**)&TempBuffer );
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SectorGTBytes = TRUE;
+ Total_Number_Of_Sectors = 1;
+ } else {
+ TempBuffer = Buffer;
+ }
+
+ for (;
+ Total_Number_Of_Sectors > 0;
+ Total_Number_Of_Sectors -= MaxSectorCount )
+ {
+ if ( Total_Number_Of_Sectors > MaxSectorCount ) {
+ SectorCount = 0;
+ } else {
+ SectorCount = (UINT32) Total_Number_Of_Sectors;
+ }
+
+ Status = IssueAtaReadWriteCommand( IdeBusInterface,
+ LBA,
+ SectorCount,
+ Command,
+ Features );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Update LBA for next loop
+ //
+ if ( SectorCount ) {
+ LBA += SectorCount;
+ LoopCount = (SectorCount / BlockSize);
+ LoopCount += ((SectorCount % BlockSize) > 0 ? 1 : 0);
+ }
+ else {
+ LBA += MaxSectorCount;
+ LoopCount = Div64( MaxSectorCount, BlockSize, &Remainder );
+ LoopCount += (Remainder > 0 ? 1 : 0);
+ }
+
+ //
+ //Read Data
+ //
+ for (; LoopCount > 0; LoopCount -= 1 ) {
+ //
+ //Wait for Command completion
+ //
+ Status = WaitForCmdCompletion( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ //Check for DRQ
+ //
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ DRQ,
+ DRQ_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Calculate # of Words to be read/written
+ //
+
+ WordCount = SectorSize / 2;
+
+ if ( ReadWrite ) {
+
+ for ( i=0 ; i<Total_Number_Of_Sectors ;i++ ) {
+
+ Status = IdeWriteMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ WordCount,
+ TempBuffer );
+ ((UINT8*)TempBuffer) += SectorSize;
+ pBS->Stall(100); //10ms Delay after 1 sector write
+ }
+
+ } else {
+
+ for ( i=0 ; i<Total_Number_Of_Sectors ;i++ ) {
+
+ Status = IdeReadMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ WordCount,
+ TempBuffer );
+ (UINT8 *)TempBuffer += SectorSize;
+ pBS->Stall(100); //10ms Delay after 1 sector read
+
+ }
+ ((UINT8*)TempBuffer) -= Mul64( Total_Number_Of_Sectors, SectorSize);
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for errors.
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ &Data8 );
+
+ if ( Data8 & 0x21 ) { // ERR OR DF bit set ?
+ return EFI_DEVICE_ERROR;
+ }
+
+// ((UINT8*)TempBuffer) += (WordCount * 2);
+
+ if ( SectorCount ) {
+ SectorCount -= (WordCount * 2) / SectorSize;
+ }
+ else {
+ SectorCount = (UINT32) ( MaxSectorCount - ((WordCount * 2) / SectorSize));
+ }
+ }
+ }
+ if (SectorGTBytes) {
+ pBS->CopyMem( Buffer, TempBuffer, ByteCount);
+ pBS->FreePool( TempBuffer );
+ }
+
+ //
+ // Check for errors
+ //
+ Status = WaitForCmdCompletion( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IssueAtaReadWriteCommand
+//
+// Description: Issues ATA Read/Write Command
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// UINT64 LBA,
+// INT32 SectorCount,
+// UINT8 Command
+// UINT8 Features OPTIONAL
+//
+// Output:
+// EFI_STATUS
+// Modified:
+//
+// Referrals: AtaReadWritePio
+//
+// Notes:
+// 1. Select the drive.
+// 2. check if BSY and DRQ bits are zero.
+// 3. Issue the command.
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IssueAtaReadWriteCommand(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINT64 LBA,
+ IN INT32 SectorCount,
+ IN UINT8 Command,
+ IN UINT8 Features )
+{
+ EFI_STATUS Status;
+ IDE_DEVICE_INTERFACE *IdeDevice = &(IdeBusInterface->IdeDevice);
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Device = (IdeDevice->Device << 4);
+
+ //
+ // Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.DeviceReg, Device );
+
+ //
+ //Before Writing to Sector Count Reg, BSY and DRQ bit should be zero
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY | DRQ,
+ DRQ_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for DRDY
+ //
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ DRDY,
+ DRDY_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_TIMEOUT;
+ }
+
+ if ( Check48BitCommand( Command )) {
+ // 48 Bit LBA
+ // Write the Upper LBA DWORD and Upper byte of Sector Count
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.SectorCountReg,
+ (UINT8)( SectorCount >> 8 ));
+
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBALowReg,
+ (UINT8)Shr64( LBA, 24 ));
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAMidReg,
+ (UINT8) Shr64( LBA, 32 ));
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAHighReg,
+ (UINT8) Shr64( LBA, 40 ));
+
+ Device = (IdeDevice->Device << 4) | 0x40; // 48Bit LBA
+ }
+ else { // 28 Bit LBA
+ Device = ((UINT8) ((UINT32) LBA >> 24 ) & 0x0f) | (IdeDevice->Device << 4) | 0x40;
+ }
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ Device );
+
+ //
+ //Issue command
+ //
+ if ( Features ) {
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.FeatureReg, //SubCommand
+ Features );
+ }
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.SectorCountReg,
+ (UINT8) SectorCount );
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBALowReg,
+ (UINT8)LBA );
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAMidReg,
+ (UINT8) (((UINT32)LBA >> 8) & 0xff ));
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAHighReg,
+ (UINT8) (((UINT32)LBA >> 16) & 0xff ));
+
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.CommandReg,
+ Command );
+
+ //
+ //Wait for 400nsec for status to be available
+ //
+ pBS->Stall( 1 );
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeNonDataCommand
+//
+// Description: Issues command where no data transfer takes place
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINT32 ByteCount,
+// UINT8 SectorCount,
+// UINT8 LBALow,
+// UINT8 LBAMid,
+// UINT8 LBAHigh,
+// UINT8 Device,
+// UINT8 Command,
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals: IdeSetFeatureCommand
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeNonDataCommand(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINT8 Features,
+ IN UINT8 SectorCount,
+ IN UINT8 LBALow,
+ IN UINT8 LBAMid,
+ IN UINT8 LBAHigh,
+ IN UINT8 Device,
+ IN UINT8 Command )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.DeviceReg, Device );
+
+ //
+ //Wiat for DRDY to be set
+ //
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ DRDY,
+ DRDY_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_TIMEOUT;
+ }
+
+ //
+ //Issue the Command
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.FeatureReg,
+ Features );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.SectorCountReg,
+ SectorCount );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBALowReg,
+ LBALow );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAMidReg,
+ LBAMid );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAHighReg,
+ LBAHigh );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.CommandReg,
+ Command );
+
+ //
+ //Wait for 400nsec before reading the status. To accomplish it, read ATL_STATUS and ignore the result
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ //
+ //Check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY | DRQ,
+ gPlatformIdeProtocol->PoweonBusyClearTimeout );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for any errors
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.StatusReg, &Data8 );
+
+ if ( Data8 & (DF | ERR)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeNonDataCommandExp
+//
+// Description: Issues command where no data transfer takes place
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINT32 ByteCount,
+// UINT8 SectorCount,
+// UINT8 SectorCountExp,
+// UINT8 LBALow,
+// UINT8 LBALowExp,
+// UINT8 LBAMid,
+// UINT8 LBAMidExp,
+// UINT8 LBAHigh,
+// UINT8 LBAHighExp,
+// UINT8 Device,
+// UINT8 Command,
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals: IdeSetFeatureCommand
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeNonDataCommandExp(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINT8 Features,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorCountExp,
+ IN UINT8 LBALow,
+ IN UINT8 LBALowExp,
+ IN UINT8 LBAMid,
+ IN UINT8 LBAMidExp,
+ IN UINT8 LBAHigh,
+ IN UINT8 LBAHighExp,
+ IN UINT8 Device,
+ IN UINT8 Command )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.DeviceReg, Device );
+
+ //
+ //Wiat for DRDY to be set
+ //
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ DRDY,
+ DRDY_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_TIMEOUT;
+ }
+
+ // 48 Bit LBA
+ // Write the Upper LBA DWORD and Upper byte of Sector Count
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.SectorCountReg,
+ SectorCountExp);
+
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBALowReg,
+ LBALowExp);
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAMidReg,
+ LBAMidExp);
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAHighReg,
+ LBAHighExp);
+
+ //
+ //Issue the Command
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.FeatureReg,
+ Features );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.SectorCountReg,
+ SectorCount );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBALowReg,
+ LBALow );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAMidReg,
+ LBAMid );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAHighReg,
+ LBAHigh );
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.CommandReg,
+ Command );
+
+ //
+ //Wait for 400nsec before reading the status. To accomplish it, read ATL_STATUS and ignore the result
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ //
+ //Check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY | DRQ,
+ gPlatformIdeProtocol->PoweonBusyClearTimeout );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for any errors
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.StatusReg, &Data8 );
+
+ if ( Data8 & (DF | ERR)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtaIdentifyCommand
+//
+// Description: Issues IDENTIFY DATA command (0xEC)
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// IN OUT VOID *Buffer
+//
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals: AtaPioDataIn
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaIdentifyCommand(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer )
+{
+ EFI_STATUS Status = AtaPioDataIn(
+ IdeBusInterface,
+ Buffer,
+ 512,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ IDENTIFY_COMMAND,
+ FALSE );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AtapiIdentifyCommand
+//
+// Description: Issues IDENTIFY PACKET DATA command (0xA1)
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// IN OUT VOID *Buffer
+//
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals: AtaPioDataIn
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtapiIdentifyCommand(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer )
+{
+ return AtaPioDataIn(
+ IdeBusInterface,
+ Buffer,
+ 512, // Byte Count
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ IDENTIFY_PACKET_COMMAND,
+ FALSE );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: GetIdentifyData
+//
+// Description: Gets Identify command data.
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: ATA/ATAPI device type should have beeen known already.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetIdentifyData(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer )
+{
+ //
+ //check whether it is a ATA or ATAPI device
+ //
+ if ( IdeBusInterface->IdeDevice.DeviceType == ATAPI ) {
+ return AtaPioDataIn(
+ IdeBusInterface,
+ Buffer,
+ 512, // Byte Count
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ IDENTIFY_PACKET_COMMAND,
+ FALSE );
+ }
+ else {
+ EFI_STATUS Status = AtaPioDataIn(
+ IdeBusInterface,
+ Buffer,
+ 512,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ IDENTIFY_COMMAND,
+ FALSE );
+
+ return Status;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeSetFeatureCommand
+//
+// Description: Issue a ATA Non-Data Command
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IdeNonDataCommand
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeSetFeatureCommand(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 SubCommand,
+ UINT8 Mode )
+{
+ return IdeNonDataCommand(
+ IdeBusInterface,
+ SubCommand,
+ Mode,
+ 0,
+ 0,
+ 0,
+ IdeBusInterface->IdeDevice.Device << 4,
+ SET_FEATURE_COMMAND );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeSoftReset
+//
+// Description: Issue a Soft Reset
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: DetectIdeDevice
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeSoftReset(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ UINT8 Device = IdeBusInterface->IdeDevice.Device;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+
+ PROGRESS_CODE( DXE_IDE_RESET );
+
+ //
+ //Select the drive. Not needed.
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ Device << 4 );
+
+ //
+ //Read the status Register
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.StatusReg, &Data8 );
+
+ //
+ //If BSY bit set, don't issue Soft reset
+ //
+ if ( Data8 & 0x80 ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Assert SRST, disable nIEN
+ //
+ Data8 = SRST | nIEN;
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.DeviceControlReg,
+ Data8 );
+ pBS->Stall( 100 ); // 100 usec
+
+ //
+ //Deassert SRST
+ //
+ Data8 = nIEN;
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.DeviceControlReg,
+ Data8 );
+ pBS->Stall( 10000 ); // 10 msec
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: WaitForCmdCompletionWithTimeOutValue
+//
+// Description: Waits for BSY bit to get clear
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface
+// IN UINT32 TimeOutValue
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AtaReadWritePio
+//
+// Notes: Wait for BSY bit to get clear. Check for any errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitForCmdCompletionWithTimeOutValue(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINT32 TimeOutvalue )
+{
+ UINT8 Data8;
+ EFI_STATUS Status;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+
+ // Read ATL_STATUS and ignore the result. Just a delay
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ // if the Timeout Value is 0, check Busy bit to clear without Timeout Value.
+ // Otherwise Use the Timeout value to check the Busy bit to clear.
+ if ( TimeOutvalue == 0 ) {
+ //
+ //Check for BSY bit to be clear without Timout value
+ //
+ Status = WaitforBitClearWithoutTimeout(
+ IdeBusInterface->PciIO,
+ Regs.ControlBlock.
+ AlternateStatusReg,
+ BSY );
+ }
+ else {
+ //
+ //Check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY,
+ TimeOutvalue );
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //Check for errors.
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ &Data8 );
+
+ if ( Data8 & (ERR | DF)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: WaitForCmdCompletion
+//
+// Description: Waits for BSY bit to get clear
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AtaReadWritePio
+//
+// Notes: Wait for BSY bit to get clear. Check for any errors.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitForCmdCompletion(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ UINT8 Data8;
+ EFI_STATUS Status;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+
+ //
+ //Read ATL_STATUS and ignore the result. Just a delay
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ //
+ //Check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY,
+ COMMAND_COMPLETE_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for errors.
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.StatusReg, &Data8 );
+
+ if ( Data8 & (ERR | DF)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: DisableIdeInterrupt
+//
+// Description: Disabled Interrupt generation feature
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+void DisableIdeInterrupt(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8, Flags;
+
+ //
+ // Disable IEN
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+
+ //
+ //Clear interrupt status
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.BusMasterBlock.BMStatusRegister,
+ &Data8 );
+ Flags = Data8;
+ //
+ // Preserve DMA capabilities and set Interrupt bit
+ //
+ Data8 = (Data8 & 0x60);
+
+ if ( Flags & BM_INTERRUPT ) {
+ Data8 |= BM_INTERRUPT;
+ }
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.BusMasterBlock.BMStatusRegister,
+ Data8 );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CheckDriveReady
+//
+// Description: Check if BSY is cleared and DRDY set
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckDriveReady(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ IdeBusInterface->IdeDevice.Device << 4 );
+
+ //
+ //Read Alt Status
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.DeviceControlReg,
+ &Data8 );
+
+ if ((Data8 & 0xc0) == 0x40 ) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: WaitforBitSet
+//
+// Description: Checks for a particular Bit to be set for a given amount of time
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// UINT16 AlternateStatusReg,
+// UINT8 BitSet,
+// UINT32 TimeOut
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitforBitSet(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ UINT16 AlternateStatusReg,
+ UINT8 BitSet,
+ UINT32 TimeOut )
+{
+ UINT8 Delay;
+ UINT8 Data8;
+
+ for (; TimeOut > 0; TimeOut-- )
+ {
+ for ( Delay = 100; Delay > 0; Delay-- )
+ {
+ IdeReadByte( PciIO, AlternateStatusReg, &Data8 );
+
+ if ( Data8 & BitSet ) {
+ return EFI_SUCCESS;
+ }
+ pBS->Stall( 10 ); // 10usec
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: WaitforBitClear
+//
+// Description: Waits for the given bit to be clear
+//
+// Input:
+// UINT16 AlternateStatus,
+// UINT8 BitClear
+// UINT32 BUSY_CLEAR_TIMEOUT // Millisecond
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitforBitClear(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ UINT16 AlternateStatus,
+ UINT8 BitClear,
+ UINT32 Timeout )
+{
+ UINT8 Delay;
+ UINT8 Data8;
+
+ for (; Timeout > 0; Timeout-- )
+ {
+ for ( Delay = 100; Delay > 0; Delay-- )
+ {
+ IdeReadByte( PciIO, AlternateStatus, &Data8 );
+
+ if ( !(Data8 & BitClear)) {
+ return EFI_SUCCESS;
+ }
+ pBS->Stall( 10 ); // 10 Usec
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: WaitforBitClearWithoutTimeout
+//
+// Description: Waits for the given bit to be clear
+//
+// Input:
+// UINT16 AlternateStatus,
+// UINT8 BitClear
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitforBitClearWithoutTimeout(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ UINT16 AlternateStatus,
+ UINT8 BitClear )
+{
+ UINT8 Data8;
+
+ do
+ {
+ IdeReadByte( PciIO, AlternateStatus, &Data8 );
+
+ if ( !(Data8 & BitClear)) {
+ return EFI_SUCCESS;
+ }
+ pBS->Stall( 10 ); // 10 Usec
+ } while ( 1 );
+
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: ReturnMSBset
+//
+// Description: Returns the MOST significant Bit set.
+//
+// Input:
+// UINT32 Data
+//
+// Output:
+// UINT8
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8 ReturnMSBset(
+ UINT32 Data )
+{
+ UINT8 Index;
+ UINT8 Value = 0xFF;
+
+ for ( Index = 0; Index < 32; Index++ )
+ {
+ if ( Data & 1 ) {
+ Value = Index;
+ }
+ Data >>= 1;
+ }
+
+ return Value;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeReadByte
+//
+// Description: Reads 1 Byte of data from the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// OUT UINT8 *Data8
+//
+// Output:
+// OUT UINT8 *Data8
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeReadByte(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ OUT UINT8 *Data8 )
+{
+ PciIO->Io. Read(
+ PciIO,
+ EfiPciIoWidthFifoUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ 1,
+ Data8 );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeReadMultipleByte
+//
+// Description: Reads N Bytes of data from the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// IN UINT64 Count
+// OUT UINT8 *Data8
+//
+// Output:
+// OUT UINT8 *Data8
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeReadMultipleByte(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ OUT UINT8 *Data8 )
+{
+ EFI_STATUS Status;
+
+ Status = PciIO->Io.Read(
+ PciIO,
+ EfiPciIoWidthFifoUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ Count,
+ Data8 );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeReadWord
+//
+// Description: Reads 1 Word of data from the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// OUT UINT16 *Data16
+//
+// Output:
+// OUT UINT16 *Data16
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeReadWord(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ OUT UINT16 *Data16 )
+{
+ EFI_STATUS Status;
+
+ Status = PciIO->Io.Read(
+ PciIO,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ 1,
+ Data16 );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeReadMultipleWord
+//
+// Description: Reads N Word of data from the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// IN UINT32 Count (Count in WORDS)
+// OUT UINT8 *Data16
+//
+// Output:
+// OUT UINT16 *Data16
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeReadMultipleWord(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ OUT UINT16 *Data16 )
+{
+ EFI_STATUS Status;
+ UINT16 *Buffer = Data16;
+ BOOLEAN MemoryAllocated = FALSE;
+
+ //
+ //Allocate memory only if ADDRESS is not WORD aligned
+ //
+ if ((UINTN)Data16 & 1 ) {
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ Count * sizeof(UINT16),
+ (VOID**)&Buffer );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemoryAllocated = TRUE;
+ }
+
+ Status = PciIO->Io.Read(
+ PciIO,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ Count,
+ Buffer );
+
+ if ( MemoryAllocated ) {
+ pBS->CopyMem( Data16, Buffer, Count * sizeof(UINT16));
+ pBS->FreePool( Buffer );
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeWriteByte
+//
+// Description: Writes 1 Byte of data to the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// OUT UINT8 Data8
+//
+// Output:
+// OUT UINT8 *Data8
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeWriteByte(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT8 Data8 )
+{
+ PciIO->Io.Write(
+ PciIO,
+ EfiPciIoWidthFifoUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ 1,
+ &Data8 );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeWriteMultipleByte
+//
+// Description: Writes N Bytes of data to the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// IN UINT32 Count (Count in BYTES)
+// IN UINT8 *Data8
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeWriteMultipleByte(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ IN UINT8 *Data8 )
+{
+ EFI_STATUS Status;
+
+ Status = PciIO->Io.Write(
+ PciIO,
+ EfiPciIoWidthFifoUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ Count,
+ Data8 );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeWriteWord
+//
+// Description: Writes 1 word of data to the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// OUT UINT16 *Data16
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeWriteWord(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT16 Data16 )
+{
+ PciIO->Io.Write(
+ PciIO,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ 1,
+ &Data16 );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeWriteMultipleWord
+//
+// Description: Writes N Words of data to the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// IN UINT64 Count (Count in WORDS)
+// IN UINT16 *Data16
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// Count : # of WORDs to write
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeWriteMultipleWord(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ IN UINT16 *Data16 )
+{
+ EFI_STATUS Status;
+ UINT16 *Buffer = Data16;
+ BOOLEAN MemoryAllocated = FALSE;
+
+ //
+ // Allocate memory only if ADDRESS is not WORD aligned
+ //
+ if ((UINTN)Data16 & 1 ) {
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ Count * sizeof(UINT16),
+ (VOID**)&Buffer );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemoryAllocated = TRUE;
+
+ pBS->CopyMem( Buffer, Data16, Count * sizeof(UINT16));
+ }
+
+ Status = PciIO->Io.Write(
+ PciIO,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ Count,
+ Buffer );
+
+ if ( MemoryAllocated ) {
+ pBS->FreePool( Buffer );
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: IdeWriteDword
+//
+// Description: Writes 1 Dword of data to the IO port
+//
+// Input:
+// IN EFI_PCI_IO_PROTOCOL *PciIO,
+// IN UINT16 Register,
+// OUT UINT16 *Data16
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IdeWriteDword(
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Data32 )
+{
+ PciIO->Io.Write(
+ PciIO,
+ EfiPciIoWidthFifoUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Register,
+ 1,
+ &Data32 );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Check48BitCommand
+//
+// Description: Checks if the command is for 48-bit LBA
+//
+// Input:
+// IN UINT8 Command
+//
+// Output:
+// TRUE/FLASE
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN Check48BitCommand(
+ IN UINT8 Command )
+{
+ if ( Command == READ_SECTORS_EXT
+ || Command == READ_MULTIPLE_EXT
+ || Command == WRITE_SECTORS_EXT
+ || Command == WRITE_MULTIPLE_EXT
+ || Command == READ_DMA_EXT
+ || Command == WRITE_DMA_EXT ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/IdeBus/Atapi.c b/Core/EM/IdeBus/Atapi.c
new file mode 100644
index 0000000..7230aac
--- /dev/null
+++ b/Core/EM/IdeBus/Atapi.c
@@ -0,0 +1,1811 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/IdeBus/Atapi.c 23 8/16/12 3:24a Rajeshms $
+//
+// $Revision: 23 $
+//
+// $Date: 8/16/12 3:24a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/Atapi.c $
+//
+// 23 8/16/12 3:24a 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
+//
+// 22 11/08/11 5:16a Deepthins
+// [TAG] EIP74607
+// [Category] Improvement
+// [Description] Block IO Read/Write function, the alignment should be
+// proper. IoAlign value is 0 or 1 means that the buffer can be placed
+// anywhere in memory. Otherwise, IoAlign must be a power of 2, and the
+// requirement is that the start address of a buffer must be evenly
+// divisible by IoAlign with no remainder.
+// [Files] Ata.c, Atapi.c and AhciController.c
+//
+// 21 11/07/11 4:27a Deepthins
+// [TAG] EIP74607
+// [Category] Improvement
+// [Description] IoAlign values is 0 or 1 means that the buffer can be
+// placed anywhere in memory. Otherwise, IoAlign must be a power of 2, and
+// the requirement is that the start address of a buffer must be evenly
+// divisible by 2 to the power of IoAlign with no remainder.
+// [Files] Atapi.c
+//
+// 20 9/27/11 3:11a Rajeshms
+// [TAG] EIP69295
+// [Category] New Feature
+// [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
+//
+// 19 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
+//
+// 18 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
+//
+// 17 10/11/10 11:28a Krishnakumarg
+// [TAG] - EIP 43249
+// [Category] - IMPROVEMENT
+// [Severity] - Minor
+// [Symptom] - Non-Ascii character in comments causing build problem in
+// japanese XP
+// [RootCause]- Presence of Non-Ascii character
+// [Solution] - Remove Non-Ascii character present in the file
+// [Files] - IdeSecurity.c,IDESMM.c, InstallIdeSmi, Ata.c, Atapi.c,
+// IDEBusComponentName.c, IdeBusMaster.c, IdeHPA.c, IdePowerManagement.c
+//
+// 16 8/25/10 4:08a Rameshr
+// New Feature: EIP 37748
+// Description: Move all the IDEBus Source driver SDL token into IdeBus
+// Bin Driver.
+// FilesModified: All.
+//
+// 15 7/01/09 12:23p Rameshr
+// Coding Standard and File header updated.
+//
+// 14 6/22/09 11:38a Rameshr
+// Odd Type information Saved in Atapi Device Structure.
+// EIP:21548
+//
+// 13 9/30/08 4:43p Felixp
+// Bug fix(EIP 15310):Invalid error code (EFI_DEVICE_ERROR instead of
+// EFI_NO_MEDIA) was returned for removable devices with no media
+//
+// 11 8/07/08 10:05a Rameshraju
+// Interrupt cleared properly on Atapihandleerror.
+//
+// 10 4/22/08 4:29p Felixp
+// New status codes added
+//
+// 9 3/06/08 4:42p Ambikas
+//
+// 8 13/04/07 3:00p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 7 3/13/06 2:21a Felixp
+//
+// 6 3/07/06 8:41a Srinin
+// AtapiReset function returns EFI_SUCCESS
+//
+// 5 3/03/06 11:28a Srinin
+// To detect Media not found error, check for Sense key = 2, ASC = 3A
+// and ASCQ = 0/1/2.
+//
+// 4 1/09/06 11:36a Felixp
+//
+// 2 12/14/05 3:07p Srinin
+// For Read Capacity command, available Buffer size is set to 8.
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 9 10/21/05 1:38p Srinin
+// Fixed Media detection problem with slow CDROM.
+//
+// 8 10/06/05 12:59p Felixp
+//
+// 7 7/25/05 12:52p Srinin
+// Delay between successive "TestUnitReady" command changed to 10msec.
+//
+// 6 7/18/05 4:31p Felixp
+// 64-bit compatibility warnings removed
+//
+// 5 3/04/05 11:34a Mandal
+//
+// 4 2/24/05 12:21p Felixp
+// bug fix in AtapiBlkRead and AtapiBlkWrite functions:
+// EFI_INVALID_PARAMETER was returned when last block is read or written
+// to
+//
+// 3 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 2 1/05/05 11:21a Srinin
+// BusMaster and Password Support added.
+//
+// 1 12/10/04 1:01p Srinin
+// Initial Checkin of IdeBus Driver.
+//
+//
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ATAPI.C
+//
+// Description: Supports ATAPI devices
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#include "IdeBus.h"
+#include <Protocol\IdeBusBoard.h>
+
+//
+//External variables
+//
+extern PLATFORM_IDE_PROTOCOL *gPlatformIdeProtocol;
+extern EFI_GUID gEfiBlockIoProtocolGuid;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtapiReset
+//
+// Description: Issues ATAPI Reset command.
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN BOOLEAN ExtendedVerification
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IssueAtapiReset, InitIdeBlockIO
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtapiReset(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification )
+{
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtapiBlkRead
+//
+// Description: Read from the Atapi Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AtapiReadWritePio, InitIdeBlockIO
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtapiBlkRead(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer )
+{
+ UINTN DataN;
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((IDE_BLOCK_IO*)This)->IdeBusInterface;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = This->Media;
+ UINT32 BlockSize = BlkMedia->BlockSize;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+ UINTN BufferAddress;
+
+ //
+ //Check if Media Present
+ //
+ if ( BlkMedia->MediaPresent == FALSE ) {
+ Status = DetectAtapiMedia( IdeBusInterface );
+
+ if ( Status == EFI_SUCCESS ) {
+ return EFI_MEDIA_CHANGED;
+ }
+ return Status;
+ }
+
+ //
+ //Check if Media ID matches
+ //
+ if ( BlkMedia->MediaId != MediaId ) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if ( BufferSize == 0 ) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((BlkMedia->IoAlign > 1 ) && (BufferAddress % BlkMedia->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check whether the block size is multiple of BlkMedia->BlockSize
+ //
+ DataN = BufferSize % BlkMedia->BlockSize;
+
+ if ( DataN ) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Check for Valid start LBA #
+ if ( LBA > BlkMedia->LastBlock ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check for Valid End LBA #
+ //
+ DataN = BufferSize / BlkMedia->BlockSize;
+
+ if ( LBA + DataN > BlkMedia->LastBlock + 1 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( ( gPlatformIdeProtocol->IdeBusMasterSupport ) && ( gPlatformIdeProtocol->AtapiBusMasterSupport ) ) {
+ if ( DMACapable( IdeBusInterface )) {
+ Status = AtapiReadWriteBusMaster(
+ IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.ReadCommand,
+ FALSE );
+ return Status;
+ }
+ }
+
+
+ Status = AtapiReadWritePio( IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.ReadCommand,
+ FALSE );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtapiBlkWrite
+//
+// Description: Write to the Atapi Device
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+// IN UINT32 MediaId,
+// IN EFI_LBA LBA,
+// IN UINTN BufferSize,
+// OUT VOID *Buffer
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AtapiReadWritePio, InitIdeBlockIO
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtapiBlkWrite(
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer )
+{
+ UINTN DataN;
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((IDE_BLOCK_IO*)This)->IdeBusInterface;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = This->Media;
+ UINT32 BlockSize = BlkMedia->BlockSize;
+ UINTN BufferAddress;
+
+ //
+ // Check if Media Present
+ //
+ if ( BlkMedia->MediaPresent == FALSE ) {
+ Status = DetectAtapiMedia( IdeBusInterface );
+
+ if ( Status == EFI_SUCCESS ) {
+ return EFI_MEDIA_CHANGED;
+ }
+ return Status;
+ }
+
+ //
+ //Check if Media ID matches
+ //
+ if ( BlkMedia->MediaId != MediaId ) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if ( BufferSize == 0 ) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If IoAlign values is 0 or 1, means that the buffer can be placed
+ // anywhere in memory or else IoAlign value should be power of 2. To be
+ // properly aligned the buffer address should be divisible by IoAlign
+ // with no remainder.
+ //
+ (VOID *)BufferAddress = Buffer;
+ if((BlkMedia->IoAlign > 1 ) && (BufferAddress % BlkMedia->IoAlign)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check whether the block size is multiple of BlkMedia->BlockSize
+ //
+ DataN = BufferSize % BlkMedia->BlockSize;
+
+ if ( DataN ) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //
+ //Check for Valid start LBA #
+ //
+ if ( LBA > BlkMedia->LastBlock ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ //Check for Valid End LBA #
+ //
+ DataN = BufferSize / BlkMedia->BlockSize;
+
+ if ( LBA + DataN > BlkMedia->LastBlock + 1 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( ( gPlatformIdeProtocol->IdeBusMasterSupport ) && ( gPlatformIdeProtocol->AtapiBusMasterSupport ) ) {
+ if ( DMACapable( IdeBusInterface )) {
+ Status = AtapiReadWriteBusMaster(
+ IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.WriteCommand,
+ TRUE );
+ return Status;
+ }
+ }
+
+
+ Status = AtapiReadWritePio( IdeBusInterface,
+ Buffer,
+ BufferSize,
+ LBA,
+ IdeBusInterface->IdeDevice.WriteCommand,
+ TRUE );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtapiBlkFlush
+//
+// Description: Flush the cache
+//
+// Input:
+// IN EFI_BLOCK_IO_PROTOCOL *This,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeBlockIO
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtapiBlkFlush(
+ IN EFI_BLOCK_IO_PROTOCOL *This )
+{
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: DetectAtapiMedia
+//
+// Description: Detects whether a Media is present in the ATAPI Removable device or not.
+//
+// Input:
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeBlockIO
+//
+// Notes:
+// 1. Issue Read Capacity command for CDROM or Read Format command for other ATAPI devices.
+// 2. If step 1 is successfull, update last LBA, Block Size, Read/Write capable, Media ID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS DetectAtapiMedia(
+ IN OUT IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ UINT8 *InputData, *PacketBuffer, LoopCount;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+ UINT8 Current_Channel = IdeBusInterface->IdeDevice.Channel;
+ UINT8 Current_Device = IdeBusInterface->IdeDevice.Device;
+ EFI_BLOCK_IO_MEDIA *BlkMedia = IdeBusInterface->IdeBlkIo->BlkIo.Media;
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ UINT16 ByteCount = 256, Data16;
+ BOOLEAN ReadCapacity = FALSE;
+
+ PROGRESS_CODE( DXE_REMOVABLE_MEDIA_DETECT );
+
+ //
+ //Default Values
+ //
+ BlkMedia->MediaPresent = FALSE;
+ BlkMedia->LastBlock = 0x100; // Dummy value
+ IdeBusInterface->IdeDevice.ReadCommand = ATAPI_READ_10;
+ IdeBusInterface->IdeDevice.WriteCommand = ATAPI_WRITE_10;
+
+ Status = TestUnitReady( IdeBusInterface );
+
+ if ((Status != EFI_MEDIA_CHANGED) && (Status != EFI_SUCCESS)) {
+ return Status;
+ }
+
+ //
+ //Issue Read Capacity command
+ //
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ ByteCount,
+ (VOID**)&InputData );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ Status = pBS->AllocatePool( EfiBootServicesData, 16, (VOID**)&PacketBuffer );
+
+ if ( EFI_ERROR( Status )) {
+ pBS->FreePool( InputData );
+ return Status;
+ }
+
+ ZeroMemory( PacketBuffer, 16 );
+
+ //
+ //For CDROM use Read Capacity command else use Read Format Command
+ //
+ if ( AtapiDevice->DeviceType == CDROM_DEVICE ) {
+ BlkMedia->BlockSize = CDROM_BLOCK_SIZE;
+ AtapiDevice->BlockSize = BlkMedia->BlockSize;
+ PacketBuffer[0] = ATAPI_READ_CAPACITY;
+ PacketBuffer[1] = AtapiDevice->Lun << 5;
+ Data16 = 8;
+ }
+ else {
+ BlkMedia->BlockSize = LS120_BLOCK_SIZE;
+ AtapiDevice->BlockSize = BlkMedia->BlockSize;
+ PacketBuffer[0] = ATAPI_READ_FORMAT_CAPACITIES;
+ PacketBuffer[1] = AtapiDevice->Lun << 5;
+ PacketBuffer[7] = ByteCount >> 8;
+ PacketBuffer[8] = ByteCount & 0xff;
+ Data16 = ByteCount;
+ }
+
+ for ( LoopCount = 0; LoopCount < 5; LoopCount++ ) {
+ ByteCount = Data16;
+ ZeroMemory( InputData, ByteCount );
+ Status = GeneralAtapiCommandAndData( IdeBusInterface,
+ PacketBuffer,
+ InputData,
+ &ByteCount );
+
+ if ( PacketBuffer[0] == ATAPI_READ_FORMAT_CAPACITIES
+ && AtapiDevice->Atapi_Status == ILLEGAL_REQUEST ) {
+ //
+ //If the Read Format Capacities not supported by device, try
+ //ReadCapacity command
+ //
+ ZeroMemory( PacketBuffer, 16 );
+ BlkMedia->BlockSize = CDROM_BLOCK_SIZE; // Default size
+ AtapiDevice->BlockSize = BlkMedia->BlockSize;
+ PacketBuffer[0] = ATAPI_READ_CAPACITY;
+ PacketBuffer[1] = AtapiDevice->Lun << 5;
+ Data16 = 8;
+ ReadCapacity = TRUE;
+ }
+
+ if ( AtapiDevice->Atapi_Status == EFI_SUCCESS ) {
+ break;
+ }
+
+ if ( AtapiDevice->Atapi_Status == MEDIUM_NOT_PRESENT ) {
+ break;
+ }
+ }
+
+ if ( Status == EFI_SUCCESS ) {
+ if ( ReadCapacity == TRUE ) {
+ BlkMedia->LastBlock = InputData[0] << 24 | InputData[1] << 16
+ | InputData[2] << 8 | InputData[3];
+
+ BlkMedia->LastBlock--;
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->MediaId++;
+ BlkMedia->BlockSize = InputData[4] << 24 | InputData[5] << 16
+ | InputData[6] << 8 | InputData[7];
+
+ AtapiDevice->BlockSize = BlkMedia->BlockSize;
+ BlkMedia->ReadOnly = FALSE;
+ }
+ else if ( AtapiDevice->DeviceType == CDROM_DEVICE )
+ {
+ BlkMedia->LastBlock = InputData[0] << 24 | InputData[1] << 16
+ | InputData[2] << 8 | InputData[3];
+ BlkMedia->LastBlock--;
+ BlkMedia->BlockSize = CDROM_BLOCK_SIZE;
+ AtapiDevice->BlockSize = BlkMedia->BlockSize;
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->MediaId++;
+ BlkMedia->ReadOnly = TRUE;
+ }
+ else if ( InputData[8] != 3 ) // No media present
+ {
+ BlkMedia->LastBlock = InputData[4] << 24 | InputData[5] << 16
+ | InputData[6] << 8 | InputData[7];
+ BlkMedia->LastBlock--;
+ BlkMedia->MediaPresent = TRUE;
+ BlkMedia->MediaId++;
+ BlkMedia->BlockSize = InputData[9] << 16 | InputData[10] << 8
+ | InputData[11];
+ BlkMedia->ReadOnly = FALSE;
+ AtapiDevice->BlockSize = BlkMedia->BlockSize;
+ }
+
+ //
+ // Update ReadOnly Status
+ //
+ if ( AtapiDevice->DeviceType != CDROM_DEVICE ) {
+ ByteCount = 256;
+ ZeroMemory( PacketBuffer, 16 );
+ ZeroMemory( InputData, ByteCount );
+ PacketBuffer[0] = ATAPI_MODE_SENSE;
+ PacketBuffer[2] = RETURN_ALL_PAGES;
+ PacketBuffer[7] = ByteCount >> 8;
+ PacketBuffer[8] = ByteCount & 0xff;
+ Status = GeneralAtapiCommandAndData( IdeBusInterface,
+ PacketBuffer,
+ InputData,
+ &ByteCount );
+
+ if ((Status == EFI_SUCCESS) && (ByteCount > 8)) {
+ BlkMedia->ReadOnly = (InputData[3] & 0x80) != 0 ? TRUE : FALSE;
+ }
+ }
+
+ if(pST->Hdr.Revision >= 0x0002001F) {
+ //
+ // For Atapi Devices, Default set the 1 for logical blocks per PhysicalBlock
+ //
+ BlkMedia->LogicalBlocksPerPhysicalBlock=1;
+
+ //
+ // For Atapi Devices, Default value set to 0 for Lowest Aligned LBA
+ //
+ BlkMedia->LowestAlignedLba=0;
+
+ BlkMedia->OptimalTransferLengthGranularity=BlkMedia->BlockSize;
+ }
+ }
+
+ pBS->FreePool( InputData );
+ pBS->FreePool( PacketBuffer );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtapiInquiryData
+//
+// Description: Issues Atapi Inquiry Command and returns the DATA.
+//
+// Input:
+// IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface
+// UINT8 *InquiryData,
+// UINT32 *InquiryDataSize
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: InitIdeBlockIO
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtapiInquiryData(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ OUT UINT8 *InquiryData,
+ IN OUT UINT16 *InquiryDataSize )
+{
+ EFI_STATUS Status;
+ UINT8 *PacketBuffer;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+
+
+ Status = pBS->AllocatePool( EfiBootServicesData, 16, (VOID**)&PacketBuffer );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ ZeroMemory( PacketBuffer, 16 );
+ PacketBuffer[0] = ATAPI_INQUIRY;
+ PacketBuffer[1] = AtapiDevice->Lun << 5;
+ PacketBuffer[4] = (UINT8) *InquiryDataSize;
+ Status = GeneralAtapiCommandAndData( IdeBusInterface,
+ PacketBuffer,
+ InquiryData,
+ InquiryDataSize );
+ pBS->FreePool( PacketBuffer );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtapiReadWritePio
+//
+// Description: Read/Write data from/to the ATAPI device
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINTN ByteCount,
+// UINT64 LBA,
+// UINT8 ReadWriteCommand,
+// BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AtapiBlkRead, AtapiBlkWrite
+//
+// Notes:
+// 1. Prepare ATAPI Command Packet
+// 2. Check for errors. If Media_Change, detect the new atapi media if present and return status accordingly.
+// 3. Read/write data if the command packet is issues successfully.
+// 4. Repeat from step 1 untill all data has been read/written.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtapiReadWritePio(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE )
+{
+ EFI_STATUS Status;
+ INTN TotalNumberofBlocks;
+ INTN TransferLength;
+ UINT16 BytesRead;
+ UINTN BytesRemainingTobeRead;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+ VOID *TempBuffer = Buffer;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+
+ //
+ //Disable Interrupt
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+
+ //
+ //Check for CHK bit in status register before proceeding, if set give ATAPI reset
+ //
+ Status = CheckCHKonEntry( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ TotalNumberofBlocks = ByteCount / AtapiDevice->BlockSize;
+
+ for (; TotalNumberofBlocks > 0; TotalNumberofBlocks -= TransferLength ) {
+ //
+ //Clear the buffer
+ //
+ ZeroMemory( AtapiDevice->PacketBuffer, AtapiDevice->PacketSize );
+
+ //
+ //Calculate # of blocks to be transferred
+ //
+ if ( TotalNumberofBlocks > 0xffff ) {
+ TransferLength = 0xffff;
+ } else {
+ TransferLength = TotalNumberofBlocks;
+ }
+
+ // If the ATAPI device is old, below "ATAPI-3" standard, use one block
+ // per transfer. Some of the old devices don't update the ByteCount value
+ // before setting the DRQ bit. Instead of adding delay, we will transfer 1 block at a time.
+ // Even If this enabled, do it only for CDROM. LS120 write will be very slow if 1 block at time is written.
+ // if (IdeBusInterface->IdeDevice.IdentifyData.Major_Revision_80 < 3) TransferLength = 1;
+
+ // Update the buffer
+ AtapiDevice->PacketBuffer[0] = ReadWriteCommand;
+ AtapiDevice->PacketBuffer[1] = AtapiDevice->Lun << 5;
+ AtapiDevice->PacketBuffer[2] = ((UINT32) LBA) >> 24;
+ AtapiDevice->PacketBuffer[3] = ((UINT32) LBA) >> 16;
+ AtapiDevice->PacketBuffer[4] = ((UINT16) LBA) >> 8;
+ AtapiDevice->PacketBuffer[5] = ((UINT8) LBA) & 0xff;
+
+ AtapiDevice->PacketBuffer[7] = (UINT8)( TransferLength >> 8 ); // MSB
+ AtapiDevice->PacketBuffer[8] = (UINT8)( TransferLength & 0xff ); // LSB
+
+ BytesRemainingTobeRead = TransferLength * AtapiDevice->BlockSize;
+ Status = IssueAtapiPacketCommand( IdeBusInterface,
+ (UINT16*) AtapiDevice->PacketBuffer,
+ 0,
+ 0xffff );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ do
+ {
+ //
+ //Check for errors
+ //
+ Status = HandleAtapiError( IdeBusInterface );
+
+ if ( Status != EFI_SUCCESS ) {
+ //
+ //Check if Device is getting ready. If yes, wait till it gets ready
+ //
+ if ( AtapiDevice->Atapi_Status == BECOMING_READY ) {
+ Status = TestUnitReady( IdeBusInterface );
+ }
+
+ if ( Status == EFI_MEDIA_CHANGED ) {
+ Status = DetectAtapiMedia( IdeBusInterface );
+
+ // This may happen during initial power-up also. If ReinstallProtocol needs to be done,
+ // then differentiate between power-up nad other cases.
+ if ( Status == EFI_SUCCESS ) {
+ return EFI_MEDIA_CHANGED; // Return Media Change
+ }
+ }
+ return Status;
+ }
+
+ //Check if DRQ asserted, else DEVICE error. Since BSY is cleared (HandleAtapiError) when control comes to this
+ //place, a small delay is enough.
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ DRQ,
+ DRQ_SET_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( READWRITE ) {
+ Status = WriteAtapiData( IdeBusInterface,
+ TempBuffer,
+ &BytesRead );
+ }
+ else {
+ Status = ReadAtapiData( IdeBusInterface, TempBuffer, &BytesRead );
+ }
+
+ //
+ //Update pointer
+ //
+ (UINT8*) TempBuffer += BytesRead;
+ BytesRemainingTobeRead -= BytesRead;
+ } while ( BytesRemainingTobeRead );
+
+ LBA += TransferLength;
+ //
+ //Check for errors
+ //
+ Status = HandleAtapiError( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GeneralAtapiCommandAndData
+//
+// Description: Issues the ATAPI cammand and reads the data
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// UINT8 *PacketBuffer,
+// UINT8 *Buffer,
+// IN OUT UINT16 *ByteCount
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GeneralAtapiCommandAndData(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 *PacketBuffer,
+ UINT8 *Buffer,
+ IN OUT UINT16 *ByteCount )
+{
+ EFI_STATUS Status;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+
+ Status = IssueAtapiPacketCommand( IdeBusInterface,
+ (UINT16*)PacketBuffer,
+ 0,
+ *ByteCount );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ //Check for errors
+ //
+ Status = HandleAtapiError( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if ( *ByteCount ) {
+ //
+ //Check if DRQ asserted, else DEVICE error
+ //
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ DRQ,
+ DRQ_TIMEOUT );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Read the data
+ //
+ Status = ReadAtapiData( IdeBusInterface, Buffer, ByteCount );
+ //
+ //Check for errors
+ //
+ Status = HandleAtapiError( IdeBusInterface );
+ return Status;
+ } else {
+ *ByteCount = 0;
+ return Status;
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IssueAtapiPacketCommand
+//
+// Description: Issues ATAPI Packet command and send the packet.
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// UINT16 *PacketBuffer, // Pointer to packet
+// UINT16 ByteCount // Byte count Limit
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: The Packet Command and the packet are sent. Error is not analysed in this
+// Routine. Once the packet is sent successfully, EFI_SUCCESS is returned.
+// It is the callers responsibilty to check the status.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IssueAtapiPacketCommand(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINT16 *PacketBuffer,
+ IN UINT8 Features,
+ IN UINT16 ByteCount )
+{
+ IDE_DEVICE_INTERFACE *IdeDevice = &(IdeBusInterface->IdeDevice);
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+ UINT16 Data16;
+ EFI_STATUS Status;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+
+ //
+ // Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ IdeDevice->Device << 4 );
+ //
+ // Before Writing to any register check for BSY and DRQ bit. Should be zero
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY | DRQ,
+ gPlatformIdeProtocol->AtaPiBusyClearTimeout );
+
+ if ( EFI_ERROR( Status )) {
+ Status = IssueAtapiReset( IdeBusInterface, TRUE );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Write Feature register. No OVL and DMA
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.FeatureReg,
+ Features );
+
+ //
+ //Write Byte Count
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAMidReg,
+ (ByteCount & 0xff));
+
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAHighReg,
+ (ByteCount >> 8));
+
+ //
+ //Write Command Register
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.CommandReg,
+ PACKET_COMMAND );
+
+ // Wait for 400nsec before reading the status. To accomplish it, read ATL_STATUS and ignore the result.
+ // Assumption is, this call will take atleast 400nsec to complete.
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+ //
+ // Check for BSY bit to be clear 30msec
+ //
+ Data16 = 30;
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ BSY,
+ (UINT32) Data16 );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check for DRQ set
+ //
+ Status = WaitforBitSet( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ DRQ,
+ (UINT32) Data16 );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Write the Data
+ Status = IdeWriteMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ AtapiDevice->PacketSize / 2,
+ PacketBuffer );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IssueAtapiReset
+//
+// Description: Issues ATAPI Reset command
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface
+// IN BOOLEAN TESTUNITREADY
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// If TESTUNITREADY is TRUE, after ATAPI Reset, TestUnitReady command is issued.
+// Generally after DEVICE RESET command, ATAPI device respond to and command with
+// POWER ON RESET OCCURRED and followed by MEDIA CHANGE.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IssueAtapiReset(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN BOOLEAN TESTUNITREADY )
+
+{
+ IDE_DEVICE_INTERFACE *IdeDevice = &(IdeBusInterface->IdeDevice);
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+ EFI_STATUS Status;
+
+ PROGRESS_CODE( DXE_REMOVABLE_MEDIA_RESET );
+
+ //
+ // Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ IdeDevice->Device << 4 );
+
+ //
+ //Disable Interrupt
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+
+ //
+ //Issue Device reset Command
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.CommandReg,
+ DEVICE_RESET );
+
+ //
+ //Wait for 400nsec before reading the status. To accomplish it, read ATL_STATUS and ignore the result
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ //
+ //Check for BSY bit to be clear
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ BSY,
+ gPlatformIdeProtocol->AtaPiResetCommandTimeout );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAMidReg,
+ &Data8 );
+
+ if ( Data8 == (ATAPI_SIGNATURE & 0xff)) {
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.LBAHighReg,
+ &Data8 );
+
+ if ( Data8 == (ATAPI_SIGNATURE >> 8)) {
+ if ( TESTUNITREADY ) {
+ return TestUnitReady( IdeBusInterface );
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: HandleAtapiError
+//
+// Description: Handle Atapi error if any.
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: If DF and CHK bits are not set, return EFI_SUCCESS. If either
+// one of the bits are set, analyse the error and return appropraite
+// error message.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HandleAtapiError(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ IDE_DEVICE_INTERFACE *IdeDevice = &(IdeBusInterface->IdeDevice);
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+ UINT8 Data8;
+ EFI_STATUS Status;
+ UINT8 *SenseData;
+ UINT8 *SensePacket;
+ UINT16 BytesRead;
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ IdeDevice->Device << 4 );
+
+ //
+ //Read the status register
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ //
+ //Check if BSY clear else DEVICE error
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ BSY,
+ gPlatformIdeProtocol->AtaPiBusyClearTimeout );
+
+ IdeBusInterface->AtapiSenseDataLength = 0;
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Read the status register
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ //
+ //Check for DF
+ //
+ if ( Data8 & DF ) {
+ AtapiDevice->Atapi_Status = DEVICE_ERROR;
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ //Check for CHK
+ //
+ if ( Data8 & CHK ) {
+ AtapiDevice->Atapi_Status = DEVICE_ERROR;
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ 256,
+ (VOID**)&SenseData
+ );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ 16,
+ (VOID**)&SensePacket
+ );
+
+ if ( EFI_ERROR( Status )) {
+ pBS->FreePool( SenseData );
+ return Status;
+ }
+
+ //
+ //Update the buffer
+ //
+ ZeroMemory( SenseData, 256 );
+ ZeroMemory( SensePacket, 16 );
+
+ SensePacket[0] = ATAPI_REQUEST_SENSE;
+ SensePacket[4] = 0xff;
+
+ Status = IssueAtapiPacketCommand( IdeBusInterface,
+ (UINT16*) SensePacket,
+ 0,
+ 256 );
+
+ if ( EFI_ERROR( Status )) {
+ goto exit_HandleAtapiError;
+ }
+
+
+ //
+ //Wait for BSY to get cleared
+ //
+ Status = WaitforBitClear( IdeBusInterface->PciIO,
+ Regs.CommandBlock.StatusReg,
+ BSY,
+ gPlatformIdeProtocol->AtaPiBusyClearTimeout );
+
+ if ( EFI_ERROR( Status )) {
+ goto exit_HandleAtapiError;
+ }
+
+ //
+ //read the status register
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ Status = EFI_DEVICE_ERROR;
+
+ //
+ //Check for DF and CHK
+ //
+ if ( Data8 & (DF | CHK)) {
+ goto exit_HandleAtapiError_with_Reset;
+ }
+
+ //
+ //Check if DRQ asserted, else DEVICE error
+ //
+ if ( !(Data8 & DRQ)) {
+ goto exit_HandleAtapiError_with_Reset;
+ }
+
+ //
+ //Read the data
+ //
+ Status = ReadAtapiData( IdeBusInterface, (UINT16*)SenseData, &BytesRead );
+
+ Status = EFI_DEVICE_ERROR; // Default Value
+ AtapiDevice->Atapi_Status = DEVICE_ERROR;
+
+ //
+ // Store the SenseData whcih would be used by ScsiPassThruAtapi PassThru Interface.
+ //
+ pBS->CopyMem( IdeBusInterface->AtapiSenseData, SenseData, BytesRead);
+ IdeBusInterface->AtapiSenseDataLength = (UINT8)BytesRead;
+
+ if (((SenseData[2] & 0xf) == 2) && (SenseData[12] == 0x3a)) {
+ Status = EFI_NO_MEDIA;
+ AtapiDevice->Atapi_Status = MEDIUM_NOT_PRESENT;
+ }
+
+ if (((SenseData[2] & 0xf) == 2) && (SenseData[12] == 0x04)
+ && (SenseData[13] == 0x01)) {
+ Status = EFI_MEDIA_CHANGED;
+ AtapiDevice->Atapi_Status = BECOMING_READY;
+ }
+
+ if (((SenseData[2] & 0xf) == 6) && (SenseData[12] == 0x28)) {
+ Status = EFI_MEDIA_CHANGED;
+ AtapiDevice->Atapi_Status = MEDIA_CHANGED;
+ }
+
+ if (((SenseData[2] & 0xf) == 7) && (SenseData[12] == 0x27)) {
+ Status = EFI_WRITE_PROTECTED;
+ AtapiDevice->Atapi_Status = WRITE_PROTECTED_MEDIA;
+ }
+
+ if (((SenseData[2] & 0xf) == 6) && (SenseData[12] == 0x29)) {
+ AtapiDevice->Atapi_Status = POWER_ON_OR_DEVICE_RESET;
+ }
+
+ if (((SenseData[2] & 0xf) == 5) && (SenseData[0] == 0x70)) {
+ AtapiDevice->Atapi_Status = ILLEGAL_REQUEST;
+ }
+
+exit_HandleAtapiError:
+ pBS->FreePool( SenseData );
+ pBS->FreePool( SensePacket );
+ return Status;
+
+exit_HandleAtapiError_with_Reset:
+ IssueAtapiReset( IdeBusInterface, TRUE );
+ goto exit_HandleAtapiError;
+ }
+
+ AtapiDevice->Atapi_Status = EFI_SUCCESS;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: TestUnitReady
+//
+// Description: Issues Start/Stop unit Command
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS EFI_SUCCESS : If Media is accessible
+// EFI_NO_MEDIA
+// EFI_MEDIA_CHANGED
+// EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS TestUnitReady(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status;
+ UINT8 *Packet;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+ UINT16 ByteCount = 0;
+ UINT16 LoopCount;
+
+
+ Status = pBS->AllocatePool( EfiBootServicesData, 16, (VOID**)&Packet );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ ZeroMemory( Packet, 16 );
+ Packet[0] = ATAPI_TEST_UNIT_READY;
+ Packet[1] = AtapiDevice->Lun << 5;
+
+ for ( LoopCount = 0; LoopCount < 1000; LoopCount++ )
+ {
+ Status = GeneralAtapiCommandAndData( IdeBusInterface,
+ Packet,
+ NULL,
+ &ByteCount );
+
+ if ( Status == EFI_SUCCESS ) {
+ break;
+ }
+
+ if ( AtapiDevice->Atapi_Status == MEDIUM_NOT_PRESENT ) {
+ break;
+ }
+
+ if ( AtapiDevice->Atapi_Status == MEDIA_CHANGED ) {
+ break;
+ }
+ pBS->Stall( 10000 ); // 10msec
+ }
+
+ pBS->FreePool( Packet );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetOddType
+//
+// Description: Find the ODD device Type and return it
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// OUT UINT16 *OddType
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetOddType(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT UINT16 *OddType )
+{
+ EFI_STATUS Status;
+ UINT8 *PacketBuffer;
+ UINT8 *ProfileData;
+ UINT16 ProfileDataSize = 16;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+
+ Status = pBS->AllocatePool( EfiBootServicesData, 16, (VOID**)&PacketBuffer );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ Status = pBS->AllocatePool( EfiBootServicesData, 16, (VOID**)&ProfileData );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ ZeroMemory( ProfileData, 16 );
+ ZeroMemory( PacketBuffer, 16 );
+ PacketBuffer[0] = ATAPI_GET_CONFIGURATION;
+ //
+ // Get the Feature Discriptor.
+ //
+ PacketBuffer[1] = FEATURE_DISCRIPTOR;
+ //
+ // Get the Profile list
+ //
+ PacketBuffer[3] = GET_PROFILE_LIST;
+ //
+ // Responce Data Size
+ //
+ PacketBuffer[8] = 0x10;
+
+ Status = GeneralAtapiCommandAndData( IdeBusInterface,
+ PacketBuffer,
+ ProfileData,
+ &ProfileDataSize );
+
+ if ( !EFI_ERROR( Status )) {
+ //
+ // Get the Profile Number
+ //
+ *OddType = (UINT16 )(((ProfileData[sizeof(GET_CONFIGURATION_HEADER) + 4]) << 8)
+ + ProfileData[sizeof(GET_CONFIGURATION_HEADER) + 5] );
+ }
+
+ pBS->FreePool( PacketBuffer );
+ pBS->FreePool( ProfileData );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetOddLoadingType
+//
+// Description: Find the ODD Loading Type information and return it
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// OUT UINT16 *OddLoadingType
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetOddLoadingType(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT UINT8 *OddLoadingType )
+{
+ EFI_STATUS Status;
+ UINT8 *PacketBuffer;
+ UINT8 *ProfileData;
+ UINT16 ProfileDataSize = 16;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+
+ Status = pBS->AllocatePool( EfiBootServicesData, 16, (VOID**)&PacketBuffer );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ Status = pBS->AllocatePool( EfiBootServicesData, 16, (VOID**)&ProfileData );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ ZeroMemory( ProfileData, 16 );
+ ZeroMemory( PacketBuffer, 16 );
+ PacketBuffer[0] = ATAPI_GET_CONFIGURATION;
+ //
+ // Get the Feature Discriptor.
+ //
+ PacketBuffer[1] = FEATURE_DISCRIPTOR;
+ //
+ // Get the Removable Medium feature
+ //
+ PacketBuffer[3] = GET_REMOVEABLE_MEDIUM_FEATURE;
+ //
+ // Responce Data Size
+ //
+ PacketBuffer[8] = 0x10;
+
+ Status = GeneralAtapiCommandAndData( IdeBusInterface,
+ PacketBuffer,
+ ProfileData,
+ &ProfileDataSize );
+
+ if ( !EFI_ERROR( Status )) {
+ //
+ // Get the ODD Loading Type
+ //
+ *OddLoadingType=(UINT8 )(((ProfileData[sizeof(GET_CONFIGURATION_HEADER)+4]) & 0xE0) >> 5);
+ }
+
+ pBS->FreePool( PacketBuffer );
+ pBS->FreePool( ProfileData );
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CheckCHKonEntry
+//
+// Description: Check for CHK bit. If set Issue ATAPI reset.
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckCHKonEntry(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ IDE_DEVICE_INTERFACE *IdeDevice = &(IdeBusInterface->IdeDevice);
+ UINT8 Data8;
+
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DeviceReg,
+ IdeDevice ->Device << 4 );
+
+ //
+ //Disable Interrupt
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+
+ //
+ //Read Status
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ Regs.ControlBlock.AlternateStatusReg,
+ &Data8 );
+
+ if ( Data8 & CHK ) {
+ return (IssueAtapiReset( IdeBusInterface, TRUE ));
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ReadAtapiData
+//
+// Description: Read data from the data port based on Byte count value
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// OUT UINT8 AtapiCommand
+// OUT UINT16 *BytesRead
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadAtapiData(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ OUT void *Data,
+ OUT UINT16 *BytesRead )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+ UINT16 ByteCount = 0;
+ EFI_STATUS Status;
+
+ //
+ //Get the number of Bytes to read
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAHighReg, &Data8 );
+ ByteCount = Data8 << 8;
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAMidReg, &Data8 );
+ ByteCount |= Data8;
+
+ *BytesRead = ByteCount;
+ Status = IdeReadMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ ByteCount / 2,
+ Data );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: WriteAtapiData
+//
+// Description: Write data to the data port based on Byte count value
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// OUT UINT8 AtapiCommand
+// OUT UINT16 *BytesRead
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WriteAtapiData(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ OUT void *Data,
+ OUT UINT16 *BytesRead )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+ UINT16 ByteCount = 0;
+ EFI_STATUS Status;
+
+ //
+ //Get the number of Bytes to Write
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAHighReg, &Data8 );
+ ByteCount = Data8 << 8;
+ IdeReadByte( IdeBusInterface->PciIO, Regs.CommandBlock.LBAMidReg, &Data8 );
+ ByteCount |= Data8;
+
+ *BytesRead = ByteCount;
+ Status = IdeWriteMultipleWord( IdeBusInterface->PciIO,
+ Regs.CommandBlock.DataReg,
+ ByteCount / 2,
+ Data );
+
+ return Status;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/IdeBus/IDEBusComponentName.c b/Core/EM/IdeBus/IDEBusComponentName.c
new file mode 100644
index 0000000..95b8a2f
--- /dev/null
+++ b/Core/EM/IdeBus/IDEBusComponentName.c
@@ -0,0 +1,374 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/IdeBus/IDEBusComponentName.c 17 10/11/10 11:29a Krishnakumarg $
+//
+// $Revision: 17 $
+//
+// $Date: 10/11/10 11:29a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/IDEBusComponentName.c $
+//
+// 17 10/11/10 11:29a Krishnakumarg
+// [TAG] - EIP 43249
+// [Category] - IMPROVEMENT
+// [Severity] - Minor
+// [Symptom] - Non-Ascii character in comments causing build problem in
+// japanese XP
+// [RootCause]- Presence of Non-Ascii character
+// [Solution] - Remove Non-Ascii character present in the file
+// [Files] - IdeSecurity.c,IDESMM.c, InstallIdeSmi, Ata.c, Atapi.c,
+// IDEBusComponentName.c, IdeBusMaster.c, IdeHPA.c, IdePowerManagement.c
+//
+// 16 8/25/10 4:13a 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
+//
+// 15 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).
+//
+// 14 7/01/09 12:24p Rameshr
+// Coding Standard and File header updated.
+//
+// 13 3/04/08 7:51p Felixp
+//
+// 11 28/02/08 7:01p Anandakrishnanl
+// Changed the Protocol member as defined for IdeSecurity.
+//
+// 10 4/30/07 1:16p Srinin
+// Check for valid Child Controller handle added.
+//
+// 9 4/20/07 6:13p Felixp
+//
+// 8 13/04/07 3:02p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 7 4/10/07 9:05a Felixp
+// Bug fix: undeclared identifier
+//
+// 6 4/05/07 12:54p Srinin
+// IdeBusCtlGetControllerName modified to check for valid controller and
+// Child Handles.
+//
+// 5 3/13/06 2:21a Felixp
+//
+// 4 1/09/06 11:36a Felixp
+//
+// 2 12/14/05 3:11p Srinin
+// Component name will be returned if either BLOCK_IO or SECURITY
+// Protocol is installed on the device.
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 7 3/04/05 11:36a Mandal
+//
+// 6 2/02/05 2:10p Felixp
+//
+// 5 2/01/05 1:01p Srinin
+// Fixed Build errors when library is not used.
+//
+// 4 1/31/05 11:06a Srinin
+// Return proper ComponentName for IDE devices.
+//
+// 3 1/28/05 1:19p Felixp
+// IdeBus is linked together with CORE_DXE
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 12/10/04 1:01p Srinin
+// Initial Checkin of IdeBus Driver.
+//
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: IDEBusComponentName.c
+//
+// Description: Component Name Protocol Member Functions for IDE Bus.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+#include "IdeBus.h"
+#include <Protocol\IdeBusBoard.h>
+
+//
+//External variables
+//
+
+extern EFI_DRIVER_BINDING_PROTOCOL gIdeBusDriverBinding;
+extern PLATFORM_IDE_PROTOCOL *gPlatformIdeProtocol;
+extern EFI_GUID gSecurityModeProtocolGuid;
+static EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+
+extern BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2 );
+
+EFI_STATUS IdeBusCtlDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName );
+
+EFI_STATUS IdeBusCtlGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName );
+
+
+CHAR16 *gIdeBusDriverName = L"AMI IDE BUS Driver";
+CHAR16 *gIdeBusControllerName = L"PCI IDE Mass Storage Device";
+
+
+EFI_COMPONENT_NAME_PROTOCOL gIdeBusControllerDriverName = {
+ IdeBusCtlDriverName,
+ IdeBusCtlGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: IdeBusCtlDriverName
+//
+// DESCRIPTION: Retrieves a Unicode string that is the user readable name of
+// the EFI Driver.
+//
+//
+// PARAMETERS:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// Language - A pointer to a three character ISO 639-2 language identifier.
+// This is the language of the driver name that that the caller
+// is requesting, and it must match one of the languages specified
+// in SupportedLanguages. The number of languages supported by a
+// driver is up to the driver writer.
+// DriverName - A pointer to the Unicode string to return. This Unicode string
+// is the name of the driver specified by This in the language
+// specified by Language.
+//
+// RETURN:
+// EFI_SUCCES - The Unicode string for the Driver specified by This
+// and the language specified by Language was returned
+// in DriverName.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - DriverName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS IdeBusCtlDriverName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName )
+{
+ //
+ //Supports only English
+ //
+ if ( !Language || !DriverName ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ( !LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH) ) {
+ return EFI_UNSUPPORTED;
+ }
+ *DriverName = gIdeBusDriverName;
+ return EFI_SUCCESS;
+}
+
+//---------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// FUNCTION: IdeBusCtlGetControllerName
+//
+// DESCRIPTION: Retrieves a Unicode string that is the user readable name of
+// the controller that is being managed by an EFI Driver.
+//
+// PARAMETERS:
+// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+// ControllerHandle - The handle of a controller that the driver specified by
+// This is managing. This handle specifies the controller
+// whose name is to be returned.
+// ChildHandle - The handle of the child controller to retrieve the name
+// of. This is an optional parameter that may be NULL. It
+// will be NULL for device drivers. It will also be NULL
+// for a bus drivers that wish to retrieve the name of the
+// bus controller. It will not be NULL for a bus driver
+// that wishes to retrieve the name of a child controller.
+// Language - A pointer to a three character ISO 639-2 language
+// identifier. This is the language of the controller name
+// that that the caller is requesting, and it must match one
+// of the languages specified in SupportedLanguages. The
+// number of languages supported by a driver is up to the
+// driver writer.
+// ControllerName - A pointer to the Unicode string to return. This Unicode
+// string is the name of the controller specified by
+// ControllerHandle and ChildHandle in the language
+// specified by Language from the point of view of the
+// driver specified by This.
+//
+// RETURNS:
+// EFI_SUCCESS - The Unicode string for the user readable name in the
+// language specified by Language for the driver
+// specified by This was returned in DriverName.
+// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
+// EFI_HANDLE.
+// EFI_INVALID_PARAMETER - Language is NULL.
+// EFI_INVALID_PARAMETER - ControllerName is NULL.
+// EFI_UNSUPPORTED - The driver specified by This is not currently
+// managing the controller specified by
+// ControllerHandle and ChildHandle.
+// EFI_UNSUPPORTED - The driver specified by This does not support the
+// language specified by Language.
+//
+//<AMI_PHDR_END>
+//---------------------------------------------------------------------------
+EFI_STATUS IdeBusCtlGetControllerName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ SECURITY_PROTOCOL *IdeSecurityInterface;
+ UINTN j, InfoCount;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *pInfo;
+
+ Status = pBS->OpenProtocol( Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ NULL,
+ gIdeBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL );
+
+ if ( Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ //Supports only English
+ //
+ if ( !Language || !ControllerName ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( !LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ( ChildHandle == NULL ) {
+ *ControllerName = gIdeBusControllerName;
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Make sure the CHILD handle is really a child of controller
+ //
+ Status = pBS->OpenProtocolInformation(
+ Controller,
+ &(gPlatformIdeProtocol->gIdeControllerProtocolGuid),
+ &pInfo, &InfoCount
+ );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for ( j = 0; j < InfoCount; j++ )
+ {
+ if ( pInfo[j].Attributes != EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ) {
+ continue;
+ }
+
+ if ( pInfo[j].ControllerHandle == ChildHandle ) {
+ break;
+ }
+ }
+
+ if ( InfoCount ) {
+ pBS->FreePool( pInfo );
+ }
+
+ if ( j >= InfoCount ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ //Open the BLOCK_IO protocol installed on the child device.
+ //
+ Status = pBS->OpenProtocol( ChildHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID**)&BlkIo,
+ gIdeBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+
+ if ( EFI_ERROR( Status )) {
+ //
+ //If BLKIO protocol is not installed, maybe Securitymode protocol is installed.
+ //
+ Status = pBS->OpenProtocol( ChildHandle,
+ &gSecurityModeProtocolGuid,
+ (VOID**)&IdeSecurityInterface,
+ gIdeBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+
+ //
+ //Return Error.
+ //
+ if ( EFI_ERROR( Status )) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeBusInterface = IdeSecurityInterface->BusInterface;
+ }
+ else {
+ IdeBusInterface = ((IDE_BLOCK_IO*)BlkIo)->IdeBusInterface;
+ }
+
+ if ( IdeBusInterface->IdeDeviceHandle != ChildHandle ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *ControllerName = IdeBusInterface->IdeDevice.UDeviceName->UnicodeString;
+ return EFI_SUCCESS;
+ }
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
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 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/IdeBus/IdeBus.chm b/Core/EM/IdeBus/IdeBus.chm
new file mode 100644
index 0000000..5b8094a
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBus.chm
Binary files differ
diff --git a/Core/EM/IdeBus/IdeBus.cif b/Core/EM/IdeBus/IdeBus.cif
new file mode 100644
index 0000000..73a732d
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBus.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "IdeBus"
+ category = ModulePart
+ LocalRoot = "Core\EM\IdeBus\"
+ RefName = "IdeBus"
+[files]
+"IdeBus.sdl"
+"IdeBus.mak"
+"IdeBus.chm"
+[parts]
+"IDEBusProtocol"
+"IdeBusBoard"
+<endComponent>
diff --git a/Core/EM/IdeBus/IdeBus.h b/Core/EM/IdeBus/IdeBus.h
new file mode 100644
index 0000000..7b77dbf
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBus.h
@@ -0,0 +1,821 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, 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.h 29 7/20/12 6:14a Anandakrishnanl $
+//
+// $Revision: 29 $
+//
+// $Date: 7/20/12 6:14a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/IdeBus.h $
+//
+// 29 7/20/12 6:14a 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
+//
+// 28 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
+//
+// 27 9/27/11 3:14a 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
+//
+// 26 4/12/11 4:06a 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
+//
+// 25 12/23/10 3:55a 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
+//
+// 24 11/08/10 6:11p Felixp
+// The Core source files are updated to remove upper ASCII characters
+// (above 128)
+// from the comment blocks. The characters caused build errors
+// with Japanese version of Microsoft compiler.
+//
+// 23 8/25/10 4:14a 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
+//
+// 22 7/01/09 12:22p Rameshr
+// Coding Standard and File header updated.
+//
+// 21 6/22/09 11:39a Rameshr
+// Odd Type information Saved in Atapi Device Structure.
+// EIP:21548
+//
+// 20 5/01/09 5:17p Felixp
+// Prototype for WaitForCmdCompletionWithTimeOutValue is added to resolve
+// compilation error.
+//
+// 19 7/03/08 5:40p Anandakrishnanl
+// Removed Smart related Definitions and Function Prototypes since Smart
+// feature is in Seperate Driver Now.
+//
+// 16 28/02/08 7:00p Anandakrishnanl
+// Removed few definitions and function declarations and moved to
+// IdeSecurity module.
+//
+// 15 10/23/07 4:16p Felixp
+// IDE Security support moved from Sources to Binary
+//
+// 14 14/08/07 1:51p Anandakrishnanl
+// Changes made for password storing in NVRAM which converts HDD dataInfo
+// to string in ConvertHddDataIdToString function.
+//
+// 13 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.
+//
+// 12 13/04/07 3:02p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with "AMI coding
+// standard"!!!
+//
+// 11 2/12/07 3:39p Pats
+// Increased POWERON_BUSY_CLEAR_TIMEOUT to 10 sec.
+//
+// 10 11/17/06 2:58p Ambikas
+//
+// 9 10/27/06 4:20p Felixp
+// Reverted back to the previous version
+//
+// 7 8/24/06 9:30a Felixp
+// x64 support (bug fixes)
+//
+// 5 3/13/06 2:20a Felixp
+//
+// 4 1/09/06 11:36a Felixp
+//
+// 2 12/14/05 3:02p Srinin
+// HDD password related equates added.
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 10 11/03/05 10:41a Srinin
+// VC7 compilation error fixed.
+//
+// 9 3/04/05 11:33a Mandal
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: IdeBus.h
+//
+// Description: This file contains the Includes, Definitions, typedefs,
+// Variable and External Declarations, Structure and
+// function prototypes needed for the IdeBus driver
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#ifndef _IdeBus_
+#define _IdeBus_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Efi.h>
+#include <Token.h>
+#include <Dxe.h>
+#include <AmiDxeLib.h>
+#include "Protocol\PciIo.h"
+#include "Protocol\DevicePath.h"
+#include "protocol\DriverBinding.h"
+#include "protocol\BlockIo.h"
+#include "Protocol\PDiskInfo.h"
+#include "Protocol\PIDEController.h"
+#include "Protocol\PIDEBus.h"
+#include <Protocol\ComponentName.h>
+#include <Protocol\BootScriptSave.h>
+#include <protocol\AtaPassThru.h>
+
+
+#define IDE_BUS_DRIVER_VERSION 0x01
+
+#define PRIMARY_COMMAND_BLOCK 0x1F0
+#define PRIMARY_CONTROL_BLOCK 0x3F6
+#define SECONDARY_COMMAND_BLOCK 0x170
+#define SECONDARY_CONTROL_BLOCK 0x376
+
+#define BUSY_CLEAR_TIMEOUT 1000 // 1Sec
+#define DRDY_TIMEOUT 1000 // 1Sec
+#define DRQ_TIMEOUT 10 // 10msec
+#define DRQ_CLEAR_TIMEOUT 1000 // 1sec
+#define DRQ_SET_TIMEOUT 10 // 10msec
+#define HP_COMMAND_COMPLETE_TIMEOUT 2000 // 2Sec
+#define COMMAND_COMPLETE_TIMEOUT 5000 // 5Sec
+
+#define BLKIO_REVISION 1
+
+#define DEVICE_DISABLED 0
+#define DEVICE_IN_RESET_STATE 1
+#define DEVICE_DETECTION_FAILED 2
+#define DEVICE_DETECTED_SUCCESSFULLY 3
+#define DEVICE_CONFIGURED_SUCCESSFULLY 4
+#define DEVICE_REMOVED 5
+#define CONTROLLER_NOT_PRESENT 0xff
+
+#define ENUMERATE_ALL 0xff
+#define ENUMERATE_PRIMARY_MASTER 0x0
+#define ENUMERATE_PRIMARY_SLAVE 0x1
+#define ENUMERATE_SECONDARY_MASTER 0x2
+#define ENUMERATE_SECONDARY_SLAVE 0x3
+#define INQUIRY_DATA_LENGTH 0x96
+#define READ_CAPACITY_DATA_LENGTH 0x08
+
+// PCI Config Space equates
+#define PROGRAMMING_INTERFACE_OFFSET 0x09
+#define IDE_SUB_CLASS_CODE 0x0A
+#define SCC_IDE_CONTROLLER 0x01
+#define SCC_AHCI_CONTROLLER 0x06
+#define SCC_RAID_CONTROLLER 0x04
+#define IDE_BASE_CLASS_CODE 0x0B
+#define BASE_CODE_IDE_CONTROLLER 0x01
+#define PRIMARY_COMMAND_BLOCK_OFFSET 0x10
+#define PRIMARY_CONTROL_BLOCK_OFFSET 0x14
+#define SECONDARY_COMMAND_BLOCK_OFFSET 0x18
+#define SECONDARY_CONTROL_BLOCK_OFFSET 0x1C
+#define LEGACY_BUS_MASTER_OFFSET 0x20
+
+#define EFI_SUCCESS_ACTIVE_SET 0x80000000
+#define ZeroMemory( Buffer, Size ) pBS->SetMem( Buffer, Size, 0 )
+
+
+//###DEBUG Uncomment the following for Required Debug Level.
+
+//#define Debug_Level_1
+//#define Debug_Level_2
+//#define Debug_Level_3
+
+//###DEBUG END
+
+// Forward reference for pure ANSI compatability
+typedef struct _IDE_BUS_PROTOCOL IDE_BUS_PROTOCOL;
+
+typedef struct
+{
+ UINT32 Lowdword;
+ UINT32 Upperdword;
+} STRUCT_U64_U32;
+
+VOID EfiDebugPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ ... );
+
+EFI_STATUS CreateIdeDevicePath (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface,
+ IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ UINT8 Current_Channel,
+ UINT8 Current_Device );
+
+EFI_STATUS InitIdeBlockIO (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS InitIdeDiskInfo (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS
+InstallBusInitProtocol(
+ IN EFI_HANDLE Controller,
+ IDE_BUS_INIT_PROTOCOL * IdeBusInitInterface,
+ VOID * IdeControllerInterface
+ );
+
+EFI_STATUS
+ConfigureIdeDeviceAndController(
+ IDE_BUS_PROTOCOL * IdeBusInterface,
+ VOID * IdeControllerInterface,
+ IDE_BUS_INIT_PROTOCOL * IdeBusInitInterface
+ );
+
+UINT8 ReturnMSBset (
+ UINT32 Data );
+
+EFI_STATUS IdeReadByte (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ OUT UINT8 *Data8 );
+
+EFI_STATUS IdeReadMultipleByte (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ OUT UINT8 *Data8 );
+
+EFI_STATUS IdeReadWord (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ OUT UINT16 *Data16 );
+
+EFI_STATUS IdeReadMultipleWord (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ OUT UINT16 *Data16 );
+
+EFI_STATUS IdeWriteByte (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT8 Data8 );
+
+EFI_STATUS IdeWriteMultipleByte (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ IN UINT8 *Data8 );
+
+EFI_STATUS IdeWriteWord (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT16 Data16 );
+
+EFI_STATUS IdeWriteMultipleWord (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Count,
+ IN UINT16 *Data16 );
+
+EFI_STATUS IdeWriteDword (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ IN UINT16 Register,
+ IN UINT32 Data32 );
+
+EFI_STATUS AtaReadWritePio (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ VOID *Buffer,
+ UINTN ByteCount,
+ UINT64 LBA,
+ UINT8 readWriteCommand,
+ BOOLEAN ReadWrite );
+
+EFI_STATUS IssueAtaReadWriteCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT64 LBA,
+ INT32 SectorCount,
+ UINT8 Command,
+ UINT8 Features );
+
+EFI_STATUS AtaPioDataIn (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ VOID *Buffer,
+ UINT32 ByteCount,
+ UINT8 Features,
+ UINT8 SectorCount,
+ UINT8 LBALow,
+ UINT8 LBAMid,
+ UINT8 LBAHigh,
+ UINT8 DeviceReg,
+ UINT8 Command,
+ BOOLEAN Multiple );
+
+EFI_STATUS AtaPioDataOut (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ VOID *Buffer,
+ UINTN ByteCount,
+ UINT8 Features,
+ UINT32 SectorCountIn,
+ UINT8 LBALow,
+ UINT8 LBALowExp,
+ UINT8 LBAMid,
+ UINT8 LBAMidExp,
+ UINT8 LBAHigh,
+ UINT8 LBAHighExp,
+ UINT8 Device,
+ UINT8 Command,
+ BOOLEAN ReadWrite,
+ BOOLEAN Multiple );
+
+EFI_STATUS IdeNonDataCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 Features,
+ UINT8 SectorCount,
+ UINT8 LBALow,
+ UINT8 LBAMid,
+ UINT8 LBAHigh,
+ UINT8 Device,
+ UINT8 Command );
+
+EFI_STATUS IdeNonDataCommandExp (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 Features,
+ UINT8 SectorCount,
+ UINT8 SectorCountExp,
+ UINT8 LBALow,
+ UINT8 LBALowExp,
+ UINT8 LBAMid,
+ UINT8 LBAMidExp,
+ UINT8 LBAHigh,
+ UINT8 LBAHighExp,
+ UINT8 Device,
+ UINT8 Command );
+
+EFI_STATUS AtaIdentifyCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer );
+
+EFI_STATUS AtapiIdentifyCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer );
+
+EFI_STATUS GetIdentifyData (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer );
+
+EFI_STATUS IdeSetFeatureCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 SubCommand,
+ UINT8 Mode );
+
+EFI_STATUS IdeSoftReset (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS WaitForCmdCompletion (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS WaitForCmdCompletionWithTimeOutValue (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINT32 TimeOutvalue );
+
+EFI_STATUS CheckDriveReady (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS WaitforBitSet (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ UINT16 AlternateStatusReg,
+ UINT8 BitSet,
+ UINT32 TimeOut );
+
+EFI_STATUS WaitforBitClear (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ UINT16 AlternateStatus,
+ UINT8 BitSet,
+ UINT32 Timeout );
+
+EFI_STATUS WaitforBitClearWithoutTimeout (
+ IN EFI_PCI_IO_PROTOCOL *PciIO,
+ UINT16 AlternateStatus,
+ UINT8 BitClear );
+
+EFI_STATUS ControllerPresence (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+void DisableIdeInterrupt (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS DetectIdeDevice (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS ConfigureIdeDevice (
+ IDE_BUS_PROTOCOL *IdeBusInterface,
+ IDE_BUS_INIT_PROTOCOL *IdeBusInitInterface );
+
+EFI_STATUS InitAcousticSupport (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS UpdateBaseAddress (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS IdeBusSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS IdeBusStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS IdeBusStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer );
+
+EFI_STATUS AtaReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification );
+
+EFI_STATUS AtaBlkRead (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer );
+
+EFI_STATUS AtaBlkWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer );
+
+EFI_STATUS AtaBlkFlush (
+ IN EFI_BLOCK_IO_PROTOCOL *This );
+
+EFI_STATUS AtapiReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification );
+
+EFI_STATUS AtapiBlkRead (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer );
+
+EFI_STATUS AtapiBlkWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer );
+
+EFI_STATUS AtapiBlkFlush (
+ IN EFI_BLOCK_IO_PROTOCOL *This );
+
+EFI_STATUS DetectAtapiMedia (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS AtapiInquiryData (
+ IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 *InquiryData,
+ IN OUT UINT16 *InquiryDataSize );
+
+EFI_STATUS AtapiReadWritePio (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ VOID *Buffer,
+ UINTN ByteCount,
+ UINT64 LBA,
+ UINT8 ReadWriteCommand,
+ BOOLEAN READWRITE );
+
+EFI_STATUS AtapiWritePio (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ VOID *Buffer,
+ UINTN ByteCount,
+ UINT64 LBA,
+ UINT8 WriteCommand );
+
+EFI_STATUS GeneralAtapiCommandAnddData (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 *Buffer,
+ UINT16 ByteCount );
+
+EFI_STATUS IssueAtapiPacketCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT16 *PacketBuffer,
+ UINT8 Features,
+ UINT16 ByteCount );
+
+EFI_STATUS IssueAtapiReset (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN BOOLEAN TESTUNITREADY );
+
+EFI_STATUS HandleAtapiError (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS DiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize );
+
+EFI_STATUS DiskInfoIdentify (
+ EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize );
+
+EFI_STATUS DiskInfoSenseData (
+ EFI_DISK_INFO_PROTOCOL *This,
+ VOID *SenseData,
+ UINT32 *SenseDataSize,
+ UINT8 *SenseDataNumber );
+
+EFI_STATUS DiskInfoWhichIDE (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice );
+
+EFI_STATUS GetOddType (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT UINT16 *OddType );
+
+EFI_STATUS GetOddLoadingType(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT UINT8 *OddLoadingType );
+
+ODD_TYPE GetEnumOddType (
+ IN UINT16 OddType );
+
+BOOLEAN Check48BitCommand (
+ UINT8 Command );
+
+EFI_STATUS StartStopUnitCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINT8 LoEjStart );
+
+EFI_STATUS TestUnitReady (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS CheckCHKonEntry (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS ReadAtapiData (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ void *Data,
+ UINT16 *BytesRead );
+
+EFI_STATUS WriteAtapiData (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ OUT void *Data,
+ OUT UINT16 *BytesRead );
+
+EFI_STATUS GeneralAtapiCommandAndData (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 *PacketBuffer,
+ UINT8 *Buffer,
+ UINT16 *ByteCount );
+
+EFI_STATUS AtaReadWriteBusMaster (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN ReadWrite );
+
+EFI_STATUS AtapiReadWriteBusMaster (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE );
+
+EFI_STATUS CreateDescriptorTable (
+ IN OUT UINTN *DescriptorBuffer,
+ IN UINT8 *StartAddress,
+ IN UINTN ByteCount,
+ OUT UINTN *RemainingByteCount );
+
+EFI_STATUS InitBusMasterRegisters (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT UINTN DescriptorBuffer,
+ IN BOOLEAN ReadWrite );
+
+EFI_STATUS StartStopBusMastering (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN BOOLEAN StartStop );
+
+EFI_STATUS WaitforDMAtoCompletion (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINTN TimeDelay );
+
+BOOLEAN DMACapable (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS HandleATABMErrors (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS MaskandSaveInterrupt (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS RestoreInterrupt (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+void PrintIdeDeviceInfo (
+ IDE_BUS_PROTOCOL *IdeBusInterface );
+
+//---------------------------------------------------------------------------
+// IDE POWER MANAGEMENT SUPPORT START
+//---------------------------------------------------------------------------
+
+
+EFI_STATUS InitIDEPowerManagement (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+UINT8 ConvertStanbyTimeoutValue (
+ IN UINT8 StandbyTimeout );
+
+EFI_STATUS InstallIDEPowerMgmtInterface (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS StopIDEPowerMgmtInterface (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+
+// IDE POWER MANAGEMENT INTERFACE SUPPORT START
+//---------------------------------------------------------------------------
+
+EFI_STATUS CheckPowerMode (
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN OUT UINT8 *PowerMode );
+
+EFI_STATUS IdleMode (
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN UINT8 StandbyTimeout );
+
+EFI_STATUS StandbyMode (
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN UINT8 StandbyTimeout );
+
+EFI_STATUS AdvancePowerMgmtMode (
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN UINT8 AdvPowerMgmtLevel );
+
+// IDE POWER MANAGEMENT INTERFACE SUPPORT END
+//---------------------------------------------------------------------------
+// IDE POWER MANAGEMENT SUPPORT END
+//---------------------------------------------------------------------------
+
+// HOST PROTECTED AREA SUPPORT START
+//---------------------------------------------------------------------------
+
+
+EFI_STATUS InstallHPAInterface (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS StopHPAInterface (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS GetNativeMaxAddress (
+ IN IDE_HPA_INTERFACE *This,
+ OUT UINT64 *LBA );
+
+EFI_STATUS SetMaxAddress (
+ IN IDE_HPA_INTERFACE *This,
+ OUT UINT64 LBA,
+ IN BOOLEAN Volatile );
+
+EFI_STATUS HPADisabledLastLBA (
+ IN IDE_HPA_INTERFACE *This,
+ OUT UINT64 *LBA
+);
+
+EFI_STATUS SetMaxPassword (
+ IN IDE_HPA_INTERFACE *This,
+ IN UINT8 *PasswordBuffer );
+
+EFI_STATUS SetMaxLock (
+ IN IDE_HPA_INTERFACE *This );
+
+EFI_STATUS SetMaxUnLock (
+ IN IDE_HPA_INTERFACE *This,
+ IN UINT8 *PasswordBuffer );
+
+EFI_STATUS SetMaxFreezeLock (
+ IN IDE_HPA_INTERFACE *This );
+
+EFI_STATUS IssueSetMaxPasswordCmd (
+ IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 *PasswordBuffer,
+ UINT8 Cmd );
+
+// HOST PROTECTED AREA SUPPORT END
+//---------------------------------------------------------------------------
+
+// IDE HP SUPPORT START
+//---------------------------------------------------------------------------
+
+VOID IdeHPTimer (
+ IN EFI_EVENT Event,
+ IN VOID *Context );
+
+EFI_STATUS CheckHPControllerPresence (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+EFI_STATUS FlagDeviceRemoval (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+// IDE HP SUPPORT END
+//---------------------------------------------------------------------------
+EFI_STATUS IssueFreezeLockCommand (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+EFI_STATUS ReturnSecurityStatusWrapper (
+ IN IDE_SECURITY_PROTOCOL *This,
+ UINT16 *SecurityStatus );
+
+EFI_STATUS InstallIdeFeatures (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+VOID UnInstallIdeFeatures (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface );
+
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/IdeBus/IdeBus.mak b/Core/EM/IdeBus/IdeBus.mak
new file mode 100644
index 0000000..e904cc9
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBus.mak
@@ -0,0 +1,114 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+# $Header: /Alaska/BIN/Core/Modules/IdeBus/IdeBus.mak 8 8/25/10 5:35a Rameshr $
+#
+# $Revision: 8 $
+#
+# $Date: 8/25/10 5:35a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Core/Modules/IdeBus/IdeBus.mak $
+#
+# 8 8/25/10 5:35a 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
+#
+# 7 7/01/09 12:25p Rameshr
+# Coding Standard and File header updated.
+#
+# 6 3/04/08 7:50p Felixp
+#
+# 4 28/02/08 7:10p Anandakrishnanl
+# Moved the files from IdeBus to the Security module.
+#
+# 3 10/24/07 2:53p Felixp
+#
+# 2 10/23/07 4:18p Felixp
+# IDE Security support moved from Sources to Binary
+# IDE Security Setup screen added
+#
+# 1 12/01/05 9:38a Felixp
+#
+# 2 2/11/05 5:49p Felixp
+# Binary files organization improved:
+# - extra layer of sub-component removed
+# - macros initialization moved to SDL tokens to eliminate undefined
+# macros situation
+# - debug and release binaries have different names now (workaround for
+# VeB limitation)
+# - binaries reside in the component home directory (eliminates
+# hardcoded paths)
+#
+# 1 1/28/05 12:45p Felixp
+#
+# 4 1/18/05 3:22p Felixp
+# PrintDebugMessage renamed to Trace
+#
+# 3 12/24/04 3:25p Felixp
+#
+# 2 12/24/04 3:24p Felixp
+#
+# 1 12/10/04 1:01p Srinin
+# Initial Checkin of IdeBus Driver.
+#
+#
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: IDEBUS_mak
+#
+# Description:IdeBus BIN make file.
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+
+CORE_DXEBin : $(BUILD_DIR)\IdeBusBin.lib
+
+$(BUILD_DIR)\IdeBusBin.lib : IdeBusBin
+
+IdeBusBin : $(BUILD_DIR)\IdeBus.mak IdeBusBinBin
+
+$(BUILD_DIR)\IdeBus.mak : $(IDEBUS_DIR)\IdeBus.cif Board\EM\IdeBusBoard\IdeBusBoard.cif $(IDEBUS_DIR)\IdeBus.mak $(BUILD_RULES)
+ $(CIF2MAK) $(IDEBUS_DIR)\IdeBus.cif $(CIF2MAK_DEFAULTS) Board\EM\IdeBusBoard\IdeBusBoard.cif
+
+IDEBUS_BOARD_OBJECTS = $(BUILD_DIR)\Board\EM\IdeBusBoard\IdeBusBoard.obj
+
+IdeBusBinBin : $(IdeBusSrc_LIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\IdeBus.mak all\
+ MAKEFILE=$(IDEBUS_DIR)\IdeBus.mak \
+ OBJECTS="$(IDEBUS_BOARD_OBJECTS)" \
+ "EXT_HEADERS=$(BUILD_DIR)\token.h"\
+ TYPE=LIBRARY LIBRARY_NAME=$(BUILD_DIR)\IdeBusBin.lib LIBRARIES=\
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
diff --git a/Core/EM/IdeBus/IdeBus.sdl b/Core/EM/IdeBus/IdeBus.sdl
new file mode 100644
index 0000000..2faa756
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBus.sdl
@@ -0,0 +1,195 @@
+TOKEN
+ Name = "IdeBus_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Legacy8259 support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "MASTER_SLAVE_ENUMERATION"
+ Value = "1"
+ Help = "When off, Slave device is detected first and \then Master is detected."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "IDEBUSMASTER_SUPPORT"
+ Value = "1"
+ Help = "Master Switch to enable ATA and ATAPI \Busmaster support.\For ATAPI devices, ATAPI_BUSMASTER_SUPPORT \also needs to be enabled.\MWDMA and UDMA programming in devices \and the controller will be done irrespective of \this switch."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ATAPI_BUSMASTER_SUPPORT"
+ Value = "1"
+ Help = "Enable/Disable ATAPI Busmaster Support.\If Enabled, Busmastering will be used for ATAPI \devices else PIO transfer. "
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "IDEBUSMASTER_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "ACOUSTIC_MANAGEMENT_SUPPORT"
+ Value = "0"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "IDE_POWER_MANAGEMENT_SUPPORT"
+ Value = "0"
+ Help = "Enables IDE Power Management support."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "STANDBY_TIMEOUT"
+ Value = "5"
+ Help = "Standby Timeout value in MINUTES.\A value of ZERO, disables Standby Timer"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "0 - 480"
+ Token = "IDE_POWER_MANAGEMENT_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "ADVANCED_POWER_MANAGEMENT_SUPPORT"
+ Value = "0"
+ Help = "Enables Advanced Power Managment Support."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "IDE_POWER_MANAGEMENT_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "ADVANCED_POWER_MANAGEMENT_LEVEL"
+ Value = "1"
+ Help = "Disable : 0\Minimum Power Consumption : 1\Intermediate level with Standy : 2 - 7Fh\Minimum Power Consumption with out Standby : 80h\Intermediate level without Standy : 81 - FDh\Maximum Performance : 0FEh"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "0 - 0FEh"
+End
+
+TOKEN
+ Name = "POWERUP_IN_STANDBY_SUPPORT"
+ Value = "0"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "IDE_POWER_MANAGEMENT_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "POWERUP_IN_STANDBY_MODE"
+ Value = "0"
+ Help = "ON : Device Spins up when powered on.\0FF: Device will not spinup when powered on"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "IDE_POWER_MANAGEMENT_INTERFACE_SUPPORT"
+ Value = "0"
+ Help = "Installs IDE power Management Interface"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "IDE_POWER_MANAGEMENT_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "HOST_PROTECTED_AREA_SUPPORT"
+ Value = "0"
+ Help = "Enables HOST Protected Area Interface."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "IDE_HP_SUPPORT"
+ Value = "0"
+ Help = "Enables IDE Hot Plug Support."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "EFI_IDE_PROTOCOL"
+ Value = "1"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INTEL_IDE_PROTOCOL"
+ Value = "$(EFI_IDE_PROTOCOL)"
+ Help = "For backward compatibility, will keep this token value same as EFI_IDE_PROTOCOL."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Lock = Yes
+End
+
+TOKEN
+ Name = "AHCI_COMPATIBLE_MODE"
+ Value = "0"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+PATH
+ Name = "IDEBUS_DIR"
+End
+
+MODULE
+ Help = "Includes IdeBus.mak to Project"
+ File = "IdeBus.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\IDEBusSrc.ffs"
+ Parent = "FV_MAIN"
+ Disable = Yes
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "IdeBusEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(IDEBUS_DIR)\IdeBusSrc$(ARCH).lib"
+ Parent = "IdeBusSrc_LIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "IdeBusSrc_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "IdeBusBoardEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\IdeBusBin.lib"
+ Parent = "IdeBus_LIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "IdeBus_LIB"
+ InvokeOrder = ReplaceParent
+End
+
diff --git a/Core/EM/IdeBus/IdeBusMaster.c b/Core/EM/IdeBus/IdeBusMaster.c
new file mode 100644
index 0000000..da234af
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBusMaster.c
@@ -0,0 +1,836 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/IdeBus/IdeBusMaster.c 11 9/27/11 3:16a Rajeshms $
+//
+// $Revision: 11 $
+//
+// $Date: 9/27/11 3:16a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/IdeBusMaster.c $
+//
+// 11 9/27/11 3:16a 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
+//
+// 10 12/23/10 3:56a 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
+//
+// 9 10/11/10 11:30a Krishnakumarg
+// [TAG] - EIP 43249
+// [Category] - IMPROVEMENT
+// [Severity] - Minor
+// [Symptom] - Non-Ascii character in comments causing build problem in
+// japanese XP
+// [RootCause]- Presence of Non-Ascii character
+// [Solution] - Remove Non-Ascii character present in the file
+// [Files] - IdeSecurity.c,IDESMM.c, InstallIdeSmi, Ata.c, Atapi.c,
+// IDEBusComponentName.c, IdeBusMaster.c, IdeHPA.c, IdePowerManagement.c
+//
+// 8 8/25/10 4:13a 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
+//
+// 7 4/16/10 4:05p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 6 7/01/09 12:23p Rameshr
+// Coding Standard and File header updated.
+//
+// 5 1/08/09 4:55p Rameshraju
+// Symptom: When we have HDD and CD-ROM connected, system hangs while
+// booting through Cd-ROM
+// RootCause: Interrupt is not cleared properly on Bus master Atapi
+// read/write, that cause further interrupts not to be generated.
+// Solution: Clear the Bus master interrupt status if set
+//
+// 4 9/30/08 4:43p Felixp
+// Bug fix(EIP 15310):Invalid error code (EFI_DEVICE_ERROR instead of
+// EFI_NO_MEDIA) was returned for removable devices with no media
+//
+// 2 13/04/07 3:02p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 8 11/03/05 10:53a Srinin
+// VC7 compilation error fixed. 64KB buffer alignment removed for
+// Busmaster.
+// It should be Dword aligned.
+//
+// 7 9/27/05 4:38p Olegi
+// Change in AtaReadWriteBusMaster routine - clear interrupt status after
+// every read/write.
+//
+// 6 3/04/05 11:34a Mandal
+//
+// 5 2/11/05 6:17p Felixp
+// Bug fix: data corruption during DMA write operation
+//
+// 4 2/10/05 6:15p Felixp
+// Bug fix (in case of transfer of 64K*N bytes, the last 64K block was
+// lost)
+//
+// 3 1/28/05 12:10p Srinin
+// Before Setting up Busmater registers select the device.
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 1/05/05 11:21a Srinin
+// IDE BusMaster Support added.
+//
+//
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IDEBusMaster.c
+//
+// Description: BusMaster Services
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "IdeBus.h"
+#include <Protocol\IdeBusBoard.h>
+
+extern PLATFORM_IDE_PROTOCOL *gPlatformIdeProtocol;
+extern VOID *gDescriptorBuffer;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtaReadWriteBusMaster
+//
+// Description: Issues Read/Write Command and Read/Write the data from/to the ATA device
+// using BusMaster
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINT32 ByteCount,
+// UINT64 LBA
+//
+// Output:
+// *Buffer
+//
+// Modified:
+//
+// Referrals: AtaBlkWrite, AtaBlkRead
+//
+// Notes:
+// 1. Create Descriptor Table
+// 2. Issue ATA Read/Write command. Enable BusMastering
+// 3. Wait for Data Transfer
+// 4. Check for errors
+// 5. If success, check if any more data need to transferred, if yes, goto step 1
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaReadWriteBusMaster(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE )
+{
+ EFI_STATUS Status;
+ EFI_STATUS DMAStatus;
+ UINTN RemaingByteCount;
+ UINTN Total_Number_Of_Sectors;
+ UINTN MaxSectorCount;
+ UINTN CurrentSectorCount;
+ UINTN CurrentByteCount;
+ UINT8 *TempBuffer;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINTN DMATimeout;
+ UINTN DescriptorBuffer;
+ UINT8 Data8;
+ UINT32 SectorSize = ATA_SECTOR_BYTES;
+ BOOLEAN SectorGTBytes = FALSE;
+ //
+ //Select the drive
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.CommandBlock.DeviceReg, IdeBusInterface->IdeDevice.Device << 4 );
+
+ if ( Check48BitCommand( ReadWriteCommand )) {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO_48BIT;
+ }
+ else {
+ MaxSectorCount = MAX_SECTOR_COUNT_PIO;
+ }
+
+ //
+ // Calculate Sector Size
+ //
+ 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;
+ }
+
+ Total_Number_Of_Sectors = ByteCount / SectorSize; //512
+
+ // If the caller is requesting less bytes than one sector, we need to
+ // allocate space for one sector.
+ if ((ByteCount < SectorSize) && (ByteCount > 0)) {
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ SectorSize,
+ (VOID**)&TempBuffer );
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SectorGTBytes = TRUE;
+ Total_Number_Of_Sectors = 1;
+ } else {
+ TempBuffer = Buffer;
+ }
+
+ do
+ {
+ if ( Total_Number_Of_Sectors > MaxSectorCount ) {
+ CurrentSectorCount = 0;
+ }
+ else {
+ CurrentSectorCount = Total_Number_Of_Sectors;
+ }
+ CurrentByteCount = (CurrentSectorCount == 0 ? MaxSectorCount : CurrentSectorCount) * SectorSize;
+
+ DescriptorBuffer = (UINTN) gDescriptorBuffer;
+ Status = CreateDescriptorTable( &DescriptorBuffer, TempBuffer, CurrentByteCount, &RemaingByteCount );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ Status = InitBusMasterRegisters( IdeBusInterface, DescriptorBuffer, READWRITE );
+
+ MaskandSaveInterrupt( IdeBusInterface );
+ //
+ //Enable Interrupt
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 0 );
+
+ StartStopBusMastering( IdeBusInterface, TRUE );
+
+ Status = IssueAtaReadWriteCommand( IdeBusInterface, LBA, (UINT32)CurrentSectorCount, ReadWriteCommand, NULL );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //Timeout = 5000msec + Number of Sectors * 2
+ DMATimeout = ((CurrentSectorCount == 0 ? MaxSectorCount : CurrentSectorCount) << 1) + gPlatformIdeProtocol->DmaAtaCompleteCommandTimeout;
+
+ DMAStatus = WaitforDMAtoCompletion( IdeBusInterface, DMATimeout );
+
+ Status = HandleATABMErrors( IdeBusInterface );
+
+ StartStopBusMastering( IdeBusInterface, FALSE );
+ //
+ //Disable Interrupt
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+ //
+ //Clear interrupt status
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMStatusRegister,
+ &Data8 );
+
+ if ( Data8 & 4 ) {
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMStatusRegister,
+ Data8 );
+ }
+
+ RestoreInterrupt( IdeBusInterface );
+
+ //
+ //Check the status from WaitforDMAtoCompletion. More Descriptors are never formed. So EFI_SUCCESS_ACTIVE_SET is an error.
+ //
+ if ( EFI_ERROR( DMAStatus )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ TempBuffer += CurrentByteCount;
+ Total_Number_Of_Sectors -= (CurrentSectorCount == 0 ? MaxSectorCount : CurrentSectorCount);
+ LBA += (CurrentSectorCount == 0 ? MaxSectorCount : CurrentSectorCount);
+ } while ( Total_Number_Of_Sectors );
+
+ if (SectorGTBytes) {
+ pBS->CopyMem( Buffer, TempBuffer, ByteCount);
+ pBS->FreePool( TempBuffer );
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AtapiReadWriteBusMaster
+//
+// Description: Read/Write data from/to the ATAPI device
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// VOID *Buffer,
+// UINTN ByteCount,
+// UINT64 LBA,
+// UINT8 ReadWriteCommand,
+// BOOLEAN READWRITE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: AtapiBlkRead, AtapiBlkWrite
+//
+// Notes:
+// 1. Prepare ATAPI Command Packet
+// 2. Check for errors. If Media_Change, detect the new atapi media if present and return status accordingly.
+// 3. Read/write data if the command packet is issues successfully.
+// 4. Repeat from step 1 untill all data has been read/written.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS AtapiReadWriteBusMaster(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT VOID *Buffer,
+ IN UINTN ByteCount,
+ IN UINT64 LBA,
+ IN UINT8 ReadWriteCommand,
+ IN BOOLEAN READWRITE )
+{
+ EFI_STATUS Status;
+ EFI_STATUS DMAStatus;
+ INTN TotalNumberofBlocks;
+ INTN TransferLength;
+ UINTN BytesRemainingTobeRead;
+ UINTN RemaingByteCount;
+ ATAPI_DEVICE *AtapiDevice = IdeBusInterface->IdeDevice.AtapiDevice;
+ VOID *TempBuffer = Buffer;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+ UINTN DescriptorBuffer = (UINTN)gDescriptorBuffer;
+
+ //
+ //Check for CHK bit in status register before proceeding, if set give ATAPI reset
+ //
+ Status = CheckCHKonEntry( IdeBusInterface );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ TotalNumberofBlocks = ByteCount / AtapiDevice->BlockSize;
+
+ for (; TotalNumberofBlocks > 0; TotalNumberofBlocks -= TransferLength )
+ {
+ //
+ //Clear the buffer
+ //
+ ZeroMemory( AtapiDevice->PacketBuffer, AtapiDevice->PacketSize );
+
+ //
+ //Calculate # of blocks to be transferred
+ //
+ if ( TotalNumberofBlocks > 0xffff ) {
+ TransferLength = 0xffff;
+ }
+ else {
+ TransferLength = TotalNumberofBlocks;
+ }
+
+ //Update the buffer
+ AtapiDevice->PacketBuffer[0] = ReadWriteCommand;
+ AtapiDevice->PacketBuffer[1] = AtapiDevice->Lun << 5;
+ AtapiDevice->PacketBuffer[2] = ((UINT32) LBA) >> 24;
+ AtapiDevice->PacketBuffer[3] = ((UINT32) LBA) >> 16;
+ AtapiDevice->PacketBuffer[4] = ((UINT16) LBA) >> 8;
+ AtapiDevice->PacketBuffer[5] = ((UINT8) LBA) & 0xff;
+
+ AtapiDevice->PacketBuffer[7] = (UINT8) ( TransferLength >> 8 ); // MSB
+ AtapiDevice->PacketBuffer[8] = (UINT8) ( TransferLength & 0xff ); // LSB
+
+ BytesRemainingTobeRead = TransferLength * AtapiDevice->BlockSize;
+
+ Status = CreateDescriptorTable( &DescriptorBuffer, TempBuffer, BytesRemainingTobeRead, &RemaingByteCount );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ Status = InitBusMasterRegisters( IdeBusInterface, DescriptorBuffer, READWRITE );
+
+ MaskandSaveInterrupt( IdeBusInterface );
+
+ //Enable Interrupt
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 0 );
+
+ StartStopBusMastering( IdeBusInterface, TRUE );
+
+ Status = IssueAtapiPacketCommand( IdeBusInterface, (UINT16*) AtapiDevice->PacketBuffer, DMA, 0xffff );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ DMAStatus = WaitforDMAtoCompletion( IdeBusInterface, gPlatformIdeProtocol->DmaAtaPiCompleteCommandTimeout );
+
+ //Check for errors
+ Status = HandleAtapiError( IdeBusInterface );
+
+ StartStopBusMastering( IdeBusInterface, FALSE );
+
+ //Disable Interrupt
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.ControlBlock.DeviceControlReg, 2 );
+
+ //Clear interrupt status
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMStatusRegister,
+ &Data8 );
+
+ if ( Data8 & 4 ) {
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.BusMasterBlock.BMStatusRegister,
+ Data8 );
+ }
+
+ RestoreInterrupt( IdeBusInterface );
+
+ if ( Status != EFI_SUCCESS ) {
+ //Some error has occured
+ //Check if Device is getting ready. If yes, wait till it gets ready
+ if ( AtapiDevice->Atapi_Status == BECOMING_READY ) {
+ Status = TestUnitReady( IdeBusInterface );
+ }
+
+ if ( Status == EFI_MEDIA_CHANGED ) {
+ Status = DetectAtapiMedia( IdeBusInterface );
+
+ // This may happen during initial power-up also. If ReinstallProtocol needs to be done,
+ // then differentiate between power-up nad other cases.
+ if ( Status == EFI_SUCCESS ) {
+ return EFI_MEDIA_CHANGED; // Return Media Change
+ }
+ }
+ return Status;
+ }
+
+ //
+ //If WaitforDMAtoCompletion returns a error, read the status register again to make sure it is indeed a failure.
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMStatusRegister, &Data8 );
+
+ if ( Data8 & (BM_ERROR | BM_ACTIVE)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //Update pointer
+ (UINT8*) TempBuffer += BytesRemainingTobeRead;
+ LBA += TransferLength;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CreateDescriptorTable
+//
+// Description: Creates a IDE BUS master Descriptor Table
+//
+// Input:
+// IN OUT VOID **DescriptorBuffer // 128KB buffer
+// IN UINT32 StartAddress
+// IN UINT32 ByteCount
+// OUT UINTN *FinalByteCount
+//
+// Output:
+// DescriptorBuffer, EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Create a Physical Region Descriptor for IDE Bus Master.
+// 2. FinalByteCount will be the total # of Bytes that can be transferred
+// using this Descriptor. Most of the time FinalByteCount will be equal to ByteCount.
+/// If the Descriptor Buffer exceeds 64K, then partial transfer will take place.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS CreateDescriptorTable(
+ IN OUT UINTN *DescriptorBuffer,
+ IN UINT8 *StartAddress,
+ IN UINTN ByteCount,
+ OUT UINTN *RemainingByteCount )
+{
+ UINT16 Index;
+ UINTN Address = (UINTN) &(*StartAddress);
+ BUS_MASTER_DESCRIPTOR_TABLE *DescriptorTable;
+
+ //64KB alignment
+ *DescriptorBuffer &= 0xffff0000;
+ *DescriptorBuffer += 0x10000;
+ DescriptorTable = (BUS_MASTER_DESCRIPTOR_TABLE*)(*DescriptorBuffer);
+
+
+ //Address should be DWORD aligned
+ if ( Address & 0x3 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //Restore Address
+ Address = (UINTN) &(*StartAddress);
+
+ for ( Index = 0; Index < 0x10000 / 8; Index++ )
+ {
+ DescriptorTable[Index].BaseAddress = (UINT32) Address;
+ DescriptorTable[Index].Flag = 0;
+ //
+ // if Start address is not 64KB aligned, then bytecount cannot be 64KB (Data tranfer cannot cross 64KB boundry
+ //
+ if ( Address & 0xffff ) {
+ DescriptorTable[Index].ByteCount = 0x10000 - (UINT16)( Address & 0xffff );
+
+ if ( DescriptorTable[Index].ByteCount > ByteCount ) {
+ DescriptorTable[Index].ByteCount = (UINT16)ByteCount;
+ }
+ ByteCount -= DescriptorTable[Index].ByteCount;
+ Address += DescriptorTable[Index].ByteCount;
+
+ if ( ByteCount == 0 ) {
+ break;
+ }
+ }
+ else { // address is 64KB aligned
+ if ( ByteCount >= 0x10000 ) {
+ DescriptorTable[Index].ByteCount = 0;
+ ByteCount -= 0x10000;
+ Address += 0x10000;
+
+ if ( ByteCount == 0 ) {
+ break;
+ }
+ }
+ else {
+ DescriptorTable[Index].ByteCount = (UINT16) ByteCount;
+ ByteCount = 0;
+ break;
+ }
+ }
+ }
+
+ //
+ //Update EOT
+ //
+ DescriptorTable[Index].Flag = 0x8000;
+
+ *RemainingByteCount = ByteCount;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitBusMasterRegisters
+//
+// Description: Initialize Bus Master registers
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// IN OUT VOID *DescriptorBuffer
+// IN BOOLEAN ReadWrite
+//
+// Output:
+// DescriptorBuffer, EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Create a Physical Region Descriptor for IDE Bus Master.
+// 2. FinalByteCount will be the total # of Bytes that can be transferred
+// using this Descriptor. Most of the time FinalByteCount will be equal to ByteCount.
+/// If the Descriptor Buffer exceeds 64K, then partial transfer will take place.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InitBusMasterRegisters(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN OUT UINTN DescriptorBuffer,
+ IN BOOLEAN ReadWrite )
+
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+
+ //
+ //Update Read/Write Control and clear Start/Stop bit
+ //
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMCommandRegister, (ReadWrite == FALSE ? 1 : 0) << 3 );
+
+ //
+ //Clear the status
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMStatusRegister, &Data8 );
+ Data8 |= BM_INTERRUPT | BM_ERROR;
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMStatusRegister, Data8 );
+
+ //
+ //Update Descriptor Table Pointer
+ //
+ IdeWriteDword( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMDescriptorTablePointerReg, (UINT32) DescriptorBuffer );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: StartStopBusMastering
+//
+// Description: Start/Stop Bus mAstering
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// IN BOOLEAN StartStop // Start = TRUE
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// Don't destroy Read/Write Control bit
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS StartStopBusMastering(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN BOOLEAN StartStop )
+{
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+ UINT8 Data8;
+
+ //
+ //Update Start/Stop bit in Command Register
+ //
+ IdeReadByte( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMCommandRegister, &Data8 );
+ Data8 &= 0xFE;
+ Data8 |= (StartStop == TRUE ? 1 : 0);
+ IdeWriteByte( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMCommandRegister, Data8 );
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: WaitforDMAtoCompletion
+//
+// Description: Start/Stop Bus mAstering
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+// IN UINT32 TimeDelay (msec)
+//
+// Output:
+// EFI_STATUS Success : If DMA completes with or with out Error.
+// EFI_DEVICE_ERROR : If timed out.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// 1. Check for Interrupt bit set. If yes, command completed.
+// 2. Check for Active bit to go Zero. If yes, command completed.
+// 3. Waits for a max. of TimeDelay/10,000 sec for the command to get completed.
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitforDMAtoCompletion(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface,
+ IN UINTN TimeDelay )
+{
+ UINT8 Data8;
+ UINT8 Index2;
+ UINT32 Index;
+ IO_REGS Regs = IdeBusInterface->IdeDevice.Regs;
+
+ for ( Index = 0; Index < TimeDelay; Index++ )
+ {
+ for ( Index2 = 0; Index2 < 10; Index2++ )
+ {
+ IdeReadByte( IdeBusInterface->PciIO, Regs.BusMasterBlock.BMStatusRegister, &Data8 );
+
+ if ((Data8 & (BM_INTERRUPT | BM_ACTIVE)) == 4 ) {
+ return EFI_SUCCESS;
+ }
+
+ if ((Data8 & (BM_INTERRUPT | BM_ACTIVE)) == 5 ) {
+ return EFI_SUCCESS_ACTIVE_SET;
+ }
+
+ if ((Data8 & BM_ERROR) == 2 ) {
+ return EFI_DEVICE_ERROR;
+ }
+ pBS->Stall( 100 ); // 100 usec
+ }
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: HandleATABMErrors
+//
+// Description: Check for any errors
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HandleATABMErrors(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status;
+
+ Status = WaitForCmdCompletion( IdeBusInterface );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: MaskandSaveInterrupt
+//
+// Description: Mask IDE interrupt
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+//
+// Modified:
+//
+// Referrals: AtaReadWriteBusMaster
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS MaskandSaveInterrupt(
+ IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: RestoreInterrupt
+//
+// Description: Restore the Interrupt mask
+//
+// Input:
+// IN IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+//
+// Modified:
+//
+// Referrals: AtaReadWriteBusMaster
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RestoreInterrupt(
+ IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ return EFI_SUCCESS;
+}
+
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/IdeBus/IdeBusSrc.chm b/Core/EM/IdeBus/IdeBusSrc.chm
new file mode 100644
index 0000000..96bb270
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBusSrc.chm
Binary files differ
diff --git a/Core/EM/IdeBus/IdeBusSrc.cif b/Core/EM/IdeBus/IdeBusSrc.cif
new file mode 100644
index 0000000..052afc0
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBusSrc.cif
@@ -0,0 +1,18 @@
+<component>
+ name = "IdeBus Sources"
+ category = ModulePart
+ LocalRoot = "Core\em\IdeBus\"
+ RefName = "IdeBusSrc"
+[files]
+"IdeBusSrc.sdl"
+"IdeBusSrc.mak"
+"IdeBus.h"
+"IdeBus.c"
+"Ata.c"
+"Atapi.c"
+"IdeBusMaster.c"
+"IdePowerManagement.c"
+"IdeHPA.c"
+"IDEBusComponentName.c"
+"IdeBusSrc.chm"
+<endComponent>
diff --git a/Core/EM/IdeBus/IdeBusSrc.mak b/Core/EM/IdeBus/IdeBusSrc.mak
new file mode 100644
index 0000000..488f0ee
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBusSrc.mak
@@ -0,0 +1,98 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Core/Modules/IdeBus/IdeBusSrc.mak 5 8/25/10 4:11a Rameshr $
+#
+# $Revision: 5 $
+#
+# $Date: 8/25/10 4:11a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Core/Modules/IdeBus/IdeBusSrc.mak $
+#
+# 5 8/25/10 4:11a 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
+#
+# 4 7/01/09 12:22p Rameshr
+# Coding Standard and File header updated.
+#
+# 3 12/02/05 11:21a Felixp
+#
+# 2 12/02/05 11:21a Felixp
+#
+# 1 12/01/05 9:43a Felixp
+#
+# 3 11/22/05 12:56p Felixp
+# dependency from token.h added
+#
+# 2 2/01/05 1:02p Srinin
+# Idebus.mak changed to Idebussrc.mak
+#
+# 1 1/28/05 12:45p Felixp
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: IdeBusSrc.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : IDEBus
+
+
+IDEBus : $(BUILD_DIR)\IdeBusSrc.mak IDEBusSrcBin
+
+$(BUILD_DIR)\IdeBusSrc.mak : $(IDEBUS_DIR)\$(@B).cif $(IDEBUS_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(IDEBUS_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+$(IdeBusSrc_LIB) : IDEBus
+
+IDEBusSrcBin:
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\IDEBusSrc.mak all\
+ "EXT_HEADERS=$(BUILD_DIR)\token.h"\
+ TYPE=LIBRARY LIBRARY_NAME=$(IdeBusSrc_LIB)
+
+# to build as a separete binary:
+# 1. Uncomment next block
+# 2. Disable IdeBusEntryPoint eLink
+# 3. Enable $(BUILD_DIR)\IDEBus.ffs eLink
+#IDEBusSrcBin: $(AMIDXELIB)
+# $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+# /f $(BUILD_DIR)\IdeBusSrc.mak all\
+# GUID=59B90A53-461B-4C50-A79F-A32773C319AE\
+# ENTRY_POINT=IdeBusEntryPoint \
+# TYPE=BS_DRIVER \
+# COMPRESS=1\
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/IdeBus/IdeBusSrc.sdl b/Core/EM/IdeBus/IdeBusSrc.sdl
new file mode 100644
index 0000000..76cad32
--- /dev/null
+++ b/Core/EM/IdeBus/IdeBusSrc.sdl
@@ -0,0 +1,22 @@
+TOKEN
+ Name = "IdeBusSrc_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable IdeBusSrc support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+
+MODULE
+ Help = "Includes IdeBusSrc.mak to Project"
+ File = "IdeBusSrc.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\IdeBusSrc.lib"
+ Parent = "$(IDEBUS_DIR)\IdeBusSrc$(ARCH).lib"
+ InvokeOrder = ReplaceParent
+End
+
diff --git a/Core/EM/IdeBus/IdeHPA.c b/Core/EM/IdeBus/IdeHPA.c
new file mode 100644
index 0000000..273cbd2
--- /dev/null
+++ b/Core/EM/IdeBus/IdeHPA.c
@@ -0,0 +1,792 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/IdeBus/IdeHPA.c 6 10/11/10 11:31a Krishnakumarg $
+//
+// $Revision: 6 $
+//
+// $Date: 10/11/10 11:31a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/IdeHPA.c $
+//
+// 6 10/11/10 11:31a Krishnakumarg
+// [TAG] - EIP 43249
+// [Category] - IMPROVEMENT
+// [Severity] - Minor
+// [Symptom] - Non-Ascii character in comments causing build problem in
+// japanese XP
+// [RootCause]- Presence of Non-Ascii character
+// [Solution] - Remove Non-Ascii character present in the file
+// [Files] - IdeSecurity.c,IDESMM.c, InstallIdeSmi, Ata.c, Atapi.c,
+// IDEBusComponentName.c, IdeBusMaster.c, IdeHPA.c, IdePowerManagement.c
+//
+// 5 8/25/10 4:10a 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
+//
+// 4 7/01/09 12:24p Rameshr
+// Coding Standard and File header updated.
+//
+// 3 13/04/07 3:03p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 2 8/24/06 9:30a Felixp
+// x64 support (bug fixes)
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 4 3/04/05 11:35a Mandal
+//
+// 3 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 1/13/05 4:25p Srinin
+// Host Protection Area Support added.
+//
+//
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: IdeHPA.c
+//
+// Description: Host Protection Area Support
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "IdeBus.h"
+
+extern EFI_GUID gHPAProtocolGuid;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InstallHPAInterface
+//
+// Description: Checks whether Host Protcted Area feature is supported or not.
+// If Supported, installs HPAProtocol.
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS : EFI_UNSUPPORTED/EFI_SUCCESS/EFI_OUT_OF_RESOURCES
+//
+// Modified:
+//
+// Referrals: IdeBusStart
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS InstallHPAInterface(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status;
+ HPA_INTERFACE *HPAInterface;
+
+ //
+ //Check if HPA is supported or not
+ //
+ if ((IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_82 & 0x400) == 0 ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ //Install the Interface
+ //
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ sizeof(HPA_INTERFACE),
+ (VOID**)&HPAInterface );
+
+ if ( EFI_ERROR( Status )) {
+ pBS->FreePool( HPAInterface );
+ return Status;
+ }
+
+ HPAInterface->IdeBusInterface = IdeBusInterface;
+ IdeBusInterface->HPAInterface = HPAInterface;
+ HPAInterface->GetNativeMaxAddress = GetNativeMaxAddress;
+ HPAInterface->SetMaxAddress = SetMaxAddress;
+ HPAInterface->HPADisabledLastLBA = HPADisabledLastLBA;
+ HPAInterface->SetMaxPassword = SetMaxPassword;
+ HPAInterface->SetMaxLock = SetMaxLock;
+ HPAInterface->SetMaxUnLock = SetMaxUnLock;
+ HPAInterface->SetMaxFreezeLock = SetMaxFreezeLock;
+
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &(IdeBusInterface->IdeDeviceHandle),
+ &gHPAProtocolGuid, HPAInterface,
+ NULL );
+
+ if ( EFI_ERROR( Status )) {
+ pBS->FreePool( HPAInterface );
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: StopHPAInterface
+//
+// Description: Uninstall HPA Protocol
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface,
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IdeBusStop
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS StopHPAInterface(
+ IN IDE_BUS_PROTOCOL *IdeBusInterface )
+{
+ EFI_STATUS Status;
+
+ if ( IdeBusInterface->HPAInterface == NULL ) {
+ return EFI_SUCCESS;
+ }
+
+ Status = pBS->UninstallMultipleProtocolInterfaces(
+ IdeBusInterface->IdeDeviceHandle,
+ &gHPAProtocolGuid, IdeBusInterface->HPAInterface,
+ NULL );
+
+ if ( Status == EFI_SUCCESS ) {
+ pBS->FreePool( IdeBusInterface->HPAInterface );
+ IdeBusInterface->HPAInterface = NULL;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: GetNativeMaxAddress
+//
+// Description: Returns the Native Max LBA address supported by the device
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+// OUT UINT64 *LBA
+//
+// Output: LBA : Returns Native MAX LBA address.
+// EFI_STATUS : EFI_SUCCESS/EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GetNativeMaxAddress(
+ IN IDE_HPA_INTERFACE *This,
+ OUT UINT64 *LBA )
+{
+ EFI_STATUS Status;
+ BOOLEAN Ext48BitSupport = FALSE;
+ UINT8 ReadNativeMaxAddressCmd = READ_NATIVE_MAX_ADDRESS;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((HPA_INTERFACE*)This)->IdeBusInterface;
+ UINT32 dData;
+ UINT8 bData;
+
+ *LBA = 0;
+
+ //
+ //Check for 48 Bit Mode Support
+ //
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ ReadNativeMaxAddressCmd = READ_NATIVE_MAX_ADDRESS_EXT;
+ }
+
+ //
+ //Get Native Max Address.
+ //
+ Status = IdeNonDataCommand( IdeBusInterface,
+ 0, // Features
+ 0, // Sector Count
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ 0x40 | IdeBusInterface->IdeDevice.Device << 4, // Device
+ ReadNativeMaxAddressCmd ); // Command
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_UNSUPPORTED;
+ }
+
+
+ //
+ //Read Bits 47:24 if 48Bit LBA is supported
+ //
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ //
+ //Set HOB to 1 to read the upper DWROD
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.ControlBlock.DeviceControlReg,
+ HOB | nIEN );
+ dData = 0;
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAHighReg,
+ &bData );
+
+ dData = bData; // LBA 47:40
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAMidReg,
+ &bData );
+ dData <<= 8;
+ dData |= bData; // LBA 39:32
+
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBALowReg,
+ &bData );
+ dData <<= 8;
+ dData |= bData; // LBA 31:24
+
+ *LBA = dData;
+ //
+ //Shift Left *LBA by 24 Bits
+ //
+ *LBA = Shl64(*LBA, 24);
+ //
+ //Set HOB to 0 to read the Lower DWROD
+ //
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.ControlBlock.DeviceControlReg,
+ nIEN );
+ }
+
+ //
+ //Read 27:24 only when 48Bit LBA is not supported
+ //
+ if ((IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400) == 0 ) {
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.DeviceReg,
+ &bData );
+ bData &= 0xf;
+ dData = bData; // LBA 27:24
+ }
+
+ //
+ //Read 23:0 bits of LBA address
+ //
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAHighReg,
+ &bData );
+ dData <<= 8; // LBA 23:16
+ dData |= bData;
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAMidReg,
+ &bData );
+ dData <<= 8;
+ dData |= bData; // LBA 15:8
+ IdeReadByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBALowReg,
+ &bData );
+ dData <<= 8;
+ dData |= bData; // LBA 7:0
+
+ ((UINT32) *LBA) |= dData;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SetMaxAddress
+//
+// Description: Set the Max LBA address
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+// OUT UINT64 LBA,
+// IN BOOLEAN Volatile
+//
+// Output:
+// EFI_STATUS :
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: if Volatile = TRUE, Values will not be preserved across resets.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SetMaxAddress(
+ IN IDE_HPA_INTERFACE *This,
+ OUT UINT64 LBA,
+ IN BOOLEAN Volatile )
+{
+ EFI_STATUS Status;
+ UINT32 dData;
+ UINT32 Cmd;
+ UINT64 NativeMaxLBA;
+ UINT8 bData;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((HPA_INTERFACE*)This)->IdeBusInterface;
+ BOOLEAN Ext48BitSupport = FALSE;
+
+
+ //
+ //Issue Read MAX Native command before issuing a SET MAX Address command
+ //
+ Status = GetNativeMaxAddress( This, &NativeMaxLBA );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ //Check for 48 Bit Mode Support
+ //
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ Ext48BitSupport = TRUE;
+ }
+
+ //
+ //If 48Bit LBA is supported write LBA bits 47:24
+ //
+ if ( Ext48BitSupport ) {
+ // Enable HOB
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.ControlBlock.DeviceControlReg,
+ HOB | nIEN );
+ //get Bits 47:24 from LBA to dData
+ dData = (UINT32)Shr64(LBA, 24);
+
+ //dDATA has LBA bits 47:24
+ bData = dData >> 16; // LBA 47:40
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAHighReg,
+ bData );
+
+ bData = dData >> 8; // LBA 39:32
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBAMidReg,
+ bData );
+
+ bData = dData; // LBA 31:24
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.LBALowReg,
+ bData );
+
+ //Reset HOB
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.ControlBlock.DeviceControlReg,
+ nIEN );
+ }
+
+ //
+ // Write Bits 23:0
+ //
+ dData = (UINT32) LBA;
+
+ //
+ // if 48Bit LBA is not supported, write bits 27:24 to Device register
+ //
+ if ( Ext48BitSupport == FALSE ) {
+ bData = dData >> 24;
+ }
+ else {
+ bData = 0;
+ }
+
+ bData &= 0xf;
+ bData |= 0x40 | IdeBusInterface->IdeDevice.Device << 4;
+ Cmd = Ext48BitSupport == FALSE ? SET_MAX_ADDRESS : SET_MAX_ADDRESS_EXT;
+
+ //
+ //Set Max Address.
+ //
+ Status = IdeNonDataCommand( IdeBusInterface,
+ 0, // Features
+ Volatile == TRUE ? 0 : 1, // Sector Count
+ (UINT8)dData, // LBA Low
+ (UINT8)( dData >> 8 ), // LBA Mid
+ (UINT8)( dData >> 16 ), // LBA High
+ bData, // Device
+ Cmd ); // Command
+
+ //
+ // Update Identify Data
+ //
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+
+ //
+ //Update the LAST LBA number
+ //
+ if ( Ext48BitSupport ) {
+ IdeBusInterface->IdeBlkIo->BlkIo.Media->LastBlock = IdeBusInterface->IdeDevice.IdentifyData.LBA_48 - 1;
+ }
+ else {
+ IdeBusInterface->IdeBlkIo->BlkIo.Media->LastBlock = IdeBusInterface->IdeDevice.IdentifyData.Addressable_Sector_60 - 1;
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: HPADisabledLastLBA
+//
+// Description: Returns the valid last LBA # when HPA is disabled.
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+// OUT UINT64 *LBA
+//
+// Output:
+// EFI_STATUS : EFI_SUCCESS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: The LBA returned will be the maximum valid LBA number an OS can make use of.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS HPADisabledLastLBA(
+ IN IDE_HPA_INTERFACE *This,
+ OUT UINT64 *LBA )
+{
+ BOOLEAN Ext48BitSupport = FALSE;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((HPA_INTERFACE*)This)->IdeBusInterface;
+
+ //
+ //Check for 48 Bit Mode Support
+ //
+ if ( IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x400 ) {
+ Ext48BitSupport = TRUE;
+ }
+
+ //
+ //Update the LAST LBA number
+ //
+ if ( Ext48BitSupport ) {
+ *LBA = IdeBusInterface->IdeDevice.IdentifyData.LBA_48 - 1;
+ }
+ else {
+ *LBA = IdeBusInterface->IdeDevice.IdentifyData.Addressable_Sector_60 - 1;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SetMaxPassword
+//
+// Description: Sets the Password
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+// IN UINT8 *PasswordBuffer, (32 Bytes of Password)
+//
+// Output:
+// EFI_STATUS : EFI_UNSUPPORTED/EFI_SUCCESS/EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: READ NATIVE MAX ADDRESS should not have immediatley PRECEEDED this command.
+// To take care of this situation, a Dummy Identify Device Command will be given before
+// issuing a SET MAX PASSWORD command
+// Once the device is locked, it should be unlocked with the password before
+// issuing any SETMAXADDRESS.
+// After issuing this command device will be in UNLOCKED state.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SetMaxPassword(
+ IN IDE_HPA_INTERFACE *This,
+ IN UINT8 *PasswordBuffer )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((HPA_INTERFACE*)This)->IdeBusInterface;
+
+ //
+ //Check for HPA feature set security extensions are implemented or not?
+ //
+ if ( !(IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x100)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = IssueSetMaxPasswordCmd( IdeBusInterface, PasswordBuffer, SET_MAX_SET_PASSWORD );
+
+ //
+ //Update the Identify Device Data buffer
+ //
+ GetIdentifyData( IdeBusInterface, &(IdeBusInterface->IdeDevice));
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SetMaxLock
+//
+// Description: Locks the device from accepting commands except UNLOCK and FREEZELOCK
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+//
+// Output:
+// EFI_STATUS : EFI_UNSUPPORTED/EFI_SUCCESS/EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: READ NATIVE MAX ADDRESS should not have immediatley PRECEED this command.
+// To take care of this situation, a Dummy Identify Device Command will be given before
+// issuing a SET MAX LOCK/UNLOCK command
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SetMaxLock(
+ IN IDE_HPA_INTERFACE *This )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((HPA_INTERFACE*)This)->IdeBusInterface;
+
+ //Check for HPA feature set security extensions are implemented or not? AND
+ //Check whether SET MAX PASSWORD command has been issued before or not?
+ if ((!(IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x100))
+ || (!(IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Enabled_86 & 0x100))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = IdeNonDataCommand(
+ IdeBusInterface,
+ SET_MAX_LOCK, // Features
+ 0, // Sector Count
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ SET_MAX_ADDRESS ); // Command
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SetMaxUnLock
+//
+// Description: Unlocks the device and allows it to accept all SET MAX commands
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+// IN UINT8 *PasswordBuffer
+//
+// Output:
+// EFI_STATUS : EFI_UNSUPPORTED/EFI_SUCCESS/EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: READ NATIVE MAX ADDRESS should not have immediatley PRECEED this command.
+// To take care of this situation, a Dummy Identify Device Command will be given before
+// issuing a SET MAX LOCK/UNLOCK command
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SetMaxUnLock(
+ IN IDE_HPA_INTERFACE *This,
+ IN UINT8 *PasswordBuffer )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((HPA_INTERFACE*)This)->IdeBusInterface;
+
+ //Check for HPA feature set security extensions are implemented or not? AND
+ //Check whether SET MAX PASSWORD command has been issued before or not?
+ if ((!(IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x100))
+ || (!(IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Enabled_86 & 0x100))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = IssueSetMaxPasswordCmd( IdeBusInterface, PasswordBuffer, SET_MAX_UNLOCK );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: SetMaxFreezeLock
+//
+// Description: Locks all SET MAX ADDRESS/PASSWORD/LOCK/UNLOCK command untill
+// next power cycle. GetNativeMaxAddress is allowed.
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+//
+// Output:
+// EFI_STATUS : EFI_UNSUPPORTED/EFI_SUCCESS/EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: READ NATIVE MAX ADDRESS should not have immediatley PRECEED this command.
+// To take care of this situation, a Dummy Identify Device Command will be given before
+// issuing a SET MAX FREEZELOCK command
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SetMaxFreezeLock(
+ IN IDE_HPA_INTERFACE *This )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((HPA_INTERFACE*)This)->IdeBusInterface;
+
+ //Check for HPA feature set security extensions are implemented or not? AND
+ //Check whether SET MAX PASSWORD command has been issued before or not?
+ if ((!(IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x100))
+ || (!(IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Enabled_86 & 0x100))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = IdeNonDataCommand(
+ IdeBusInterface,
+ SET_MAX_FREEZE_LOCK, // Features
+ 0, // Sector Count
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ SET_MAX_ADDRESS ); // Command
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IssueSetMaxPasswordCmd
+//
+// Description: Sets the Password to Lock/Unlock use of SETMAXADDRESS command
+//
+// Input:
+// IN IDE_HPA_INTERFACE *This,
+// IN BOOLEAN LockUnLock (TRUE : LOCK, FALSE :UNLOCK
+//
+// Output:
+// EFI_STATUS : EFI_UNSUPPORTED/EFI_SUCCESS/EFI_DEVICE_ERROR
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: READ NATIVE MAX ADDRESS should not have immediatley PRECEED this command.
+// To take care of this situation, a Dummy Identify Device Command will be given before
+// issuing a SET MAX LOCK/UNLOCK command
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS IssueSetMaxPasswordCmd(
+ IDE_BUS_PROTOCOL *IdeBusInterface,
+ UINT8 *PasswordBuffer,
+ UINT8 Cmd )
+{
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+
+ //Issues Identify Device Command
+ //Allocate 512 Bytes
+ Status = pBS->AllocatePool( EfiBootServicesData,
+ 512,
+ (VOID**)&Buffer );
+
+ if ( EFI_ERROR( Status )) {
+ pBS->FreePool( Buffer );
+ return Status;
+ }
+
+ Status = GetIdentifyData( IdeBusInterface, Buffer );
+
+ //
+ //Clear the Buffer
+ //
+ ZeroMemory( Buffer, 512 );
+
+ //
+ //Copy 32 bytes to Password starting from offset 2
+ //
+ pBS->CopyMem( &(Buffer[2]), PasswordBuffer, 32 );
+
+ // Issue SET MAX PASSWORD Command
+ // Update the Feature Register
+ IdeWriteByte( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.FeatureReg,
+ Cmd );
+ Status = AtaReadWritePio( IdeBusInterface, Buffer, 512, 0, SET_MAX_ADDRESS, TRUE );
+
+ pBS->FreePool( Buffer );
+ return Status;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/IdeBus/IdePowerManagement.c b/Core/EM/IdeBus/IdePowerManagement.c
new file mode 100644
index 0000000..4275d29
--- /dev/null
+++ b/Core/EM/IdeBus/IdePowerManagement.c
@@ -0,0 +1,546 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/IdeBus/IdePowerManagement.c 11 10/11/10 11:32a Krishnakumarg $
+//
+// $Revision: 11 $
+//
+// $Date: 10/11/10 11:32a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/IdeBus/IdePowerManagement.c $
+//
+// 11 10/11/10 11:32a Krishnakumarg
+// [TAG] - EIP 43249
+// [Category] - IMPROVEMENT
+// [Severity] - Minor
+// [Symptom] - Non-Ascii character in comments causing build problem in
+// japanese XP
+// [RootCause]- Presence of Non-Ascii character
+// [Solution] - Remove Non-Ascii character present in the file
+// [Files] - IdeSecurity.c,IDESMM.c, InstallIdeSmi, Ata.c, Atapi.c,
+// IDEBusComponentName.c, IdeBusMaster.c, IdeHPA.c, IdePowerManagement.c
+//
+// 10 8/25/10 4:10a 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
+//
+// 9 8/31/09 10:40a Felixp
+// IDLE_CMD is used instead of STANDBY_CMD if standby time is zero to
+// avoid HDD spin up and down-EIP 22135
+//
+
+//
+// 6 7/01/09 12:23p Rameshr
+// Coding Standard and File header updated.
+//
+// 5 13/04/07 3:05p Anandakrishnanl
+// Ide Bus Module - Update source files to comply with AMI coding
+// standard"!!!
+//
+// 4 1/09/06 11:36a Felixp
+//
+// 2 12/14/05 3:10p Srinin
+//
+// 1 12/01/05 9:43a Felixp
+//
+// 4 3/04/05 11:35a Mandal
+//
+// 3 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 1/11/05 2:26p Srinin
+// IDE Power Management Support added.
+//
+//
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: IDEPOWERMANAGEMENT.c
+//
+// Description: IDE Power Management Support
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "IdeBus.h"
+#include <Protocol\IdeBusBoard.h>
+
+//
+//External variables
+//
+extern PLATFORM_IDE_PROTOCOL *gPlatformIdeProtocol;
+extern EFI_GUID gPowerMgmtProtocolGuid;
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InitIDEPowerManagement
+//
+// Description: Initializes IDE power Management
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: ConfigureIdeDevice
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InitIDEPowerManagement (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface
+ )
+{
+
+ UINT8 bData = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ //Check if POWER Managmentfeature is enabled
+ //
+ if (IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Enabled_85 & 0x8) {
+
+ //
+ //Enable/Disable STANDBY Timer
+ //
+ bData = ConvertStanbyTimeoutValue ((UINT8)gPlatformIdeProtocol->StandbyTimeout);
+ if ( (gPlatformIdeProtocol->StandbyTimeout) == 0 ) {
+ Status = IdeNonDataCommand (
+ IdeBusInterface,
+ 0, // Features
+ bData, // Sector Count
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ IDLE_CMD); // IDLE_CMD when StandbyTimeout = 0
+ } else {
+ Status = IdeNonDataCommand (
+ IdeBusInterface,
+ 0, // Features
+ bData, // Sector Count
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ STANDBY_CMD); // STANDBY_CMD when StandbyTimeout > 0
+ }
+ //
+ //Enable/Disable STANDBY Timer
+ //
+
+ }
+
+ //
+ //Check Advanced Power Management Mode
+ //
+ if ( gPlatformIdeProtocol->AdvPowerManagementSupport ) {
+ if (IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x8){
+ //
+ //Enable/Disable Advanced Power Management
+ //
+ bData = ( gPlatformIdeProtocol->AdvPowerManagementLevel ) == 0 ? DISABLE_ADV_POWER_MANAGEMENT : ADV_POWER_MANAGEMENT;
+ IdeSetFeatureCommand (IdeBusInterface, bData, gPlatformIdeProtocol->AdvPowerManagementLevel );
+ }
+ }
+
+
+ if ( gPlatformIdeProtocol->PowerupInStandbySupport ) {
+ //
+ //Check Power-up in Standby Mode Support
+ //
+ if (IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x20){
+ //
+ //Check if the desires state is already present or not
+ //
+ if (!((IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Enabled_86 & 0x20) == (gPlatformIdeProtocol->PowerupInStandbyMode))){
+ bData = ( gPlatformIdeProtocol->PowerupInStandbyMode ) == 0 ? DISABLE_POWERUP_IN_STANDBY : ENABLE_POWERUP_IN_STANDBY;
+ IdeSetFeatureCommand (IdeBusInterface, bData, 0);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: InstallIDEPowerMgmtInterface
+//
+// Description: Install IDE power Management Interface
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IdeBusStart
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+InstallIDEPowerMgmtInterface (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface
+ )
+{
+
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ POWER_MGMT_INTERFACE *PowerMgmtInterface;
+
+
+ //
+ //Check if Power Management is Supported or not
+ //
+ if (IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Enabled_85 & 0x8){
+ Status = pBS->AllocatePool (EfiBootServicesData,
+ sizeof (POWER_MGMT_INTERFACE),
+ (VOID**)&PowerMgmtInterface);
+ if (EFI_ERROR(Status)) return Status;
+
+ PowerMgmtInterface->CheckPowerMode = CheckPowerMode;
+ PowerMgmtInterface->IdleMode = IdleMode;
+ PowerMgmtInterface->StandbyMode = StandbyMode;
+ PowerMgmtInterface->AdvancePowerMgmtMode = AdvancePowerMgmtMode;
+ PowerMgmtInterface->IdeBusInterface = IdeBusInterface;
+ IdeBusInterface->PowerMgmtInterface = PowerMgmtInterface;
+
+ //
+ //Install the protocol on the device
+ //
+ Status = pBS->InstallMultipleProtocolInterfaces (
+ &(IdeBusInterface->IdeDeviceHandle),
+ &gPowerMgmtProtocolGuid, IdeBusInterface->PowerMgmtInterface,
+ NULL);
+
+ if (EFI_ERROR(Status)) pBS->FreePool(PowerMgmtInterface);
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: StopIDEPowerMgmtInterface
+//
+// Description: Uninstall IDE power Management Interface
+//
+// Input:
+// IDE_BUS_PROTOCOL *IdeBusInterface;
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals: IdeBusStop
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+StopIDEPowerMgmtInterface (
+ IN IDE_BUS_PROTOCOL *IdeBusInterface
+ )
+{
+
+ EFI_STATUS Status;
+ POWER_MGMT_INTERFACE *PowerMgmtInterface = IdeBusInterface->PowerMgmtInterface;
+
+ if (IdeBusInterface->PowerMgmtInterface == NULL) return EFI_SUCCESS;
+ Status = pBS->UninstallMultipleProtocolInterfaces (
+ IdeBusInterface->IdeDeviceHandle,
+ &gPowerMgmtProtocolGuid, IdeBusInterface->PowerMgmtInterface,
+ NULL);
+ if (Status == EFI_SUCCESS) {
+ pBS->FreePool(IdeBusInterface->PowerMgmtInterface);
+ IdeBusInterface->PowerMgmtInterface = NULL;
+ }
+
+ return Status;
+}
+ //IDE_POWER_MANAGEMENT_INTERFACE_SUPPORT ends
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------//
+// Procedure: ConvertStanbyTimeoutValue
+//
+// Description: Initializes IDE power Managment
+//
+// Input:
+// IN UINT8 StandbyTimeout (In Minutes)
+//
+// Output:
+// UINT8 StandbyTimeout (Converted Timeout period)
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+ConvertStanbyTimeoutValue (
+ IN UINT8 StandbyTimeout
+ )
+{
+
+ if ( StandbyTimeout ) {
+ if ( StandbyTimeout < 30 ) {
+ if ( StandbyTimeout > 20 ) {
+ StandbyTimeout = 20;
+ }
+ return StandbyTimeout * 60 / 5;
+ }
+ if ( StandbyTimeout < 16 * 30 ) {
+ return StandbyTimeout / 30;
+ }
+ }
+ return 0; // Standby Timer Disabled
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: CheckPowerMode
+//
+// Description: Returns the Current State of the device
+//
+// Input:
+//
+//
+// Output:
+// EFI_STATUS, Current state of the Device,
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: PowerMode : 00 Standby Mode, 80h : Idle Mode, FF : Active/Idle Mode
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+CheckPowerMode (
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN OUT UINT8 *PowerMode
+ )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((POWER_MGMT_INTERFACE *)IdePowerMgmtInterface)->IdeBusInterface;
+
+ Status = IdeNonDataCommand (
+ IdeBusInterface,
+ 0, // Features
+ 0, // SectorCount
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ CHECK_POWER_MODE); // Command
+
+ if (Status == EFI_SUCCESS) {
+ IdeReadByte ( IdeBusInterface->PciIO,
+ IdeBusInterface->IdeDevice.Regs.CommandBlock.SectorCountReg,
+ PowerMode);
+ }
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: IdleMode
+//
+// Description: Puts the device in Idle Mode
+//
+// Input: StandbyTimeout : Value in Minutes. (0 : Disabled)
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+IdleMode(
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN UINT8 StandbyTimeout
+ )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((POWER_MGMT_INTERFACE *)IdePowerMgmtInterface)->IdeBusInterface;
+ UINT8 bData;
+
+ bData = ConvertStanbyTimeoutValue (StandbyTimeout);
+ Status = IdeNonDataCommand (
+ IdeBusInterface,
+ 0, // Features
+ bData, // SectorCount
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ IDLE_CMD); // Command
+
+ return Status;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: StandbyMode
+//
+// Description: Puts the device in StandbyMode
+//
+// Input: StandbyTimeout : Value in Minutes. (0 : Disabled)
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+StandbyMode(
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN UINT8 StandbyTimeout
+ )
+{
+ EFI_STATUS Status;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((POWER_MGMT_INTERFACE *)IdePowerMgmtInterface)->IdeBusInterface;
+ UINT8 bData;
+
+ bData = ConvertStanbyTimeoutValue (StandbyTimeout);
+ Status = IdeNonDataCommand (
+ IdeBusInterface,
+ 0, // Features
+ bData, // SectorCount
+ 0, // LBA Low
+ 0, // LBA Mid
+ 0, // LBA High
+ IdeBusInterface->IdeDevice.Device << 4, // Device
+ STANDBY_CMD); // Command
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: AdvancePowerMgmtMode
+//
+// Description: Enables Adavance Power Management
+//
+// Input: AdvPowerMgmtLevel ( 0 : Disable, FEh : Max. Performance, 81h - FDh Intermediate performance without Standby
+// 80h : Min. Power Consumption without Standby, 02h - 7Fh Intermediate Performance with Standby
+// 01h : Min. Power Consumption with Standby)
+//
+// Output:
+// EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+AdvancePowerMgmtMode(
+ IN IDE_POWER_MGMT_INTERFACE *IdePowerMgmtInterface,
+ IN UINT8 AdvPowerMgmtLevel
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ IDE_BUS_PROTOCOL *IdeBusInterface = ((POWER_MGMT_INTERFACE *)IdePowerMgmtInterface)->IdeBusInterface;
+ UINT8 bData;
+
+ if (IdeBusInterface->IdeDevice.IdentifyData.Command_Set_Supported_83 & 0x8){
+ //
+ //Enable/Disable Advanced Power Management
+ //
+ bData = AdvPowerMgmtLevel == 0 ? DISABLE_ADV_POWER_MANAGEMENT : ADV_POWER_MANAGEMENT;
+ Status = IdeSetFeatureCommand (IdeBusInterface, bData, AdvPowerMgmtLevel);
+ }
+
+ return Status;
+
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************