a. Update PciBusDxe module, and move it from IntelFrameworkModulePkg to MdeModulePkg b. Move IncompatiblePciDeviceSupportDxe module from IntelFrameworkModulePkg to MdeModulePkg c. Update the related consumes in inf/dsc/fdf git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9347 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			383 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			383 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Driver Binding functions for PCI Bus module.
 | 
						|
 | 
						|
  Single PCI bus driver instance will manager all PCI Root Bridges in one EFI based firmware,
 | 
						|
  since all PCI Root Bridges' resources need to be managed together.
 | 
						|
  Supported() function will try to get PCI Root Bridge IO Protocol.
 | 
						|
  Start() function will get PCI Host Bridge Resource Allocation Protocol to manage all
 | 
						|
  PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
 | 
						|
  PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2009, 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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "PciBus.h"
 | 
						|
 | 
						|
//
 | 
						|
// PCI Bus Driver Global Variables
 | 
						|
//
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {
 | 
						|
  PciBusDriverBindingSupported,
 | 
						|
  PciBusDriverBindingStart,
 | 
						|
  PciBusDriverBindingStop,
 | 
						|
  0xa,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
EFI_HANDLE                                    gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
 | 
						|
EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *gEfiIncompatiblePciDeviceSupport = NULL;
 | 
						|
UINTN                                         gPciHostBridgeNumber = 0;
 | 
						|
BOOLEAN                                       gFullEnumeration     = TRUE;
 | 
						|
UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
 | 
						|
UINT64                                        gAllZero             = 0;
 | 
						|
 | 
						|
EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
 | 
						|
EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
 | 
						|
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {
 | 
						|
  PciHotPlugRequestNotify
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  The Entry Point for PCI Bus module. The user code starts with this function.
 | 
						|
 | 
						|
  Installs driver module protocols and. Creates virtual device handles for ConIn,
 | 
						|
  ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
 | 
						|
  Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
 | 
						|
  Installs Graphics Output protocol and/or UGA Draw protocol if needed.
 | 
						|
 | 
						|
  @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 occurred when executing this entry point.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PciBusEntryPoint (
 | 
						|
  IN EFI_HANDLE         ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE   *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_HANDLE  Handle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initializes PCI devices pool
 | 
						|
  //
 | 
						|
  InitializePciDevicePool ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Install driver model protocol(s).
 | 
						|
  //
 | 
						|
  Status = EfiLibInstallDriverBindingComponentName2 (
 | 
						|
             ImageHandle,
 | 
						|
             SystemTable,
 | 
						|
             &gPciBusDriverBinding,
 | 
						|
             ImageHandle,
 | 
						|
             &gPciBusComponentName,
 | 
						|
             &gPciBusComponentName2
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
 | 
						|
    //
 | 
						|
    // If Hot Plug is supported, install EFI PCI Hot Plug Request protocol.
 | 
						|
    //
 | 
						|
    Handle = NULL;
 | 
						|
    Status = gBS->InstallProtocolInterface (
 | 
						|
                    &Handle,
 | 
						|
                    &gEfiPciHotPlugRequestProtocolGuid,
 | 
						|
                    EFI_NATIVE_INTERFACE,
 | 
						|
                    &mPciHotPlugRequest
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Test to see if this driver supports ControllerHandle. Any ControllerHandle
 | 
						|
  than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.
 | 
						|
 | 
						|
  @param  This                Protocol instance pointer.
 | 
						|
  @param  Controller          Handle of device to test.
 | 
						|
  @param  RemainingDevicePath Optional parameter use to pick a specific child.
 | 
						|
                              device to start.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         This driver supports this device.
 | 
						|
  @retval EFI_ALREADY_STARTED This driver is already running on this device.
 | 
						|
  @retval other               This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PciBusDriverBindingSupported (
 | 
						|
  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_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
 | 
						|
  EFI_DEV_PATH_PTR                Node;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check RemainingDevicePath validation
 | 
						|
  //
 | 
						|
  if (RemainingDevicePath != NULL) {
 | 
						|
    //
 | 
						|
    // Check if RemainingDevicePath is the End of Device Path Node, 
 | 
						|
    // if yes, go on checking other conditions
 | 
						|
    //
 | 
						|
    if (!IsDevicePathEnd (RemainingDevicePath)) {
 | 
						|
      //
 | 
						|
      // If RemainingDevicePath isn't the End of Device Path Node,
 | 
						|
      // check its validation
 | 
						|
      //
 | 
						|
      Node.DevPath = RemainingDevicePath;
 | 
						|
      if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
 | 
						|
          Node.DevPath->SubType != HW_PCI_DP         ||
 | 
						|
          DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {
 | 
						|
        return EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if Pci Root Bridge IO protocol is installed by platform
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciRootBridgeIoProtocolGuid,
 | 
						|
                  (VOID **) &PciRootBridgeIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (Status == EFI_ALREADY_STARTED) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Close the I/O Abstraction(s) used to perform the supported test
 | 
						|
  //
 | 
						|
  gBS->CloseProtocol (
 | 
						|
        Controller,
 | 
						|
        &gEfiPciRootBridgeIoProtocolGuid,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        Controller
 | 
						|
        );
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the EFI Device Path protocol 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
 | 
						|
        );
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start this driver on ControllerHandle and enumerate Pci bus and start
 | 
						|
  all device under PCI bus.
 | 
						|
 | 
						|
  @param  This                 Protocol instance pointer.
 | 
						|
  @param  Controller           Handle of device to bind driver to.
 | 
						|
  @param  RemainingDevicePath  Optional parameter use to pick a specific child.
 | 
						|
                               device to start.
 | 
						|
 | 
						|
  @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
 | 
						|
PciBusDriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check RemainingDevicePath validation
 | 
						|
  //
 | 
						|
  if (RemainingDevicePath != NULL) {
 | 
						|
    //
 | 
						|
    // Check if RemainingDevicePath is the End of Device Path Node, 
 | 
						|
    // if yes, return EFI_SUCCESS
 | 
						|
    //
 | 
						|
    if (IsDevicePathEnd (RemainingDevicePath)) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiIncompatiblePciDeviceSupportProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) &gEfiIncompatiblePciDeviceSupport
 | 
						|
                  );
 | 
						|
 | 
						|
  //
 | 
						|
  // If PCI Platform protocol is available, get it now.
 | 
						|
  // If the platform implements this, it must be installed before BDS phase
 | 
						|
  //
 | 
						|
  gPciPlatformProtocol = NULL;
 | 
						|
  gBS->LocateProtocol (
 | 
						|
        &gEfiPciPlatformProtocolGuid,
 | 
						|
        NULL,
 | 
						|
        (VOID **) &gPciPlatformProtocol
 | 
						|
        );
 | 
						|
 | 
						|
  //
 | 
						|
  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
 | 
						|
  //
 | 
						|
  if (gPciPlatformProtocol == NULL) { 
 | 
						|
    gPciOverrideProtocol = NULL;
 | 
						|
    gBS->LocateProtocol (
 | 
						|
          &gEfiPciOverrideProtocolGuid,
 | 
						|
          NULL,
 | 
						|
          (VOID **) &gPciOverrideProtocol
 | 
						|
          );
 | 
						|
  }  
 | 
						|
 | 
						|
  gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));
 | 
						|
 | 
						|
  //
 | 
						|
  // Enumerate the entire host bridge
 | 
						|
  // After enumeration, a database that records all the device information will be created
 | 
						|
  //
 | 
						|
  //
 | 
						|
  Status = PciEnumerator (Controller);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Start all the devices under the entire host bridge.
 | 
						|
  //
 | 
						|
  StartPciDevices (Controller);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stop this driver on ControllerHandle. Support stoping any child handles
 | 
						|
  created by this driver.
 | 
						|
 | 
						|
  @param  This              Protocol instance pointer.
 | 
						|
  @param  Controller        Handle of device to stop driver on.
 | 
						|
  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
 | 
						|
                            children is zero stop the entire bus driver.
 | 
						|
  @param  ChildHandleBuffer List of Child Handles to Stop.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
 | 
						|
  @retval other             This driver was not removed from this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PciBusDriverBindingStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
 | 
						|
  IN  EFI_HANDLE                    Controller,
 | 
						|
  IN  UINTN                         NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                    *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       Index;
 | 
						|
  BOOLEAN     AllChildrenStopped;
 | 
						|
 | 
						|
  if (NumberOfChildren == 0) {
 | 
						|
    //
 | 
						|
    // Close the bus driver
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Controller,
 | 
						|
          &gEfiDevicePathProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Controller
 | 
						|
          );
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Controller,
 | 
						|
          &gEfiPciRootBridgeIoProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Controller
 | 
						|
          );
 | 
						|
 | 
						|
    DestroyRootBridgeByHandle (
 | 
						|
      Controller
 | 
						|
      );
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Stop all the children
 | 
						|
  //
 | 
						|
 | 
						|
  AllChildrenStopped = TRUE;
 | 
						|
 | 
						|
  for (Index = 0; Index < NumberOfChildren; Index++) {
 | 
						|
 | 
						|
    //
 | 
						|
    // De register all the pci device
 | 
						|
    //
 | 
						|
    Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      AllChildrenStopped = FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!AllChildrenStopped) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 |