3 Copyright (c) 2006 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "PciDeviceSupport.h"
19 // This device structure is serviced as a header.
20 // Its Next field points to the first root bridge device node
22 LIST_ENTRY gPciDevicePool
;
25 Initialize the gPciDevicePool.
28 InitializePciDevicePool (
32 InitializeListHead (&gPciDevicePool
);
38 Insert a root bridge into PCI device pool
40 @param RootBridge - A pointer to the PCI_IO_DEVICE.
45 PCI_IO_DEVICE
*RootBridge
49 InsertTailList (&gPciDevicePool
, &(RootBridge
->Link
));
55 This function is used to insert a PCI device node under
58 @param Bridge A pointer to the PCI_IO_DEVICE.
59 @param PciDeviceNode A pointer to the PCI_IO_DEVICE.
64 PCI_IO_DEVICE
*Bridge
,
65 PCI_IO_DEVICE
*PciDeviceNode
69 InsertTailList (&Bridge
->ChildList
, &(PciDeviceNode
->Link
));
70 PciDeviceNode
->Parent
= Bridge
;
76 Destroy root bridge and remove it from deivce tree.
78 @param RootBridge The bridge want to be removed.
83 IN PCI_IO_DEVICE
*RootBridge
86 DestroyPciDeviceTree (RootBridge
);
88 FreePciDevice (RootBridge
);
94 Destroy a pci device node.
95 Also all direct or indirect allocated resource for this node will be freed.
97 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
102 IN PCI_IO_DEVICE
*PciIoDevice
107 // Assume all children have been removed underneath this device
109 if (PciIoDevice
->ResourcePaddingDescriptors
!= NULL
) {
110 gBS
->FreePool (PciIoDevice
->ResourcePaddingDescriptors
);
113 if (PciIoDevice
->DevicePath
!= NULL
) {
114 gBS
->FreePool (PciIoDevice
->DevicePath
);
117 gBS
->FreePool (PciIoDevice
);
123 Destroy all the pci device node under the bridge.
124 Bridge itself is not included.
126 @param Bridge A pointer to the PCI_IO_DEVICE.
130 DestroyPciDeviceTree (
131 IN PCI_IO_DEVICE
*Bridge
134 LIST_ENTRY
*CurrentLink
;
137 while (!IsListEmpty (&Bridge
->ChildList
)) {
139 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
142 // Remove this node from the linked list
144 RemoveEntryList (CurrentLink
);
146 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
148 if (!IsListEmpty (&Temp
->ChildList
)) {
149 DestroyPciDeviceTree (Temp
);
152 FreePciDevice (Temp
);
159 Destroy all device nodes under the root bridge
160 specified by Controller.
161 The root bridge itself is also included.
163 @param Controller An efi handle.
167 DestroyRootBridgeByHandle (
168 EFI_HANDLE Controller
172 LIST_ENTRY
*CurrentLink
;
175 CurrentLink
= gPciDevicePool
.ForwardLink
;
177 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
178 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
180 if (Temp
->Handle
== Controller
) {
182 RemoveEntryList (CurrentLink
);
184 DestroyPciDeviceTree (Temp
);
186 FreePciDevice (Temp
);
191 CurrentLink
= CurrentLink
->ForwardLink
;
194 return EFI_NOT_FOUND
;
198 This function registers the PCI IO device. It creates a handle for this PCI IO device
199 (if the handle does not exist), attaches appropriate protocols onto the handle, does
200 necessary initialization, and sets up parent/child relationship with its bus controller.
202 @param Controller - An EFI handle for the PCI bus controller.
203 @param PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
204 @param Handle - A pointer to hold the EFI handle for the PCI IO device.
206 @retval EFI_SUCCESS - The PCI device is successfully registered.
207 @retval Others - An error occurred when registering the PCI device.
212 IN EFI_HANDLE Controller
,
213 IN PCI_IO_DEVICE
*PciIoDevice
,
214 OUT EFI_HANDLE
*Handle OPTIONAL
218 VOID
*PlatformOpRomBuffer
;
219 UINTN PlatformOpRomSize
;
220 UINT8 PciExpressCapRegOffset
;
221 EFI_PCI_IO_PROTOCOL
*PciIo
;
226 // Install the pciio protocol, device path protocol
228 Status
= gBS
->InstallMultipleProtocolInterfaces (
229 &PciIoDevice
->Handle
,
230 &gEfiDevicePathProtocolGuid
,
231 PciIoDevice
->DevicePath
,
232 &gEfiPciIoProtocolGuid
,
236 if (EFI_ERROR (Status
)) {
241 // Detect if PCI Express Device
243 PciExpressCapRegOffset
= 0;
244 Status
= LocateCapabilityRegBlock (
246 EFI_PCI_CAPABILITY_ID_PCIEXP
,
247 &PciExpressCapRegOffset
,
250 if (!EFI_ERROR (Status
)) {
251 PciIoDevice
->IsPciExp
= TRUE
;
255 // Force Interrupt line to "Unknown" or "No Connection"
257 PciIo
= &(PciIoDevice
->PciIo
);
258 Data8
= PCI_INT_LINE_UNKNOWN
;
259 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &Data8
);
264 if (!PciIoDevice
->AllOpRomProcessed
) {
267 // Get the OpRom provided by platform
269 if (gPciPlatformProtocol
!= NULL
) {
270 Status
= gPciPlatformProtocol
->GetPciRom (
271 gPciPlatformProtocol
,
273 &PlatformOpRomBuffer
,
276 if (!EFI_ERROR (Status
)) {
277 PciIoDevice
->RomSize
= PlatformOpRomSize
;
278 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
279 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
281 // For OpROM read from gPciPlatformProtocol:
282 // Add the Rom Image to internal database for later PCI light enumeration
284 PciRomAddImageMapping (
286 PciIoDevice
->PciRootBridgeIo
->SegmentNumber
,
287 PciIoDevice
->BusNumber
,
288 PciIoDevice
->DeviceNumber
,
289 PciIoDevice
->FunctionNumber
,
290 (UINT64
) (UINTN
) PciIoDevice
->PciIo
.RomImage
,
291 PciIoDevice
->PciIo
.RomSize
298 // Determine if there are EFI images in the option rom
300 HasEfiImage
= ContainEfiImage (PciIoDevice
->PciIo
.RomImage
, PciIoDevice
->PciIo
.RomSize
);
303 Status
= gBS
->InstallMultipleProtocolInterfaces (
304 &PciIoDevice
->Handle
,
305 &gEfiLoadFile2ProtocolGuid
,
306 &PciIoDevice
->LoadFile2
,
309 if (EFI_ERROR (Status
)) {
310 gBS
->UninstallMultipleProtocolInterfaces (
311 &PciIoDevice
->Handle
,
312 &gEfiDevicePathProtocolGuid
,
313 PciIoDevice
->DevicePath
,
314 &gEfiPciIoProtocolGuid
,
323 if (!PciIoDevice
->AllOpRomProcessed
) {
325 PciIoDevice
->AllOpRomProcessed
= TRUE
;
328 // Dispatch the EFI OpRom for the PCI device.
329 // The OpRom is got from platform in the above code
330 // or loaded from device in the previous round of bus enumeration
333 ProcessOpRomImage (PciIoDevice
);
337 if (PciIoDevice
->BusOverride
) {
339 // Install BusSpecificDriverOverride Protocol
341 Status
= gBS
->InstallMultipleProtocolInterfaces (
342 &PciIoDevice
->Handle
,
343 &gEfiBusSpecificDriverOverrideProtocolGuid
,
344 &PciIoDevice
->PciDriverOverride
,
347 if (EFI_ERROR (Status
)) {
348 gBS
->UninstallMultipleProtocolInterfaces (
349 &PciIoDevice
->Handle
,
350 &gEfiDevicePathProtocolGuid
,
351 PciIoDevice
->DevicePath
,
352 &gEfiPciIoProtocolGuid
,
357 gBS
->UninstallMultipleProtocolInterfaces (
358 &PciIoDevice
->Handle
,
359 &gEfiLoadFile2ProtocolGuid
,
360 &PciIoDevice
->LoadFile2
,
369 Status
= gBS
->OpenProtocol (
371 &gEfiPciRootBridgeIoProtocolGuid
,
372 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
373 gPciBusDriverBinding
.DriverBindingHandle
,
375 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
377 if (EFI_ERROR (Status
)) {
382 // Install Pccard Hotplug GUID for Pccard device so that
383 // to notify CardBus driver to stop the device when de-register happens
385 InstallPciHotplugGuid (PciIoDevice
);
387 if (Handle
!= NULL
) {
388 *Handle
= PciIoDevice
->Handle
;
392 // Indicate the pci device is registered
394 PciIoDevice
->Registered
= TRUE
;
400 This function is used to remove the whole PCI devices from the bridge.
402 @param RootBridgeHandle An efi handle.
403 @param Bridge A pointer to the PCI_IO_DEVICE.
408 RemoveAllPciDeviceOnBridge (
409 EFI_HANDLE RootBridgeHandle
,
410 PCI_IO_DEVICE
*Bridge
415 LIST_ENTRY
*CurrentLink
;
418 while (!IsListEmpty (&Bridge
->ChildList
)) {
420 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
421 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
424 // Check if the current node has been deregistered before
425 // If it is not, then deregister it
427 if (Temp
->Registered
) {
428 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
432 // Remove this node from the linked list
434 RemoveEntryList (CurrentLink
);
436 if (!IsListEmpty (&Temp
->ChildList
)) {
437 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
440 FreePciDevice (Temp
);
448 This function is used to de-register the PCI device from the EFI,
449 That includes un-installing PciIo protocol from the specified PCI
452 @param Controller - controller handle
453 @param Handle - device handle
455 @return Status of de-register pci device
458 DeRegisterPciDevice (
459 IN EFI_HANDLE Controller
,
464 EFI_PCI_IO_PROTOCOL
*PciIo
;
466 PCI_IO_DEVICE
*PciIoDevice
;
468 LIST_ENTRY
*CurrentLink
;
469 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
471 Status
= gBS
->OpenProtocol (
473 &gEfiPciIoProtocolGuid
,
475 gPciBusDriverBinding
.DriverBindingHandle
,
477 EFI_OPEN_PROTOCOL_GET_PROTOCOL
479 if (!EFI_ERROR (Status
)) {
480 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
483 // If it is already de-registered
485 if (!PciIoDevice
->Registered
) {
490 // If it is PPB, first de-register its children
493 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
495 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
497 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
498 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
499 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
501 if (EFI_ERROR (Status
)) {
505 CurrentLink
= CurrentLink
->ForwardLink
;
509 // Uninstall Pccard Hotplug GUID for Pccard device
511 UninstallPciHotplugGuid (PciIoDevice
);
514 // Close the child handle
516 Status
= gBS
->CloseProtocol (
518 &gEfiPciRootBridgeIoProtocolGuid
,
519 gPciBusDriverBinding
.DriverBindingHandle
,
524 // Un-install the device path protocol and pci io protocol
526 if (PciIoDevice
->BusOverride
) {
527 Status
= gBS
->UninstallMultipleProtocolInterfaces (
529 &gEfiDevicePathProtocolGuid
,
530 PciIoDevice
->DevicePath
,
531 &gEfiPciIoProtocolGuid
,
533 &gEfiBusSpecificDriverOverrideProtocolGuid
,
534 &PciIoDevice
->PciDriverOverride
,
538 Status
= gBS
->UninstallMultipleProtocolInterfaces (
540 &gEfiDevicePathProtocolGuid
,
541 PciIoDevice
->DevicePath
,
542 &gEfiPciIoProtocolGuid
,
548 if (!EFI_ERROR (Status
)) {
550 // Try to uninstall LoadFile2 protocol if exists
552 Status
= gBS
->OpenProtocol (
554 &gEfiLoadFile2ProtocolGuid
,
556 gPciBusDriverBinding
.DriverBindingHandle
,
558 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
560 if (!EFI_ERROR (Status
)) {
561 Status
= gBS
->UninstallMultipleProtocolInterfaces (
563 &gEfiLoadFile2ProtocolGuid
,
564 &PciIoDevice
->LoadFile2
,
571 Status
= EFI_SUCCESS
;
575 if (EFI_ERROR (Status
)) {
578 &gEfiPciRootBridgeIoProtocolGuid
,
579 (VOID
**) &PciRootBridgeIo
,
580 gPciBusDriverBinding
.DriverBindingHandle
,
582 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
588 // The Device Driver should disable this device after disconnect
589 // so the Pci Bus driver will not touch this device any more.
590 // Restore the register field to the original value
592 PciIoDevice
->Registered
= FALSE
;
593 PciIoDevice
->Handle
= NULL
;
597 // Handle may be closed before
606 Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
608 @param Controller An efi handle.
609 @param RootBridge A pointer to the PCI_IO_DEVICE.
610 @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
611 @param NumberOfChildren Children number.
612 @param ChildHandleBuffer A pointer to the child handle buffer.
614 @retval EFI_NOT_READY Device is not allocated
615 @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
616 @retval EFI_NOT_FOUND Can not find the specific device
617 @retval EFI_SUCCESS Success to start Pci device on bridge
621 StartPciDevicesOnBridge (
622 IN EFI_HANDLE Controller
,
623 IN PCI_IO_DEVICE
*RootBridge
,
624 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
625 IN OUT UINT8
*NumberOfChildren
,
626 IN OUT EFI_HANDLE
*ChildHandleBuffer
630 PCI_IO_DEVICE
*PciIoDevice
;
631 EFI_DEV_PATH_PTR Node
;
632 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
634 LIST_ENTRY
*CurrentLink
;
637 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
639 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
641 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
642 if (RemainingDevicePath
!= NULL
) {
644 Node
.DevPath
= RemainingDevicePath
;
646 if (Node
.Pci
->Device
!= PciIoDevice
->DeviceNumber
||
647 Node
.Pci
->Function
!= PciIoDevice
->FunctionNumber
) {
648 CurrentLink
= CurrentLink
->ForwardLink
;
653 // Check if the device has been assigned with required resource
655 if (!PciIoDevice
->Allocated
) {
656 return EFI_NOT_READY
;
660 // Check if the current node has been registered before
661 // If it is not, register it
663 if (!PciIoDevice
->Registered
) {
664 Status
= RegisterPciDevice (
672 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
673 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
674 (*NumberOfChildren
)++;
678 // Get the next device path
680 CurrentDevicePath
= NextDevicePathNode (RemainingDevicePath
);
681 if (IsDevicePathEnd (CurrentDevicePath
)) {
688 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
689 Status
= StartPciDevicesOnBridge (
697 PciIoDevice
->PciIo
.Attributes (
698 &(PciIoDevice
->PciIo
),
699 EfiPciIoAttributeOperationSupported
,
703 Supports
&= EFI_PCI_DEVICE_ENABLE
;
704 PciIoDevice
->PciIo
.Attributes (
705 &(PciIoDevice
->PciIo
),
706 EfiPciIoAttributeOperationEnable
,
715 // Currently, the PCI bus driver only support PCI-PCI bridge
717 return EFI_UNSUPPORTED
;
723 // If remaining device path is NULL,
724 // try to enable all the pci devices under this bridge
727 if (!PciIoDevice
->Registered
&& PciIoDevice
->Allocated
) {
728 Status
= RegisterPciDevice (
736 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
737 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
738 (*NumberOfChildren
)++;
741 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
742 Status
= StartPciDevicesOnBridge (
750 PciIoDevice
->PciIo
.Attributes (
751 &(PciIoDevice
->PciIo
),
752 EfiPciIoAttributeOperationSupported
,
756 Supports
&= EFI_PCI_DEVICE_ENABLE
;
757 PciIoDevice
->PciIo
.Attributes (
758 &(PciIoDevice
->PciIo
),
759 EfiPciIoAttributeOperationEnable
,
766 CurrentLink
= CurrentLink
->ForwardLink
;
770 return EFI_NOT_FOUND
;
774 Start to manage all the PCI devices it found previously under
775 the entire host bridge.
777 @param Controller - root bridge handle.
782 IN EFI_HANDLE Controller
786 PCI_IO_DEVICE
*RootBridge
;
787 EFI_HANDLE ThisHostBridge
;
788 LIST_ENTRY
*CurrentLink
;
790 RootBridge
= GetRootBridgeByHandle (Controller
);
791 ASSERT (RootBridge
!= NULL
);
792 ThisHostBridge
= RootBridge
->PciRootBridgeIo
->ParentHandle
;
794 CurrentLink
= gPciDevicePool
.ForwardLink
;
796 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
798 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
800 // Locate the right root bridge to start
802 if (RootBridge
->PciRootBridgeIo
->ParentHandle
== ThisHostBridge
) {
803 StartPciDevicesOnBridge (
812 CurrentLink
= CurrentLink
->ForwardLink
;
819 Create root bridge device
821 @param RootBridgeHandle - Parent bridge handle.
823 @return pointer to new root bridge
827 IN EFI_HANDLE RootBridgeHandle
833 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
834 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
837 Status
= gBS
->AllocatePool (
839 sizeof (PCI_IO_DEVICE
),
843 if (EFI_ERROR (Status
)) {
847 ZeroMem (Dev
, sizeof (PCI_IO_DEVICE
));
848 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
849 Dev
->Handle
= RootBridgeHandle
;
850 InitializeListHead (&Dev
->ChildList
);
852 Status
= gBS
->OpenProtocol (
854 &gEfiDevicePathProtocolGuid
,
855 (VOID
**) &ParentDevicePath
,
856 gPciBusDriverBinding
.DriverBindingHandle
,
858 EFI_OPEN_PROTOCOL_GET_PROTOCOL
861 if (EFI_ERROR (Status
)) {
867 // Record the root bridge parent device path
869 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
872 // Get the pci root bridge io protocol
874 Status
= gBS
->OpenProtocol (
876 &gEfiPciRootBridgeIoProtocolGuid
,
877 (VOID
**) &PciRootBridgeIo
,
878 gPciBusDriverBinding
.DriverBindingHandle
,
880 EFI_OPEN_PROTOCOL_GET_PROTOCOL
883 if (EFI_ERROR (Status
)) {
888 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
891 // Initialize the PCI I/O instance structure
893 InitializePciIoInstance (Dev
);
894 InitializePciDriverOverrideInstance (Dev
);
895 InitializePciLoadFile2 (Dev
);
898 // Initialize reserved resource list and
899 // option rom driver list
901 InitializeListHead (&Dev
->ReservedResourceList
);
902 InitializeListHead (&Dev
->OptionRomDriverList
);
908 Get root bridge device instance by specific handle.
910 @param RootBridgeHandle Given root bridge handle.
912 @return root bridge device instance.
915 GetRootBridgeByHandle (
916 EFI_HANDLE RootBridgeHandle
919 PCI_IO_DEVICE
*RootBridgeDev
;
920 LIST_ENTRY
*CurrentLink
;
922 CurrentLink
= gPciDevicePool
.ForwardLink
;
924 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
926 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
927 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
928 return RootBridgeDev
;
931 CurrentLink
= CurrentLink
->ForwardLink
;
938 Judege whether Pci device existed.
940 @param Bridge Parent bridege instance.
941 @param PciIoDevice Device instance.
943 @return whether Pci device existed.
947 IN PCI_IO_DEVICE
*Bridge
,
948 IN PCI_IO_DEVICE
*PciIoDevice
953 LIST_ENTRY
*CurrentLink
;
955 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
957 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
959 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
961 if (Temp
== PciIoDevice
) {
965 if (!IsListEmpty (&Temp
->ChildList
)) {
966 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
971 CurrentLink
= CurrentLink
->ForwardLink
;
980 @param VgaDevice device instance for VGA.
982 @return device instance.
985 ActiveVGADeviceOnTheSameSegment (
986 IN PCI_IO_DEVICE
*VgaDevice
989 LIST_ENTRY
*CurrentLink
;
992 CurrentLink
= gPciDevicePool
.ForwardLink
;
994 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
996 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
998 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
1000 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1007 CurrentLink
= CurrentLink
->ForwardLink
;
1014 Active VGA device on root bridge.
1016 @param RootBridge Root bridge device instance.
1018 @return VGA device instance.
1021 ActiveVGADeviceOnTheRootBridge (
1022 IN PCI_IO_DEVICE
*RootBridge
1025 LIST_ENTRY
*CurrentLink
;
1026 PCI_IO_DEVICE
*Temp
;
1028 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1030 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1032 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1034 if (IS_PCI_VGA(&Temp
->Pci
) &&
1036 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
1037 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1038 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) != 0) {
1042 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1044 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1051 CurrentLink
= CurrentLink
->ForwardLink
;
1058 Get HPC PCI address according to its device path.
1059 @param PciRootBridgeIo Root bridege Io instance.
1060 @param HpcDevicePath Given searching device path.
1061 @param PciAddress Buffer holding searched result.
1063 @retval EFI_NOT_FOUND Can not find the specific device path.
1064 @retval EFI_SUCCESS Success to get the device path.
1068 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1069 IN EFI_DEVICE_PATH_PROTOCOL
*HpcDevicePath
,
1070 OUT UINT64
*PciAddress
1073 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1074 EFI_DEV_PATH_PTR Node
;
1075 LIST_ENTRY
*CurrentLink
;
1076 PCI_IO_DEVICE
*RootBridge
;
1079 CurrentDevicePath
= HpcDevicePath
;
1082 // Get the remaining device path for this PCI device, if it is a PCI device
1084 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1086 Node
.DevPath
= CurrentDevicePath
;
1089 // Check if it is PCI device Path?
1091 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
1092 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
1093 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))) {
1094 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1102 // Check if it is not PCI device path
1104 if (IsDevicePathEnd (CurrentDevicePath
)) {
1105 return EFI_NOT_FOUND
;
1108 CurrentLink
= gPciDevicePool
.ForwardLink
;
1110 while (CurrentLink
!= NULL
&& CurrentLink
!= &gPciDevicePool
) {
1112 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1114 // Locate the right root bridge to start
1116 if (RootBridge
->PciRootBridgeIo
== PciRootBridgeIo
) {
1117 Status
= GetHpcPciAddressFromRootBridge (
1122 if (EFI_ERROR (Status
)) {
1123 return EFI_NOT_FOUND
;
1130 CurrentLink
= CurrentLink
->ForwardLink
;
1133 return EFI_NOT_FOUND
;
1137 Get HPC PCI address according to its device path.
1138 @param RootBridge Root bridege Io instance.
1139 @param RemainingDevicePath Given searching device path.
1140 @param PciAddress Buffer holding searched result.
1142 @retval EFI_NOT_FOUND Can not find the specific device path.
1145 GetHpcPciAddressFromRootBridge (
1146 IN PCI_IO_DEVICE
*RootBridge
,
1147 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1148 OUT UINT64
*PciAddress
1151 EFI_DEV_PATH_PTR Node
;
1152 PCI_IO_DEVICE
*Temp
;
1153 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1154 LIST_ENTRY
*CurrentLink
;
1159 CurrentDevicePath
= RemainingDevicePath
;
1160 Node
.DevPath
= CurrentDevicePath
;
1163 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1165 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1166 Node
.DevPath
= CurrentDevicePath
;
1168 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1169 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1171 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1172 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1177 CurrentLink
= CurrentLink
->ForwardLink
;
1181 // Check if we find the bridge
1183 if (CurrentLink
== &RootBridge
->ChildList
) {
1190 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1195 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1197 if (IsDevicePathEnd (CurrentDevicePath
)) {
1198 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1202 return EFI_NOT_FOUND
;
1205 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);