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 Light PCI Bus Driver Lib file
19 It abstracts some functions that can be different
20 between light PCI bus driver and full PCI bus driver
29 // Light PCI bus driver woundn't support hotplug device
33 InstallHotPlugRequestProtocol (
48 // TODO: Status - add argument and description to function comment
54 // Light PCI bus driver woundn't support hotplug device
55 // So just skip install this GUID
58 InstallPciHotplugGuid (
59 IN PCI_IO_DEVICE
*PciIoDevice
73 // TODO: PciIoDevice - add argument and description to function comment
79 // Light PCI bus driver woundn't support hotplug device
80 // So just skip uninstall the GUID
83 UninstallPciHotplugGuid (
84 IN PCI_IO_DEVICE
*PciIoDevice
98 // TODO: PciIoDevice - add argument and description to function comment
104 // Light PCI bus driver woundn't support PCCard
105 // So it needn't get the bar of CardBus
109 IN PCI_IO_DEVICE
*PciIoDevice
115 TODO: Add function description
119 PciIoDevice - TODO: add argument description
123 TODO: add return values
131 // Light PCI bus driver woundn't support resource reallocation
135 RemoveRejectedPciDevices (
136 EFI_HANDLE RootBridgeHandle
,
137 IN PCI_IO_DEVICE
*Bridge
143 TODO: Add function description
147 RootBridgeHandle - TODO: add argument description
148 Bridge - TODO: add argument description
152 EFI_SUCCESS - TODO: Add description for return value
160 // Light PCI bus driver woundn't support resource reallocation
161 // Simplified the code
164 PciHostBridgeResourceAllocator (
165 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
178 // TODO: PciResAlloc - add argument and description to function comment
179 // TODO: EFI_NOT_FOUND - add return value to function comment
180 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
181 // TODO: EFI_NOT_FOUND - add return value to function comment
182 // TODO: EFI_SUCCESS - add return value to function comment
184 PCI_IO_DEVICE
*RootBridgeDev
;
185 EFI_HANDLE RootBridgeHandle
;
193 UINT64 MaxOptionRomSize
;
194 PCI_RESOURCE_NODE
*IoBridge
;
195 PCI_RESOURCE_NODE
*Mem32Bridge
;
196 PCI_RESOURCE_NODE
*PMem32Bridge
;
197 PCI_RESOURCE_NODE
*Mem64Bridge
;
198 PCI_RESOURCE_NODE
*PMem64Bridge
;
199 PCI_RESOURCE_NODE IoPool
;
200 PCI_RESOURCE_NODE Mem32Pool
;
201 PCI_RESOURCE_NODE PMem32Pool
;
202 PCI_RESOURCE_NODE Mem64Pool
;
203 PCI_RESOURCE_NODE PMem64Pool
;
204 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData
;
207 // Initialize resource pool
210 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
211 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
212 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
213 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
214 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
216 RootBridgeDev
= NULL
;
217 RootBridgeHandle
= 0;
219 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
221 // Get RootBridg Device by handle
223 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
225 if (RootBridgeDev
== NULL
) {
226 return EFI_NOT_FOUND
;
230 // Get host bridge handle for status report
232 ExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
235 // Create the entire system resource map from the information collected by
236 // enumerator. Several resource tree was created
239 IoBridge
= CreateResourceNode (
248 Mem32Bridge
= CreateResourceNode (
257 PMem32Bridge
= CreateResourceNode (
266 Mem64Bridge
= CreateResourceNode (
275 PMem64Bridge
= CreateResourceNode (
285 // Create resourcemap by going through all the devices subject to this root bridge
287 Status
= CreateResourceMap (
297 // Get the max ROM size that the root bridge can process
299 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
302 // Get Max Option Rom size for current root bridge
304 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
307 // Enlarger the mem32 resource to accomdate the option rom
308 // if the mem32 resource is not enough to hold the rom
310 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
312 Mem32Bridge
->Length
= MaxOptionRomSize
;
313 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
316 // Alignment should be adjusted as well
318 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
319 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
324 // Based on the all the resource tree, contruct ACPI resource node to
325 // submit the resource aperture to pci host bridge protocol
327 Status
= ConstructAcpiResourceRequestor (
338 // Insert these resource nodes into the database
340 InsertResourceNode (&IoPool
, IoBridge
);
341 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
342 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
343 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
344 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
346 if (Status
== EFI_SUCCESS
) {
348 // Submit the resource requirement
350 Status
= PciResAlloc
->SubmitResources (
352 RootBridgeDev
->Handle
,
357 // Free acpi resource node
360 gBS
->FreePool (AcpiConfig
);
363 if (EFI_ERROR (Status
)) {
365 // Destroy all the resource tree
367 DestroyResourceTree (&IoPool
);
368 DestroyResourceTree (&Mem32Pool
);
369 DestroyResourceTree (&PMem32Pool
);
370 DestroyResourceTree (&Mem64Pool
);
371 DestroyResourceTree (&PMem64Pool
);
380 // Notify pci bus driver starts to program the resource
382 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
384 if (EFI_ERROR (Status
)) {
386 // Allocation failed, then return
388 return EFI_OUT_OF_RESOURCES
;
391 // Raise the EFI_IOB_PCI_RES_ALLOC status code
393 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
395 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
396 (VOID
*) &ExtendedData
,
397 sizeof (ExtendedData
)
401 // Notify pci bus driver starts to program the resource
403 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
405 RootBridgeDev
= NULL
;
407 RootBridgeHandle
= 0;
409 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
411 // Get RootBridg Device by handle
413 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
415 if (RootBridgeDev
== NULL
) {
416 return EFI_NOT_FOUND
;
420 // Get acpi resource node for all the resource types
423 Status
= PciResAlloc
->GetProposedResources (
425 RootBridgeDev
->Handle
,
429 if (EFI_ERROR (Status
)) {
434 // Get the resource base by interpreting acpi resource node
447 // Process option rom for this root bridge
449 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
452 // Create the entire system resource map from the information collected by
453 // enumerator. Several resource tree was created
455 Status
= GetResourceMap (
469 if (EFI_ERROR (Status
)) {
474 // Program IO resources
482 // Program Mem32 resources
490 // Program PMem32 resources
498 // Program Mem64 resources
506 // Program PMem64 resources
513 if (AcpiConfig
!= NULL
) {
514 gBS
->FreePool (AcpiConfig
);
519 // Destroy all the resource tree
521 DestroyResourceTree (&IoPool
);
522 DestroyResourceTree (&Mem32Pool
);
523 DestroyResourceTree (&PMem32Pool
);
524 DestroyResourceTree (&Mem64Pool
);
525 DestroyResourceTree (&PMem64Pool
);
528 // Notify the resource allocation phase is to end
530 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
537 IN PCI_IO_DEVICE
*Bridge
,
538 IN UINT8 StartBusNumber
,
539 OUT UINT8
*SubBusNumber
,
540 OUT UINT8
*PaddedBusRange
546 This routine is used to assign bus number to the given PCI bus system
555 // TODO: Bridge - add argument and description to function comment
556 // TODO: StartBusNumber - add argument and description to function comment
557 // TODO: SubBusNumber - add argument and description to function comment
558 // TODO: PaddedBusRange - add argument and description to function comment
559 // TODO: EFI_DEVICE_ERROR - add return value to function comment
560 // TODO: EFI_SUCCESS - add return value to function comment
569 PCI_IO_DEVICE
*PciDevice
;
570 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
572 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
576 ResetAllPpbBusReg (Bridge
, StartBusNumber
);
578 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
579 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
582 // Check to see whether a pci device is present
584 Status
= PciDevicePresent (
592 if (!EFI_ERROR (Status
) &&
593 (IS_PCI_BRIDGE (&Pci
) ||
594 IS_CARDBUS_BRIDGE (&Pci
))) {
597 // Get the bridge information
599 Status
= PciSearchDevice (
608 if (EFI_ERROR (Status
)) {
614 SecondBus
= (*SubBusNumber
);
616 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
618 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
620 Status
= PciRootBridgeIo
->Pci
.Write (
629 // Initialize SubBusNumber to SecondBus
631 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
632 Status
= PciRootBridgeIo
->Pci
.Write (
640 // If it is PPB, resursively search down this bridge
642 if (IS_PCI_BRIDGE (&Pci
)) {
644 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
645 // PCI configuration transaction to go through any PPB
647 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
649 Status
= PciRootBridgeIo
->Pci
.Write (
657 PreprocessController (
659 PciDevice
->BusNumber
,
660 PciDevice
->DeviceNumber
,
661 PciDevice
->FunctionNumber
,
662 EfiPciBeforeChildBusEnumeration
665 Status
= PciScanBus (
672 if (EFI_ERROR (Status
)) {
673 return EFI_DEVICE_ERROR
;
678 // Set the current maximum bus number under the PPB
681 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
683 Status
= PciRootBridgeIo
->Pci
.Write (
693 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
696 // Skip sub functions, this is not a multi function device
708 // Light PCI bus driver woundn't support P2C
712 PciHostBridgeP2CProcess (
713 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
726 // TODO: PciResAlloc - add argument and description to function comment
727 // TODO: EFI_SUCCESS - add return value to function comment
733 // Light PCI bus driver woundn't support hotplug device
734 // Simplified the code
737 PciHostBridgeEnumerator (
738 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
744 This function is used to enumerate the entire host bridge
749 PciResAlloc A pointer to the protocol to allocate resource.
756 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
757 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
758 // TODO: EFI_SUCCESS - add return value to function comment
760 EFI_HANDLE RootBridgeHandle
;
761 PCI_IO_DEVICE
*RootBridgeDev
;
763 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
765 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
767 InitializeHotPlugSupport ();
770 // Notify the bus allocation phase is about to start
772 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
774 RootBridgeHandle
= NULL
;
775 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
778 // if a root bridge instance is found, create root bridge device for it
781 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
783 if (RootBridgeDev
== NULL
) {
784 return EFI_OUT_OF_RESOURCES
;
788 // Enumerate all the buses under this root bridge
791 Status
= PciRootBridgeEnumerator (
796 if (EFI_ERROR (Status
)) {
800 DestroyRootBridge (RootBridgeDev
);
803 // Error proccess here
808 // Notify the bus allocation phase is to end
810 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
813 // Notify the resource allocation phase is to start
815 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
817 RootBridgeHandle
= NULL
;
818 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
821 // if a root bridge instance is found, create root bridge device for it
824 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
826 if (RootBridgeDev
== NULL
) {
827 return EFI_OUT_OF_RESOURCES
;
830 Status
= StartManagingRootBridge (RootBridgeDev
);
832 if (EFI_ERROR (Status
)) {
836 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
837 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
839 if (EFI_ERROR (Status
)) {
843 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
845 if (EFI_ERROR (Status
)) {
850 // Determine root bridge attribute by calling interface of Pcihostbridge
853 DetermineRootBridgeAttributes (
859 // Collect all the resource information under this root bridge
860 // A database that records all the information about pci device subject to this
861 // root bridge will then be created
863 Status
= PciPciDeviceInfoCollector (
868 if (EFI_ERROR (Status
)) {
872 InsertRootBridge (RootBridgeDev
);
875 // Record the hostbridge handle
877 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);