summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/Pcibus.c
diff options
context:
space:
mode:
Diffstat (limited to 'IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/Pcibus.c')
-rw-r--r--IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/Pcibus.c310
1 files changed, 310 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/Pcibus.c b/IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/Pcibus.c
new file mode 100644
index 0000000000..d5e0661bfb
--- /dev/null
+++ b/IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/Pcibus.c
@@ -0,0 +1,310 @@
+/**@file
+ Driver Binding functions for PCI bus module.
+
+Copyright (c) 2006, 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_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport = NULL;
+EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
+UINTN gPciHostBridgeNumber;
+BOOLEAN gFullEnumeration;
+UINT64 gAllOne = 0xFFFFFFFFFFFFFFFFULL;
+UINT64 gAllZero = 0;
+
+EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
+
+//
+// PCI Bus Driver Support Functions
+//
+/**
+ Initialize the global variables
+ publish the driver binding protocol
+
+ @param[IN] ImageHandle,
+ @param[IN] *SystemTable
+
+ @retval status of installing driver binding component name protocol.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ InitializePciDevicePool ();
+
+ gFullEnumeration = TRUE;
+
+ gPciHostBridgeNumber = 0;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gPciBusDriverBinding,
+ ImageHandle,
+ &gPciBusComponentName,
+ &gPciBusComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ InstallHotPlugRequestProtocol (&Status);
+
+ 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 ControllerHandle 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;
+
+ if (RemainingDevicePath != NULL) {
+ 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;
+ }
+ }
+ //
+ // 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;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ 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;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ 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 ControllerHandle 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;
+
+ 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
+ );
+
+ 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 ControllerHandle 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;
+}
+