/*++ | |
Copyright (c) 2005 - 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. | |
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; | |
} |