2 Supporting functions implementaion for PCI devices management.
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // This device structure is serviced as a header.
19 // Its next field points to the first root bridge device node.
21 LIST_ENTRY mPciDevicePool
;
24 Initialize the PCI devices pool.
28 InitializePciDevicePool (
32 InitializeListHead (&mPciDevicePool
);
36 Insert a root bridge into PCI device pool.
38 @param RootBridge A pointer to the PCI_IO_DEVICE.
43 IN PCI_IO_DEVICE
*RootBridge
46 InsertTailList (&mPciDevicePool
, &(RootBridge
->Link
));
50 This function is used to insert a PCI device node under
53 @param Bridge The PCI bridge.
54 @param PciDeviceNode The PCI device needs inserting.
59 IN PCI_IO_DEVICE
*Bridge
,
60 IN PCI_IO_DEVICE
*PciDeviceNode
63 InsertTailList (&Bridge
->ChildList
, &(PciDeviceNode
->Link
));
64 PciDeviceNode
->Parent
= Bridge
;
68 Destroy root bridge and remove it from deivce tree.
70 @param RootBridge The bridge want to be removed.
75 IN PCI_IO_DEVICE
*RootBridge
78 DestroyPciDeviceTree (RootBridge
);
80 FreePciDevice (RootBridge
);
84 Destroy a pci device node.
86 All direct or indirect allocated resource for this node will be freed.
88 @param PciIoDevice A pointer to the PCI_IO_DEVICE to be destoried.
93 IN PCI_IO_DEVICE
*PciIoDevice
96 ASSERT (PciIoDevice
!= NULL
);
98 // Assume all children have been removed underneath this device
100 if (PciIoDevice
->ResourcePaddingDescriptors
!= NULL
) {
101 FreePool (PciIoDevice
->ResourcePaddingDescriptors
);
104 if (PciIoDevice
->DevicePath
!= NULL
) {
105 FreePool (PciIoDevice
->DevicePath
);
108 FreePool (PciIoDevice
);
112 Destroy all the pci device node under the bridge.
113 Bridge itself is not included.
115 @param Bridge A pointer to the PCI_IO_DEVICE.
119 DestroyPciDeviceTree (
120 IN PCI_IO_DEVICE
*Bridge
123 LIST_ENTRY
*CurrentLink
;
126 while (!IsListEmpty (&Bridge
->ChildList
)) {
128 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
131 // Remove this node from the linked list
133 RemoveEntryList (CurrentLink
);
135 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
137 if (!IsListEmpty (&Temp
->ChildList
)) {
138 DestroyPciDeviceTree (Temp
);
141 FreePciDevice (Temp
);
146 Destroy all device nodes under the root bridge
147 specified by Controller.
149 The root bridge itself is also included.
151 @param Controller Root bridge handle.
153 @retval EFI_SUCCESS Destory all devcie nodes successfully.
154 @retval EFI_NOT_FOUND Cannot find any PCI device under specified
159 DestroyRootBridgeByHandle (
160 IN EFI_HANDLE Controller
164 LIST_ENTRY
*CurrentLink
;
167 CurrentLink
= mPciDevicePool
.ForwardLink
;
169 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
170 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
172 if (Temp
->Handle
== Controller
) {
174 RemoveEntryList (CurrentLink
);
176 DestroyPciDeviceTree (Temp
);
178 FreePciDevice (Temp
);
183 CurrentLink
= CurrentLink
->ForwardLink
;
186 return EFI_NOT_FOUND
;
190 This function registers the PCI IO device.
192 It creates a handle for this PCI IO device (if the handle does not exist), attaches
193 appropriate protocols onto the handle, does necessary initialization, and sets up
194 parent/child relationship with its bus controller.
196 @param Controller An EFI handle for the PCI bus controller.
197 @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
198 @param Handle A pointer to hold the returned EFI handle for the PCI IO device.
200 @retval EFI_SUCCESS The PCI device is successfully registered.
201 @retval other An error occurred when registering the PCI device.
206 IN EFI_HANDLE Controller
,
207 IN PCI_IO_DEVICE
*PciIoDevice
,
208 OUT EFI_HANDLE
*Handle OPTIONAL
212 VOID
*PlatformOpRomBuffer
;
213 UINTN PlatformOpRomSize
;
214 UINT8 PciExpressCapRegOffset
;
215 EFI_PCI_IO_PROTOCOL
*PciIo
;
218 PCI_IO_DEVICE
*ParrentPciIoDevice
;
219 EFI_PCI_IO_PROTOCOL
*ParrentPciIo
;
224 // Install the pciio protocol, device path protocol
226 Status
= gBS
->InstallMultipleProtocolInterfaces (
227 &PciIoDevice
->Handle
,
228 &gEfiDevicePathProtocolGuid
,
229 PciIoDevice
->DevicePath
,
230 &gEfiPciIoProtocolGuid
,
234 if (EFI_ERROR (Status
)) {
239 // Detect if PCI Express Device
241 PciExpressCapRegOffset
= 0;
242 Status
= LocateCapabilityRegBlock (
244 EFI_PCI_CAPABILITY_ID_PCIEXP
,
245 &PciExpressCapRegOffset
,
248 if (!EFI_ERROR (Status
)) {
249 PciIoDevice
->IsPciExp
= TRUE
;
253 // Force Interrupt line to "Unknown" or "No Connection"
255 PciIo
= &(PciIoDevice
->PciIo
);
256 Data8
= PCI_INT_LINE_UNKNOWN
;
257 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &Data8
);
260 // PCI-IOV programming
262 if (((FeaturePcdGet(PcdAriSupport
) & EFI_PCI_IOV_POLICY_ARI
) != 0) && (PciIoDevice
->AriCapabilityOffset
!= 0) && ((FeaturePcdGet(PcdSrIovSupport
) & EFI_PCI_IOV_POLICY_SRIOV
) != 0) &&
263 (PciIoDevice
->SrIovCapabilityOffset
!= 0)) {
265 // Check its parrent ARI forwarding capability
267 ParrentPciIoDevice
= PciIoDevice
->Parent
;
268 ParrentPciIo
= &(ParrentPciIoDevice
->PciIo
);
269 ParrentPciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ParrentPciIoDevice
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET
, 1, &Data32
);
270 if (Data32
& EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING
) {
272 // ARI forward support in bridge, so enable it.
274 ParrentPciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ParrentPciIoDevice
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
, 1, &Data32
);
275 Data32
|= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
;
276 ParrentPciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ParrentPciIoDevice
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
, 1, &Data32
);
279 // Set ARI Capable Hierarchy for device
281 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
, 1, &Data16
);
282 Data16
|= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY
;
283 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
, 1, &Data16
);
290 if (!PciIoDevice
->AllOpRomProcessed
) {
293 // Get the OpRom provided by platform
295 if (gPciPlatformProtocol
!= NULL
) {
296 Status
= gPciPlatformProtocol
->GetPciRom (
297 gPciPlatformProtocol
,
299 &PlatformOpRomBuffer
,
302 if (!EFI_ERROR (Status
)) {
303 PciIoDevice
->RomSize
= PlatformOpRomSize
;
304 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
305 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
307 // For OpROM read from gPciPlatformProtocol:
308 // Add the Rom Image to internal database for later PCI light enumeration
310 PciRomAddImageMapping (
312 PciIoDevice
->PciRootBridgeIo
->SegmentNumber
,
313 PciIoDevice
->BusNumber
,
314 PciIoDevice
->DeviceNumber
,
315 PciIoDevice
->FunctionNumber
,
316 (UINT64
) (UINTN
) PciIoDevice
->PciIo
.RomImage
,
317 PciIoDevice
->PciIo
.RomSize
324 // Determine if there are EFI images in the option rom
326 HasEfiImage
= ContainEfiImage (PciIoDevice
->PciIo
.RomImage
, PciIoDevice
->PciIo
.RomSize
);
329 Status
= gBS
->InstallMultipleProtocolInterfaces (
330 &PciIoDevice
->Handle
,
331 &gEfiLoadFile2ProtocolGuid
,
332 &PciIoDevice
->LoadFile2
,
335 if (EFI_ERROR (Status
)) {
336 gBS
->UninstallMultipleProtocolInterfaces (
337 &PciIoDevice
->Handle
,
338 &gEfiDevicePathProtocolGuid
,
339 PciIoDevice
->DevicePath
,
340 &gEfiPciIoProtocolGuid
,
349 if (!PciIoDevice
->AllOpRomProcessed
) {
351 PciIoDevice
->AllOpRomProcessed
= TRUE
;
354 // Dispatch the EFI OpRom for the PCI device.
355 // The OpRom is got from platform in the above code
356 // or loaded from device in the previous round of bus enumeration
359 ProcessOpRomImage (PciIoDevice
);
363 if (PciIoDevice
->BusOverride
) {
365 // Install Bus Specific Driver Override Protocol
367 Status
= gBS
->InstallMultipleProtocolInterfaces (
368 &PciIoDevice
->Handle
,
369 &gEfiBusSpecificDriverOverrideProtocolGuid
,
370 &PciIoDevice
->PciDriverOverride
,
373 if (EFI_ERROR (Status
)) {
374 gBS
->UninstallMultipleProtocolInterfaces (
375 &PciIoDevice
->Handle
,
376 &gEfiDevicePathProtocolGuid
,
377 PciIoDevice
->DevicePath
,
378 &gEfiPciIoProtocolGuid
,
383 gBS
->UninstallMultipleProtocolInterfaces (
384 &PciIoDevice
->Handle
,
385 &gEfiLoadFile2ProtocolGuid
,
386 &PciIoDevice
->LoadFile2
,
395 Status
= gBS
->OpenProtocol (
397 &gEfiPciRootBridgeIoProtocolGuid
,
398 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
399 gPciBusDriverBinding
.DriverBindingHandle
,
401 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
403 if (EFI_ERROR (Status
)) {
407 if (Handle
!= NULL
) {
408 *Handle
= PciIoDevice
->Handle
;
412 // Indicate the pci device is registered
414 PciIoDevice
->Registered
= TRUE
;
420 This function is used to remove the whole PCI devices on the specified bridge from
423 @param RootBridgeHandle The root bridge device handle.
424 @param Bridge The bridge device to be removed.
428 RemoveAllPciDeviceOnBridge (
429 EFI_HANDLE RootBridgeHandle
,
430 PCI_IO_DEVICE
*Bridge
433 LIST_ENTRY
*CurrentLink
;
436 while (!IsListEmpty (&Bridge
->ChildList
)) {
438 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
439 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
442 // Check if the current node has been deregistered before
443 // If it is not, then deregister it
445 if (Temp
->Registered
) {
446 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
450 // Remove this node from the linked list
452 RemoveEntryList (CurrentLink
);
454 if (!IsListEmpty (&Temp
->ChildList
)) {
455 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
458 FreePciDevice (Temp
);
463 This function is used to de-register the PCI IO device.
465 That includes un-installing PciIo protocol from the specified PCI
468 @param Controller An EFI handle for the PCI bus controller.
469 @param Handle PCI device handle.
471 @retval EFI_SUCCESS The PCI device is successfully de-registered.
472 @retval other An error occurred when de-registering the PCI device.
476 DeRegisterPciDevice (
477 IN EFI_HANDLE Controller
,
482 EFI_PCI_IO_PROTOCOL
*PciIo
;
484 PCI_IO_DEVICE
*PciIoDevice
;
486 LIST_ENTRY
*CurrentLink
;
487 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
489 Status
= gBS
->OpenProtocol (
491 &gEfiPciIoProtocolGuid
,
493 gPciBusDriverBinding
.DriverBindingHandle
,
495 EFI_OPEN_PROTOCOL_GET_PROTOCOL
497 if (!EFI_ERROR (Status
)) {
498 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
501 // If it is already de-registered
503 if (!PciIoDevice
->Registered
) {
508 // If it is PPB, first de-register its children
511 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
513 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
515 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
516 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
517 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
519 if (EFI_ERROR (Status
)) {
523 CurrentLink
= CurrentLink
->ForwardLink
;
528 // Close the child handle
530 Status
= gBS
->CloseProtocol (
532 &gEfiPciRootBridgeIoProtocolGuid
,
533 gPciBusDriverBinding
.DriverBindingHandle
,
538 // Un-install the Device Path protocol and PCI I/O protocol
539 // and Bus Specific Driver Override protocol if needed.
541 if (PciIoDevice
->BusOverride
) {
542 Status
= gBS
->UninstallMultipleProtocolInterfaces (
544 &gEfiDevicePathProtocolGuid
,
545 PciIoDevice
->DevicePath
,
546 &gEfiPciIoProtocolGuid
,
548 &gEfiBusSpecificDriverOverrideProtocolGuid
,
549 &PciIoDevice
->PciDriverOverride
,
553 Status
= gBS
->UninstallMultipleProtocolInterfaces (
555 &gEfiDevicePathProtocolGuid
,
556 PciIoDevice
->DevicePath
,
557 &gEfiPciIoProtocolGuid
,
563 if (!EFI_ERROR (Status
)) {
565 // Try to uninstall LoadFile2 protocol if exists
567 Status
= gBS
->OpenProtocol (
569 &gEfiLoadFile2ProtocolGuid
,
571 gPciBusDriverBinding
.DriverBindingHandle
,
573 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
575 if (!EFI_ERROR (Status
)) {
576 Status
= gBS
->UninstallMultipleProtocolInterfaces (
578 &gEfiLoadFile2ProtocolGuid
,
579 &PciIoDevice
->LoadFile2
,
586 Status
= EFI_SUCCESS
;
590 if (EFI_ERROR (Status
)) {
593 &gEfiPciRootBridgeIoProtocolGuid
,
594 (VOID
**) &PciRootBridgeIo
,
595 gPciBusDriverBinding
.DriverBindingHandle
,
597 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
603 // The Device Driver should disable this device after disconnect
604 // so the Pci Bus driver will not touch this device any more.
605 // Restore the register field to the original value
607 PciIoDevice
->Registered
= FALSE
;
608 PciIoDevice
->Handle
= NULL
;
612 // Handle may be closed before
621 Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
623 @param Controller The root bridge handle.
624 @param RootBridge A pointer to the PCI_IO_DEVICE.
625 @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
626 @param NumberOfChildren Children number.
627 @param ChildHandleBuffer A pointer to the child handle buffer.
629 @retval EFI_NOT_READY Device is not allocated.
630 @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
631 @retval EFI_NOT_FOUND Can not find the specific device.
632 @retval EFI_SUCCESS Success to start Pci devices on bridge.
636 StartPciDevicesOnBridge (
637 IN EFI_HANDLE Controller
,
638 IN PCI_IO_DEVICE
*RootBridge
,
639 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
640 IN OUT UINT8
*NumberOfChildren
,
641 IN OUT EFI_HANDLE
*ChildHandleBuffer
645 PCI_IO_DEVICE
*PciIoDevice
;
646 EFI_DEV_PATH_PTR Node
;
647 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
649 LIST_ENTRY
*CurrentLink
;
653 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
655 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
657 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
658 if (RemainingDevicePath
!= NULL
) {
660 Node
.DevPath
= RemainingDevicePath
;
662 if (Node
.Pci
->Device
!= PciIoDevice
->DeviceNumber
||
663 Node
.Pci
->Function
!= PciIoDevice
->FunctionNumber
) {
664 CurrentLink
= CurrentLink
->ForwardLink
;
669 // Check if the device has been assigned with required resource
671 if (!PciIoDevice
->Allocated
) {
672 return EFI_NOT_READY
;
676 // Check if the current node has been registered before
677 // If it is not, register it
679 if (!PciIoDevice
->Registered
) {
680 Status
= RegisterPciDevice (
688 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
689 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
690 (*NumberOfChildren
)++;
694 // Get the next device path
696 CurrentDevicePath
= NextDevicePathNode (RemainingDevicePath
);
697 if (IsDevicePathEnd (CurrentDevicePath
)) {
704 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
705 Status
= StartPciDevicesOnBridge (
713 PciIoDevice
->PciIo
.Attributes (
714 &(PciIoDevice
->PciIo
),
715 EfiPciIoAttributeOperationSupported
,
719 Supports
&= EFI_PCI_DEVICE_ENABLE
;
720 PciIoDevice
->PciIo
.Attributes (
721 &(PciIoDevice
->PciIo
),
722 EfiPciIoAttributeOperationEnable
,
731 // Currently, the PCI bus driver only support PCI-PCI bridge
733 return EFI_UNSUPPORTED
;
739 // If remaining device path is NULL,
740 // try to enable all the pci devices under this bridge
742 if (!PciIoDevice
->Registered
&& PciIoDevice
->Allocated
) {
743 Status
= RegisterPciDevice (
751 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
752 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
753 (*NumberOfChildren
)++;
756 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
757 Status
= StartPciDevicesOnBridge (
765 PciIoDevice
->PciIo
.Attributes (
766 &(PciIoDevice
->PciIo
),
767 EfiPciIoAttributeOperationSupported
,
771 Supports
&= EFI_PCI_DEVICE_ENABLE
;
772 PciIoDevice
->PciIo
.Attributes (
773 &(PciIoDevice
->PciIo
),
774 EfiPciIoAttributeOperationEnable
,
781 CurrentLink
= CurrentLink
->ForwardLink
;
785 if (PciIoDevice
== NULL
) {
786 return EFI_NOT_FOUND
;
793 Start to manage all the PCI devices it found previously under
794 the entire host bridge.
796 @param Controller The root bridge handle.
798 @retval EFI_NOT_READY Device is not allocated.
799 @retval EFI_SUCCESS Success to start Pci device on host bridge.
804 IN EFI_HANDLE Controller
807 PCI_IO_DEVICE
*RootBridge
;
808 EFI_HANDLE ThisHostBridge
;
809 LIST_ENTRY
*CurrentLink
;
811 RootBridge
= GetRootBridgeByHandle (Controller
);
812 ASSERT (RootBridge
!= NULL
);
813 ThisHostBridge
= RootBridge
->PciRootBridgeIo
->ParentHandle
;
815 CurrentLink
= mPciDevicePool
.ForwardLink
;
817 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
819 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
821 // Locate the right root bridge to start
823 if (RootBridge
->PciRootBridgeIo
->ParentHandle
== ThisHostBridge
) {
824 StartPciDevicesOnBridge (
833 CurrentLink
= CurrentLink
->ForwardLink
;
840 Create root bridge device.
842 @param RootBridgeHandle Specified root bridge hanle.
844 @return The crated root bridge device instance, NULL means no
845 root bridge device instance created.
850 IN EFI_HANDLE RootBridgeHandle
855 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
856 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
858 Dev
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
863 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
864 Dev
->Handle
= RootBridgeHandle
;
865 InitializeListHead (&Dev
->ChildList
);
867 Status
= gBS
->OpenProtocol (
869 &gEfiDevicePathProtocolGuid
,
870 (VOID
**) &ParentDevicePath
,
871 gPciBusDriverBinding
.DriverBindingHandle
,
873 EFI_OPEN_PROTOCOL_GET_PROTOCOL
876 if (EFI_ERROR (Status
)) {
882 // Record the root bridge parent device path
884 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
887 // Get the pci root bridge io protocol
889 Status
= gBS
->OpenProtocol (
891 &gEfiPciRootBridgeIoProtocolGuid
,
892 (VOID
**) &PciRootBridgeIo
,
893 gPciBusDriverBinding
.DriverBindingHandle
,
895 EFI_OPEN_PROTOCOL_GET_PROTOCOL
898 if (EFI_ERROR (Status
)) {
903 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
906 // Initialize the PCI I/O instance structure
908 InitializePciIoInstance (Dev
);
909 InitializePciDriverOverrideInstance (Dev
);
910 InitializePciLoadFile2 (Dev
);
913 // Initialize reserved resource list and
914 // option rom driver list
916 InitializeListHead (&Dev
->ReservedResourceList
);
917 InitializeListHead (&Dev
->OptionRomDriverList
);
923 Get root bridge device instance by specific root bridge handle.
925 @param RootBridgeHandle Given root bridge handle.
927 @return The root bridge device instance, NULL means no root bridge
928 device instance found.
932 GetRootBridgeByHandle (
933 EFI_HANDLE RootBridgeHandle
936 PCI_IO_DEVICE
*RootBridgeDev
;
937 LIST_ENTRY
*CurrentLink
;
939 CurrentLink
= mPciDevicePool
.ForwardLink
;
941 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
943 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
944 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
945 return RootBridgeDev
;
948 CurrentLink
= CurrentLink
->ForwardLink
;
955 Judege whether Pci device existed.
957 @param Bridge Parent bridege instance.
958 @param PciIoDevice Device instance.
960 @retval TRUE Pci device existed.
961 @retval FALSE Pci device did not exist.
966 IN PCI_IO_DEVICE
*Bridge
,
967 IN PCI_IO_DEVICE
*PciIoDevice
972 LIST_ENTRY
*CurrentLink
;
974 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
976 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
978 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
980 if (Temp
== PciIoDevice
) {
984 if (!IsListEmpty (&Temp
->ChildList
)) {
985 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
990 CurrentLink
= CurrentLink
->ForwardLink
;
997 Get the active VGA device on the same segment.
999 @param VgaDevice PCI IO instance for the VGA device.
1001 @return The active VGA device on the same segment.
1005 ActiveVGADeviceOnTheSameSegment (
1006 IN PCI_IO_DEVICE
*VgaDevice
1009 LIST_ENTRY
*CurrentLink
;
1010 PCI_IO_DEVICE
*Temp
;
1012 CurrentLink
= mPciDevicePool
.ForwardLink
;
1014 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
1016 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1018 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
1020 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1027 CurrentLink
= CurrentLink
->ForwardLink
;
1034 Get the active VGA device on the root bridge.
1036 @param RootBridge PCI IO instance for the root bridge.
1038 @return The active VGA device.
1042 ActiveVGADeviceOnTheRootBridge (
1043 IN PCI_IO_DEVICE
*RootBridge
1046 LIST_ENTRY
*CurrentLink
;
1047 PCI_IO_DEVICE
*Temp
;
1049 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1051 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1053 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1055 if (IS_PCI_VGA(&Temp
->Pci
) &&
1057 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
1058 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1059 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) != 0) {
1063 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1065 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1072 CurrentLink
= CurrentLink
->ForwardLink
;
1080 Get HPC PCI address according to its device path.
1082 @param RootBridge Root bridege Io instance.
1083 @param RemainingDevicePath Given searching device path.
1084 @param PciAddress Buffer holding searched result.
1086 @retval EFI_SUCCESS PCI address was stored in PciAddress
1087 @retval EFI_NOT_FOUND Can not find the specific device path.
1091 GetHpcPciAddressFromRootBridge (
1092 IN PCI_IO_DEVICE
*RootBridge
,
1093 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1094 OUT UINT64
*PciAddress
1097 EFI_DEV_PATH_PTR Node
;
1098 PCI_IO_DEVICE
*Temp
;
1099 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1100 LIST_ENTRY
*CurrentLink
;
1105 CurrentDevicePath
= RemainingDevicePath
;
1106 Node
.DevPath
= CurrentDevicePath
;
1109 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1111 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1112 Node
.DevPath
= CurrentDevicePath
;
1114 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1115 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1117 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1118 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1123 CurrentLink
= CurrentLink
->ForwardLink
;
1127 // Check if we find the bridge
1129 if (CurrentLink
== &RootBridge
->ChildList
) {
1136 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1141 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1143 if (IsDevicePathEnd (CurrentDevicePath
)) {
1144 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1148 return EFI_NOT_FOUND
;
1152 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1154 return EFI_NOT_FOUND
;