| /*++ | |
| Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR> | |
| 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. | |
| Module Name: | |
| PciDeviceSupport.c | |
| Abstract: | |
| This file provides routine to support Pci device node manipulation | |
| Revision History | |
| --*/ | |
| #include "PciBus.h" | |
| // | |
| // This device structure is serviced as a header. | |
| // Its Next field points to the first root bridge device node | |
| // | |
| LIST_ENTRY gPciDevicePool; | |
| EFI_STATUS | |
| InitializePciDevicePool ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Initialize the gPciDevicePool | |
| Arguments: | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| InitializeListHead (&gPciDevicePool); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| InsertRootBridge ( | |
| IN PCI_IO_DEVICE *RootBridge | |
| ) | |
| /*++ | |
| Routine Description: | |
| Insert a root bridge into PCI device pool | |
| Arguments: | |
| RootBridge - A pointer to the PCI_IO_DEVICE. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| InsertTailList (&gPciDevicePool, &(RootBridge->Link)); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| InsertPciDevice ( | |
| PCI_IO_DEVICE *Bridge, | |
| PCI_IO_DEVICE *PciDeviceNode | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function is used to insert a PCI device node under | |
| a bridge | |
| Arguments: | |
| Bridge - A pointer to the PCI_IO_DEVICE. | |
| PciDeviceNode - A pointer to the PCI_IO_DEVICE. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link)); | |
| PciDeviceNode->Parent = Bridge; | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| DestroyRootBridge ( | |
| IN PCI_IO_DEVICE *RootBridge | |
| ) | |
| /*++ | |
| Routine Description: | |
| Arguments: | |
| RootBridge - A pointer to the PCI_IO_DEVICE. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| DestroyPciDeviceTree (RootBridge); | |
| gBS->FreePool (RootBridge); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| DestroyPciDeviceTree ( | |
| IN PCI_IO_DEVICE *Bridge | |
| ) | |
| /*++ | |
| Routine Description: | |
| Destroy all the pci device node under the bridge. | |
| Bridge itself is not included. | |
| Arguments: | |
| Bridge - A pointer to the PCI_IO_DEVICE. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| LIST_ENTRY *CurrentLink; | |
| PCI_IO_DEVICE *Temp; | |
| while (!IsListEmpty (&Bridge->ChildList)) { | |
| CurrentLink = Bridge->ChildList.ForwardLink; | |
| // | |
| // Remove this node from the linked list | |
| // | |
| RemoveEntryList (CurrentLink); | |
| Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| if (IS_PCI_BRIDGE (&(Temp->Pci))) { | |
| DestroyPciDeviceTree (Temp); | |
| } | |
| gBS->FreePool (Temp); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| DestroyRootBridgeByHandle ( | |
| EFI_HANDLE Controller | |
| ) | |
| /*++ | |
| Routine Description: | |
| Destroy all device nodes under the root bridge | |
| specified by Controller. | |
| The root bridge itself is also included. | |
| Arguments: | |
| Controller - An efi handle. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| LIST_ENTRY *CurrentLink; | |
| PCI_IO_DEVICE *Temp; | |
| CurrentLink = gPciDevicePool.ForwardLink; | |
| while (CurrentLink && CurrentLink != &gPciDevicePool) { | |
| Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| if (Temp->Handle == Controller) { | |
| RemoveEntryList (CurrentLink); | |
| DestroyPciDeviceTree (Temp); | |
| gBS->FreePool(Temp); | |
| return EFI_SUCCESS; | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| RegisterPciDevice ( | |
| IN EFI_HANDLE Controller, | |
| IN PCI_IO_DEVICE *PciIoDevice, | |
| OUT EFI_HANDLE *Handle OPTIONAL | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function registers the PCI IO device. It creates a handle for this PCI IO device | |
| (if the handle does not exist), attaches appropriate protocols onto the handle, does | |
| necessary initialization, and sets up parent/child relationship with its bus controller. | |
| Arguments: | |
| Controller - An EFI handle for the PCI bus controller. | |
| PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered. | |
| Handle - A pointer to hold the EFI handle for the PCI IO device. | |
| Returns: | |
| EFI_SUCCESS - The PCI device is successfully registered. | |
| Others - An error occurred when registering the PCI device. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINT8 PciExpressCapRegOffset; | |
| // | |
| // Install the pciio protocol, device path protocol and | |
| // Bus Specific Driver Override Protocol | |
| // | |
| if (PciIoDevice->BusOverride) { | |
| Status = gBS->InstallMultipleProtocolInterfaces ( | |
| &PciIoDevice->Handle, | |
| &gEfiDevicePathProtocolGuid, | |
| PciIoDevice->DevicePath, | |
| &gEfiPciIoProtocolGuid, | |
| &PciIoDevice->PciIo, | |
| &gEfiBusSpecificDriverOverrideProtocolGuid, | |
| &PciIoDevice->PciDriverOverride, | |
| NULL | |
| ); | |
| } else { | |
| Status = gBS->InstallMultipleProtocolInterfaces ( | |
| &PciIoDevice->Handle, | |
| &gEfiDevicePathProtocolGuid, | |
| PciIoDevice->DevicePath, | |
| &gEfiPciIoProtocolGuid, | |
| &PciIoDevice->PciIo, | |
| NULL | |
| ); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } else { | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiPciRootBridgeIoProtocolGuid, | |
| (VOID **)&(PciIoDevice->PciRootBridgeIo), | |
| gPciBusDriverBinding.DriverBindingHandle, | |
| PciIoDevice->Handle, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| } | |
| if (Handle != NULL) { | |
| *Handle = PciIoDevice->Handle; | |
| } | |
| // | |
| // Detect if PCI Express Device | |
| // | |
| PciExpressCapRegOffset = 0; | |
| Status = LocateCapabilityRegBlock ( | |
| PciIoDevice, | |
| EFI_PCI_CAPABILITY_ID_PCIEXP, | |
| &PciExpressCapRegOffset, | |
| NULL | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| PciIoDevice->IsPciExp = TRUE; | |
| DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber)); | |
| } | |
| // | |
| // Indicate the pci device is registered | |
| // | |
| PciIoDevice->Registered = TRUE; | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| DeRegisterPciDevice ( | |
| IN EFI_HANDLE Controller, | |
| IN EFI_HANDLE Handle | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function is used to de-register the PCI device from the EFI, | |
| That includes un-installing PciIo protocol from the specified PCI | |
| device handle. | |
| Arguments: | |
| Controller - An efi handle. | |
| Handle - An efi handle. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| EFI_PCI_IO_PROTOCOL *PciIo; | |
| EFI_STATUS Status; | |
| PCI_IO_DEVICE *PciIoDevice; | |
| PCI_IO_DEVICE *Node; | |
| LIST_ENTRY *CurrentLink; | |
| EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; | |
| Status = gBS->OpenProtocol ( | |
| Handle, | |
| &gEfiPciIoProtocolGuid, | |
| (VOID **) &PciIo, | |
| gPciBusDriverBinding.DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); | |
| // | |
| // If it is already de-registered | |
| // | |
| if (!PciIoDevice->Registered) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // If it is PPB, first de-register its children | |
| // | |
| if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) { | |
| CurrentLink = PciIoDevice->ChildList.ForwardLink; | |
| while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) { | |
| Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| Status = DeRegisterPciDevice (Controller, Node->Handle); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| } | |
| } | |
| // | |
| // First disconnect this device | |
| // | |
| // PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo), | |
| // EfiPciIoAttributeOperationDisable, | |
| // EFI_PCI_DEVICE_ENABLE, | |
| // NULL | |
| // ); | |
| // | |
| // Close the child handle | |
| // | |
| Status = gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiPciRootBridgeIoProtocolGuid, | |
| gPciBusDriverBinding.DriverBindingHandle, | |
| Handle | |
| ); | |
| // | |
| // Un-install the device path protocol and pci io protocol | |
| // | |
| if (PciIoDevice->BusOverride) { | |
| Status = gBS->UninstallMultipleProtocolInterfaces ( | |
| Handle, | |
| &gEfiDevicePathProtocolGuid, | |
| PciIoDevice->DevicePath, | |
| &gEfiPciIoProtocolGuid, | |
| &PciIoDevice->PciIo, | |
| &gEfiBusSpecificDriverOverrideProtocolGuid, | |
| &PciIoDevice->PciDriverOverride, | |
| NULL | |
| ); | |
| } else { | |
| Status = gBS->UninstallMultipleProtocolInterfaces ( | |
| Handle, | |
| &gEfiDevicePathProtocolGuid, | |
| PciIoDevice->DevicePath, | |
| &gEfiPciIoProtocolGuid, | |
| &PciIoDevice->PciIo, | |
| NULL | |
| ); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiPciRootBridgeIoProtocolGuid, | |
| (VOID **) &PciRootBridgeIo, | |
| gPciBusDriverBinding.DriverBindingHandle, | |
| Handle, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| return Status; | |
| } | |
| // | |
| // The Device Driver should disable this device after disconnect | |
| // so the Pci Bus driver will not touch this device any more. | |
| // Restore the register field to the original value | |
| // | |
| PciIoDevice->Registered = FALSE; | |
| PciIoDevice->Handle = NULL; | |
| } else { | |
| // | |
| // Handle may be closed before | |
| // | |
| return EFI_SUCCESS; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| EnableBridgeAttributes ( | |
| IN PCI_IO_DEVICE *PciIoDevice | |
| ) | |
| { | |
| PCI_TYPE01 PciData; | |
| // | |
| // NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge | |
| // directly, because some legacy BIOS will NOT assign | |
| // IO or Memory resource for a bridge who has no child | |
| // device. So we add check IO or Memory here. | |
| // | |
| PciIoDevice->PciIo.Pci.Read ( | |
| &PciIoDevice->PciIo, | |
| EfiPciIoWidthUint8, | |
| 0, | |
| sizeof (PciData), | |
| &PciData | |
| ); | |
| if ((((PciData.Bridge.IoBase & 0xF) == 0) && | |
| (PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) || | |
| (((PciData.Bridge.IoBase & 0xF) == 1) && | |
| ((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) { | |
| PciIoDevice->PciIo.Attributes( | |
| &(PciIoDevice->PciIo), | |
| EfiPciIoAttributeOperationEnable, | |
| (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), | |
| NULL | |
| ); | |
| } | |
| if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) { | |
| PciIoDevice->PciIo.Attributes( | |
| &(PciIoDevice->PciIo), | |
| EfiPciIoAttributeOperationEnable, | |
| (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), | |
| NULL | |
| ); | |
| } | |
| if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) && | |
| (PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) || | |
| (((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) && | |
| ((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) { | |
| PciIoDevice->PciIo.Attributes( | |
| &(PciIoDevice->PciIo), | |
| EfiPciIoAttributeOperationEnable, | |
| (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), | |
| NULL | |
| ); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| StartPciDevicesOnBridge ( | |
| IN EFI_HANDLE Controller, | |
| IN PCI_IO_DEVICE *RootBridge, | |
| IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
| ) | |
| /*++ | |
| Routine Description: | |
| Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge | |
| Arguments: | |
| Controller - An efi handle. | |
| RootBridge - A pointer to the PCI_IO_DEVICE. | |
| RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. | |
| NumberOfChildren - Children number. | |
| ChildHandleBuffer - A pointer to the child handle buffer. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| PCI_IO_DEVICE *Temp; | |
| PCI_IO_DEVICE *PciIoDevice; | |
| EFI_DEV_PATH_PTR Node; | |
| EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; | |
| EFI_STATUS Status; | |
| LIST_ENTRY *CurrentLink; | |
| CurrentLink = RootBridge->ChildList.ForwardLink; | |
| while (CurrentLink && CurrentLink != &RootBridge->ChildList) { | |
| Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| if (RemainingDevicePath != NULL) { | |
| Node.DevPath = RemainingDevicePath; | |
| if (Node.Pci->Device != Temp->DeviceNumber || | |
| Node.Pci->Function != Temp->FunctionNumber) { | |
| CurrentLink = CurrentLink->ForwardLink; | |
| continue; | |
| } | |
| // | |
| // Check if the device has been assigned with required resource | |
| // | |
| if (!Temp->Allocated) { | |
| return EFI_NOT_READY; | |
| } | |
| // | |
| // Check if the current node has been registered before | |
| // If it is not, register it | |
| // | |
| if (!Temp->Registered) { | |
| PciIoDevice = Temp; | |
| Status = RegisterPciDevice ( | |
| Controller, | |
| PciIoDevice, | |
| NULL | |
| ); | |
| } | |
| // | |
| // Get the next device path | |
| // | |
| CurrentDevicePath = NextDevicePathNode (RemainingDevicePath); | |
| if (IsDevicePathEnd (CurrentDevicePath)) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // If it is a PPB | |
| // | |
| if (IS_PCI_BRIDGE (&(Temp->Pci))) { | |
| Status = StartPciDevicesOnBridge ( | |
| Controller, | |
| Temp, | |
| CurrentDevicePath | |
| ); | |
| EnableBridgeAttributes (Temp); | |
| return Status; | |
| } else { | |
| // | |
| // Currently, the PCI bus driver only support PCI-PCI bridge | |
| // | |
| return EFI_UNSUPPORTED; | |
| } | |
| } else { | |
| // | |
| // If remaining device path is NULL, | |
| // try to enable all the pci devices under this bridge | |
| // | |
| if (!Temp->Registered && Temp->Allocated) { | |
| PciIoDevice = Temp; | |
| Status = RegisterPciDevice ( | |
| Controller, | |
| PciIoDevice, | |
| NULL | |
| ); | |
| } | |
| if (IS_PCI_BRIDGE (&(Temp->Pci))) { | |
| Status = StartPciDevicesOnBridge ( | |
| Controller, | |
| Temp, | |
| RemainingDevicePath | |
| ); | |
| EnableBridgeAttributes (Temp); | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| continue; | |
| } | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| StartPciDevices ( | |
| IN EFI_HANDLE Controller, | |
| IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
| ) | |
| /*++ | |
| Routine Description: | |
| Start to manage the PCI device according to RemainingDevicePath | |
| If RemainingDevicePath == NULL, the PCI bus driver will start | |
| to manage all the PCI devices it found previously | |
| Arguments: | |
| Controller - An efi handle. | |
| RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| EFI_DEV_PATH_PTR Node; | |
| PCI_IO_DEVICE *RootBridge; | |
| LIST_ENTRY *CurrentLink; | |
| if (RemainingDevicePath != NULL) { | |
| // | |
| // Check if the RemainingDevicePath is valid | |
| // | |
| 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; | |
| } | |
| } | |
| CurrentLink = gPciDevicePool.ForwardLink; | |
| while (CurrentLink && CurrentLink != &gPciDevicePool) { | |
| RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| // | |
| // Locate the right root bridge to start | |
| // | |
| if (RootBridge->Handle == Controller) { | |
| StartPciDevicesOnBridge ( | |
| Controller, | |
| RootBridge, | |
| RemainingDevicePath | |
| ); | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| PCI_IO_DEVICE * | |
| CreateRootBridge ( | |
| IN EFI_HANDLE RootBridgeHandle | |
| ) | |
| /*++ | |
| Routine Description: | |
| Arguments: | |
| RootBridgeHandle - An efi handle. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| PCI_IO_DEVICE *Dev; | |
| Dev = NULL; | |
| Status = gBS->AllocatePool ( | |
| EfiBootServicesData, | |
| sizeof (PCI_IO_DEVICE), | |
| (VOID **) &Dev | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return NULL; | |
| } | |
| ZeroMem (Dev, sizeof (PCI_IO_DEVICE)); | |
| Dev->Signature = PCI_IO_DEVICE_SIGNATURE; | |
| Dev->Handle = RootBridgeHandle; | |
| InitializeListHead (&Dev->ChildList); | |
| return Dev; | |
| } | |
| PCI_IO_DEVICE * | |
| GetRootBridgeByHandle ( | |
| EFI_HANDLE RootBridgeHandle | |
| ) | |
| /*++ | |
| Routine Description: | |
| Arguments: | |
| RootBridgeHandle - An efi handle. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| PCI_IO_DEVICE *RootBridgeDev; | |
| LIST_ENTRY *CurrentLink; | |
| CurrentLink = gPciDevicePool.ForwardLink; | |
| while (CurrentLink && CurrentLink != &gPciDevicePool) { | |
| RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| if (RootBridgeDev->Handle == RootBridgeHandle) { | |
| return RootBridgeDev; | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| } | |
| return NULL; | |
| } | |
| BOOLEAN | |
| RootBridgeExisted ( | |
| IN EFI_HANDLE RootBridgeHandle | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function searches if RootBridgeHandle has already existed | |
| in current device pool. | |
| If so, it means the given root bridge has been already enumerated. | |
| Arguments: | |
| RootBridgeHandle - An efi handle. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| PCI_IO_DEVICE *Bridge; | |
| Bridge = GetRootBridgeByHandle (RootBridgeHandle); | |
| if (Bridge != NULL) { | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| BOOLEAN | |
| PciDeviceExisted ( | |
| IN PCI_IO_DEVICE *Bridge, | |
| IN PCI_IO_DEVICE *PciIoDevice | |
| ) | |
| /*++ | |
| Routine Description: | |
| Arguments: | |
| Bridge - A pointer to the PCI_IO_DEVICE. | |
| PciIoDevice - A pointer to the PCI_IO_DEVICE. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| PCI_IO_DEVICE *Temp; | |
| LIST_ENTRY *CurrentLink; | |
| CurrentLink = Bridge->ChildList.ForwardLink; | |
| while (CurrentLink && CurrentLink != &Bridge->ChildList) { | |
| Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| if (Temp == PciIoDevice) { | |
| return TRUE; | |
| } | |
| if (!IsListEmpty (&Temp->ChildList)) { | |
| if (PciDeviceExisted (Temp, PciIoDevice)) { | |
| return TRUE; | |
| } | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| } | |
| return FALSE; | |
| } | |
| PCI_IO_DEVICE * | |
| ActiveVGADeviceOnTheSameSegment ( | |
| IN PCI_IO_DEVICE *VgaDevice | |
| ) | |
| /*++ | |
| Routine Description: | |
| Arguments: | |
| VgaDevice - A pointer to the PCI_IO_DEVICE. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| LIST_ENTRY *CurrentLink; | |
| PCI_IO_DEVICE *Temp; | |
| CurrentLink = gPciDevicePool.ForwardLink; | |
| while (CurrentLink && CurrentLink != &gPciDevicePool) { | |
| Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) { | |
| Temp = ActiveVGADeviceOnTheRootBridge (Temp); | |
| if (Temp != NULL) { | |
| return Temp; | |
| } | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| } | |
| return NULL; | |
| } | |
| PCI_IO_DEVICE * | |
| ActiveVGADeviceOnTheRootBridge ( | |
| IN PCI_IO_DEVICE *RootBridge | |
| ) | |
| /*++ | |
| Routine Description: | |
| Arguments: | |
| RootBridge - A pointer to the PCI_IO_DEVICE. | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| LIST_ENTRY *CurrentLink; | |
| PCI_IO_DEVICE *Temp; | |
| CurrentLink = RootBridge->ChildList.ForwardLink; | |
| while (CurrentLink && CurrentLink != &RootBridge->ChildList) { | |
| Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); | |
| if (IS_PCI_VGA(&Temp->Pci) && | |
| (Temp->Attributes & | |
| (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | | |
| EFI_PCI_IO_ATTRIBUTE_VGA_IO | | |
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) { | |
| return Temp; | |
| } | |
| if (IS_PCI_BRIDGE (&Temp->Pci)) { | |
| Temp = ActiveVGADeviceOnTheRootBridge (Temp); | |
| if (Temp != NULL) { | |
| return Temp; | |
| } | |
| } | |
| CurrentLink = CurrentLink->ForwardLink; | |
| } | |
| return NULL; | |
| } |