diff options
Diffstat (limited to 'Core/EM/IdeBus/IdeBusMaster.c')
-rw-r--r-- | Core/EM/IdeBus/IdeBusMaster.c | 836 |
1 files changed, 836 insertions, 0 deletions
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 ** +//** ** +//********************************************************************** +//********************************************************************** |