//********************************************************************** //********************************************************************** //** ** //** (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. // // // //---------------------------------------------------------------------------- // // Name: IdeBus.c // // Description: Provides IDE Block IO protocol // //---------------------------------------------------------------------------- // #include "IdeBus.h" #include 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 ); // //--------------------------------------------------------------------------- // // 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: // //--------------------------------------------------------------------------- // 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 ); } } } } } } } } // //--------------------------------------------------------------------------- // // 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. //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } } } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Procedure: GetEnumOddType // // Description: Get the Enum value for ODD type found on profile // // Input: // // UINT16 Oddtype // Output: // ODD_TYPE EnumValue // // Modified: // // Referrals: // // Notes: // //--------------------------------------------------------------------------- // 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; } } // //--------------------------------------------------------------------------- // // Procedure: InitIdeDiskInfo // // Description: Initializes IDE DiskInfo Interface // // Input: // // IDE_BUS_PROTOCOL *IdeBusInterface, // // Output: // EFI_STATUS // // Modified: // // Referrals: AllocatePool OpenProtocol // // Notes: // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } //********************************************************************** // // // Procedure: InitMiscConfig // // Description: Initialize misc IDE configurations. // // Input: // IN SATA_DEVICE_INTERFACE *SataDevInterface // // Output: // None // // //********************************************************************** 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); } } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Procedure: DMACapable // // Description: Check if DMA is supported // // Input: // IN IDE_BUS_PROTOCOL *IdeBusInterface, // // Output: // TRUE : DMA Capable // // Modified: // // Referrals: // // Notes: // //--------------------------------------------------------------------------- // 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; } } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } } } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // EFI_STATUS DiskInfoSenseData( IN EFI_DISK_INFO_PROTOCOL *This, OUT VOID *SenseData, OUT UINT32 *SenseDataSize, OUT UINT8 *SenseDataNumber ) { return EFI_NOT_FOUND; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Procedure: IdeHPTimer // // Description: Checks for any HP IDE device // // Input: // IN EFI_EVENT Event, // IN VOID *Context // // Output: // EFI_STATUS // // Modified: // // Referrals: // // Notes: // //--------------------------------------------------------------------------- // 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; } } } // //--------------------------------------------------------------------------- // // 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: // //--------------------------------------------------------------------------- // 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 // //--------------------------------------------------------------------------- // // Procedure: PrintIdeDeviceInfo // // Description: Prints Debug Level 3 Trace Messages // // Input: // IN IDE_BUS_PROTOCOL *IdeBusInterface // // Output: // EFI_STATUS // // Modified: // // Referrals: // // Notes: // //--------------------------------------------------------------------------- // 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 */ // //--------------------------------------------------------------------------- // // 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: // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Procedure: IssueFreezeLockCommand // // Description: Issue the Freeze lock command. // // Input: // IDE_BUS_PROTOCOL *IdeBusInterface; // // Output: // // Modified: // // Referrals: // // Notes: // //--------------------------------------------------------------------------- // 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 ** //** ** //********************************************************************** //**********************************************************************