diff options
Diffstat (limited to 'Core/EM/IdeBus')
-rw-r--r-- | Core/EM/IdeBus/Ata.c | 2986 | ||||
-rw-r--r-- | Core/EM/IdeBus/Atapi.c | 1811 | ||||
-rw-r--r-- | Core/EM/IdeBus/IDEBusComponentName.c | 374 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBus.c | 3607 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBus.chm | bin | 0 -> 151925 bytes | |||
-rw-r--r-- | Core/EM/IdeBus/IdeBus.cif | 13 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBus.h | 821 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBus.mak | 114 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBus.sdl | 195 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBusMaster.c | 836 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBusSrc.chm | bin | 0 -> 152056 bytes | |||
-rw-r--r-- | Core/EM/IdeBus/IdeBusSrc.cif | 18 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBusSrc.mak | 98 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeBusSrc.sdl | 22 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdeHPA.c | 792 | ||||
-rw-r--r-- | Core/EM/IdeBus/IdePowerManagement.c | 546 |
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 Binary files differnew file mode 100644 index 0000000..5b8094a --- /dev/null +++ b/Core/EM/IdeBus/IdeBus.chm 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 Binary files differnew file mode 100644 index 0000000..96bb270 --- /dev/null +++ b/Core/EM/IdeBus/IdeBusSrc.chm 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 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** |