2 Provides the basic interfaces to abstract a PCI Host Bridge Resource
5 Copyright (C) 2015, Red Hat, Inc.
6 Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "PciHostBridge.h"
22 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate
= {
28 (UINT8
) (sizeof(ACPI_HID_DEVICE_PATH
)),
29 (UINT8
) ((sizeof(ACPI_HID_DEVICE_PATH
)) >> 8)
32 EISA_PNP_ID(0x0A03), // HID
38 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
40 END_DEVICE_PATH_LENGTH
,
47 // Hard code: Root Bridge's resource aperture
50 PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture
[1] = {
51 {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
54 EFI_HANDLE mDriverImageHandle
;
56 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate
= {
57 PCI_HOST_BRIDGE_SIGNATURE
, // Signature
58 NULL
, // HostBridgeHandle
59 0, // RootBridgeNumber
61 FALSE
, // ResourceSubiteed
80 Entry point of this driver
82 @param ImageHandle Handle of driver image
83 @param SystemTable Point to EFI_SYSTEM_TABLE
85 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
86 @retval EFI_DEVICE_ERROR Can not install the protocol instance
87 @retval EFI_SUCCESS Success to initialize the Pci host bridge.
91 InitializePciHostBridge (
92 IN EFI_HANDLE ImageHandle
,
93 IN EFI_SYSTEM_TABLE
*SystemTable
98 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
99 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
101 mDriverImageHandle
= ImageHandle
;
104 // Create Host Bridge Device Handle
106 HostBridge
= AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE
),
107 &mPciHostBridgeInstanceTemplate
);
108 if (HostBridge
== NULL
) {
109 return EFI_OUT_OF_RESOURCES
;
112 HostBridge
->RootBridgeNumber
= 1;
113 InitializeListHead (&HostBridge
->Head
);
115 Status
= gBS
->InstallMultipleProtocolInterfaces (
116 &HostBridge
->HostBridgeHandle
,
117 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
118 &HostBridge
->ResAlloc
,
121 if (EFI_ERROR (Status
)) {
122 FreePool (HostBridge
);
123 return EFI_DEVICE_ERROR
;
127 // Create Root Bridge Device Handle in this Host Bridge
130 for (Loop2
= 0; Loop2
< HostBridge
->RootBridgeNumber
; Loop2
++) {
131 PrivateData
= AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE
));
132 if (PrivateData
== NULL
) {
133 return EFI_OUT_OF_RESOURCES
;
136 PrivateData
->Signature
= PCI_ROOT_BRIDGE_SIGNATURE
;
138 CopyMem (&PrivateData
->DevicePath
, &mRootBridgeDevicePathTemplate
,
139 sizeof mRootBridgeDevicePathTemplate
);
140 PrivateData
->DevicePath
.AcpiDevicePath
.UID
= Loop2
;
142 RootBridgeConstructor (
144 HostBridge
->HostBridgeHandle
,
145 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
,
149 Status
= gBS
->InstallMultipleProtocolInterfaces(
150 &PrivateData
->Handle
,
151 &gEfiDevicePathProtocolGuid
,
152 &PrivateData
->DevicePath
,
153 &gEfiPciRootBridgeIoProtocolGuid
,
157 if (EFI_ERROR (Status
)) {
158 FreePool(PrivateData
);
159 return EFI_DEVICE_ERROR
;
162 InsertTailList (&HostBridge
->Head
, &PrivateData
->Link
);
170 These are the notifications from the PCI bus driver that it is about to enter
171 a certain phase of the PCI enumeration process.
173 This member function can be used to notify the host bridge driver to perform
174 specific actions, including any chipset-specific initialization, so that the
175 chipset is ready to enter the next phase. Eight notification points are
176 defined at this time. See belows:
178 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures
179 and internal data structures. The PCI
180 enumerator should issue this
181 notification before starting a fresh
182 enumeration process. Enumeration
183 cannot be restarted after sending any
184 other notification such as
185 EfiPciHostBridgeBeginBusAllocation.
187 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to
188 begin. No specific action is required
189 here. This notification can be used to
190 perform any chipset-specific
193 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming
194 phase is complete. No specific action
195 is required here. This notification
196 can be used to perform any
197 chipset-specific programming.
199 EfiPciHostBridgeBeginResourceAllocation
200 The resource allocation phase is about
201 to begin. No specific action is
202 required here. This notification can
203 be used to perform any
204 chipset-specific programming.
206 EfiPciHostBridgeAllocateResources Allocates resources per previously
207 submitted requests for all the PCI
208 root bridges. These resource settings
209 are returned on the next call to
210 GetProposedResources(). Before calling
211 NotifyPhase() with a Phase of
212 EfiPciHostBridgeAllocateResource, the
213 PCI bus enumerator is responsible for
214 gathering I/O and memory requests for
215 all the PCI root bridges and
216 submitting these requests using
217 SubmitResources(). This function pads
218 the resource amount to suit the root
219 bridge hardware, takes care of
220 dependencies between the PCI root
221 bridges, and calls the Global
222 Coherency Domain (GCD) with the
223 allocation request. In the case of
224 padding, the allocated range could be
225 bigger than what was requested.
227 EfiPciHostBridgeSetResources Programs the host bridge hardware to
228 decode previously allocated resources
229 (proposed resources) for all the PCI
230 root bridges. After the hardware is
231 programmed, reassigning resources will
232 not be supported. The bus settings are
235 EfiPciHostBridgeFreeResources Deallocates resources that were
236 previously allocated for all the PCI
237 root bridges and resets the I/O and
238 memory apertures to their initial
239 state. The bus settings are not
240 affected. If the request to allocate
241 resources fails, the PCI enumerator
242 can use this notification to
243 deallocate previous resources, adjust
244 the requests, and retry allocation.
246 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is
247 completed. No specific action is
248 required here. This notification can
249 be used to perform any chipsetspecific
252 @param[in] This The instance pointer of
253 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
255 @param[in] Phase The phase during enumeration
257 @retval EFI_NOT_READY This phase cannot be entered at this time. For
258 example, this error is valid for a Phase of
259 EfiPciHostBridgeAllocateResources if
260 SubmitResources() has not been called for one
261 or more PCI root bridges before this call
263 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
264 This error is valid for a Phase of
265 EfiPciHostBridgeSetResources.
267 @retval EFI_INVALID_PARAMETER Invalid phase parameter
269 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
270 lack of resources. This error is valid for a
271 Phase of EfiPciHostBridgeAllocateResources if
272 the previously submitted resource requests
273 cannot be fulfilled or were only partially
276 @retval EFI_SUCCESS The notification was accepted without any
282 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
283 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
286 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
287 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
288 PCI_RESOURCE_TYPE Index
;
290 EFI_PHYSICAL_ADDRESS BaseAddress
;
292 UINTN BitsOfAlignment
;
294 EFI_STATUS ReturnStatus
;
296 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
300 case EfiPciHostBridgeBeginEnumeration
:
301 if (HostBridgeInstance
->CanRestarted
) {
303 // Reset the Each Root Bridge
305 List
= HostBridgeInstance
->Head
.ForwardLink
;
307 while (List
!= &HostBridgeInstance
->Head
) {
308 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
309 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
310 RootBridgeInstance
->ResAllocNode
[Index
].Type
= Index
;
311 RootBridgeInstance
->ResAllocNode
[Index
].Base
= 0;
312 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
313 RootBridgeInstance
->ResAllocNode
[Index
].Status
= ResNone
;
316 List
= List
->ForwardLink
;
319 HostBridgeInstance
->ResourceSubmited
= FALSE
;
320 HostBridgeInstance
->CanRestarted
= TRUE
;
325 return EFI_NOT_READY
;
329 case EfiPciHostBridgeEndEnumeration
:
332 case EfiPciHostBridgeBeginBusAllocation
:
334 // No specific action is required here, can perform any chipset specific
337 HostBridgeInstance
->CanRestarted
= FALSE
;
340 case EfiPciHostBridgeEndBusAllocation
:
342 // No specific action is required here, can perform any chipset specific
345 //HostBridgeInstance->CanRestarted = FALSE;
348 case EfiPciHostBridgeBeginResourceAllocation
:
350 // No specific action is required here, can perform any chipset specific
353 //HostBridgeInstance->CanRestarted = FALSE;
356 case EfiPciHostBridgeAllocateResources
:
357 ReturnStatus
= EFI_SUCCESS
;
358 if (HostBridgeInstance
->ResourceSubmited
) {
360 // Take care of the resource dependencies between the root bridges
362 List
= HostBridgeInstance
->Head
.ForwardLink
;
364 while (List
!= &HostBridgeInstance
->Head
) {
365 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
366 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
367 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
!= ResNone
) {
369 AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
372 // Get the number of '1' in Alignment.
375 (UINTN
)(HighBitSet64 (
376 RootBridgeInstance
->ResAllocNode
[Index
].Alignment
383 // It is impossible for this chipset to align 0xFFFF for IO16
386 if (BitsOfAlignment
>= 16) {
390 Status
= gDS
->AllocateIoSpace (
391 EfiGcdAllocateAnySearchBottomUp
,
400 if (!EFI_ERROR (Status
)) {
401 RootBridgeInstance
->ResAllocNode
[Index
].Base
=
403 RootBridgeInstance
->ResAllocNode
[Index
].Status
=
406 ReturnStatus
= Status
;
407 if (Status
!= EFI_OUT_OF_RESOURCES
) {
408 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
417 // It is impossible for this chipset to align 0xFFFFFFFF for
422 if (BitsOfAlignment
>= 32) {
426 Status
= gDS
->AllocateMemorySpace (
427 EfiGcdAllocateAnySearchBottomUp
,
428 EfiGcdMemoryTypeMemoryMappedIo
,
436 if (!EFI_ERROR (Status
)) {
437 // We were able to allocate the PCI memory
438 RootBridgeInstance
->ResAllocNode
[Index
].Base
=
440 RootBridgeInstance
->ResAllocNode
[Index
].Status
=
444 // Not able to allocate enough PCI memory
445 ReturnStatus
= Status
;
447 if (Status
!= EFI_OUT_OF_RESOURCES
) {
448 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
457 ReturnStatus
= EFI_ABORTED
;
466 List
= List
->ForwardLink
;
472 return EFI_NOT_READY
;
476 case EfiPciHostBridgeSetResources
:
479 case EfiPciHostBridgeFreeResources
:
480 ReturnStatus
= EFI_SUCCESS
;
481 List
= HostBridgeInstance
->Head
.ForwardLink
;
482 while (List
!= &HostBridgeInstance
->Head
) {
483 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
484 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
485 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
== ResAllocated
) {
486 AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
487 BaseAddress
= RootBridgeInstance
->ResAllocNode
[Index
].Base
;
491 Status
= gDS
->FreeIoSpace (BaseAddress
, AddrLen
);
492 if (EFI_ERROR (Status
)) {
493 ReturnStatus
= Status
;
498 Status
= gDS
->FreeMemorySpace (BaseAddress
, AddrLen
);
499 if (EFI_ERROR (Status
)) {
500 ReturnStatus
= Status
;
518 RootBridgeInstance
->ResAllocNode
[Index
].Type
= Index
;
519 RootBridgeInstance
->ResAllocNode
[Index
].Base
= 0;
520 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
521 RootBridgeInstance
->ResAllocNode
[Index
].Status
= ResNone
;
525 List
= List
->ForwardLink
;
528 HostBridgeInstance
->ResourceSubmited
= FALSE
;
529 HostBridgeInstance
->CanRestarted
= TRUE
;
532 case EfiPciHostBridgeEndResourceAllocation
:
533 HostBridgeInstance
->CanRestarted
= FALSE
;
537 return EFI_INVALID_PARAMETER
;
544 Return the device handle of the next PCI root bridge that is associated with
547 This function is called multiple times to retrieve the device handles of all
548 the PCI root bridges that are associated with this PCI host bridge. Each PCI
549 host bridge is associated with one or more PCI root bridges. On each call,
550 the handle that was returned by the previous call is passed into the
551 interface, and on output the interface returns the device handle of the next
552 PCI root bridge. The caller can use the handle to obtain the instance of the
553 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
554 PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
555 enumerator must enumerate the PCI root bridges in the order that they are
556 returned by this function.
558 For D945 implementation, there is only one root bridge in PCI host bridge.
560 @param[in] This The instance pointer of
561 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
563 @param[in, out] RootBridgeHandle Returns the device handle of the next PCI
566 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then
567 return the first Rootbridge handle of the
568 specific Host bridge and return EFI_SUCCESS.
570 @retval EFI_NOT_FOUND Can not find the any more root bridge in
571 specific host bridge.
573 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
574 returned on a previous call to
580 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
581 IN OUT EFI_HANDLE
*RootBridgeHandle
584 BOOLEAN NoRootBridge
;
586 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
587 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
590 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
591 List
= HostBridgeInstance
->Head
.ForwardLink
;
594 while (List
!= &HostBridgeInstance
->Head
) {
595 NoRootBridge
= FALSE
;
596 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
597 if (*RootBridgeHandle
== NULL
) {
599 // Return the first Root Bridge Handle of the Host Bridge
601 *RootBridgeHandle
= RootBridgeInstance
->Handle
;
604 if (*RootBridgeHandle
== RootBridgeInstance
->Handle
) {
608 List
= List
->ForwardLink
;
609 if (List
!=&HostBridgeInstance
->Head
) {
610 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
611 *RootBridgeHandle
= RootBridgeInstance
->Handle
;
614 return EFI_NOT_FOUND
;
619 List
= List
->ForwardLink
;
623 return EFI_NOT_FOUND
;
625 return EFI_INVALID_PARAMETER
;
630 Returns the allocation attributes of a PCI root bridge.
632 The function returns the allocation attributes of a specific PCI root bridge.
633 The attributes can vary from one PCI root bridge to another. These attributes
634 are different from the decode-related attributes that are returned by the
635 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
636 RootBridgeHandle parameter is used to specify the instance of the PCI root
637 bridge. The device handles of all the root bridges that are associated with
638 this host bridge must be obtained by calling GetNextRootBridge(). The
639 attributes are static in the sense that they do not change during or after
640 the enumeration process. The hardware may provide mechanisms to change the
641 attributes on the fly, but such changes must be completed before
642 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
643 values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
644 "Related Definitions" below. The caller uses these attributes to combine
645 multiple resource requests.
647 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
648 bus enumerator needs to include requests for the prefetchable memory in the
649 nonprefetchable memory pool and not request any prefetchable memory.
651 Attribute Description
652 ------------------------------------ ---------------------------------------
653 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root
654 bridge does not support separate
655 windows for nonprefetchable and
656 prefetchable memory. A PCI bus driver
657 needs to include requests for
658 prefetchable memory in the
659 nonprefetchable memory pool.
661 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root
662 bridge supports 64-bit memory windows.
663 If this bit is not set, the PCI bus
664 driver needs to include requests for a
665 64-bit memory address in the
666 corresponding 32-bit memory pool.
668 @param[in] This The instance pointer of
669 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
671 @param[in] RootBridgeHandle The device handle of the PCI root bridge in
672 which the caller is interested. Type
673 EFI_HANDLE is defined in
674 InstallProtocolInterface() in the UEFI 2.0
677 @param[out] Attributes The pointer to attribte of root bridge, it is
680 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
682 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
684 @retval EFI_SUCCESS Success to get attribute of interested root
690 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
691 IN EFI_HANDLE RootBridgeHandle
,
692 OUT UINT64
*Attributes
696 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
697 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
699 if (Attributes
== NULL
) {
700 return EFI_INVALID_PARAMETER
;
703 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
704 List
= HostBridgeInstance
->Head
.ForwardLink
;
706 while (List
!= &HostBridgeInstance
->Head
) {
707 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
708 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
709 *Attributes
= RootBridgeInstance
->RootBridgeAttrib
;
712 List
= List
->ForwardLink
;
716 // RootBridgeHandle is not an EFI_HANDLE
717 // that was returned on a previous call to GetNextRootBridge()
719 return EFI_INVALID_PARAMETER
;
723 Sets up the specified PCI root bridge for the bus enumeration process.
725 This member function sets up the root bridge for bus enumeration and returns
726 the PCI bus range over which the search should be performed in ACPI 2.0
727 resource descriptor format.
730 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
733 @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
735 @param[out] Configuration Pointer to the pointer to the PCI bus resource
738 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
740 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
742 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
747 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
748 IN EFI_HANDLE RootBridgeHandle
,
749 OUT VOID
**Configuration
753 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
754 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
760 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
761 List
= HostBridgeInstance
->Head
.ForwardLink
;
763 while (List
!= &HostBridgeInstance
->Head
) {
764 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
765 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
767 // Set up the Root Bridge for Bus Enumeration
769 BusStart
= RootBridgeInstance
->BusBase
;
770 BusEnd
= RootBridgeInstance
->BusLimit
;
772 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
775 Buffer
= AllocatePool (
776 sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
777 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR
)
779 if (Buffer
== NULL
) {
780 return EFI_OUT_OF_RESOURCES
;
783 Temp
= (UINT8
*)Buffer
;
785 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->Desc
= 0x8A;
786 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->Len
= 0x2B;
787 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->ResType
= 2;
788 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->GenFlag
= 0;
789 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->SpecificFlag
= 0;
790 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrSpaceGranularity
= 0;
791 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrRangeMin
= BusStart
;
792 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrRangeMax
= 0;
793 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrTranslationOffset
= 0;
794 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrLen
=
795 BusEnd
- BusStart
+ 1;
797 Temp
= Temp
+ sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
798 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Desc
= 0x79;
799 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Checksum
= 0x0;
801 *Configuration
= Buffer
;
804 List
= List
->ForwardLink
;
807 return EFI_INVALID_PARAMETER
;
811 Programs the PCI root bridge hardware so that it decodes the specified PCI
814 This member function programs the specified PCI root bridge to decode the bus
815 range that is specified by the input parameter Configuration.
816 The bus range information is specified in terms of the ACPI 2.0 resource
820 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
823 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be
826 @param[in] Configuration The pointer to the PCI bus resource descriptor
828 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
831 @retval EFI_INVALID_PARAMETER Configuration is NULL.
833 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
834 2.0 resource descriptor.
836 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI
837 2.0 bus resource descriptor.
839 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource
840 descriptors other than bus descriptors.
842 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid
843 ACPI resource descriptors.
845 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this
848 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this
851 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
853 @retval EFI_SUCCESS The bus range for the PCI root bridge was
859 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
860 IN EFI_HANDLE RootBridgeHandle
,
861 IN VOID
*Configuration
865 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
866 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
872 if (Configuration
== NULL
) {
873 return EFI_INVALID_PARAMETER
;
879 // Check the Configuration is valid
881 if(*Ptr
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
882 return EFI_INVALID_PARAMETER
;
885 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Ptr
)->ResType
!= 2) {
886 return EFI_INVALID_PARAMETER
;
889 Ptr
+= sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
890 if (*Ptr
!= ACPI_END_TAG_DESCRIPTOR
) {
891 return EFI_INVALID_PARAMETER
;
894 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
895 List
= HostBridgeInstance
->Head
.ForwardLink
;
899 while (List
!= &HostBridgeInstance
->Head
) {
900 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
901 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
902 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
904 Desc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Ptr
;
905 BusStart
= (UINTN
)Desc
->AddrRangeMin
;
906 BusLen
= (UINTN
)Desc
->AddrLen
;
907 BusEnd
= BusStart
+ BusLen
- 1;
909 if (BusStart
> BusEnd
) {
910 return EFI_INVALID_PARAMETER
;
913 if ((BusStart
< RootBridgeInstance
->BusBase
) ||
914 (BusEnd
> RootBridgeInstance
->BusLimit
)) {
915 return EFI_INVALID_PARAMETER
;
919 // Update the Bus Range
921 RootBridgeInstance
->ResAllocNode
[TypeBus
].Base
= BusStart
;
922 RootBridgeInstance
->ResAllocNode
[TypeBus
].Length
= BusLen
;
923 RootBridgeInstance
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
926 // Program the Root Bridge Hardware
932 List
= List
->ForwardLink
;
935 return EFI_INVALID_PARAMETER
;
940 Submits the I/O and memory resource requirements for the specified PCI root
943 This function is used to submit all the I/O and memory resources that are
944 required by the specified PCI root bridge. The input parameter Configuration
945 is used to specify the following:
946 - The various types of resources that are required
947 - The associated lengths in terms of ACPI 2.0 resource descriptor format
949 @param[in] This Pointer to the
950 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
953 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory
954 resource requirements are being submitted.
956 @param[in] Configuration The pointer to the PCI I/O and PCI memory
959 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI
960 root bridge were accepted.
962 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
965 @retval EFI_INVALID_PARAMETER Configuration is NULL.
967 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
968 2.0 resource descriptor.
970 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or
971 more resource types that are not supported by
972 this PCI root bridge. This error will happen
973 if the caller did not combine resources
974 according to Attributes that were returned by
975 GetAllocAttributes().
977 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
979 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI
982 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for
983 this PCI root bridge.
988 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
989 IN EFI_HANDLE RootBridgeHandle
,
990 IN VOID
*Configuration
994 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
995 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
997 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1002 // Check the input parameter: Configuration
1004 if (Configuration
== NULL
) {
1005 return EFI_INVALID_PARAMETER
;
1008 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
1009 List
= HostBridgeInstance
->Head
.ForwardLink
;
1011 Temp
= (UINT8
*)Configuration
;
1012 while ( *Temp
== 0x8A) {
1013 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) ;
1015 if (*Temp
!= 0x79) {
1016 return EFI_INVALID_PARAMETER
;
1019 Temp
= (UINT8
*)Configuration
;
1020 while (List
!= &HostBridgeInstance
->Head
) {
1021 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
1022 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
1023 while ( *Temp
== 0x8A) {
1024 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1027 // Check Address Length
1029 if (Ptr
->AddrLen
> 0xffffffff) {
1030 return EFI_INVALID_PARAMETER
;
1034 // Check address range alignment
1036 if (Ptr
->AddrRangeMax
>= 0xffffffff ||
1037 Ptr
->AddrRangeMax
!= (GetPowerOfTwo64 (
1038 Ptr
->AddrRangeMax
+ 1) - 1)) {
1039 return EFI_INVALID_PARAMETER
;
1042 switch (Ptr
->ResType
) {
1047 // Check invalid Address Sapce Granularity
1049 if (Ptr
->AddrSpaceGranularity
!= 32) {
1050 return EFI_INVALID_PARAMETER
;
1054 // check the memory resource request is supported by PCI root bridge
1056 if (RootBridgeInstance
->RootBridgeAttrib
==
1057 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
&&
1058 Ptr
->SpecificFlag
== 0x06) {
1059 return EFI_INVALID_PARAMETER
;
1062 AddrLen
= Ptr
->AddrLen
;
1063 Alignment
= Ptr
->AddrRangeMax
;
1064 if (Ptr
->AddrSpaceGranularity
== 32) {
1065 if (Ptr
->SpecificFlag
== 0x06) {
1069 RootBridgeInstance
->ResAllocNode
[TypePMem32
].Status
=
1072 RootBridgeInstance
->ResAllocNode
[TypeMem32
].Length
= AddrLen
;
1073 RootBridgeInstance
->ResAllocNode
[TypeMem32
].Alignment
=
1075 RootBridgeInstance
->ResAllocNode
[TypeMem32
].Status
=
1077 HostBridgeInstance
->ResourceSubmited
= TRUE
;
1081 if (Ptr
->AddrSpaceGranularity
== 64) {
1082 if (Ptr
->SpecificFlag
== 0x06) {
1083 RootBridgeInstance
->ResAllocNode
[TypePMem64
].Status
=
1086 RootBridgeInstance
->ResAllocNode
[TypeMem64
].Status
=
1093 AddrLen
= (UINTN
) Ptr
->AddrLen
;
1094 Alignment
= (UINTN
) Ptr
->AddrRangeMax
;
1095 RootBridgeInstance
->ResAllocNode
[TypeIo
].Length
= AddrLen
;
1096 RootBridgeInstance
->ResAllocNode
[TypeIo
].Alignment
= Alignment
;
1097 RootBridgeInstance
->ResAllocNode
[TypeIo
].Status
= ResRequested
;
1098 HostBridgeInstance
->ResourceSubmited
= TRUE
;
1105 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) ;
1111 List
= List
->ForwardLink
;
1114 return EFI_INVALID_PARAMETER
;
1118 Returns the proposed resource settings for the specified PCI root bridge.
1120 This member function returns the proposed resource settings for the
1121 specified PCI root bridge. The proposed resource settings are prepared when
1122 NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
1123 The output parameter Configuration specifies the following:
1124 - The various types of resources, excluding bus resources, that are
1126 - The associated lengths in terms of ACPI 2.0 resource descriptor format
1128 @param[in] This Pointer to the
1129 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1132 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is
1133 defined in InstallProtocolInterface() in the
1134 UEFI 2.0 Specification.
1136 @param[out] Configuration The pointer to the pointer to the PCI I/O and
1137 memory resource descriptor.
1139 @retval EFI_SUCCESS The requested parameters were returned.
1141 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1144 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1146 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1151 GetProposedResources(
1152 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1153 IN EFI_HANDLE RootBridgeHandle
,
1154 OUT VOID
**Configuration
1158 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
1159 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
1164 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1170 // Get the Host Bridge Instance from the resource allocation protocol
1172 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
1173 List
= HostBridgeInstance
->Head
.ForwardLink
;
1176 // Enumerate the root bridges in this host bridge
1178 while (List
!= &HostBridgeInstance
->Head
) {
1179 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
1180 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
1181 for (Index
= 0; Index
< TypeBus
; Index
++) {
1182 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
!= ResNone
) {
1188 return EFI_INVALID_PARAMETER
;
1191 Buffer
= AllocateZeroPool (
1192 Number
* sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
1193 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR
)
1195 if (Buffer
== NULL
) {
1196 return EFI_OUT_OF_RESOURCES
;
1200 for (Index
= 0; Index
< TypeBus
; Index
++) {
1201 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
!= ResNone
) {
1202 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1203 ResStatus
= RootBridgeInstance
->ResAllocNode
[Index
].Status
;
1215 Ptr
->SpecificFlag
= 0;
1216 Ptr
->AddrRangeMin
= RootBridgeInstance
->ResAllocNode
[Index
].Base
;
1217 Ptr
->AddrRangeMax
= 0;
1218 Ptr
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ?
1219 EFI_RESOURCE_SATISFIED
:
1221 Ptr
->AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
1232 Ptr
->SpecificFlag
= 0;
1233 Ptr
->AddrSpaceGranularity
= 32;
1234 Ptr
->AddrRangeMin
= RootBridgeInstance
->ResAllocNode
[Index
].Base
;
1235 Ptr
->AddrRangeMax
= 0;
1236 Ptr
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ?
1237 EFI_RESOURCE_SATISFIED
:
1239 Ptr
->AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
1244 // Prefetch memory 32
1250 Ptr
->SpecificFlag
= 6;
1251 Ptr
->AddrSpaceGranularity
= 32;
1252 Ptr
->AddrRangeMin
= 0;
1253 Ptr
->AddrRangeMax
= 0;
1254 Ptr
->AddrTranslationOffset
= EFI_RESOURCE_NONEXISTENT
;
1266 Ptr
->SpecificFlag
= 0;
1267 Ptr
->AddrSpaceGranularity
= 64;
1268 Ptr
->AddrRangeMin
= 0;
1269 Ptr
->AddrRangeMax
= 0;
1270 Ptr
->AddrTranslationOffset
= EFI_RESOURCE_NONEXISTENT
;
1276 // Prefetch memory 64
1282 Ptr
->SpecificFlag
= 6;
1283 Ptr
->AddrSpaceGranularity
= 64;
1284 Ptr
->AddrRangeMin
= 0;
1285 Ptr
->AddrRangeMax
= 0;
1286 Ptr
->AddrTranslationOffset
= EFI_RESOURCE_NONEXISTENT
;
1291 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1295 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Desc
= 0x79;
1296 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Checksum
= 0x0;
1298 *Configuration
= Buffer
;
1303 List
= List
->ForwardLink
;
1306 return EFI_INVALID_PARAMETER
;
1310 Provides the hooks from the PCI bus driver to every PCI controller
1311 (device/function) at various stages of the PCI enumeration process that allow
1312 the host bridge driver to preinitialize individual PCI controllers before
1315 This function is called during the PCI enumeration process. No specific
1316 action is expected from this member function. It allows the host bridge
1317 driver to preinitialize individual PCI controllers before enumeration.
1319 @param This Pointer to the
1320 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1323 @param RootBridgeHandle The associated PCI root bridge handle. Type
1324 EFI_HANDLE is defined in InstallProtocolInterface()
1325 in the UEFI 2.0 Specification.
1327 @param PciAddress The address of the PCI device on the PCI bus. This
1328 address can be passed to the
1329 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
1330 access the PCI configuration space of the device.
1331 See Table 12-1 in the UEFI 2.0 Specification for the
1333 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
1335 @param Phase The phase of the PCI device enumeration.
1337 @retval EFI_SUCCESS The requested parameters were returned.
1339 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1342 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined
1344 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1346 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1347 The PCI enumerator should not enumerate this
1348 device, including its child devices if it is
1349 a PCI-to-PCI bridge.
1353 PreprocessController (
1354 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1355 IN EFI_HANDLE RootBridgeHandle
,
1356 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1357 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1360 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
1361 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
1364 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
1365 List
= HostBridgeInstance
->Head
.ForwardLink
;
1368 // Enumerate the root bridges in this host bridge
1370 while (List
!= &HostBridgeInstance
->Head
) {
1371 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
1372 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
1375 List
= List
->ForwardLink
;
1377 if (List
== &HostBridgeInstance
->Head
) {
1378 return EFI_INVALID_PARAMETER
;
1381 if ((UINT32
)Phase
> EfiPciBeforeResourceCollection
) {
1382 return EFI_INVALID_PARAMETER
;