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.
18 This file provides routine to support Pci device node manipulation
25 #include "PciDeviceSupport.h"
28 // This device structure is serviced as a header.
29 // Its Next field points to the first root bridge device node
31 LIST_ENTRY gPciDevicePool
;
34 InitializePciDevicePool (
41 Initialize the gPciDevicePool
50 // TODO: EFI_SUCCESS - add return value to function comment
52 InitializeListHead (&gPciDevicePool
);
59 PCI_IO_DEVICE
*RootBridge
65 Insert a root bridge into PCI device pool
69 RootBridge - A pointer to the PCI_IO_DEVICE.
76 // TODO: EFI_SUCCESS - add return value to function comment
79 InsertTailList (&gPciDevicePool
, &(RootBridge
->Link
));
86 PCI_IO_DEVICE
*Bridge
,
87 PCI_IO_DEVICE
*PciDeviceNode
93 This function is used to insert a PCI device node under
97 Bridge - A pointer to the PCI_IO_DEVICE.
98 PciDeviceNode - A pointer to the PCI_IO_DEVICE.
105 // TODO: EFI_SUCCESS - add return value to function comment
108 InsertTailList (&Bridge
->ChildList
, &(PciDeviceNode
->Link
));
109 PciDeviceNode
->Parent
= Bridge
;
116 IN PCI_IO_DEVICE
*RootBridge
125 RootBridge - A pointer to the PCI_IO_DEVICE.
132 // TODO: EFI_SUCCESS - add return value to function comment
134 DestroyPciDeviceTree (RootBridge
);
136 FreePciDevice (RootBridge
);
143 IN PCI_IO_DEVICE
*PciIoDevice
149 Destroy a pci device node.
150 Also all direct or indirect allocated resource for this node will be freed.
154 PciIoDevice - A pointer to the PCI_IO_DEVICE.
161 // TODO: EFI_SUCCESS - add return value to function comment
165 // Assume all children have been removed underneath this device
167 if (PciIoDevice
->ResourcePaddingDescriptors
!= NULL
) {
168 gBS
->FreePool (PciIoDevice
->ResourcePaddingDescriptors
);
171 if (PciIoDevice
->DevicePath
!= NULL
) {
172 gBS
->FreePool (PciIoDevice
->DevicePath
);
175 gBS
->FreePool (PciIoDevice
);
181 DestroyPciDeviceTree (
182 IN PCI_IO_DEVICE
*Bridge
188 Destroy all the pci device node under the bridge.
189 Bridge itself is not included.
193 Bridge - A pointer to the PCI_IO_DEVICE.
200 // TODO: EFI_SUCCESS - add return value to function comment
202 LIST_ENTRY
*CurrentLink
;
205 while (!IsListEmpty (&Bridge
->ChildList
)) {
207 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
210 // Remove this node from the linked list
212 RemoveEntryList (CurrentLink
);
214 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
216 if (!IsListEmpty (&Temp
->ChildList
)) {
217 DestroyPciDeviceTree (Temp
);
220 FreePciDevice (Temp
);
227 DestroyRootBridgeByHandle (
228 EFI_HANDLE Controller
234 Destroy all device nodes under the root bridge
235 specified by Controller.
236 The root bridge itself is also included.
240 Controller - An efi handle.
247 // TODO: EFI_SUCCESS - add return value to function comment
248 // TODO: EFI_NOT_FOUND - add return value to function comment
251 LIST_ENTRY
*CurrentLink
;
254 CurrentLink
= gPciDevicePool
.ForwardLink
;
256 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
257 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
259 if (Temp
->Handle
== Controller
) {
261 RemoveEntryList (CurrentLink
);
263 DestroyPciDeviceTree (Temp
);
265 FreePciDevice (Temp
);
270 CurrentLink
= CurrentLink
->ForwardLink
;
273 return EFI_NOT_FOUND
;
278 IN EFI_HANDLE Controller
,
279 IN PCI_IO_DEVICE
*PciIoDevice
,
280 OUT EFI_HANDLE
*Handle OPTIONAL
286 This function is used to register the PCI device to the EFI,
287 create a handle for this PCI device,then attach apporpriate protocols
292 Controller - An efi handle.
293 PciIoDevice - A pointer to the PCI_IO_DEVICE.
294 Handle - A pointer to a efi handle.
301 // TODO: EFI_SUCCESS - add return value to function comment
304 VOID
*PlatformOpRomBuffer
;
305 UINTN PlatformOpRomSize
;
306 UINT8 PciExpressCapRegOffset
;
307 EFI_PCI_IO_PROTOCOL
*PciIo
;
310 // Install the pciio protocol, device path protocol
312 Status
= gBS
->InstallMultipleProtocolInterfaces (
313 &PciIoDevice
->Handle
,
314 &gEfiDevicePathProtocolGuid
,
315 PciIoDevice
->DevicePath
,
316 &gEfiPciIoProtocolGuid
,
320 if (EFI_ERROR (Status
)) {
325 // Detect if PCI Express Device
327 PciExpressCapRegOffset
= 0;
328 Status
= LocateCapabilityRegBlock (
330 EFI_PCI_CAPABILITY_ID_PCIEXP
,
331 &PciExpressCapRegOffset
,
334 if (!EFI_ERROR (Status
)) {
335 PciIoDevice
->IsPciExp
= TRUE
;
339 // Force Interrupt line to zero for cards that come up randomly
341 PciIo
= &(PciIoDevice
->PciIo
);
342 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
344 // Process Platform OpRom
346 if (gPciPlatformProtocol
!= NULL
&& !PciIoDevice
->AllOpRomProcessed
) {
347 PciIoDevice
->AllOpRomProcessed
= TRUE
;
349 Status
= gPciPlatformProtocol
->GetPciRom (
350 gPciPlatformProtocol
,
352 &PlatformOpRomBuffer
,
356 if (!EFI_ERROR (Status
)) {
359 // Have Platform OpRom
361 PciIoDevice
->RomSize
= PlatformOpRomSize
;
362 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
363 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
368 ProcessOpRomImage (PciIoDevice
);
372 if (PciIoDevice
->BusOverride
) {
374 // Install BusSpecificDriverOverride Protocol
376 Status
= gBS
->InstallMultipleProtocolInterfaces (
377 &PciIoDevice
->Handle
,
378 &gEfiBusSpecificDriverOverrideProtocolGuid
,
379 &PciIoDevice
->PciDriverOverride
,
382 if (EFI_ERROR (Status
)) {
383 gBS
->UninstallMultipleProtocolInterfaces (
384 &PciIoDevice
->Handle
,
385 &gEfiDevicePathProtocolGuid
,
386 PciIoDevice
->DevicePath
,
387 &gEfiPciIoProtocolGuid
,
396 Status
= gBS
->OpenProtocol (
398 &gEfiPciRootBridgeIoProtocolGuid
,
399 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
400 gPciBusDriverBinding
.DriverBindingHandle
,
402 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
404 if (EFI_ERROR (Status
)) {
409 // Install Pccard Hotplug GUID for Pccard device so that
410 // to notify CardBus driver to stop the device when de-register happens
412 InstallPciHotplugGuid (PciIoDevice
);
414 if (Handle
!= NULL
) {
415 *Handle
= PciIoDevice
->Handle
;
419 // Indicate the pci device is registered
421 PciIoDevice
->Registered
= TRUE
;
427 RemoveAllPciDeviceOnBridge (
428 EFI_HANDLE RootBridgeHandle
,
429 PCI_IO_DEVICE
*Bridge
435 This function is used to remove the whole PCI devices from the bridge.
439 RootBridgeHandle - An efi handle.
440 Bridge - A pointer to the PCI_IO_DEVICE.
447 // TODO: EFI_SUCCESS - add return value to function comment
450 LIST_ENTRY
*CurrentLink
;
453 while (!IsListEmpty (&Bridge
->ChildList
)) {
455 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
456 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
459 // Check if the current node has been deregistered before
460 // If it is not, then deregister it
462 if (Temp
->Registered
) {
463 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
467 // Remove this node from the linked list
469 RemoveEntryList (CurrentLink
);
471 if (!IsListEmpty (&Temp
->ChildList
)) {
472 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
475 FreePciDevice (Temp
);
482 DeRegisterPciDevice (
483 IN EFI_HANDLE Controller
,
490 This function is used to de-register the PCI device from the EFI,
491 That includes un-installing PciIo protocol from the specified PCI
496 Controller - An efi handle.
497 Handle - An efi handle.
504 // TODO: EFI_SUCCESS - add return value to function comment
505 // TODO: EFI_SUCCESS - add return value to function comment
506 // TODO: EFI_SUCCESS - add return value to function comment
508 EFI_PCI_IO_PROTOCOL
*PciIo
;
510 PCI_IO_DEVICE
*PciIoDevice
;
512 LIST_ENTRY
*CurrentLink
;
513 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
515 Status
= gBS
->OpenProtocol (
517 &gEfiPciIoProtocolGuid
,
519 gPciBusDriverBinding
.DriverBindingHandle
,
521 EFI_OPEN_PROTOCOL_GET_PROTOCOL
523 if (!EFI_ERROR (Status
)) {
524 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
527 // If it is already de-registered
529 if (!PciIoDevice
->Registered
) {
534 // If it is PPB, first de-register its children
537 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
539 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
541 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
542 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
543 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
545 if (EFI_ERROR (Status
)) {
549 CurrentLink
= CurrentLink
->ForwardLink
;
553 // Uninstall Pccard Hotplug GUID for Pccard device
555 UninstallPciHotplugGuid (PciIoDevice
);
558 // Close the child handle
560 Status
= gBS
->CloseProtocol (
562 &gEfiPciRootBridgeIoProtocolGuid
,
563 gPciBusDriverBinding
.DriverBindingHandle
,
568 // Un-install the device path protocol and pci io protocol
570 if (PciIoDevice
->BusOverride
) {
571 Status
= gBS
->UninstallMultipleProtocolInterfaces (
573 &gEfiDevicePathProtocolGuid
,
574 PciIoDevice
->DevicePath
,
575 &gEfiPciIoProtocolGuid
,
577 &gEfiBusSpecificDriverOverrideProtocolGuid
,
578 &PciIoDevice
->PciDriverOverride
,
582 Status
= gBS
->UninstallMultipleProtocolInterfaces (
584 &gEfiDevicePathProtocolGuid
,
585 PciIoDevice
->DevicePath
,
586 &gEfiPciIoProtocolGuid
,
592 if (EFI_ERROR (Status
)) {
595 &gEfiPciRootBridgeIoProtocolGuid
,
596 (VOID
**) &PciRootBridgeIo
,
597 gPciBusDriverBinding
.DriverBindingHandle
,
599 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
605 // The Device Driver should disable this device after disconnect
606 // so the Pci Bus driver will not touch this device any more.
607 // Restore the register field to the original value
609 PciIoDevice
->Registered
= FALSE
;
610 PciIoDevice
->Handle
= NULL
;
614 // Handle may be closed before
623 StartPciDevicesOnBridge (
624 IN EFI_HANDLE Controller
,
625 IN PCI_IO_DEVICE
*RootBridge
,
626 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
627 IN OUT UINT8
*NumberOfChildren
,
628 IN OUT EFI_HANDLE
*ChildHandleBuffer
634 Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
638 Controller - An efi handle.
639 RootBridge - A pointer to the PCI_IO_DEVICE.
640 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
641 NumberOfChildren - Children number.
642 ChildHandleBuffer - A pointer to the child handle buffer.
649 // TODO: EFI_NOT_READY - add return value to function comment
650 // TODO: EFI_SUCCESS - add return value to function comment
651 // TODO: EFI_UNSUPPORTED - add return value to function comment
652 // TODO: EFI_NOT_FOUND - add return value to function comment
655 PCI_IO_DEVICE
*PciIoDevice
;
656 EFI_DEV_PATH_PTR Node
;
657 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
659 LIST_ENTRY
*CurrentLink
;
662 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
664 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
666 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
667 if (RemainingDevicePath
!= NULL
) {
669 Node
.DevPath
= RemainingDevicePath
;
671 if (Node
.Pci
->Device
!= Temp
->DeviceNumber
||
672 Node
.Pci
->Function
!= Temp
->FunctionNumber
) {
673 CurrentLink
= CurrentLink
->ForwardLink
;
678 // Check if the device has been assigned with required resource
680 if (!Temp
->Allocated
) {
681 return EFI_NOT_READY
;
685 // Check if the current node has been registered before
686 // If it is not, register it
688 if (!Temp
->Registered
) {
691 Status
= RegisterPciDevice (
699 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& Temp
->Registered
) {
700 ChildHandleBuffer
[*NumberOfChildren
] = Temp
->Handle
;
701 (*NumberOfChildren
)++;
705 // Get the next device path
707 CurrentDevicePath
= EfiNextDevicePathNode (RemainingDevicePath
);
708 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
715 if (!IsListEmpty (&Temp
->ChildList
)) {
716 Status
= StartPciDevicesOnBridge (
724 Temp
->PciIo
.Attributes (
726 EfiPciIoAttributeOperationSupported
,
730 Supports
&= EFI_PCI_DEVICE_ENABLE
;
731 Temp
->PciIo
.Attributes (
733 EfiPciIoAttributeOperationEnable
,
742 // Currently, the PCI bus driver only support PCI-PCI bridge
744 return EFI_UNSUPPORTED
;
750 // If remaining device path is NULL,
751 // try to enable all the pci devices under this bridge
754 if (!Temp
->Registered
&& Temp
->Allocated
) {
758 Status
= RegisterPciDevice (
766 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& Temp
->Registered
) {
767 ChildHandleBuffer
[*NumberOfChildren
] = Temp
->Handle
;
768 (*NumberOfChildren
)++;
771 if (!IsListEmpty (&Temp
->ChildList
)) {
772 Status
= StartPciDevicesOnBridge (
780 Temp
->PciIo
.Attributes (
782 EfiPciIoAttributeOperationSupported
,
786 Supports
&= EFI_PCI_DEVICE_ENABLE
;
787 Temp
->PciIo
.Attributes (
789 EfiPciIoAttributeOperationEnable
,
796 CurrentLink
= CurrentLink
->ForwardLink
;
801 return EFI_NOT_FOUND
;
806 IN EFI_HANDLE Controller
,
807 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
813 Start to manage the PCI device according to RemainingDevicePath
814 If RemainingDevicePath == NULL, the PCI bus driver will start
815 to manage all the PCI devices it found previously
818 Controller - An efi handle.
819 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
826 // TODO: EFI_UNSUPPORTED - add return value to function comment
827 // TODO: EFI_SUCCESS - add return value to function comment
829 EFI_DEV_PATH_PTR Node
;
830 PCI_IO_DEVICE
*RootBridge
;
831 LIST_ENTRY
*CurrentLink
;
833 if (RemainingDevicePath
!= NULL
) {
836 // Check if the RemainingDevicePath is valid
838 Node
.DevPath
= RemainingDevicePath
;
839 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
840 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
841 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))
843 return EFI_UNSUPPORTED
;
847 CurrentLink
= gPciDevicePool
.ForwardLink
;
849 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
851 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
853 // Locate the right root bridge to start
855 if (RootBridge
->Handle
== Controller
) {
856 StartPciDevicesOnBridge (
865 CurrentLink
= CurrentLink
->ForwardLink
;
873 IN EFI_HANDLE RootBridgeHandle
881 RootBridgeHandle - An efi handle.
892 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
893 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
896 Status
= gBS
->AllocatePool (
898 sizeof (PCI_IO_DEVICE
),
902 if (EFI_ERROR (Status
)) {
906 ZeroMem (Dev
, sizeof (PCI_IO_DEVICE
));
907 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
908 Dev
->Handle
= RootBridgeHandle
;
909 InitializeListHead (&Dev
->ChildList
);
911 Status
= gBS
->OpenProtocol (
913 &gEfiDevicePathProtocolGuid
,
914 (VOID
**) &ParentDevicePath
,
915 gPciBusDriverBinding
.DriverBindingHandle
,
917 EFI_OPEN_PROTOCOL_GET_PROTOCOL
920 if (EFI_ERROR (Status
)) {
926 // Record the root bridge parent device path
928 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
931 // Get the pci root bridge io protocol
933 Status
= gBS
->OpenProtocol (
935 &gEfiPciRootBridgeIoProtocolGuid
,
936 (VOID
**) &PciRootBridgeIo
,
937 gPciBusDriverBinding
.DriverBindingHandle
,
939 EFI_OPEN_PROTOCOL_GET_PROTOCOL
942 if (EFI_ERROR (Status
)) {
947 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
950 // Initialize the PCI I/O instance structure
952 Status
= InitializePciIoInstance (Dev
);
953 Status
= InitializePciDriverOverrideInstance (Dev
);
956 // Initialize reserved resource list and
957 // option rom driver list
959 InitializeListHead (&Dev
->ReservedResourceList
);
960 InitializeListHead (&Dev
->OptionRomDriverList
);
966 GetRootBridgeByHandle (
967 EFI_HANDLE RootBridgeHandle
976 RootBridgeHandle - An efi handle.
984 PCI_IO_DEVICE
*RootBridgeDev
;
985 LIST_ENTRY
*CurrentLink
;
987 CurrentLink
= gPciDevicePool
.ForwardLink
;
989 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
991 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
992 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
993 return RootBridgeDev
;
996 CurrentLink
= CurrentLink
->ForwardLink
;
1004 IN EFI_HANDLE RootBridgeHandle
1008 Routine Description:
1010 This function searches if RootBridgeHandle has already existed
1011 in current device pool.
1013 If so, it means the given root bridge has been already enumerated.
1017 RootBridgeHandle - An efi handle.
1025 PCI_IO_DEVICE
*Bridge
;
1027 Bridge
= GetRootBridgeByHandle (RootBridgeHandle
);
1029 if (Bridge
!= NULL
) {
1038 IN PCI_IO_DEVICE
*Bridge
,
1039 IN PCI_IO_DEVICE
*PciIoDevice
1043 Routine Description:
1047 Bridge - A pointer to the PCI_IO_DEVICE.
1048 PciIoDevice - A pointer to the PCI_IO_DEVICE.
1057 PCI_IO_DEVICE
*Temp
;
1058 LIST_ENTRY
*CurrentLink
;
1060 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1062 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
1064 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1066 if (Temp
== PciIoDevice
) {
1070 if (!IsListEmpty (&Temp
->ChildList
)) {
1071 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
1076 CurrentLink
= CurrentLink
->ForwardLink
;
1083 ActiveVGADeviceOnTheSameSegment (
1084 IN PCI_IO_DEVICE
*VgaDevice
1088 Routine Description:
1092 VgaDevice - A pointer to the PCI_IO_DEVICE.
1100 LIST_ENTRY
*CurrentLink
;
1101 PCI_IO_DEVICE
*Temp
;
1103 CurrentLink
= gPciDevicePool
.ForwardLink
;
1105 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
1107 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1109 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
1111 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1118 CurrentLink
= CurrentLink
->ForwardLink
;
1125 ActiveVGADeviceOnTheRootBridge (
1126 IN PCI_IO_DEVICE
*RootBridge
1130 Routine Description:
1134 RootBridge - A pointer to the PCI_IO_DEVICE.
1142 LIST_ENTRY
*CurrentLink
;
1143 PCI_IO_DEVICE
*Temp
;
1145 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1147 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
1149 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1151 if (IS_PCI_VGA(&Temp
->Pci
) &&
1152 (Temp
->Attributes
& (EFI_PCI_IO_ATTRIBUTE_MEMORY
| EFI_PCI_IO_ATTRIBUTE_IO
))) {
1156 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1158 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1165 CurrentLink
= CurrentLink
->ForwardLink
;
1173 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1174 IN EFI_DEVICE_PATH_PROTOCOL
*HpcDevicePath
,
1175 OUT UINT64
*PciAddress
1179 Routine Description:
1183 PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1184 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
1185 PciAddress - A pointer to the pci address.
1192 // TODO: EFI_NOT_FOUND - add return value to function comment
1193 // TODO: EFI_NOT_FOUND - add return value to function comment
1194 // TODO: EFI_SUCCESS - add return value to function comment
1195 // TODO: EFI_NOT_FOUND - add return value to function comment
1197 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1198 EFI_DEV_PATH_PTR Node
;
1199 LIST_ENTRY
*CurrentLink
;
1200 PCI_IO_DEVICE
*RootBridge
;
1203 CurrentDevicePath
= HpcDevicePath
;
1206 // Get the remaining device path for this PCI device, if it is a PCI device
1208 while (!EfiIsDevicePathEnd (CurrentDevicePath
)) {
1210 Node
.DevPath
= CurrentDevicePath
;
1213 // Check if it is PCI device Path?
1215 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
1216 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
1217 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))) {
1218 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1226 // Check if it is not PCI device path
1228 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
1229 return EFI_NOT_FOUND
;
1232 CurrentLink
= gPciDevicePool
.ForwardLink
;
1234 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
1236 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1238 // Locate the right root bridge to start
1240 if (RootBridge
->PciRootBridgeIo
== PciRootBridgeIo
) {
1241 Status
= GetHpcPciAddressFromRootBridge (
1246 if (EFI_ERROR (Status
)) {
1247 return EFI_NOT_FOUND
;
1254 CurrentLink
= CurrentLink
->ForwardLink
;
1257 return EFI_NOT_FOUND
;
1261 GetHpcPciAddressFromRootBridge (
1262 IN PCI_IO_DEVICE
*RootBridge
,
1263 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1264 OUT UINT64
*PciAddress
1268 Routine Description:
1272 PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1273 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
1274 PciAddress - A pointer to the pci address.
1281 // TODO: RootBridge - add argument and description to function comment
1282 // TODO: RemainingDevicePath - add argument and description to function comment
1283 // TODO: EFI_SUCCESS - add return value to function comment
1284 // TODO: EFI_NOT_FOUND - add return value to function comment
1285 // TODO: EFI_SUCCESS - add return value to function comment
1287 EFI_DEV_PATH_PTR Node
;
1288 PCI_IO_DEVICE
*Temp
;
1289 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1290 LIST_ENTRY
*CurrentLink
;
1295 CurrentDevicePath
= RemainingDevicePath
;
1296 Node
.DevPath
= CurrentDevicePath
;
1299 while (!EfiIsDevicePathEnd (CurrentDevicePath
)) {
1301 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1302 Node
.DevPath
= CurrentDevicePath
;
1304 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
1305 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1307 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1308 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1313 CurrentLink
= CurrentLink
->ForwardLink
;
1317 // Check if we find the bridge
1319 if (CurrentLink
== &RootBridge
->ChildList
) {
1326 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1331 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1333 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
1334 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1338 return EFI_NOT_FOUND
;
1341 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);