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
) != 0) {
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
320 } else if (gPciOverrideProtocol
!= NULL
) {
321 Status
= gPciOverrideProtocol
->GetPciRom (
322 gPciOverrideProtocol
,
324 &PlatformOpRomBuffer
,
327 if (!EFI_ERROR (Status
)) {
328 PciIoDevice
->RomSize
= PlatformOpRomSize
;
329 PciIoDevice
->PciIo
.RomSize
= PlatformOpRomSize
;
330 PciIoDevice
->PciIo
.RomImage
= PlatformOpRomBuffer
;
332 // For OpROM read from gPciOverrideProtocol:
333 // Add the Rom Image to internal database for later PCI light enumeration
335 PciRomAddImageMapping (
337 PciIoDevice
->PciRootBridgeIo
->SegmentNumber
,
338 PciIoDevice
->BusNumber
,
339 PciIoDevice
->DeviceNumber
,
340 PciIoDevice
->FunctionNumber
,
341 (UINT64
) (UINTN
) PciIoDevice
->PciIo
.RomImage
,
342 PciIoDevice
->PciIo
.RomSize
349 // Determine if there are EFI images in the option rom
351 HasEfiImage
= ContainEfiImage (PciIoDevice
->PciIo
.RomImage
, PciIoDevice
->PciIo
.RomSize
);
354 Status
= gBS
->InstallMultipleProtocolInterfaces (
355 &PciIoDevice
->Handle
,
356 &gEfiLoadFile2ProtocolGuid
,
357 &PciIoDevice
->LoadFile2
,
360 if (EFI_ERROR (Status
)) {
361 gBS
->UninstallMultipleProtocolInterfaces (
362 &PciIoDevice
->Handle
,
363 &gEfiDevicePathProtocolGuid
,
364 PciIoDevice
->DevicePath
,
365 &gEfiPciIoProtocolGuid
,
374 if (!PciIoDevice
->AllOpRomProcessed
) {
376 PciIoDevice
->AllOpRomProcessed
= TRUE
;
379 // Dispatch the EFI OpRom for the PCI device.
380 // The OpRom is got from platform in the above code
381 // or loaded from device in the previous round of bus enumeration
384 ProcessOpRomImage (PciIoDevice
);
388 if (PciIoDevice
->BusOverride
) {
390 // Install Bus Specific Driver Override Protocol
392 Status
= gBS
->InstallMultipleProtocolInterfaces (
393 &PciIoDevice
->Handle
,
394 &gEfiBusSpecificDriverOverrideProtocolGuid
,
395 &PciIoDevice
->PciDriverOverride
,
398 if (EFI_ERROR (Status
)) {
399 gBS
->UninstallMultipleProtocolInterfaces (
400 &PciIoDevice
->Handle
,
401 &gEfiDevicePathProtocolGuid
,
402 PciIoDevice
->DevicePath
,
403 &gEfiPciIoProtocolGuid
,
408 gBS
->UninstallMultipleProtocolInterfaces (
409 &PciIoDevice
->Handle
,
410 &gEfiLoadFile2ProtocolGuid
,
411 &PciIoDevice
->LoadFile2
,
420 Status
= gBS
->OpenProtocol (
422 &gEfiPciRootBridgeIoProtocolGuid
,
423 (VOID
**) &(PciIoDevice
->PciRootBridgeIo
),
424 gPciBusDriverBinding
.DriverBindingHandle
,
426 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
428 if (EFI_ERROR (Status
)) {
432 if (Handle
!= NULL
) {
433 *Handle
= PciIoDevice
->Handle
;
437 // Indicate the pci device is registered
439 PciIoDevice
->Registered
= TRUE
;
445 This function is used to remove the whole PCI devices on the specified bridge from
448 @param RootBridgeHandle The root bridge device handle.
449 @param Bridge The bridge device to be removed.
453 RemoveAllPciDeviceOnBridge (
454 EFI_HANDLE RootBridgeHandle
,
455 PCI_IO_DEVICE
*Bridge
458 LIST_ENTRY
*CurrentLink
;
461 while (!IsListEmpty (&Bridge
->ChildList
)) {
463 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
464 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
467 // Check if the current node has been deregistered before
468 // If it is not, then deregister it
470 if (Temp
->Registered
) {
471 DeRegisterPciDevice (RootBridgeHandle
, Temp
->Handle
);
475 // Remove this node from the linked list
477 RemoveEntryList (CurrentLink
);
479 if (!IsListEmpty (&Temp
->ChildList
)) {
480 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
483 FreePciDevice (Temp
);
488 This function is used to de-register the PCI IO device.
490 That includes un-installing PciIo protocol from the specified PCI
493 @param Controller An EFI handle for the PCI bus controller.
494 @param Handle PCI device handle.
496 @retval EFI_SUCCESS The PCI device is successfully de-registered.
497 @retval other An error occurred when de-registering the PCI device.
501 DeRegisterPciDevice (
502 IN EFI_HANDLE Controller
,
507 EFI_PCI_IO_PROTOCOL
*PciIo
;
509 PCI_IO_DEVICE
*PciIoDevice
;
511 LIST_ENTRY
*CurrentLink
;
512 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
514 Status
= gBS
->OpenProtocol (
516 &gEfiPciIoProtocolGuid
,
518 gPciBusDriverBinding
.DriverBindingHandle
,
520 EFI_OPEN_PROTOCOL_GET_PROTOCOL
522 if (!EFI_ERROR (Status
)) {
523 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
526 // If it is already de-registered
528 if (!PciIoDevice
->Registered
) {
533 // If it is PPB, first de-register its children
536 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
538 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
540 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
541 Node
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
542 Status
= DeRegisterPciDevice (Controller
, Node
->Handle
);
544 if (EFI_ERROR (Status
)) {
548 CurrentLink
= CurrentLink
->ForwardLink
;
553 // Close the child handle
555 Status
= gBS
->CloseProtocol (
557 &gEfiPciRootBridgeIoProtocolGuid
,
558 gPciBusDriverBinding
.DriverBindingHandle
,
563 // Un-install the Device Path protocol and PCI I/O protocol
564 // and Bus Specific Driver Override protocol if needed.
566 if (PciIoDevice
->BusOverride
) {
567 Status
= gBS
->UninstallMultipleProtocolInterfaces (
569 &gEfiDevicePathProtocolGuid
,
570 PciIoDevice
->DevicePath
,
571 &gEfiPciIoProtocolGuid
,
573 &gEfiBusSpecificDriverOverrideProtocolGuid
,
574 &PciIoDevice
->PciDriverOverride
,
578 Status
= gBS
->UninstallMultipleProtocolInterfaces (
580 &gEfiDevicePathProtocolGuid
,
581 PciIoDevice
->DevicePath
,
582 &gEfiPciIoProtocolGuid
,
588 if (!EFI_ERROR (Status
)) {
590 // Try to uninstall LoadFile2 protocol if exists
592 Status
= gBS
->OpenProtocol (
594 &gEfiLoadFile2ProtocolGuid
,
596 gPciBusDriverBinding
.DriverBindingHandle
,
598 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
600 if (!EFI_ERROR (Status
)) {
601 Status
= gBS
->UninstallMultipleProtocolInterfaces (
603 &gEfiLoadFile2ProtocolGuid
,
604 &PciIoDevice
->LoadFile2
,
611 Status
= EFI_SUCCESS
;
615 if (EFI_ERROR (Status
)) {
618 &gEfiPciRootBridgeIoProtocolGuid
,
619 (VOID
**) &PciRootBridgeIo
,
620 gPciBusDriverBinding
.DriverBindingHandle
,
622 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
628 // The Device Driver should disable this device after disconnect
629 // so the Pci Bus driver will not touch this device any more.
630 // Restore the register field to the original value
632 PciIoDevice
->Registered
= FALSE
;
633 PciIoDevice
->Handle
= NULL
;
637 // Handle may be closed before
646 Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
648 @param Controller The root bridge handle.
649 @param RootBridge A pointer to the PCI_IO_DEVICE.
650 @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
651 @param NumberOfChildren Children number.
652 @param ChildHandleBuffer A pointer to the child handle buffer.
654 @retval EFI_NOT_READY Device is not allocated.
655 @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
656 @retval EFI_NOT_FOUND Can not find the specific device.
657 @retval EFI_SUCCESS Success to start Pci devices on bridge.
661 StartPciDevicesOnBridge (
662 IN EFI_HANDLE Controller
,
663 IN PCI_IO_DEVICE
*RootBridge
,
664 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
665 IN OUT UINT8
*NumberOfChildren
,
666 IN OUT EFI_HANDLE
*ChildHandleBuffer
670 PCI_IO_DEVICE
*PciIoDevice
;
671 EFI_DEV_PATH_PTR Node
;
672 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
674 LIST_ENTRY
*CurrentLink
;
678 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
680 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
682 PciIoDevice
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
683 if (RemainingDevicePath
!= NULL
) {
685 Node
.DevPath
= RemainingDevicePath
;
687 if (Node
.Pci
->Device
!= PciIoDevice
->DeviceNumber
||
688 Node
.Pci
->Function
!= PciIoDevice
->FunctionNumber
) {
689 CurrentLink
= CurrentLink
->ForwardLink
;
694 // Check if the device has been assigned with required resource
696 if (!PciIoDevice
->Allocated
) {
697 return EFI_NOT_READY
;
701 // Check if the current node has been registered before
702 // If it is not, register it
704 if (!PciIoDevice
->Registered
) {
705 Status
= RegisterPciDevice (
713 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
714 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
715 (*NumberOfChildren
)++;
719 // Get the next device path
721 CurrentDevicePath
= NextDevicePathNode (RemainingDevicePath
);
722 if (IsDevicePathEnd (CurrentDevicePath
)) {
729 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
730 Status
= StartPciDevicesOnBridge (
738 PciIoDevice
->PciIo
.Attributes (
739 &(PciIoDevice
->PciIo
),
740 EfiPciIoAttributeOperationSupported
,
744 Supports
&= EFI_PCI_DEVICE_ENABLE
;
745 PciIoDevice
->PciIo
.Attributes (
746 &(PciIoDevice
->PciIo
),
747 EfiPciIoAttributeOperationEnable
,
756 // Currently, the PCI bus driver only support PCI-PCI bridge
758 return EFI_UNSUPPORTED
;
764 // If remaining device path is NULL,
765 // try to enable all the pci devices under this bridge
767 if (!PciIoDevice
->Registered
&& PciIoDevice
->Allocated
) {
768 Status
= RegisterPciDevice (
776 if (NumberOfChildren
!= NULL
&& ChildHandleBuffer
!= NULL
&& PciIoDevice
->Registered
) {
777 ChildHandleBuffer
[*NumberOfChildren
] = PciIoDevice
->Handle
;
778 (*NumberOfChildren
)++;
781 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
782 Status
= StartPciDevicesOnBridge (
790 PciIoDevice
->PciIo
.Attributes (
791 &(PciIoDevice
->PciIo
),
792 EfiPciIoAttributeOperationSupported
,
796 Supports
&= EFI_PCI_DEVICE_ENABLE
;
797 PciIoDevice
->PciIo
.Attributes (
798 &(PciIoDevice
->PciIo
),
799 EfiPciIoAttributeOperationEnable
,
806 CurrentLink
= CurrentLink
->ForwardLink
;
810 if (PciIoDevice
== NULL
) {
811 return EFI_NOT_FOUND
;
818 Start to manage all the PCI devices it found previously under
819 the entire host bridge.
821 @param Controller The root bridge handle.
823 @retval EFI_NOT_READY Device is not allocated.
824 @retval EFI_SUCCESS Success to start Pci device on host bridge.
829 IN EFI_HANDLE Controller
832 PCI_IO_DEVICE
*RootBridge
;
833 EFI_HANDLE ThisHostBridge
;
834 LIST_ENTRY
*CurrentLink
;
836 RootBridge
= GetRootBridgeByHandle (Controller
);
837 ASSERT (RootBridge
!= NULL
);
838 ThisHostBridge
= RootBridge
->PciRootBridgeIo
->ParentHandle
;
840 CurrentLink
= mPciDevicePool
.ForwardLink
;
842 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
844 RootBridge
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
846 // Locate the right root bridge to start
848 if (RootBridge
->PciRootBridgeIo
->ParentHandle
== ThisHostBridge
) {
849 StartPciDevicesOnBridge (
858 CurrentLink
= CurrentLink
->ForwardLink
;
865 Create root bridge device.
867 @param RootBridgeHandle Specified root bridge hanle.
869 @return The crated root bridge device instance, NULL means no
870 root bridge device instance created.
875 IN EFI_HANDLE RootBridgeHandle
880 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
881 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
883 Dev
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
888 Dev
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
889 Dev
->Handle
= RootBridgeHandle
;
890 InitializeListHead (&Dev
->ChildList
);
892 Status
= gBS
->OpenProtocol (
894 &gEfiDevicePathProtocolGuid
,
895 (VOID
**) &ParentDevicePath
,
896 gPciBusDriverBinding
.DriverBindingHandle
,
898 EFI_OPEN_PROTOCOL_GET_PROTOCOL
901 if (EFI_ERROR (Status
)) {
907 // Record the root bridge parent device path
909 Dev
->DevicePath
= DuplicateDevicePath (ParentDevicePath
);
912 // Get the pci root bridge io protocol
914 Status
= gBS
->OpenProtocol (
916 &gEfiPciRootBridgeIoProtocolGuid
,
917 (VOID
**) &PciRootBridgeIo
,
918 gPciBusDriverBinding
.DriverBindingHandle
,
920 EFI_OPEN_PROTOCOL_GET_PROTOCOL
923 if (EFI_ERROR (Status
)) {
928 Dev
->PciRootBridgeIo
= PciRootBridgeIo
;
931 // Initialize the PCI I/O instance structure
933 InitializePciIoInstance (Dev
);
934 InitializePciDriverOverrideInstance (Dev
);
935 InitializePciLoadFile2 (Dev
);
938 // Initialize reserved resource list and
939 // option rom driver list
941 InitializeListHead (&Dev
->ReservedResourceList
);
942 InitializeListHead (&Dev
->OptionRomDriverList
);
948 Get root bridge device instance by specific root bridge handle.
950 @param RootBridgeHandle Given root bridge handle.
952 @return The root bridge device instance, NULL means no root bridge
953 device instance found.
957 GetRootBridgeByHandle (
958 EFI_HANDLE RootBridgeHandle
961 PCI_IO_DEVICE
*RootBridgeDev
;
962 LIST_ENTRY
*CurrentLink
;
964 CurrentLink
= mPciDevicePool
.ForwardLink
;
966 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
968 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
969 if (RootBridgeDev
->Handle
== RootBridgeHandle
) {
970 return RootBridgeDev
;
973 CurrentLink
= CurrentLink
->ForwardLink
;
980 Judege whether Pci device existed.
982 @param Bridge Parent bridege instance.
983 @param PciIoDevice Device instance.
985 @retval TRUE Pci device existed.
986 @retval FALSE Pci device did not exist.
991 IN PCI_IO_DEVICE
*Bridge
,
992 IN PCI_IO_DEVICE
*PciIoDevice
997 LIST_ENTRY
*CurrentLink
;
999 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1001 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1003 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1005 if (Temp
== PciIoDevice
) {
1009 if (!IsListEmpty (&Temp
->ChildList
)) {
1010 if (PciDeviceExisted (Temp
, PciIoDevice
)) {
1015 CurrentLink
= CurrentLink
->ForwardLink
;
1022 Get the active VGA device on the same segment.
1024 @param VgaDevice PCI IO instance for the VGA device.
1026 @return The active VGA device on the same segment.
1030 ActiveVGADeviceOnTheSameSegment (
1031 IN PCI_IO_DEVICE
*VgaDevice
1034 LIST_ENTRY
*CurrentLink
;
1035 PCI_IO_DEVICE
*Temp
;
1037 CurrentLink
= mPciDevicePool
.ForwardLink
;
1039 while (CurrentLink
!= NULL
&& CurrentLink
!= &mPciDevicePool
) {
1041 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1043 if (Temp
->PciRootBridgeIo
->SegmentNumber
== VgaDevice
->PciRootBridgeIo
->SegmentNumber
) {
1045 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1052 CurrentLink
= CurrentLink
->ForwardLink
;
1059 Get the active VGA device on the root bridge.
1061 @param RootBridge PCI IO instance for the root bridge.
1063 @return The active VGA device.
1067 ActiveVGADeviceOnTheRootBridge (
1068 IN PCI_IO_DEVICE
*RootBridge
1071 LIST_ENTRY
*CurrentLink
;
1072 PCI_IO_DEVICE
*Temp
;
1074 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1076 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1078 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1080 if (IS_PCI_VGA(&Temp
->Pci
) &&
1082 (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
|
1083 EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1084 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) != 0) {
1088 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
1090 Temp
= ActiveVGADeviceOnTheRootBridge (Temp
);
1097 CurrentLink
= CurrentLink
->ForwardLink
;
1105 Get HPC PCI address according to its device path.
1107 @param RootBridge Root bridege Io instance.
1108 @param RemainingDevicePath Given searching device path.
1109 @param PciAddress Buffer holding searched result.
1111 @retval EFI_SUCCESS PCI address was stored in PciAddress
1112 @retval EFI_NOT_FOUND Can not find the specific device path.
1116 GetHpcPciAddressFromRootBridge (
1117 IN PCI_IO_DEVICE
*RootBridge
,
1118 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
1119 OUT UINT64
*PciAddress
1122 EFI_DEV_PATH_PTR Node
;
1123 PCI_IO_DEVICE
*Temp
;
1124 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
1125 LIST_ENTRY
*CurrentLink
;
1130 CurrentDevicePath
= RemainingDevicePath
;
1131 Node
.DevPath
= CurrentDevicePath
;
1134 while (!IsDevicePathEnd (CurrentDevicePath
)) {
1136 CurrentLink
= RootBridge
->ChildList
.ForwardLink
;
1137 Node
.DevPath
= CurrentDevicePath
;
1139 while (CurrentLink
!= NULL
&& CurrentLink
!= &RootBridge
->ChildList
) {
1140 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1142 if (Node
.Pci
->Device
== Temp
->DeviceNumber
&&
1143 Node
.Pci
->Function
== Temp
->FunctionNumber
) {
1148 CurrentLink
= CurrentLink
->ForwardLink
;
1152 // Check if we find the bridge
1154 if (CurrentLink
== &RootBridge
->ChildList
) {
1161 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1166 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
1168 if (IsDevicePathEnd (CurrentDevicePath
)) {
1169 *PciAddress
= EFI_PCI_ADDRESS (RootBridge
->BusNumber
, Node
.Pci
->Device
, Node
.Pci
->Function
, 0);
1173 return EFI_NOT_FOUND
;
1177 *PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1179 return EFI_NOT_FOUND
;