diff options
Diffstat (limited to 'IntelFrameworkModulePkg/Bus/Pci')
-rw-r--r-- | IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h | 2 | ||||
-rw-r--r-- | IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c | 2952 |
2 files changed, 1477 insertions, 1477 deletions
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h index 0b637e00f9..a5a2e02d7a 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h @@ -202,7 +202,7 @@ DiscoverIdeDevice ( detection of one channel.
**/
-VOID +VOID
InitializeIDEChannelData (
VOID
);
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c index 629eadec52..3c7159502d 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c @@ -1,1520 +1,1520 @@ -/** @file +/** @file
This file implement UEFI driver for IDE Bus which includes device identification,
Child device(Disk, CDROM, etc) enumeration and child handler installation, and
- driver stop. + driver stop.
- Copyright (c) 2006 - 2008, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - @par Revision Reference: - This module is modified from DXE\IDE module for Ide Contriller Init support - -**/ - -#include "IdeBus.h" - -#define PCI_CLASS_MASS_STORAGE 0x01 -#define PCI_SUB_CLASS_IDE 0x01 - - -// -// IDE Bus Driver Binding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = { - IDEBusDriverBindingSupported, - IDEBusDriverBindingStart, - IDEBusDriverBindingStop, - 0xa, - NULL, - NULL -}; -/** - Deregister an IDE device and free resources - - @param This Protocol instance pointer. - @param Controller Ide device handle - @param Handle Handle of device to deregister driver on - - @retval EFI_SUCCESS Deregiter a specific IDE device successfully - - -**/ -EFI_STATUS -DeRegisterIdeDevice ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_HANDLE Handle - ) -{ - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN Index; - - Status = gBS->OpenProtocol ( - Handle, - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); - - // - // Report Status code: Device disabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE), - IdeBlkIoDevice->DevicePath - ); - - // - // Close the child handle - // - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Handle - ); - - Status = gBS->UninstallMultipleProtocolInterfaces ( - Handle, - &gEfiDevicePathProtocolGuid, - IdeBlkIoDevice->DevicePath, - &gEfiBlockIoProtocolGuid, - &IdeBlkIoDevice->BlkIo, - &gEfiDiskInfoProtocolGuid, - &IdeBlkIoDevice->DiskInfo, - NULL - ); - - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - return Status; - } - - // - // Release allocated resources - // - Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device; - if (Index < MAX_IDE_DEVICE) { - IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE; - } - ReleaseIdeResources (IdeBlkIoDevice); - - return EFI_SUCCESS; -} -/** - Supported function of Driver Binding protocol for this driver. - - @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param ControllerHandle The handle of the controller to test. - @param RemainingDevicePath A pointer to the remaining portion of a device path. - - @retval EFI_SUCCESS Driver loaded. - @retval other Driver not loaded. - -**/ -EFI_STATUS -EFIAPI -IDEBusDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_DEV_PATH *Node; - EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; - - if (RemainingDevicePath != NULL) { - Node = (EFI_DEV_PATH *) RemainingDevicePath; - if (Node->DevPath.Type != MESSAGING_DEVICE_PATH || - Node->DevPath.SubType != MSG_ATAPI_DP || - DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) { - return EFI_UNSUPPORTED; - } - } - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Close protocol, don't use device path protocol in the .Support() function - // - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Verify the Ide Controller Init Protocol, which installed by the - // IdeController module. - // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't - // open BY_DRIVER here) That's why we don't check pciio protocol - // Note 2: ide_init driver check ide controller's pci config space, so we dont - // check here any more to save code size - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - (VOID **) &IdeInit, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - // - // If protocols were opened normally, closed it - // - gBS->CloseProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - - -/** - Start function of Driver binding protocol which start this driver on Controller - by detecting all disks and installing BlockIo protocol on them. - - @param This Protocol instance pointer. - @param Controller Handle of device to bind driver to. - @param RemainingDevicePath produce all possible children. - - @retval EFI_SUCCESS This driver is added to ControllerHandle. - @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. - @retval other This driver does not support this device. - -**/ -EFI_STATUS -EFIAPI -IDEBusDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_STATUS SavedStatus; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_DEV_PATH *Node; - UINT8 IdeChannel; - UINT8 BeginningIdeChannel; - UINT8 EndIdeChannel; - UINT8 IdeDevice; - UINT8 BeginningIdeDevice; - UINT8 EndIdeDevice; - IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice]; - IDE_BLK_IO_DEV *IdeBlkIoDevicePtr; - IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; - ATA_TRANSFER_MODE TransferMode; - ATA_DRIVE_PARMS DriveParameters; - EFI_DEV_PATH NewNode; - UINT8 ConfigurationOptions; - UINT16 CommandBlockBaseAddr; - UINT16 ControlBlockBaseAddr; - UINTN DataSize; - IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; - UINT64 Supports; - - // - // Local variables declaration for IdeControllerInit support - // - EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; - BOOLEAN EnumAll; - BOOLEAN ChannelEnabled; - UINT8 MaxDevices; - EFI_IDENTIFY_DATA IdentifyData; - EFI_ATA_COLLECTIVE_MODE *SupportedModes; - - IdeBusDriverPrivateData = NULL; - SupportedModes = NULL; - - // - // Perform IdeBus initialization - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { - return Status; - } - - // - // Now open the IDE_CONTROLLER_INIT protocol. Step7.1 - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - (VOID **) &IdeInit, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - // - // The following OpenProtocol function with _GET_PROTOCOL attribute and - // will not return EFI_ALREADY_STARTED, so save it for now - // - SavedStatus = Status; - - if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { - DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status)); - // - // open protocol is not SUCCESS or not ALREADY_STARTED, error exit - // - goto ErrorExit; - } - - // - // Save Enumall. Step7.2 - // - EnumAll = IdeInit->EnumAll; - - // - // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL - // attribute will not return EFI_ALREADY_STARTED - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status)); - goto ErrorExit; - } - - // - // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable - // - if (SavedStatus != EFI_ALREADY_STARTED) { - IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); - if (IdeBusDriverPrivateData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiCallerIdGuid, - IdeBusDriverPrivateData, - NULL - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - } else { - Status = gBS->OpenProtocol ( - Controller, - &gEfiCallerIdGuid, - (VOID **) &IdeBusDriverPrivateData, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData = NULL; - goto ErrorExit; - } - } - - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } - - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - // - // Read the environment variable that contains the IDEBus Driver's - // Config options that were set by the Driver Configuration Protocol - // - DataSize = sizeof (ConfigurationOptions); - Status = gRT->GetVariable ( - (CHAR16 *) L"Configuration", - &gEfiCallerIdGuid, - NULL, - &DataSize, - &ConfigurationOptions - ); - if (EFI_ERROR (Status)) { - ConfigurationOptions = 0x0f; - } - - if (EnumAll) { - // - // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway - // - BeginningIdeChannel = IdePrimary; - EndIdeChannel = IdeSecondary; - BeginningIdeDevice = IdeMaster; - EndIdeDevice = IdeSlave; - } else if (RemainingDevicePath == NULL) { - // - // RemainingDevicePath is NULL, scan IDE bus for each device; - // - BeginningIdeChannel = IdePrimary; - EndIdeChannel = IdeSecondary; - BeginningIdeDevice = IdeMaster; - // - // default, may be redefined by IdeInit - // - EndIdeDevice = IdeSlave; - } else { - // - // RemainingDevicePath is not NULL, only scan the specified device. - // - Node = (EFI_DEV_PATH *) RemainingDevicePath; - BeginningIdeChannel = Node->Atapi.PrimarySecondary; - EndIdeChannel = BeginningIdeChannel; - BeginningIdeDevice = Node->Atapi.SlaveMaster; - EndIdeDevice = BeginningIdeDevice; - if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) { - Status = EFI_INVALID_PARAMETER; - goto ErrorExit; - } - if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) { - Status = EFI_INVALID_PARAMETER; - goto ErrorExit; - } - } - - // - // Obtain IDE IO port registers' base addresses - // - Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - // - // Report status code: begin IdeBus initialization - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), - ParentDevicePath - ); - - // - // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol - // - for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { - - IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel); - - // - // now obtain channel information fron IdeControllerInit protocol. Step9 - // - Status = IdeInit->GetChannelInfo ( - IdeInit, - IdeChannel, - &ChannelEnabled, - &MaxDevices - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status)); - continue; - } - - if (!ChannelEnabled) { - continue; - } - - EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice); - ASSERT (EndIdeDevice < IdeMaxDevice); - // - // Now inform the IDE Controller Init Module. Sept10 - // - IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel); - - // - // No reset channel function implemented. Sept11 - // - IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel); - - // - // Step13 - // - IdeInit->NotifyPhase ( - IdeInit, - EfiIdeBusBeforeDevicePresenceDetection, - IdeChannel - ); - - // - // Prepare to detect IDE device of this channel - // - InitializeIDEChannelData (); - - // - // -- 1st inner loop --- Master/Slave ------------ Step14 - // - for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { - // - // Check whether the configuration options allow this device - // - if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) { - continue; - } - - // - // The device has been scanned in another Start(), No need to scan it again - // for perf optimization. - // - if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) { - continue; - } - - // - // create child handle for the detected device. - // - IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV)); - if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) { - continue; - } - - IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; - - ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV)); - - IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE; - IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel; - IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice; - - // - // initialize Block IO interface's Media pointer - // - IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia; - - // - // Initialize IDE IO port addresses, including Command Block registers - // and Control Block registers - // - IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS)); - if (IdeBlkIoDevicePtr->IoPort == NULL) { - continue; - } - - ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS)); - CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr; - ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr; - - IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr; - (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); - IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); - IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); - IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); - IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); - IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); - (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); - - (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr; - IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); - - IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0); - - IdeBlkIoDevicePtr->PciIo = PciIo; - IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData; - IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr; - - // - // Report Status code: is about to detect IDE drive - // - REPORT_STATUS_CODE_EX ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT), - 0, - &gEfiCallerIdGuid, - NULL, - NULL, - 0 - ); - - // - // Discover device, now! - // - PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0); - Status = DiscoverIdeDevice (IdeBlkIoDevicePtr); - PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0); - - IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE; - IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE; - - if (!EFI_ERROR (Status)) { - // - // Set Device Path - // - ZeroMem (&NewNode, sizeof (NewNode)); - NewNode.DevPath.Type = MESSAGING_DEVICE_PATH; - NewNode.DevPath.SubType = MSG_ATAPI_DP; - SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH)); - - NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel; - NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device; - NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun; - IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode ( - ParentDevicePath, - &NewNode.DevPath - ); - if (IdeBlkIoDevicePtr->DevicePath == NULL) { - ReleaseIdeResources (IdeBlkIoDevicePtr); - continue; - } - - // - // Submit identify data to IDE controller init driver - // - CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData)); - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE; - IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData); - } else { - // - // Device detection failed - // - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL); - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - } - // - // end of 1st inner loop --- - // - } - // - // end of 1st outer loop ========= - // - } - - // - // = 2nd outer loop == Primary/Secondary ================= - // - for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { - - // - // -- 2nd inner loop --- Master/Slave -------- - // - for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { - - if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) { - continue; - } - - if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) { - continue; - } - - Status = IdeInit->CalculateMode ( - IdeInit, - IdeChannel, - IdeDevice, - &SupportedModes - ); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status)); - continue; - } - - IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; - - // - // Set best supported PIO mode on this IDE device - // - if (SupportedModes->PioMode.Mode <= AtaPioMode2) { - TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO; - } else { - TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO; - } - - TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode); - - if (SupportedModes->ExtModeCount == 0){ - Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); - - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - continue; - } - } - - // - // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't - // be set together. Only one DMA mode can be set to a device. If setting - // DMA mode operation fails, we can continue moving on because we only use - // PIO mode at boot time. DMA modes are used by certain kind of OS booting - // - if (SupportedModes->UdmaMode.Valid) { - - TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA; - TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode); - Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); - - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - continue; - } - // - // Record Udma Mode - // - IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE; - IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode; - EnableInterrupt (IdeBlkIoDevicePtr); - } else if (SupportedModes->MultiWordDmaMode.Valid) { - - TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA; - TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode; - Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); - - if (EFI_ERROR (Status)) { - IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; - ReleaseIdeResources (IdeBlkIoDevicePtr); - IdeBlkIoDevicePtr = NULL; - continue; - } - - EnableInterrupt (IdeBlkIoDevicePtr); - } - // - // Init driver parameters - // - DriveParameters.Sector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.sectors_per_track; - DriveParameters.Heads = (UINT8) (IdeBlkIoDevicePtr->IdData->AtaData.heads - 1); - DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt; - // - // Set Parameters for the device: - // 1) Init - // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command - // - if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) { - Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters); - } - - // - // Record PIO mode used in private data - // - IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode; - - // - // Set IDE controller Timing Blocks in the PCI Configuration Space - // - IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes); - - // - // Add Component Name for the IDE/ATAPI device that was discovered. - // - IdeBlkIoDevicePtr->ControllerNameTable = NULL; - ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr); - - Status = gBS->InstallMultipleProtocolInterfaces ( - &IdeBlkIoDevicePtr->Handle, - &gEfiDevicePathProtocolGuid, - IdeBlkIoDevicePtr->DevicePath, - &gEfiBlockIoProtocolGuid, - &IdeBlkIoDevicePtr->BlkIo, - &gEfiDiskInfoProtocolGuid, - &IdeBlkIoDevicePtr->DiskInfo, - NULL - ); - - if (EFI_ERROR (Status)) { - ReleaseIdeResources (IdeBlkIoDevicePtr); - } - - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - IdeBlkIoDevicePtr->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - - IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE; - - // - // Report status code: device eanbled! - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE), - IdeBlkIoDevicePtr->DevicePath - ); - - // - // Create event to clear pending IDE interrupt - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - ClearInterrupt, - IdeBlkIoDevicePtr, - &gEfiEventExitBootServicesGuid, - &IdeBlkIoDevicePtr->ExitBootServiceEvent - ); - - // - // end of 2nd inner loop ---- - // - } - // - // end of 2nd outer loop ========== - // - } - - // - // All configurations done! Notify IdeController to do post initialization - // work such as saving IDE controller PCI settings for S3 resume - // - IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0); - - if (SupportedModes != NULL) { - gBS->FreePool (SupportedModes); - } - - PERF_START (NULL, "Finish IDE detection", "IDE", 1); - PERF_END (NULL, "Finish IDE detection", "IDE", 0); - - return EFI_SUCCESS; - -ErrorExit: - - // - // Report error code: controller error - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR), - ParentDevicePath - ); - - gBS->CloseProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiCallerIdGuid, - IdeBusDriverPrivateData, - NULL - ); - - if (IdeBusDriverPrivateData != NULL) { - gBS->FreePool (IdeBusDriverPrivateData); - } - - if (SupportedModes != NULL) { - gBS->FreePool (SupportedModes); - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; - -} -/** - Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all - child handle attached to the controller handle if there are. - - @param This Protocol instance pointer. - @param Controller Handle of device to stop driver on - @param NumberOfChildren Not used - @param ChildHandleBuffer Not used - - @retval EFI_SUCCESS This driver is removed DeviceHandle - @retval other This driver was not removed from this device - -**/ -EFI_STATUS -EFIAPI -IDEBusDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - BOOLEAN AllChildrenStopped; - UINTN Index; - IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; - UINT64 Supports; - - IdeBusDriverPrivateData = NULL; - - if (NumberOfChildren == 0) { - - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - if (!EFI_ERROR (Status)) { - Supports &= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE; - PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationDisable, - Supports, - NULL - ); - } - } - - gBS->OpenProtocol ( - Controller, - &gEfiCallerIdGuid, - (VOID **) &IdeBusDriverPrivateData, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiCallerIdGuid, - IdeBusDriverPrivateData, - NULL - ); - - if (IdeBusDriverPrivateData != NULL) { - gBS->FreePool (IdeBusDriverPrivateData); - } - // - // Close the bus driver - // - gBS->CloseProtocol ( - Controller, - &gEfiIdeControllerInitProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return EFI_SUCCESS; - } - - AllChildrenStopped = TRUE; - - for (Index = 0; Index < NumberOfChildren; Index++) { - - Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]); - - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - issue ATA or ATAPI command to reset a block IO device. - @param This Block IO protocol instance pointer. - @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method - If TRUE, for ATAPI device, driver need invoke ATA reset method after - invoke ATAPI reset method - - @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device. - @retval EFI_SUCCESS The device reset successfully - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_STATUS Status; - EFI_TPL OldTpl; - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); - // - // Requery IDE IO resources in case of the switch of native and legacy modes - // - ReassignIdeResources (IdeBlkIoDevice); - - // - // for ATA device, using ATA reset method - // - if (IdeBlkIoDevice->Type == IdeHardDisk || - IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - Status = AtaSoftReset (IdeBlkIoDevice); - goto Done; - } - - if (IdeBlkIoDevice->Type == IdeUnknown) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - // - // for ATAPI device, using ATAPI reset method - // - Status = AtapiSoftReset (IdeBlkIoDevice); - if (ExtendedVerification) { - Status = AtaSoftReset (IdeBlkIoDevice); - } - -Done: - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - Read data from a block IO device - - @param This Block IO protocol instance pointer. - @param MediaId The media ID of the device + Copyright (c) 2006 - 2008, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This module is modified from DXE\IDE module for Ide Contriller Init support
+
+**/
+
+#include "IdeBus.h"
+
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_SUB_CLASS_IDE 0x01
+
+
+//
+// IDE Bus Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
+ IDEBusDriverBindingSupported,
+ IDEBusDriverBindingStart,
+ IDEBusDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+/**
+ Deregister an IDE device and free resources
+
+ @param This Protocol instance pointer.
+ @param Controller Ide device handle
+ @param Handle Handle of device to deregister driver on
+
+ @retval EFI_SUCCESS Deregiter a specific IDE device successfully
+
+
+**/
+EFI_STATUS
+DeRegisterIdeDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Index;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
+
+ //
+ // Report Status code: Device disabled
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),
+ IdeBlkIoDevice->DevicePath
+ );
+
+ //
+ // Close the child handle
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ IdeBlkIoDevice->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &IdeBlkIoDevice->BlkIo,
+ &gEfiDiskInfoProtocolGuid,
+ &IdeBlkIoDevice->DiskInfo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ //
+ // Release allocated resources
+ //
+ Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;
+ if (Index < MAX_IDE_DEVICE) {
+ IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;
+ }
+ ReleaseIdeResources (IdeBlkIoDevice);
+
+ return EFI_SUCCESS;
+}
+/**
+ Supported function of Driver Binding protocol for this driver.
+
+ @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param ControllerHandle The handle of the controller to test.
+ @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Driver loaded.
+ @retval other Driver not loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEV_PATH *Node;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
+
+ if (RemainingDevicePath != NULL) {
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
+ Node->DevPath.SubType != MSG_ATAPI_DP ||
+ DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close protocol, don't use device path protocol in the .Support() function
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Verify the Ide Controller Init Protocol, which installed by the
+ // IdeController module.
+ // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
+ // open BY_DRIVER here) That's why we don't check pciio protocol
+ // Note 2: ide_init driver check ide controller's pci config space, so we dont
+ // check here any more to save code size
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **) &IdeInit,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If protocols were opened normally, closed it
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+
+/**
+ Start function of Driver binding protocol which start this driver on Controller
+ by detecting all disks and installing BlockIo protocol on them.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath produce all possible children.
+
+ @retval EFI_SUCCESS This driver is added to ControllerHandle.
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS SavedStatus;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEV_PATH *Node;
+ UINT8 IdeChannel;
+ UINT8 BeginningIdeChannel;
+ UINT8 EndIdeChannel;
+ UINT8 IdeDevice;
+ UINT8 BeginningIdeDevice;
+ UINT8 EndIdeDevice;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
+ IDE_BLK_IO_DEV *IdeBlkIoDevicePtr;
+ IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
+ ATA_TRANSFER_MODE TransferMode;
+ ATA_DRIVE_PARMS DriveParameters;
+ EFI_DEV_PATH NewNode;
+ UINT8 ConfigurationOptions;
+ UINT16 CommandBlockBaseAddr;
+ UINT16 ControlBlockBaseAddr;
+ UINTN DataSize;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+ UINT64 Supports;
+
+ //
+ // Local variables declaration for IdeControllerInit support
+ //
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
+ BOOLEAN EnumAll;
+ BOOLEAN ChannelEnabled;
+ UINT8 MaxDevices;
+ EFI_IDENTIFY_DATA IdentifyData;
+ EFI_ATA_COLLECTIVE_MODE *SupportedModes;
+
+ IdeBusDriverPrivateData = NULL;
+ SupportedModes = NULL;
+
+ //
+ // Perform IdeBus initialization
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ //
+ // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **) &IdeInit,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ //
+ // The following OpenProtocol function with _GET_PROTOCOL attribute and
+ // will not return EFI_ALREADY_STARTED, so save it for now
+ //
+ SavedStatus = Status;
+
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
+ //
+ // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
+ //
+ goto ErrorExit;
+ }
+
+ //
+ // Save Enumall. Step7.2
+ //
+ EnumAll = IdeInit->EnumAll;
+
+ //
+ // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
+ // attribute will not return EFI_ALREADY_STARTED
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
+ goto ErrorExit;
+ }
+
+ //
+ // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
+ //
+ if (SavedStatus != EFI_ALREADY_STARTED) {
+ IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+ if (IdeBusDriverPrivateData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ } else {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &IdeBusDriverPrivateData,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData = NULL;
+ goto ErrorExit;
+ }
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Read the environment variable that contains the IDEBus Driver's
+ // Config options that were set by the Driver Configuration Protocol
+ //
+ DataSize = sizeof (ConfigurationOptions);
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Configuration",
+ &gEfiCallerIdGuid,
+ NULL,
+ &DataSize,
+ &ConfigurationOptions
+ );
+ if (EFI_ERROR (Status)) {
+ ConfigurationOptions = 0x0f;
+ }
+
+ if (EnumAll) {
+ //
+ // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
+ //
+ BeginningIdeChannel = IdePrimary;
+ EndIdeChannel = IdeSecondary;
+ BeginningIdeDevice = IdeMaster;
+ EndIdeDevice = IdeSlave;
+ } else if (RemainingDevicePath == NULL) {
+ //
+ // RemainingDevicePath is NULL, scan IDE bus for each device;
+ //
+ BeginningIdeChannel = IdePrimary;
+ EndIdeChannel = IdeSecondary;
+ BeginningIdeDevice = IdeMaster;
+ //
+ // default, may be redefined by IdeInit
+ //
+ EndIdeDevice = IdeSlave;
+ } else {
+ //
+ // RemainingDevicePath is not NULL, only scan the specified device.
+ //
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ BeginningIdeChannel = Node->Atapi.PrimarySecondary;
+ EndIdeChannel = BeginningIdeChannel;
+ BeginningIdeDevice = Node->Atapi.SlaveMaster;
+ EndIdeDevice = BeginningIdeDevice;
+ if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ErrorExit;
+ }
+ if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ErrorExit;
+ }
+ }
+
+ //
+ // Obtain IDE IO port registers' base addresses
+ //
+ Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Report status code: begin IdeBus initialization
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
+ ParentDevicePath
+ );
+
+ //
+ // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
+ //
+ for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
+
+ //
+ // now obtain channel information fron IdeControllerInit protocol. Step9
+ //
+ Status = IdeInit->GetChannelInfo (
+ IdeInit,
+ IdeChannel,
+ &ChannelEnabled,
+ &MaxDevices
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
+ continue;
+ }
+
+ if (!ChannelEnabled) {
+ continue;
+ }
+
+ EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice);
+ ASSERT (EndIdeDevice < IdeMaxDevice);
+ //
+ // Now inform the IDE Controller Init Module. Sept10
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
+
+ //
+ // No reset channel function implemented. Sept11
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
+
+ //
+ // Step13
+ //
+ IdeInit->NotifyPhase (
+ IdeInit,
+ EfiIdeBusBeforeDevicePresenceDetection,
+ IdeChannel
+ );
+
+ //
+ // Prepare to detect IDE device of this channel
+ //
+ InitializeIDEChannelData ();
+
+ //
+ // -- 1st inner loop --- Master/Slave ------------ Step14
+ //
+ for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+ //
+ // Check whether the configuration options allow this device
+ //
+ if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) {
+ continue;
+ }
+
+ //
+ // The device has been scanned in another Start(), No need to scan it again
+ // for perf optimization.
+ //
+ if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ //
+ // create child handle for the detected device.
+ //
+ IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));
+ if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
+ continue;
+ }
+
+ IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+ ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
+
+ IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE;
+ IdeBlkIoDevicePtr->Channel = (EFI_IDE_CHANNEL) IdeChannel;
+ IdeBlkIoDevicePtr->Device = (EFI_IDE_DEVICE) IdeDevice;
+
+ //
+ // initialize Block IO interface's Media pointer
+ //
+ IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
+
+ //
+ // Initialize IDE IO port addresses, including Command Block registers
+ // and Control Block registers
+ //
+ IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));
+ if (IdeBlkIoDevicePtr->IoPort == NULL) {
+ continue;
+ }
+
+ ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
+ CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
+ ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
+
+ IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
+ IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
+ IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
+ IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
+ IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
+ IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
+
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
+ IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
+
+ IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
+
+ IdeBlkIoDevicePtr->PciIo = PciIo;
+ IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
+ IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
+
+ //
+ // Report Status code: is about to detect IDE drive
+ //
+ REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+
+ //
+ // Discover device, now!
+ //
+ PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0);
+ Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
+ PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0);
+
+ IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE;
+ IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE;
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set Device Path
+ //
+ ZeroMem (&NewNode, sizeof (NewNode));
+ NewNode.DevPath.Type = MESSAGING_DEVICE_PATH;
+ NewNode.DevPath.SubType = MSG_ATAPI_DP;
+ SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
+
+ NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel;
+ NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device;
+ NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun;
+ IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ &NewNode.DevPath
+ );
+ if (IdeBlkIoDevicePtr->DevicePath == NULL) {
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ continue;
+ }
+
+ //
+ // Submit identify data to IDE controller init driver
+ //
+ CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData));
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
+ IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
+ } else {
+ //
+ // Device detection failed
+ //
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ }
+ //
+ // end of 1st inner loop ---
+ //
+ }
+ //
+ // end of 1st outer loop =========
+ //
+ }
+
+ //
+ // = 2nd outer loop == Primary/Secondary =================
+ //
+ for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+ //
+ // -- 2nd inner loop --- Master/Slave --------
+ //
+ for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+
+ if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ Status = IdeInit->CalculateMode (
+ IdeInit,
+ IdeChannel,
+ IdeDevice,
+ &SupportedModes
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
+ continue;
+ }
+
+ IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+ //
+ // Set best supported PIO mode on this IDE device
+ //
+ if (SupportedModes->PioMode.Mode <= AtaPioMode2) {
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
+ } else {
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
+ }
+
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
+
+ if (SupportedModes->ExtModeCount == 0){
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+ }
+
+ //
+ // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
+ // be set together. Only one DMA mode can be set to a device. If setting
+ // DMA mode operation fails, we can continue moving on because we only use
+ // PIO mode at boot time. DMA modes are used by certain kind of OS booting
+ //
+ if (SupportedModes->UdmaMode.Valid) {
+
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+ //
+ // Record Udma Mode
+ //
+ IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;
+ IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode;
+ EnableInterrupt (IdeBlkIoDevicePtr);
+ } else if (SupportedModes->MultiWordDmaMode.Valid) {
+
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
+ TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+
+ EnableInterrupt (IdeBlkIoDevicePtr);
+ }
+ //
+ // Init driver parameters
+ //
+ DriveParameters.Sector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.sectors_per_track;
+ DriveParameters.Heads = (UINT8) (IdeBlkIoDevicePtr->IdData->AtaData.heads - 1);
+ DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt;
+ //
+ // Set Parameters for the device:
+ // 1) Init
+ // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
+ //
+ if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
+ Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
+ }
+
+ //
+ // Record PIO mode used in private data
+ //
+ IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;
+
+ //
+ // Set IDE controller Timing Blocks in the PCI Configuration Space
+ //
+ IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
+
+ //
+ // Add Component Name for the IDE/ATAPI device that was discovered.
+ //
+ IdeBlkIoDevicePtr->ControllerNameTable = NULL;
+ ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &IdeBlkIoDevicePtr->Handle,
+ &gEfiDevicePathProtocolGuid,
+ IdeBlkIoDevicePtr->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &IdeBlkIoDevicePtr->BlkIo,
+ &gEfiDiskInfoProtocolGuid,
+ &IdeBlkIoDevicePtr->DiskInfo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ }
+
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ IdeBlkIoDevicePtr->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
+
+ //
+ // Report status code: device eanbled!
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
+ IdeBlkIoDevicePtr->DevicePath
+ );
+
+ //
+ // Create event to clear pending IDE interrupt
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ClearInterrupt,
+ IdeBlkIoDevicePtr,
+ &gEfiEventExitBootServicesGuid,
+ &IdeBlkIoDevicePtr->ExitBootServiceEvent
+ );
+
+ //
+ // end of 2nd inner loop ----
+ //
+ }
+ //
+ // end of 2nd outer loop ==========
+ //
+ }
+
+ //
+ // All configurations done! Notify IdeController to do post initialization
+ // work such as saving IDE controller PCI settings for S3 resume
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
+
+ if (SupportedModes != NULL) {
+ gBS->FreePool (SupportedModes);
+ }
+
+ PERF_START (NULL, "Finish IDE detection", "IDE", 1);
+ PERF_END (NULL, "Finish IDE detection", "IDE", 0);
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ //
+ // Report error code: controller error
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
+ ParentDevicePath
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+
+ if (IdeBusDriverPrivateData != NULL) {
+ gBS->FreePool (IdeBusDriverPrivateData);
+ }
+
+ if (SupportedModes != NULL) {
+ gBS->FreePool (SupportedModes);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+
+}
+/**
+ Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
+ child handle attached to the controller handle if there are.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on
+ @param NumberOfChildren Not used
+ @param ChildHandleBuffer Not used
+
+ @retval EFI_SUCCESS This driver is removed DeviceHandle
+ @retval other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+ UINT64 Supports;
+
+ IdeBusDriverPrivateData = NULL;
+
+ if (NumberOfChildren == 0) {
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE;
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ Supports,
+ NULL
+ );
+ }
+ }
+
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &IdeBusDriverPrivateData,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+
+ if (IdeBusDriverPrivateData != NULL) {
+ gBS->FreePool (IdeBusDriverPrivateData);
+ }
+ //
+ // Close the bus driver
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ issue ATA or ATAPI command to reset a block IO device.
+ @param This Block IO protocol instance pointer.
+ @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
+ If TRUE, for ATAPI device, driver need invoke ATA reset method after
+ invoke ATAPI reset method
+
+ @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device.
+ @retval EFI_SUCCESS The device reset successfully
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // for ATA device, using ATA reset method
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ Status = AtaSoftReset (IdeBlkIoDevice);
+ goto Done;
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // for ATAPI device, using ATAPI reset method
+ //
+ Status = AtapiSoftReset (IdeBlkIoDevice);
+ if (ExtendedVerification) {
+ Status = AtaSoftReset (IdeBlkIoDevice);
+ }
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Read data from a block IO device
+
+ @param This Block IO protocol instance pointer.
+ @param MediaId The media ID of the device
@param Lba Starting LBA address to read data
- @param BufferSize The size of data to be read - @param Buffer Caller supplied buffer to save data - - @retval EFI_DEVICE_ERROR unknown device type - @retval other read data status. - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, + @param BufferSize The size of data to be read
+ @param Buffer Caller supplied buffer to save data
+
+ @retval EFI_DEVICE_ERROR unknown device type
+ @retval other read data status.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
IN EFI_LBA Lba,
- IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_STATUS Status; - EFI_TPL OldTpl; - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); - - // - // Requery IDE IO resources in case of the switch of native and legacy modes - // - ReassignIdeResources (IdeBlkIoDevice); - - // - // For ATA compatible device, use ATA read block's mechanism - // - if (IdeBlkIoDevice->Type == IdeHardDisk || - IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - Status = AtaBlkIoReadBlocks ( - IdeBlkIoDevice, - MediaId, + IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // For ATA compatible device, use ATA read block's mechanism
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ Status = AtaBlkIoReadBlocks (
+ IdeBlkIoDevice,
+ MediaId,
Lba,
- BufferSize, - Buffer - ); - goto Done; - } - - if (IdeBlkIoDevice->Type == IdeUnknown) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - // - // for ATAPI device, using ATAPI read block's mechanism - // - Status = AtapiBlkIoReadBlocks ( - IdeBlkIoDevice, - MediaId, + BufferSize,
+ Buffer
+ );
+ goto Done;
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // for ATAPI device, using ATAPI read block's mechanism
+ //
+ Status = AtapiBlkIoReadBlocks (
+ IdeBlkIoDevice,
+ MediaId,
Lba,
- BufferSize, - Buffer - ); - -Done: - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** + BufferSize,
+ Buffer
+ );
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
Write data to block io device.
- - @param This Protocol instance pointer. - @param MediaId The media ID of the device +
+ @param This Protocol instance pointer.
+ @param MediaId The media ID of the device
@param Lba Starting LBA address to write data
- @param BufferSize The size of data to be written - @param Buffer Caller supplied buffer to save data - - @retval EFI_DEVICE_ERROR unknown device type - @retval other write data status - -**/ -EFI_STATUS -EFIAPI -IDEBlkIoWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, + @param BufferSize The size of data to be written
+ @param Buffer Caller supplied buffer to save data
+
+ @retval EFI_DEVICE_ERROR unknown device type
+ @retval other write data status
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
IN EFI_LBA Lba,
- IN UINTN BufferSize, - IN VOID *Buffer - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_STATUS Status; - EFI_TPL OldTpl; - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); - // - // Requery IDE IO resources in case of the switch of native and legacy modes - // - ReassignIdeResources (IdeBlkIoDevice); - - // - // for ATA device, using ATA write block's mechanism - // - if (IdeBlkIoDevice->Type == IdeHardDisk || - IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - - Status = AtaBlkIoWriteBlocks ( - IdeBlkIoDevice, - MediaId, + IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // for ATA device, using ATA write block's mechanism
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+
+ Status = AtaBlkIoWriteBlocks (
+ IdeBlkIoDevice,
+ MediaId,
Lba,
- BufferSize, - Buffer - ); - goto Done; - } - - if (IdeBlkIoDevice->Type == IdeUnknown) { - Status = EFI_DEVICE_ERROR; - goto Done; - } - - // - // for ATAPI device, using ATAPI write block's mechanism - // - Status = AtapiBlkIoWriteBlocks ( - IdeBlkIoDevice, - MediaId, + BufferSize,
+ Buffer
+ );
+ goto Done;
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // for ATAPI device, using ATAPI write block's mechanism
+ //
+ Status = AtapiBlkIoWriteBlocks (
+ IdeBlkIoDevice,
+ MediaId,
Lba,
- BufferSize, - Buffer - ); - -Done: - gBS->RestoreTPL (OldTpl); - return Status; -} -/** - Flushes all modified data to a physical block devices - - @param This Indicates a pointer to the calling context which to sepcify a - sepcific block device - - @retval EFI_SUCCESS Always return success. -**/ -EFI_STATUS -EFIAPI -IDEBlkIoFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ) -{ - // - // return directly - // - return EFI_SUCCESS; -} - -/** + BufferSize,
+ Buffer
+ );
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+/**
+ Flushes all modified data to a physical block devices
+
+ @param This Indicates a pointer to the calling context which to sepcify a
+ sepcific block device
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ //
+ // return directly
+ //
+ return EFI_SUCCESS;
+}
+
+/**
This function is used by the IDE bus driver to get inquiry data.
Data format of Identify data is defined by the Interface GUID.
- +
@param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
@param InquiryData Pointer to a buffer for the inquiry data.
@param InquiryDataSize Pointer to the value for the inquiry data size.
- +
@retval EFI_SUCCESS The command was accepted without any errors.
@retval EFI_NOT_FOUND Device does not support this data class
@retval EFI_DEVICE_ERROR Error reading InquiryData from device
@retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
- -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoInquiry ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *InquiryData, - IN OUT UINT32 *InquiryDataSize - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); - - if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) { - *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA); - return EFI_BUFFER_TOO_SMALL; - } - - if (IdeBlkIoDevice->InquiryData == NULL) { - return EFI_NOT_FOUND; - } - - gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA)); - *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA); - - return EFI_SUCCESS; -} - -/** +
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+ if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) {
+ *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (IdeBlkIoDevice->InquiryData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA));
+ *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
+
+ return EFI_SUCCESS;
+}
+
+/**
This function is used by the IDE bus driver to get identify data.
- Data format of Identify data is defined by the Interface GUID. - + Data format of Identify data is defined by the Interface GUID.
+
@param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
@param IdentifyData Pointer to a buffer for the identify data.
@param IdentifyDataSize Pointer to the value for the identify data size.
- +
@retval EFI_SUCCESS The command was accepted without any errors.
@retval EFI_NOT_FOUND Device does not support this data class
@retval EFI_DEVICE_ERROR Error reading IdentifyData from device
@retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
- -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoIdentify ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *IdentifyData, - IN OUT UINT32 *IdentifyDataSize - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); - - if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) { - *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); - return EFI_BUFFER_TOO_SMALL; - } - - if (IdeBlkIoDevice->IdData == NULL) { - return EFI_NOT_FOUND; - } - - gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA)); - *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); - - return EFI_SUCCESS; -} - -/** +
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+ if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {
+ *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (IdeBlkIoDevice->IdData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA));
+ *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+
+ return EFI_SUCCESS;
+}
+
+/**
This function is used by the IDE bus driver to get sense data.
- Data format of Sense data is defined by the Interface GUID. - + Data format of Sense data is defined by the Interface GUID.
+
@param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
@param SenseData Pointer to the SenseData.
@param SenseDataSize Size of SenseData in bytes.
@param SenseDataNumber Pointer to the value for the identify data size.
- +
@retval EFI_SUCCESS The command was accepted without any errors.
@retval EFI_NOT_FOUND Device does not support this data class
@retval EFI_DEVICE_ERROR Error reading InquiryData from device
@retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
- -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoSenseData ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *SenseData, - IN OUT UINT32 *SenseDataSize, - OUT UINT8 *SenseDataNumber - ) -{ - return EFI_NOT_FOUND; -} - -/** +
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
This function is used by the IDE bus driver to get controller information.
- +
@param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
@param IdeChannel Pointer to the Ide Channel number. Primary or secondary.
@param IdeDevice Pointer to the Ide Device number. Master or slave.
- +
@retval EFI_SUCCESS IdeChannel and IdeDevice are valid
@retval EFI_UNSUPPORTED This is not an IDE device
- -**/ -EFI_STATUS -EFIAPI -IDEDiskInfoWhichIde ( - IN EFI_DISK_INFO_PROTOCOL *This, - OUT UINT32 *IdeChannel, - OUT UINT32 *IdeDevice - ) -{ - IDE_BLK_IO_DEV *IdeBlkIoDevice; - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); - *IdeChannel = IdeBlkIoDevice->Channel; - *IdeDevice = IdeBlkIoDevice->Device; - - return EFI_SUCCESS; -} - -/** - The is an event(generally the event is exitBootService event) call back function. - Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. - - @param Event Pointer to this event - @param Context Event hanlder private data - -**/ -VOID -EFIAPI -ClearInterrupt ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - UINT64 IoPortForBmis; - UINT8 RegisterValue; - IDE_BLK_IO_DEV *IdeDev; - - // - // Get our context - // - IdeDev = (IDE_BLK_IO_DEV *) Context; - - // - // Obtain IDE IO port registers' base addresses - // - Status = ReassignIdeResources (IdeDev); - if (EFI_ERROR (Status)) { - return; - } - - // - // Check whether interrupt is pending - // - - // - // Reset IDE device to force it de-assert interrupt pin - // Note: this will reset all devices on this IDE channel - // - AtaSoftReset (IdeDev); - if (EFI_ERROR (Status)) { - return; - } - - // - // Get base address of IDE Bus Master Status Regsiter - // - if (IdePrimary == IdeDev->Channel) { - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; - } else { - if (IdeSecondary == IdeDev->Channel) { - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; - } else { - return; - } - } - // - // Read BMIS register and clear ERROR and INTR bit - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - - RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); - - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - - // - // Select the other device on this channel to ensure this device to release the interrupt pin - // - if (IdeDev->Device == 0) { - RegisterValue = (1 << 4) | 0xe0; - } else { - RegisterValue = (0 << 4) | 0xe0; - } - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - RegisterValue - ); - -} - -/** - The user Entry Point for module IdeBus. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InitializeIdeBus( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallAllDriverProtocols2 ( - ImageHandle, - SystemTable, - &gIDEBusDriverBinding, - ImageHandle, - &gIDEBusComponentName, - &gIDEBusComponentName2, - NULL, - NULL, - &gIDEBusDriverDiagnostics, - &gIDEBusDriverDiagnostics2 - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} +
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+ *IdeChannel = IdeBlkIoDevice->Channel;
+ *IdeDevice = IdeBlkIoDevice->Device;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The is an event(generally the event is exitBootService event) call back function.
+ Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
+
+ @param Event Pointer to this event
+ @param Context Event hanlder private data
+
+**/
+VOID
+EFIAPI
+ClearInterrupt (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINT64 IoPortForBmis;
+ UINT8 RegisterValue;
+ IDE_BLK_IO_DEV *IdeDev;
+
+ //
+ // Get our context
+ //
+ IdeDev = (IDE_BLK_IO_DEV *) Context;
+
+ //
+ // Obtain IDE IO port registers' base addresses
+ //
+ Status = ReassignIdeResources (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Check whether interrupt is pending
+ //
+
+ //
+ // Reset IDE device to force it de-assert interrupt pin
+ // Note: this will reset all devices on this IDE channel
+ //
+ AtaSoftReset (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Get base address of IDE Bus Master Status Regsiter
+ //
+ if (IdePrimary == IdeDev->Channel) {
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+ } else {
+ if (IdeSecondary == IdeDev->Channel) {
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+ } else {
+ return;
+ }
+ }
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Select the other device on this channel to ensure this device to release the interrupt pin
+ //
+ if (IdeDev->Device == 0) {
+ RegisterValue = (1 << 4) | 0xe0;
+ } else {
+ RegisterValue = (0 << 4) | 0xe0;
+ }
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ RegisterValue
+ );
+
+}
+
+/**
+ The user Entry Point for module IdeBus. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeIdeBus(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallAllDriverProtocols2 (
+ ImageHandle,
+ SystemTable,
+ &gIDEBusDriverBinding,
+ ImageHandle,
+ &gIDEBusComponentName,
+ &gIDEBusComponentName2,
+ NULL,
+ NULL,
+ &gIDEBusDriverDiagnostics,
+ &gIDEBusDriverDiagnostics2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
|