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
);
345 // Process Platform OpRom
347 if (gPciPlatformProtocol
!= NULL
&& !PciIoDevice
->AllOpRomProcessed
) {
348 PciIoDevice
->AllOpRomProcessed
= TRUE
;
350 Status
= gPciPlatformProtocol
->GetPciRom (
351 gPciPlatformProtocol
,
353 &PlatformOpRomBuffer
,
357 if (!EFI_ERROR (Status
)) {
360 // Have Platform OpRom
362 PciIoDevice
->RomSize
= PlatformOpRomSize
;
363 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
364 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
369 ProcessOpRomImage (PciIoDevice
);
373 if (PciIoDevice
->BusOverride
) {
375 // Install BusSpecificDriverOverride Protocol
377 Status
= gBS
->InstallMultipleProtocolInterfaces (
378 &PciIoDevice
->Handle
,
379 &gEfiBusSpecificDriverOverrideProtocolGuid
,
380 &PciIoDevice
->PciDriverOverride
,
383 if (EFI_ERROR (Status
)) {
384 gBS
->UninstallMultipleProtocolInterfaces (
385 &PciIoDevice
->Handle
,
386 &gEfiDevicePathProtocolGuid
,
387 PciIoDevice
->DevicePath
,
388 &gEfiPciIoProtocolGuid
,
397 Status
= gBS
->OpenProtocol (
399 &gEfiPciRootBridgeIoProtocolGuid
,
400 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
401 gPciBusDriverBinding
.DriverBindingHandle
,
403 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
405 if (EFI_ERROR (Status
)) {
410 // Install Pccard Hotplug GUID for Pccard device so that
411 // to notify CardBus driver to stop the device when de-register happens
413 InstallPciHotplugGuid (PciIoDevice
);
415 if (Handle
!= NULL
) {
416 *Handle
= PciIoDevice
->Handle
;
420 // Indicate the pci device is registered
422 PciIoDevice
->Registered
= TRUE
;
428 RemoveAllPciDeviceOnBridge (
429 EFI_HANDLE RootBridgeHandle
,
430 PCI_IO_DEVICE
*Bridge
436 This function is used to remove the whole PCI devices from the bridge.
440 RootBridgeHandle - An efi handle.
441 Bridge - A pointer to the PCI_IO_DEVICE.
448 // TODO: EFI_SUCCESS - add return value to function comment
451 LIST_ENTRY
*CurrentLink
;
454 while (!IsListEmpty (&Bridge
->ChildList
)) {
456 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
457 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
460 // Check if the current node has been deregistered before
461 // If it is not, then deregister it
463 if (Temp
->Registered
) {
464 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
468 // Remove this node from the linked list
470 RemoveEntryList (CurrentLink
);
472 if (!IsListEmpty (&Temp
->ChildList
)) {
473 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
476 FreePciDevice (Temp
);
483 DeRegisterPciDevice (
484 IN EFI_HANDLE Controller
,
491 This function is used to de-register the PCI device from the EFI,
492 That includes un-installing PciIo protocol from the specified PCI
497 Controller - An efi handle.
498 Handle - An efi handle.
505 // TODO: EFI_SUCCESS - add return value to function comment
506 // TODO: EFI_SUCCESS - add return value to function comment
507 // TODO: EFI_SUCCESS - add return value to function comment
509 EFI_PCI_IO_PROTOCOL
*PciIo
;
511 PCI_IO_DEVICE
*PciIoDevice
;
513 LIST_ENTRY
*CurrentLink
;
514 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
516 Status
= gBS
->OpenProtocol (
518 &gEfiPciIoProtocolGuid
,
520 gPciBusDriverBinding
.DriverBindingHandle
,
522 EFI_OPEN_PROTOCOL_GET_PROTOCOL
524 if (!EFI_ERROR (Status
)) {
525 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
528 // If it is already de-registered
530 if (!PciIoDevice
->Registered
) {
535 // If it is PPB, first de-register its children
538 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
540 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
542 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
543 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
544 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
546 if (EFI_ERROR (Status
)) {
550 CurrentLink
= CurrentLink
->ForwardLink
;
554 // Uninstall Pccard Hotplug GUID for Pccard device
556 UninstallPciHotplugGuid (PciIoDevice
);
559 // Close the child handle
561 Status
= gBS
->CloseProtocol (
563 &gEfiPciRootBridgeIoProtocolGuid
,
564 gPciBusDriverBinding
.DriverBindingHandle
,
569 // Un-install the device path protocol and pci io protocol
571 if (PciIoDevice
->BusOverride
) {
572 Status
= gBS
->UninstallMultipleProtocolInterfaces (
574 &gEfiDevicePathProtocolGuid
,
575 PciIoDevice
->DevicePath
,
576 &gEfiPciIoProtocolGuid
,
578 &gEfiBusSpecificDriverOverrideProtocolGuid
,
579 &PciIoDevice
->PciDriverOverride
,
583 Status
= gBS
->UninstallMultipleProtocolInterfaces (
585 &gEfiDevicePathProtocolGuid
,
586 PciIoDevice
->DevicePath
,
587 &gEfiPciIoProtocolGuid
,
593 if (EFI_ERROR (Status
)) {
596 &gEfiPciRootBridgeIoProtocolGuid
,
597 (VOID
**) &PciRootBridgeIo
,
598 gPciBusDriverBinding
.DriverBindingHandle
,
600 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
606 // The Device Driver should disable this device after disconnect
607 // so the Pci Bus driver will not touch this device any more.
608 // Restore the register field to the original value
610 PciIoDevice
->Registered
= FALSE
;
611 PciIoDevice
->Handle
= NULL
;
615 // Handle may be closed before
624 StartPciDevicesOnBridge (
625 IN EFI_HANDLE Controller
,
626 IN PCI_IO_DEVICE
*RootBridge
,
627 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
628 IN OUT UINT8
*NumberOfChildren
,
629 IN OUT EFI_HANDLE
*ChildHandleBuffer
635 Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
639 Controller - An efi handle.
640 RootBridge - A pointer to the PCI_IO_DEVICE.
641 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
642 NumberOfChildren - Children number.
643 ChildHandleBuffer - A pointer to the child handle buffer.
650 // TODO: EFI_NOT_READY - add return value to function comment
651 // TODO: EFI_SUCCESS - add return value to function comment
652 // TODO: EFI_UNSUPPORTED - add return value to function comment
653 // TODO: EFI_NOT_FOUND - add return value to function comment
656 PCI_IO_DEVICE
*PciIoDevice
;
657 EFI_DEV_PATH_PTR Node
;
658 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
660 LIST_ENTRY
*CurrentLink
;
663 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
665 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
667 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
668 if (RemainingDevicePath
!= NULL
) {
670 Node
.DevPath
= RemainingDevicePath
;
672 if (Node
.Pci
->Device
!= Temp
->DeviceNumber
||
673 Node
.Pci
->Function
!= Temp
->FunctionNumber
) {
674 CurrentLink
= CurrentLink
->ForwardLink
;
679 // Check if the device has been assigned with required resource
681 if (!Temp
->Allocated
) {
682 return EFI_NOT_READY
;
686 // Check if the current node has been registered before
687 // If it is not, register it
689 if (!Temp
->Registered
) {
692 Status
= RegisterPciDevice (
700 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& Temp
->Registered
) {
701 ChildHandleBuffer
[*NumberOfChildren
] = Temp
->Handle
;
702 (*NumberOfChildren
)++;
706 // Get the next device path
708 CurrentDevicePath
= EfiNextDevicePathNode (RemainingDevicePath
);
709 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
716 if (!IsListEmpty (&Temp
->ChildList
)) {
717 Status
= StartPciDevicesOnBridge (
725 Temp
->PciIo
.Attributes (
727 EfiPciIoAttributeOperationSupported
,
731 Supports
&= EFI_PCI_DEVICE_ENABLE
;
732 Temp
->PciIo
.Attributes (
734 EfiPciIoAttributeOperationEnable
,
743 // Currently, the PCI bus driver only support PCI-PCI bridge
745 return EFI_UNSUPPORTED
;
751 // If remaining device path is NULL,
752 // try to enable all the pci devices under this bridge
755 if (!Temp
->Registered
&& Temp
->Allocated
) {
759 Status
= RegisterPciDevice (
767 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& Temp
->Registered
) {
768 ChildHandleBuffer
[*NumberOfChildren
] = Temp
->Handle
;
769 (*NumberOfChildren
)++;
772 if (!IsListEmpty (&Temp
->ChildList
)) {
773 Status
= StartPciDevicesOnBridge (
781 Temp
->PciIo
.Attributes (
783 EfiPciIoAttributeOperationSupported
,
787 Supports
&= EFI_PCI_DEVICE_ENABLE
;
788 Temp
->PciIo
.Attributes (
790 EfiPciIoAttributeOperationEnable
,
797 CurrentLink
= CurrentLink
->ForwardLink
;
802 return EFI_NOT_FOUND
;
807 IN EFI_HANDLE Controller
,
808 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
814 Start to manage the PCI device according to RemainingDevicePath
815 If RemainingDevicePath == NULL, the PCI bus driver will start
816 to manage all the PCI devices it found previously
819 Controller - An efi handle.
820 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
827 // TODO: EFI_UNSUPPORTED - add return value to function comment
828 // TODO: EFI_SUCCESS - add return value to function comment
830 EFI_DEV_PATH_PTR Node
;
831 PCI_IO_DEVICE
*RootBridge
;
832 LIST_ENTRY
*CurrentLink
;
834 if (RemainingDevicePath
!= NULL
) {
837 // Check if the RemainingDevicePath is valid
839 Node
.DevPath
= RemainingDevicePath
;
840 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
841 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
842 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))
844 return EFI_UNSUPPORTED
;
848 CurrentLink
= gPciDevicePool
.ForwardLink
;
850 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
852 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
854 // Locate the right root bridge to start
856 if (RootBridge
->Handle
== Controller
) {
857 StartPciDevicesOnBridge (
866 CurrentLink
= CurrentLink
->ForwardLink
;
874 IN EFI_HANDLE RootBridgeHandle
882 RootBridgeHandle - An efi handle.
893 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
894 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
897 Status
= gBS
->AllocatePool (
899 sizeof (PCI_IO_DEVICE
),
903 if (EFI_ERROR (Status
)) {
907 ZeroMem (Dev
, sizeof (PCI_IO_DEVICE
));
908 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
909 Dev
->Handle
= RootBridgeHandle
;
910 InitializeListHead (&Dev
->ChildList
);
912 Status
= gBS
->OpenProtocol (
914 &gEfiDevicePathProtocolGuid
,
915 (VOID
**) &ParentDevicePath
,
916 gPciBusDriverBinding
.DriverBindingHandle
,
918 EFI_OPEN_PROTOCOL_GET_PROTOCOL
921 if (EFI_ERROR (Status
)) {
927 // Record the root bridge parent device path
929 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
932 // Get the pci root bridge io protocol
934 Status
= gBS
->OpenProtocol (
936 &gEfiPciRootBridgeIoProtocolGuid
,
937 (VOID
**) &PciRootBridgeIo
,
938 gPciBusDriverBinding
.DriverBindingHandle
,
940 EFI_OPEN_PROTOCOL_GET_PROTOCOL
943 if (EFI_ERROR (Status
)) {
948 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
951 // Initialize the PCI I/O instance structure
953 Status
= InitializePciIoInstance (Dev
);
954 Status
= InitializePciDriverOverrideInstance (Dev
);
957 // Initialize reserved resource list and
958 // option rom driver list
960 InitializeListHead (&Dev
->ReservedResourceList
);
961 InitializeListHead (&Dev
->OptionRomDriverList
);
967 GetRootBridgeByHandle (
968 EFI_HANDLE RootBridgeHandle
977 RootBridgeHandle - An efi handle.
985 PCI_IO_DEVICE
*RootBridgeDev
;
986 LIST_ENTRY
*CurrentLink
;
988 CurrentLink
= gPciDevicePool
.ForwardLink
;
990 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
992 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
993 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
994 return RootBridgeDev
;
997 CurrentLink
= CurrentLink
->ForwardLink
;
1005 IN EFI_HANDLE RootBridgeHandle
1009 Routine Description:
1011 This function searches if RootBridgeHandle has already existed
1012 in current device pool.
1014 If so, it means the given root bridge has been already enumerated.
1018 RootBridgeHandle - An efi handle.
1026 PCI_IO_DEVICE
*Bridge
;
1028 Bridge
= GetRootBridgeByHandle (RootBridgeHandle
);
1030 if (Bridge
!= NULL
) {
1039 IN PCI_IO_DEVICE
*Bridge
,
1040 IN PCI_IO_DEVICE
*PciIoDevice
1044 Routine Description:
1048 Bridge - A pointer to the PCI_IO_DEVICE.
1049 PciIoDevice - A pointer to the PCI_IO_DEVICE.
1058 PCI_IO_DEVICE
*Temp
;
1059 LIST_ENTRY
*CurrentLink
;
1061 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1063 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
1065 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1067 if (Temp
== PciIoDevice
) {
1071 if (!IsListEmpty (&Temp
->ChildList
)) {
1072 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
1077 CurrentLink
= CurrentLink
->ForwardLink
;
1084 ActiveVGADeviceOnTheSameSegment (
1085 IN PCI_IO_DEVICE
*VgaDevice
1089 Routine Description:
1093 VgaDevice - A pointer to the PCI_IO_DEVICE.
1101 LIST_ENTRY
*CurrentLink
;
1102 PCI_IO_DEVICE
*Temp
;
1104 CurrentLink
= gPciDevicePool
.ForwardLink
;
1106 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
1108 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1110 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
1112 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1119 CurrentLink
= CurrentLink
->ForwardLink
;
1126 ActiveVGADeviceOnTheRootBridge (
1127 IN PCI_IO_DEVICE
*RootBridge
1131 Routine Description:
1135 RootBridge - A pointer to the PCI_IO_DEVICE.
1143 LIST_ENTRY
*CurrentLink
;
1144 PCI_IO_DEVICE
*Temp
;
1146 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1148 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
1150 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1152 if (IS_PCI_VGA(&Temp
->Pci
) &&
1154 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
1155 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1156 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
))) {
1160 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1162 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1169 CurrentLink
= CurrentLink
->ForwardLink
;
1177 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1178 IN EFI_DEVICE_PATH_PROTOCOL
*HpcDevicePath
,
1179 OUT UINT64
*PciAddress
1183 Routine Description:
1187 PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1188 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
1189 PciAddress - A pointer to the pci address.
1196 // TODO: EFI_NOT_FOUND - add return value to function comment
1197 // TODO: EFI_NOT_FOUND - add return value to function comment
1198 // TODO: EFI_SUCCESS - add return value to function comment
1199 // TODO: EFI_NOT_FOUND - add return value to function comment
1201 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1202 EFI_DEV_PATH_PTR Node
;
1203 LIST_ENTRY
*CurrentLink
;
1204 PCI_IO_DEVICE
*RootBridge
;
1207 CurrentDevicePath
= HpcDevicePath
;
1210 // Get the remaining device path for this PCI device, if it is a PCI device
1212 while (!EfiIsDevicePathEnd (CurrentDevicePath
)) {
1214 Node
.DevPath
= CurrentDevicePath
;
1217 // Check if it is PCI device Path?
1219 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
1220 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
1221 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))) {
1222 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1230 // Check if it is not PCI device path
1232 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
1233 return EFI_NOT_FOUND
;
1236 CurrentLink
= gPciDevicePool
.ForwardLink
;
1238 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
1240 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1242 // Locate the right root bridge to start
1244 if (RootBridge
->PciRootBridgeIo
== PciRootBridgeIo
) {
1245 Status
= GetHpcPciAddressFromRootBridge (
1250 if (EFI_ERROR (Status
)) {
1251 return EFI_NOT_FOUND
;
1258 CurrentLink
= CurrentLink
->ForwardLink
;
1261 return EFI_NOT_FOUND
;
1265 GetHpcPciAddressFromRootBridge (
1266 IN PCI_IO_DEVICE
*RootBridge
,
1267 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1268 OUT UINT64
*PciAddress
1272 Routine Description:
1276 PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1277 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
1278 PciAddress - A pointer to the pci address.
1285 // TODO: RootBridge - add argument and description to function comment
1286 // TODO: RemainingDevicePath - add argument and description to function comment
1287 // TODO: EFI_SUCCESS - add return value to function comment
1288 // TODO: EFI_NOT_FOUND - add return value to function comment
1289 // TODO: EFI_SUCCESS - add return value to function comment
1291 EFI_DEV_PATH_PTR Node
;
1292 PCI_IO_DEVICE
*Temp
;
1293 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1294 LIST_ENTRY
*CurrentLink
;
1299 CurrentDevicePath
= RemainingDevicePath
;
1300 Node
.DevPath
= CurrentDevicePath
;
1303 while (!EfiIsDevicePathEnd (CurrentDevicePath
)) {
1305 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1306 Node
.DevPath
= CurrentDevicePath
;
1308 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
1309 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1311 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1312 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1317 CurrentLink
= CurrentLink
->ForwardLink
;
1321 // Check if we find the bridge
1323 if (CurrentLink
== &RootBridge
->ChildList
) {
1330 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1335 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1337 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
1338 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1342 return EFI_NOT_FOUND
;
1345 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);