3 Copyright (c) 2006, 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
&& 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
;
225 // Install the pciio protocol, device path protocol
227 Status
= gBS
->InstallMultipleProtocolInterfaces (
228 &PciIoDevice
->Handle
,
229 &gEfiDevicePathProtocolGuid
,
230 PciIoDevice
->DevicePath
,
231 &gEfiPciIoProtocolGuid
,
235 if (EFI_ERROR (Status
)) {
240 // Detect if PCI Express Device
242 PciExpressCapRegOffset
= 0;
243 Status
= LocateCapabilityRegBlock (
245 EFI_PCI_CAPABILITY_ID_PCIEXP
,
246 &PciExpressCapRegOffset
,
249 if (!EFI_ERROR (Status
)) {
250 PciIoDevice
->IsPciExp
= TRUE
;
254 // Force Interrupt line to "Unknown" or "No Connection"
256 PciIo
= &(PciIoDevice
->PciIo
);
257 Data8
= PCI_INT_LINE_UNKNOWN
;
258 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &Data8
);
263 if (!PciIoDevice
->AllOpRomProcessed
) {
264 PciIoDevice
->AllOpRomProcessed
= TRUE
;
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 // Dispatch the EFI OpRom for the PCI device.
299 // The OpRom is got from platform in the above code
300 // or loaded from device in previous bus enumeration
302 if (PciIoDevice
->RomSize
> 0) {
303 ProcessOpRomImage (PciIoDevice
);
307 if (PciIoDevice
->BusOverride
) {
309 // Install BusSpecificDriverOverride Protocol
311 Status
= gBS
->InstallMultipleProtocolInterfaces (
312 &PciIoDevice
->Handle
,
313 &gEfiBusSpecificDriverOverrideProtocolGuid
,
314 &PciIoDevice
->PciDriverOverride
,
317 if (EFI_ERROR (Status
)) {
318 gBS
->UninstallMultipleProtocolInterfaces (
319 &PciIoDevice
->Handle
,
320 &gEfiDevicePathProtocolGuid
,
321 PciIoDevice
->DevicePath
,
322 &gEfiPciIoProtocolGuid
,
331 Status
= gBS
->OpenProtocol (
333 &gEfiPciRootBridgeIoProtocolGuid
,
334 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
335 gPciBusDriverBinding
.DriverBindingHandle
,
337 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
339 if (EFI_ERROR (Status
)) {
344 // Install Pccard Hotplug GUID for Pccard device so that
345 // to notify CardBus driver to stop the device when de-register happens
347 InstallPciHotplugGuid (PciIoDevice
);
349 if (Handle
!= NULL
) {
350 *Handle
= PciIoDevice
->Handle
;
354 // Indicate the pci device is registered
356 PciIoDevice
->Registered
= TRUE
;
362 This function is used to remove the whole PCI devices from the bridge.
364 @param RootBridgeHandle An efi handle.
365 @param Bridge A pointer to the PCI_IO_DEVICE.
370 RemoveAllPciDeviceOnBridge (
371 EFI_HANDLE RootBridgeHandle
,
372 PCI_IO_DEVICE
*Bridge
377 LIST_ENTRY
*CurrentLink
;
380 while (!IsListEmpty (&Bridge
->ChildList
)) {
382 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
383 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
386 // Check if the current node has been deregistered before
387 // If it is not, then deregister it
389 if (Temp
->Registered
) {
390 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
394 // Remove this node from the linked list
396 RemoveEntryList (CurrentLink
);
398 if (!IsListEmpty (&Temp
->ChildList
)) {
399 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
402 FreePciDevice (Temp
);
410 This function is used to de-register the PCI device from the EFI,
411 That includes un-installing PciIo protocol from the specified PCI
414 @param Controller - controller handle
415 @param Handle - device handle
417 @return Status of de-register pci device
420 DeRegisterPciDevice (
421 IN EFI_HANDLE Controller
,
426 EFI_PCI_IO_PROTOCOL
*PciIo
;
428 PCI_IO_DEVICE
*PciIoDevice
;
430 LIST_ENTRY
*CurrentLink
;
431 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
433 Status
= gBS
->OpenProtocol (
435 &gEfiPciIoProtocolGuid
,
437 gPciBusDriverBinding
.DriverBindingHandle
,
439 EFI_OPEN_PROTOCOL_GET_PROTOCOL
441 if (!EFI_ERROR (Status
)) {
442 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
445 // If it is already de-registered
447 if (!PciIoDevice
->Registered
) {
452 // If it is PPB, first de-register its children
455 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
457 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
459 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
460 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
461 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
463 if (EFI_ERROR (Status
)) {
467 CurrentLink
= CurrentLink
->ForwardLink
;
471 // Uninstall Pccard Hotplug GUID for Pccard device
473 UninstallPciHotplugGuid (PciIoDevice
);
476 // Close the child handle
478 Status
= gBS
->CloseProtocol (
480 &gEfiPciRootBridgeIoProtocolGuid
,
481 gPciBusDriverBinding
.DriverBindingHandle
,
486 // Un-install the device path protocol and pci io protocol
488 if (PciIoDevice
->BusOverride
) {
489 Status
= gBS
->UninstallMultipleProtocolInterfaces (
491 &gEfiDevicePathProtocolGuid
,
492 PciIoDevice
->DevicePath
,
493 &gEfiPciIoProtocolGuid
,
495 &gEfiBusSpecificDriverOverrideProtocolGuid
,
496 &PciIoDevice
->PciDriverOverride
,
500 Status
= gBS
->UninstallMultipleProtocolInterfaces (
502 &gEfiDevicePathProtocolGuid
,
503 PciIoDevice
->DevicePath
,
504 &gEfiPciIoProtocolGuid
,
510 if (EFI_ERROR (Status
)) {
513 &gEfiPciRootBridgeIoProtocolGuid
,
514 (VOID
**) &PciRootBridgeIo
,
515 gPciBusDriverBinding
.DriverBindingHandle
,
517 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
523 // The Device Driver should disable this device after disconnect
524 // so the Pci Bus driver will not touch this device any more.
525 // Restore the register field to the original value
527 PciIoDevice
->Registered
= FALSE
;
528 PciIoDevice
->Handle
= NULL
;
532 // Handle may be closed before
541 Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
543 @param Controller An efi handle.
544 @param RootBridge A pointer to the PCI_IO_DEVICE.
545 @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
546 @param NumberOfChildren Children number.
547 @param ChildHandleBuffer A pointer to the child handle buffer.
549 @retval EFI_NOT_READY Device is not allocated
550 @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
551 @retval EFI_NOT_FOUND Can not find the specific device
552 @retval EFI_SUCCESS Success to start Pci device on bridge
556 StartPciDevicesOnBridge (
557 IN EFI_HANDLE Controller
,
558 IN PCI_IO_DEVICE
*RootBridge
,
559 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
560 IN OUT UINT8
*NumberOfChildren
,
561 IN OUT EFI_HANDLE
*ChildHandleBuffer
565 PCI_IO_DEVICE
*PciIoDevice
;
566 EFI_DEV_PATH_PTR Node
;
567 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
569 LIST_ENTRY
*CurrentLink
;
572 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
574 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
576 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
577 if (RemainingDevicePath
!= NULL
) {
579 Node
.DevPath
= RemainingDevicePath
;
581 if (Node
.Pci
->Device
!= PciIoDevice
->DeviceNumber
||
582 Node
.Pci
->Function
!= PciIoDevice
->FunctionNumber
) {
583 CurrentLink
= CurrentLink
->ForwardLink
;
588 // Check if the device has been assigned with required resource
590 if (!PciIoDevice
->Allocated
) {
591 return EFI_NOT_READY
;
595 // Check if the current node has been registered before
596 // If it is not, register it
598 if (!PciIoDevice
->Registered
) {
599 Status
= RegisterPciDevice (
607 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
608 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
609 (*NumberOfChildren
)++;
613 // Get the next device path
615 CurrentDevicePath
= NextDevicePathNode (RemainingDevicePath
);
616 if (IsDevicePathEnd (CurrentDevicePath
)) {
623 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
624 Status
= StartPciDevicesOnBridge (
632 PciIoDevice
->PciIo
.Attributes (
633 &(PciIoDevice
->PciIo
),
634 EfiPciIoAttributeOperationSupported
,
638 Supports
&= EFI_PCI_DEVICE_ENABLE
;
639 PciIoDevice
->PciIo
.Attributes (
640 &(PciIoDevice
->PciIo
),
641 EfiPciIoAttributeOperationEnable
,
650 // Currently, the PCI bus driver only support PCI-PCI bridge
652 return EFI_UNSUPPORTED
;
658 // If remaining device path is NULL,
659 // try to enable all the pci devices under this bridge
662 if (!PciIoDevice
->Registered
&& PciIoDevice
->Allocated
) {
663 Status
= RegisterPciDevice (
671 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
672 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
673 (*NumberOfChildren
)++;
676 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
677 Status
= StartPciDevicesOnBridge (
685 PciIoDevice
->PciIo
.Attributes (
686 &(PciIoDevice
->PciIo
),
687 EfiPciIoAttributeOperationSupported
,
691 Supports
&= EFI_PCI_DEVICE_ENABLE
;
692 PciIoDevice
->PciIo
.Attributes (
693 &(PciIoDevice
->PciIo
),
694 EfiPciIoAttributeOperationEnable
,
701 CurrentLink
= CurrentLink
->ForwardLink
;
705 return EFI_NOT_FOUND
;
709 Start to manage all the PCI devices it found previously under
710 the entire host bridge.
712 @param Controller - root bridge handle.
717 IN EFI_HANDLE Controller
721 PCI_IO_DEVICE
*RootBridge
;
722 EFI_HANDLE ThisHostBridge
;
723 LIST_ENTRY
*CurrentLink
;
725 RootBridge
= GetRootBridgeByHandle (Controller
);
726 ASSERT (RootBridge
!= NULL
);
727 ThisHostBridge
= RootBridge
->PciRootBridgeIo
->ParentHandle
;
729 CurrentLink
= gPciDevicePool
.ForwardLink
;
731 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
733 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
735 // Locate the right root bridge to start
737 if (RootBridge
->PciRootBridgeIo
->ParentHandle
== ThisHostBridge
) {
738 StartPciDevicesOnBridge (
747 CurrentLink
= CurrentLink
->ForwardLink
;
754 Create root bridge device
756 @param RootBridgeHandle - Parent bridge handle.
758 @return pointer to new root bridge
762 IN EFI_HANDLE RootBridgeHandle
768 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
769 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
772 Status
= gBS
->AllocatePool (
774 sizeof (PCI_IO_DEVICE
),
778 if (EFI_ERROR (Status
)) {
782 ZeroMem (Dev
, sizeof (PCI_IO_DEVICE
));
783 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
784 Dev
->Handle
= RootBridgeHandle
;
785 InitializeListHead (&Dev
->ChildList
);
787 Status
= gBS
->OpenProtocol (
789 &gEfiDevicePathProtocolGuid
,
790 (VOID
**) &ParentDevicePath
,
791 gPciBusDriverBinding
.DriverBindingHandle
,
793 EFI_OPEN_PROTOCOL_GET_PROTOCOL
796 if (EFI_ERROR (Status
)) {
802 // Record the root bridge parent device path
804 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
807 // Get the pci root bridge io protocol
809 Status
= gBS
->OpenProtocol (
811 &gEfiPciRootBridgeIoProtocolGuid
,
812 (VOID
**) &PciRootBridgeIo
,
813 gPciBusDriverBinding
.DriverBindingHandle
,
815 EFI_OPEN_PROTOCOL_GET_PROTOCOL
818 if (EFI_ERROR (Status
)) {
823 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
826 // Initialize the PCI I/O instance structure
828 Status
= InitializePciIoInstance (Dev
);
829 Status
= InitializePciDriverOverrideInstance (Dev
);
832 // Initialize reserved resource list and
833 // option rom driver list
835 InitializeListHead (&Dev
->ReservedResourceList
);
836 InitializeListHead (&Dev
->OptionRomDriverList
);
842 Get root bridge device instance by specific handle
844 @param RootBridgeHandle Given root bridge handle
846 @return root bridge device instance
849 GetRootBridgeByHandle (
850 EFI_HANDLE RootBridgeHandle
853 PCI_IO_DEVICE
*RootBridgeDev
;
854 LIST_ENTRY
*CurrentLink
;
856 CurrentLink
= gPciDevicePool
.ForwardLink
;
858 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
860 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
861 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
862 return RootBridgeDev
;
865 CurrentLink
= CurrentLink
->ForwardLink
;
872 Judege whether Pci device existed
874 @param Bridge Parent bridege instance
875 @param PciIoDevice Device instance
877 @return whether Pci device existed
881 IN PCI_IO_DEVICE
*Bridge
,
882 IN PCI_IO_DEVICE
*PciIoDevice
887 LIST_ENTRY
*CurrentLink
;
889 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
891 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
893 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
895 if (Temp
== PciIoDevice
) {
899 if (!IsListEmpty (&Temp
->ChildList
)) {
900 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
905 CurrentLink
= CurrentLink
->ForwardLink
;
914 @param VgaDevice device instance for VGA
916 @return device instance
919 ActiveVGADeviceOnTheSameSegment (
920 IN PCI_IO_DEVICE
*VgaDevice
923 LIST_ENTRY
*CurrentLink
;
926 CurrentLink
= gPciDevicePool
.ForwardLink
;
928 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
930 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
932 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
934 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
941 CurrentLink
= CurrentLink
->ForwardLink
;
948 Active VGA device on root bridge
950 @param RootBridge Root bridge device instance
952 @return VGA device instance
955 ActiveVGADeviceOnTheRootBridge (
956 IN PCI_IO_DEVICE
*RootBridge
959 LIST_ENTRY
*CurrentLink
;
962 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
964 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
966 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
968 if (IS_PCI_VGA(&Temp
->Pci
) &&
970 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
971 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
972 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
))) {
976 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
978 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
985 CurrentLink
= CurrentLink
->ForwardLink
;
992 Get HPC PCI address according to its device path
993 @param PciRootBridgeIo Root bridege Io instance
994 @param HpcDevicePath Given searching device path
995 @param PciAddress Buffer holding searched result
997 @retval EFI_NOT_FOUND Can not find the specific device path.
998 @retval EFI_SUCCESS Success to get the device path
1002 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1003 IN EFI_DEVICE_PATH_PROTOCOL
*HpcDevicePath
,
1004 OUT UINT64
*PciAddress
1007 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1008 EFI_DEV_PATH_PTR Node
;
1009 LIST_ENTRY
*CurrentLink
;
1010 PCI_IO_DEVICE
*RootBridge
;
1013 CurrentDevicePath
= HpcDevicePath
;
1016 // Get the remaining device path for this PCI device, if it is a PCI device
1018 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1020 Node
.DevPath
= CurrentDevicePath
;
1023 // Check if it is PCI device Path?
1025 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
1026 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
1027 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))) {
1028 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1036 // Check if it is not PCI device path
1038 if (IsDevicePathEnd (CurrentDevicePath
)) {
1039 return EFI_NOT_FOUND
;
1042 CurrentLink
= gPciDevicePool
.ForwardLink
;
1044 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
1046 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1048 // Locate the right root bridge to start
1050 if (RootBridge
->PciRootBridgeIo
== PciRootBridgeIo
) {
1051 Status
= GetHpcPciAddressFromRootBridge (
1056 if (EFI_ERROR (Status
)) {
1057 return EFI_NOT_FOUND
;
1064 CurrentLink
= CurrentLink
->ForwardLink
;
1067 return EFI_NOT_FOUND
;
1071 Get HPC PCI address according to its device path
1072 @param RootBridge Root bridege Io instance
1073 @param RemainingDevicePath Given searching device path
1074 @param PciAddress Buffer holding searched result
1076 @retval EFI_NOT_FOUND Can not find the specific device path.
1079 GetHpcPciAddressFromRootBridge (
1080 IN PCI_IO_DEVICE
*RootBridge
,
1081 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1082 OUT UINT64
*PciAddress
1085 EFI_DEV_PATH_PTR Node
;
1086 PCI_IO_DEVICE
*Temp
;
1087 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1088 LIST_ENTRY
*CurrentLink
;
1093 CurrentDevicePath
= RemainingDevicePath
;
1094 Node
.DevPath
= CurrentDevicePath
;
1097 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1099 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1100 Node
.DevPath
= CurrentDevicePath
;
1102 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
1103 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1105 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1106 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1111 CurrentLink
= CurrentLink
->ForwardLink
;
1115 // Check if we find the bridge
1117 if (CurrentLink
== &RootBridge
->ChildList
) {
1124 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1129 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1131 if (IsDevicePathEnd (CurrentDevicePath
)) {
1132 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1136 return EFI_NOT_FOUND
;
1139 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);