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
;
311 // Install the pciio protocol, device path protocol
313 Status
= gBS
->InstallMultipleProtocolInterfaces (
314 &PciIoDevice
->Handle
,
315 &gEfiDevicePathProtocolGuid
,
316 PciIoDevice
->DevicePath
,
317 &gEfiPciIoProtocolGuid
,
321 if (EFI_ERROR (Status
)) {
326 // Detect if PCI Express Device
328 PciExpressCapRegOffset
= 0;
329 Status
= LocateCapabilityRegBlock (
331 EFI_PCI_CAPABILITY_ID_PCIEXP
,
332 &PciExpressCapRegOffset
,
335 if (!EFI_ERROR (Status
)) {
336 PciIoDevice
->IsPciExp
= TRUE
;
340 // Force Interrupt line to zero for cards that come up randomly
342 PciIo
= &(PciIoDevice
->PciIo
);
344 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &Data8
);
346 // Process Platform OpRom
348 if (gPciPlatformProtocol
!= NULL
&& !PciIoDevice
->AllOpRomProcessed
) {
349 PciIoDevice
->AllOpRomProcessed
= TRUE
;
351 Status
= gPciPlatformProtocol
->GetPciRom (
352 gPciPlatformProtocol
,
354 &PlatformOpRomBuffer
,
358 if (!EFI_ERROR (Status
)) {
361 // Have Platform OpRom
363 PciIoDevice
->RomSize
= PlatformOpRomSize
;
364 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
365 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
370 ProcessOpRomImage (PciIoDevice
);
374 if (PciIoDevice
->BusOverride
) {
376 // Install BusSpecificDriverOverride Protocol
378 Status
= gBS
->InstallMultipleProtocolInterfaces (
379 &PciIoDevice
->Handle
,
380 &gEfiBusSpecificDriverOverrideProtocolGuid
,
381 &PciIoDevice
->PciDriverOverride
,
384 if (EFI_ERROR (Status
)) {
385 gBS
->UninstallMultipleProtocolInterfaces (
386 &PciIoDevice
->Handle
,
387 &gEfiDevicePathProtocolGuid
,
388 PciIoDevice
->DevicePath
,
389 &gEfiPciIoProtocolGuid
,
398 Status
= gBS
->OpenProtocol (
400 &gEfiPciRootBridgeIoProtocolGuid
,
401 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
402 gPciBusDriverBinding
.DriverBindingHandle
,
404 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
406 if (EFI_ERROR (Status
)) {
411 // Install Pccard Hotplug GUID for Pccard device so that
412 // to notify CardBus driver to stop the device when de-register happens
414 InstallPciHotplugGuid (PciIoDevice
);
416 if (Handle
!= NULL
) {
417 *Handle
= PciIoDevice
->Handle
;
421 // Indicate the pci device is registered
423 PciIoDevice
->Registered
= TRUE
;
429 RemoveAllPciDeviceOnBridge (
430 EFI_HANDLE RootBridgeHandle
,
431 PCI_IO_DEVICE
*Bridge
437 This function is used to remove the whole PCI devices from the bridge.
441 RootBridgeHandle - An efi handle.
442 Bridge - A pointer to the PCI_IO_DEVICE.
449 // TODO: EFI_SUCCESS - add return value to function comment
452 LIST_ENTRY
*CurrentLink
;
455 while (!IsListEmpty (&Bridge
->ChildList
)) {
457 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
458 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
461 // Check if the current node has been deregistered before
462 // If it is not, then deregister it
464 if (Temp
->Registered
) {
465 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
469 // Remove this node from the linked list
471 RemoveEntryList (CurrentLink
);
473 if (!IsListEmpty (&Temp
->ChildList
)) {
474 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
477 FreePciDevice (Temp
);
484 DeRegisterPciDevice (
485 IN EFI_HANDLE Controller
,
492 This function is used to de-register the PCI device from the EFI,
493 That includes un-installing PciIo protocol from the specified PCI
498 Controller - An efi handle.
499 Handle - An efi handle.
506 // TODO: EFI_SUCCESS - add return value to function comment
507 // TODO: EFI_SUCCESS - add return value to function comment
508 // TODO: EFI_SUCCESS - add return value to function comment
510 EFI_PCI_IO_PROTOCOL
*PciIo
;
512 PCI_IO_DEVICE
*PciIoDevice
;
514 LIST_ENTRY
*CurrentLink
;
515 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
517 Status
= gBS
->OpenProtocol (
519 &gEfiPciIoProtocolGuid
,
521 gPciBusDriverBinding
.DriverBindingHandle
,
523 EFI_OPEN_PROTOCOL_GET_PROTOCOL
525 if (!EFI_ERROR (Status
)) {
526 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
529 // If it is already de-registered
531 if (!PciIoDevice
->Registered
) {
536 // If it is PPB, first de-register its children
539 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
541 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
543 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
544 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
545 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
547 if (EFI_ERROR (Status
)) {
551 CurrentLink
= CurrentLink
->ForwardLink
;
555 // Uninstall Pccard Hotplug GUID for Pccard device
557 UninstallPciHotplugGuid (PciIoDevice
);
560 // Close the child handle
562 Status
= gBS
->CloseProtocol (
564 &gEfiPciRootBridgeIoProtocolGuid
,
565 gPciBusDriverBinding
.DriverBindingHandle
,
570 // Un-install the device path protocol and pci io protocol
572 if (PciIoDevice
->BusOverride
) {
573 Status
= gBS
->UninstallMultipleProtocolInterfaces (
575 &gEfiDevicePathProtocolGuid
,
576 PciIoDevice
->DevicePath
,
577 &gEfiPciIoProtocolGuid
,
579 &gEfiBusSpecificDriverOverrideProtocolGuid
,
580 &PciIoDevice
->PciDriverOverride
,
584 Status
= gBS
->UninstallMultipleProtocolInterfaces (
586 &gEfiDevicePathProtocolGuid
,
587 PciIoDevice
->DevicePath
,
588 &gEfiPciIoProtocolGuid
,
594 if (EFI_ERROR (Status
)) {
597 &gEfiPciRootBridgeIoProtocolGuid
,
598 (VOID
**) &PciRootBridgeIo
,
599 gPciBusDriverBinding
.DriverBindingHandle
,
601 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
607 // The Device Driver should disable this device after disconnect
608 // so the Pci Bus driver will not touch this device any more.
609 // Restore the register field to the original value
611 PciIoDevice
->Registered
= FALSE
;
612 PciIoDevice
->Handle
= NULL
;
616 // Handle may be closed before
625 StartPciDevicesOnBridge (
626 IN EFI_HANDLE Controller
,
627 IN PCI_IO_DEVICE
*RootBridge
,
628 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
629 IN OUT UINT8
*NumberOfChildren
,
630 IN OUT EFI_HANDLE
*ChildHandleBuffer
636 Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
640 Controller - An efi handle.
641 RootBridge - A pointer to the PCI_IO_DEVICE.
642 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
643 NumberOfChildren - Children number.
644 ChildHandleBuffer - A pointer to the child handle buffer.
651 // TODO: EFI_NOT_READY - add return value to function comment
652 // TODO: EFI_SUCCESS - add return value to function comment
653 // TODO: EFI_UNSUPPORTED - add return value to function comment
654 // TODO: EFI_NOT_FOUND - add return value to function comment
657 PCI_IO_DEVICE
*PciIoDevice
;
658 EFI_DEV_PATH_PTR Node
;
659 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
661 LIST_ENTRY
*CurrentLink
;
664 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
666 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
668 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
669 if (RemainingDevicePath
!= NULL
) {
671 Node
.DevPath
= RemainingDevicePath
;
673 if (Node
.Pci
->Device
!= Temp
->DeviceNumber
||
674 Node
.Pci
->Function
!= Temp
->FunctionNumber
) {
675 CurrentLink
= CurrentLink
->ForwardLink
;
680 // Check if the device has been assigned with required resource
682 if (!Temp
->Allocated
) {
683 return EFI_NOT_READY
;
687 // Check if the current node has been registered before
688 // If it is not, register it
690 if (!Temp
->Registered
) {
693 Status
= RegisterPciDevice (
701 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& Temp
->Registered
) {
702 ChildHandleBuffer
[*NumberOfChildren
] = Temp
->Handle
;
703 (*NumberOfChildren
)++;
707 // Get the next device path
709 CurrentDevicePath
= EfiNextDevicePathNode (RemainingDevicePath
);
710 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
717 if (!IsListEmpty (&Temp
->ChildList
)) {
718 Status
= StartPciDevicesOnBridge (
726 Temp
->PciIo
.Attributes (
728 EfiPciIoAttributeOperationSupported
,
732 Supports
&= EFI_PCI_DEVICE_ENABLE
;
733 Temp
->PciIo
.Attributes (
735 EfiPciIoAttributeOperationEnable
,
744 // Currently, the PCI bus driver only support PCI-PCI bridge
746 return EFI_UNSUPPORTED
;
752 // If remaining device path is NULL,
753 // try to enable all the pci devices under this bridge
756 if (!Temp
->Registered
&& Temp
->Allocated
) {
760 Status
= RegisterPciDevice (
768 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& Temp
->Registered
) {
769 ChildHandleBuffer
[*NumberOfChildren
] = Temp
->Handle
;
770 (*NumberOfChildren
)++;
773 if (!IsListEmpty (&Temp
->ChildList
)) {
774 Status
= StartPciDevicesOnBridge (
782 Temp
->PciIo
.Attributes (
784 EfiPciIoAttributeOperationSupported
,
788 Supports
&= EFI_PCI_DEVICE_ENABLE
;
789 Temp
->PciIo
.Attributes (
791 EfiPciIoAttributeOperationEnable
,
798 CurrentLink
= CurrentLink
->ForwardLink
;
803 return EFI_NOT_FOUND
;
808 IN EFI_HANDLE Controller
,
809 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
815 Start to manage the PCI device according to RemainingDevicePath
816 If RemainingDevicePath == NULL, the PCI bus driver will start
817 to manage all the PCI devices it found previously
820 Controller - An efi handle.
821 RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
828 // TODO: EFI_UNSUPPORTED - add return value to function comment
829 // TODO: EFI_SUCCESS - add return value to function comment
831 EFI_DEV_PATH_PTR Node
;
832 PCI_IO_DEVICE
*RootBridge
;
833 LIST_ENTRY
*CurrentLink
;
835 if (RemainingDevicePath
!= NULL
) {
838 // Check if the RemainingDevicePath is valid
840 Node
.DevPath
= RemainingDevicePath
;
841 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
842 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
843 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))
845 return EFI_UNSUPPORTED
;
849 CurrentLink
= gPciDevicePool
.ForwardLink
;
851 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
853 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
855 // Locate the right root bridge to start
857 if (RootBridge
->Handle
== Controller
) {
858 StartPciDevicesOnBridge (
867 CurrentLink
= CurrentLink
->ForwardLink
;
875 IN EFI_HANDLE RootBridgeHandle
883 RootBridgeHandle - An efi handle.
894 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
895 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
898 Status
= gBS
->AllocatePool (
900 sizeof (PCI_IO_DEVICE
),
904 if (EFI_ERROR (Status
)) {
908 ZeroMem (Dev
, sizeof (PCI_IO_DEVICE
));
909 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
910 Dev
->Handle
= RootBridgeHandle
;
911 InitializeListHead (&Dev
->ChildList
);
913 Status
= gBS
->OpenProtocol (
915 &gEfiDevicePathProtocolGuid
,
916 (VOID
**) &ParentDevicePath
,
917 gPciBusDriverBinding
.DriverBindingHandle
,
919 EFI_OPEN_PROTOCOL_GET_PROTOCOL
922 if (EFI_ERROR (Status
)) {
928 // Record the root bridge parent device path
930 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
933 // Get the pci root bridge io protocol
935 Status
= gBS
->OpenProtocol (
937 &gEfiPciRootBridgeIoProtocolGuid
,
938 (VOID
**) &PciRootBridgeIo
,
939 gPciBusDriverBinding
.DriverBindingHandle
,
941 EFI_OPEN_PROTOCOL_GET_PROTOCOL
944 if (EFI_ERROR (Status
)) {
949 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
952 // Initialize the PCI I/O instance structure
954 Status
= InitializePciIoInstance (Dev
);
955 Status
= InitializePciDriverOverrideInstance (Dev
);
958 // Initialize reserved resource list and
959 // option rom driver list
961 InitializeListHead (&Dev
->ReservedResourceList
);
962 InitializeListHead (&Dev
->OptionRomDriverList
);
968 GetRootBridgeByHandle (
969 EFI_HANDLE RootBridgeHandle
978 RootBridgeHandle - An efi handle.
986 PCI_IO_DEVICE
*RootBridgeDev
;
987 LIST_ENTRY
*CurrentLink
;
989 CurrentLink
= gPciDevicePool
.ForwardLink
;
991 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
993 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
994 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
995 return RootBridgeDev
;
998 CurrentLink
= CurrentLink
->ForwardLink
;
1006 IN EFI_HANDLE RootBridgeHandle
1010 Routine Description:
1012 This function searches if RootBridgeHandle has already existed
1013 in current device pool.
1015 If so, it means the given root bridge has been already enumerated.
1019 RootBridgeHandle - An efi handle.
1027 PCI_IO_DEVICE
*Bridge
;
1029 Bridge
= GetRootBridgeByHandle (RootBridgeHandle
);
1031 if (Bridge
!= NULL
) {
1040 IN PCI_IO_DEVICE
*Bridge
,
1041 IN PCI_IO_DEVICE
*PciIoDevice
1045 Routine Description:
1049 Bridge - A pointer to the PCI_IO_DEVICE.
1050 PciIoDevice - A pointer to the PCI_IO_DEVICE.
1059 PCI_IO_DEVICE
*Temp
;
1060 LIST_ENTRY
*CurrentLink
;
1062 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1064 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
1066 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1068 if (Temp
== PciIoDevice
) {
1072 if (!IsListEmpty (&Temp
->ChildList
)) {
1073 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
1078 CurrentLink
= CurrentLink
->ForwardLink
;
1085 ActiveVGADeviceOnTheSameSegment (
1086 IN PCI_IO_DEVICE
*VgaDevice
1090 Routine Description:
1094 VgaDevice - A pointer to the PCI_IO_DEVICE.
1102 LIST_ENTRY
*CurrentLink
;
1103 PCI_IO_DEVICE
*Temp
;
1105 CurrentLink
= gPciDevicePool
.ForwardLink
;
1107 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
1109 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1111 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
1113 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1120 CurrentLink
= CurrentLink
->ForwardLink
;
1127 ActiveVGADeviceOnTheRootBridge (
1128 IN PCI_IO_DEVICE
*RootBridge
1132 Routine Description:
1136 RootBridge - A pointer to the PCI_IO_DEVICE.
1144 LIST_ENTRY
*CurrentLink
;
1145 PCI_IO_DEVICE
*Temp
;
1147 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1149 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
1151 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1153 if (IS_PCI_VGA(&Temp
->Pci
) &&
1155 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
1156 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1157 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
))) {
1161 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1163 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1170 CurrentLink
= CurrentLink
->ForwardLink
;
1178 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1179 IN EFI_DEVICE_PATH_PROTOCOL
*HpcDevicePath
,
1180 OUT UINT64
*PciAddress
1184 Routine Description:
1188 PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1189 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
1190 PciAddress - A pointer to the pci address.
1197 // TODO: EFI_NOT_FOUND - add return value to function comment
1198 // TODO: EFI_NOT_FOUND - add return value to function comment
1199 // TODO: EFI_SUCCESS - add return value to function comment
1200 // TODO: EFI_NOT_FOUND - add return value to function comment
1202 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1203 EFI_DEV_PATH_PTR Node
;
1204 LIST_ENTRY
*CurrentLink
;
1205 PCI_IO_DEVICE
*RootBridge
;
1208 CurrentDevicePath
= HpcDevicePath
;
1211 // Get the remaining device path for this PCI device, if it is a PCI device
1213 while (!EfiIsDevicePathEnd (CurrentDevicePath
)) {
1215 Node
.DevPath
= CurrentDevicePath
;
1218 // Check if it is PCI device Path?
1220 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
1221 ((Node
.DevPath
->SubType
!= HW_PCI_DP
) &&
1222 (DevicePathNodeLength (Node
.DevPath
) != sizeof (PCI_DEVICE_PATH
)))) {
1223 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1231 // Check if it is not PCI device path
1233 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
1234 return EFI_NOT_FOUND
;
1237 CurrentLink
= gPciDevicePool
.ForwardLink
;
1239 while (CurrentLink
&& CurrentLink
!= &gPciDevicePool
) {
1241 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1243 // Locate the right root bridge to start
1245 if (RootBridge
->PciRootBridgeIo
== PciRootBridgeIo
) {
1246 Status
= GetHpcPciAddressFromRootBridge (
1251 if (EFI_ERROR (Status
)) {
1252 return EFI_NOT_FOUND
;
1259 CurrentLink
= CurrentLink
->ForwardLink
;
1262 return EFI_NOT_FOUND
;
1266 GetHpcPciAddressFromRootBridge (
1267 IN PCI_IO_DEVICE
*RootBridge
,
1268 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1269 OUT UINT64
*PciAddress
1273 Routine Description:
1277 PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1278 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
1279 PciAddress - A pointer to the pci address.
1286 // TODO: RootBridge - add argument and description to function comment
1287 // TODO: RemainingDevicePath - add argument and description to function comment
1288 // TODO: EFI_SUCCESS - add return value to function comment
1289 // TODO: EFI_NOT_FOUND - add return value to function comment
1290 // TODO: EFI_SUCCESS - add return value to function comment
1292 EFI_DEV_PATH_PTR Node
;
1293 PCI_IO_DEVICE
*Temp
;
1294 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1295 LIST_ENTRY
*CurrentLink
;
1300 CurrentDevicePath
= RemainingDevicePath
;
1301 Node
.DevPath
= CurrentDevicePath
;
1304 while (!EfiIsDevicePathEnd (CurrentDevicePath
)) {
1306 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1307 Node
.DevPath
= CurrentDevicePath
;
1309 while (CurrentLink
&& CurrentLink
!= &RootBridge
->ChildList
) {
1310 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1312 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1313 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1318 CurrentLink
= CurrentLink
->ForwardLink
;
1322 // Check if we find the bridge
1324 if (CurrentLink
== &RootBridge
->ChildList
) {
1331 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1336 CurrentDevicePath
= EfiNextDevicePathNode (CurrentDevicePath
);
1338 if (EfiIsDevicePathEnd (CurrentDevicePath
)) {
1339 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1343 return EFI_NOT_FOUND
;
1346 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);