2 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation
4 Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are
6 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.
15 #include "PciHostBridge.h"
18 // Hard code: Root Bridge Number within the host bridge
19 // Root Bridge's attribute
20 // Root Bridge's device path
21 // Root Bridge's resource appeture
23 UINTN RootBridgeNumber
[1] = { 1 };
25 UINT64 RootBridgeAttribute
[1][1] = { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
};
27 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath
[1][1] = {
31 (UINT8
) (sizeof(ACPI_HID_DEVICE_PATH
)),
32 (UINT8
) ((sizeof(ACPI_HID_DEVICE_PATH
)) >> 8),
36 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
37 END_DEVICE_PATH_LENGTH
,
42 PCI_ROOT_BRIDGE_RESOURCE_APPETURE mResAppeture
[1][1] = {
43 {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
46 EFI_HANDLE mDriverImageHandle
;
48 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate
= {
49 PCI_HOST_BRIDGE_SIGNATURE
, // Signature
50 NULL
, // HostBridgeHandle
51 0, // RootBridgeNumber
53 FALSE
, // ResourceSubiteed
71 Entry point of this driver
73 @param ImageHandle Handle of driver image
74 @param SystemTable Point to EFI_SYSTEM_TABLE
76 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
77 @retval EFI_DEVICE_ERROR Can not install the protocol instance
78 @retval EFI_SUCCESS Success to initialize the Pci host bridge.
82 InitializePciHostBridge (
83 IN EFI_HANDLE ImageHandle
,
84 IN EFI_SYSTEM_TABLE
*SystemTable
90 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
91 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
93 mDriverImageHandle
= ImageHandle
;
96 // Create Host Bridge Device Handle
98 for (Loop1
= 0; Loop1
< HOST_BRIDGE_NUMBER
; Loop1
++) {
99 HostBridge
= AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE
), &mPciHostBridgeInstanceTemplate
);
100 if (HostBridge
== NULL
) {
101 return EFI_OUT_OF_RESOURCES
;
104 HostBridge
->RootBridgeNumber
= RootBridgeNumber
[Loop1
];
105 InitializeListHead (&HostBridge
->Head
);
107 Status
= gBS
->InstallMultipleProtocolInterfaces (
108 &HostBridge
->HostBridgeHandle
,
109 &gEfiPciHostBridgeResourceAllocationProtocolGuid
, &HostBridge
->ResAlloc
,
112 if (EFI_ERROR (Status
)) {
113 FreePool (HostBridge
);
114 return EFI_DEVICE_ERROR
;
118 // Create Root Bridge Device Handle in this Host Bridge
121 for (Loop2
= 0; Loop2
< HostBridge
->RootBridgeNumber
; Loop2
++) {
122 PrivateData
= AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE
));
123 if (PrivateData
== NULL
) {
124 return EFI_OUT_OF_RESOURCES
;
127 PrivateData
->Signature
= PCI_ROOT_BRIDGE_SIGNATURE
;
128 PrivateData
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)&mEfiPciRootBridgeDevicePath
[Loop1
][Loop2
];
130 RootBridgeConstructor (
132 HostBridge
->HostBridgeHandle
,
133 RootBridgeAttribute
[Loop1
][Loop2
],
134 &mResAppeture
[Loop1
][Loop2
]
137 Status
= gBS
->InstallMultipleProtocolInterfaces(
138 &PrivateData
->Handle
,
139 &gEfiDevicePathProtocolGuid
, PrivateData
->DevicePath
,
140 &gEfiPciRootBridgeIoProtocolGuid
, &PrivateData
->Io
,
143 if (EFI_ERROR (Status
)) {
144 FreePool(PrivateData
);
145 return EFI_DEVICE_ERROR
;
148 InsertTailList (&HostBridge
->Head
, &PrivateData
->Link
);
157 These are the notifications from the PCI bus driver that it is about to enter a certain
158 phase of the PCI enumeration process.
160 This member function can be used to notify the host bridge driver to perform specific actions,
161 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
162 Eight notification points are defined at this time. See belows:
163 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
164 structures. The PCI enumerator should issue this notification
165 before starting a fresh enumeration process. Enumeration cannot
166 be restarted after sending any other notification such as
167 EfiPciHostBridgeBeginBusAllocation.
168 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
169 required here. This notification can be used to perform any
170 chipset-specific programming.
171 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
172 specific action is required here. This notification can be used to
173 perform any chipset-specific programming.
174 EfiPciHostBridgeBeginResourceAllocation
175 The resource allocation phase is about to begin. No specific
176 action is required here. This notification can be used to perform
177 any chipset-specific programming.
178 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
179 root bridges. These resource settings are returned on the next call to
180 GetProposedResources(). Before calling NotifyPhase() with a Phase of
181 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
182 for gathering I/O and memory requests for
183 all the PCI root bridges and submitting these requests using
184 SubmitResources(). This function pads the resource amount
185 to suit the root bridge hardware, takes care of dependencies between
186 the PCI root bridges, and calls the Global Coherency Domain (GCD)
187 with the allocation request. In the case of padding, the allocated range
188 could be bigger than what was requested.
189 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
190 resources (proposed resources) for all the PCI root bridges. After the
191 hardware is programmed, reassigning resources will not be supported.
192 The bus settings are not affected.
193 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
194 root bridges and resets the I/O and memory apertures to their initial
195 state. The bus settings are not affected. If the request to allocate
196 resources fails, the PCI enumerator can use this notification to
197 deallocate previous resources, adjust the requests, and retry
199 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
200 required here. This notification can be used to perform any chipsetspecific
203 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
204 @param[in] Phase The phase during enumeration
206 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
207 is valid for a Phase of EfiPciHostBridgeAllocateResources if
208 SubmitResources() has not been called for one or more
209 PCI root bridges before this call
210 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
211 for a Phase of EfiPciHostBridgeSetResources.
212 @retval EFI_INVALID_PARAMETER Invalid phase parameter
213 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
214 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
215 previously submitted resource requests cannot be fulfilled or
216 were only partially fulfilled.
217 @retval EFI_SUCCESS The notification was accepted without any errors.
223 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
224 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
227 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
228 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
229 PCI_RESOURCE_TYPE Index
;
231 EFI_PHYSICAL_ADDRESS BaseAddress
;
233 UINTN BitsOfAlignment
;
235 EFI_STATUS ReturnStatus
;
237 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
241 case EfiPciHostBridgeBeginEnumeration
:
242 if (HostBridgeInstance
->CanRestarted
) {
244 // Reset the Each Root Bridge
246 List
= HostBridgeInstance
->Head
.ForwardLink
;
248 while (List
!= &HostBridgeInstance
->Head
) {
249 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
250 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
251 RootBridgeInstance
->ResAllocNode
[Index
].Type
= Index
;
252 RootBridgeInstance
->ResAllocNode
[Index
].Base
= 0;
253 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
254 RootBridgeInstance
->ResAllocNode
[Index
].Status
= ResNone
;
257 List
= List
->ForwardLink
;
260 HostBridgeInstance
->ResourceSubmited
= FALSE
;
261 HostBridgeInstance
->CanRestarted
= TRUE
;
266 return EFI_NOT_READY
;
270 case EfiPciHostBridgeBeginBusAllocation
:
272 // No specific action is required here, can perform any chipset specific programing
274 HostBridgeInstance
->CanRestarted
= FALSE
;
278 case EfiPciHostBridgeEndBusAllocation
:
280 // No specific action is required here, can perform any chipset specific programing
282 //HostBridgeInstance->CanRestarted = FALSE;
286 case EfiPciHostBridgeBeginResourceAllocation
:
288 // No specific action is required here, can perform any chipset specific programing
290 //HostBridgeInstance->CanRestarted = FALSE;
294 case EfiPciHostBridgeAllocateResources
:
295 ReturnStatus
= EFI_SUCCESS
;
296 if (HostBridgeInstance
->ResourceSubmited
) {
298 // Take care of the resource dependencies between the root bridges
300 List
= HostBridgeInstance
->Head
.ForwardLink
;
302 while (List
!= &HostBridgeInstance
->Head
) {
303 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
304 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
305 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
!= ResNone
) {
307 AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
310 // Get the number of '1' in Alignment.
312 BitsOfAlignment
= HighBitSet64 (RootBridgeInstance
->ResAllocNode
[Index
].Alignment
) + 1;
318 // It is impossible for this chipset to align 0xFFFF for IO16
321 if (BitsOfAlignment
>= 16) {
325 Status
= gDS
->AllocateIoSpace (
326 EfiGcdAllocateAnySearchBottomUp
,
335 if (!EFI_ERROR (Status
)) {
336 RootBridgeInstance
->ResAllocNode
[Index
].Base
= (UINTN
)BaseAddress
;
337 RootBridgeInstance
->ResAllocNode
[Index
].Status
= ResAllocated
;
339 ReturnStatus
= Status
;
340 if (Status
!= EFI_OUT_OF_RESOURCES
) {
341 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
350 // It is impossible for this chipset to align 0xFFFFFFFF for Mem32
354 if (BitsOfAlignment
>= 32) {
358 Status
= gDS
->AllocateMemorySpace (
359 EfiGcdAllocateAnySearchBottomUp
,
360 EfiGcdMemoryTypeMemoryMappedIo
,
368 if (!EFI_ERROR (Status
)) {
369 // We were able to allocate the PCI memory
370 RootBridgeInstance
->ResAllocNode
[Index
].Base
= (UINTN
)BaseAddress
;
371 RootBridgeInstance
->ResAllocNode
[Index
].Status
= ResAllocated
;
374 // Not able to allocate enough PCI memory
375 ReturnStatus
= Status
;
377 if (Status
!= EFI_OUT_OF_RESOURCES
) {
378 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
387 ReturnStatus
= EFI_ABORTED
;
396 List
= List
->ForwardLink
;
402 return EFI_NOT_READY
;
406 case EfiPciHostBridgeSetResources
:
409 case EfiPciHostBridgeFreeResources
:
410 ReturnStatus
= EFI_SUCCESS
;
411 List
= HostBridgeInstance
->Head
.ForwardLink
;
412 while (List
!= &HostBridgeInstance
->Head
) {
413 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
414 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
415 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
== ResAllocated
) {
416 AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
417 BaseAddress
= RootBridgeInstance
->ResAllocNode
[Index
].Base
;
421 Status
= gDS
->FreeIoSpace (BaseAddress
, AddrLen
);
422 if (EFI_ERROR (Status
)) {
423 ReturnStatus
= Status
;
428 Status
= gDS
->FreeMemorySpace (BaseAddress
, AddrLen
);
429 if (EFI_ERROR (Status
)) {
430 ReturnStatus
= Status
;
448 RootBridgeInstance
->ResAllocNode
[Index
].Type
= Index
;
449 RootBridgeInstance
->ResAllocNode
[Index
].Base
= 0;
450 RootBridgeInstance
->ResAllocNode
[Index
].Length
= 0;
451 RootBridgeInstance
->ResAllocNode
[Index
].Status
= ResNone
;
455 List
= List
->ForwardLink
;
458 HostBridgeInstance
->ResourceSubmited
= FALSE
;
459 HostBridgeInstance
->CanRestarted
= TRUE
;
463 case EfiPciHostBridgeEndResourceAllocation
:
464 HostBridgeInstance
->CanRestarted
= FALSE
;
468 return EFI_INVALID_PARAMETER
;
475 Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
477 This function is called multiple times to retrieve the device handles of all the PCI root bridges that
478 are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
479 root bridges. On each call, the handle that was returned by the previous call is passed into the
480 interface, and on output the interface returns the device handle of the next PCI root bridge. The
481 caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
482 for that root bridge. When there are no more PCI root bridges to report, the interface returns
483 EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
484 are returned by this function.
485 For D945 implementation, there is only one root bridge in PCI host bridge.
487 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
488 @param[in][out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
490 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
491 specific Host bridge and return EFI_SUCCESS.
492 @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
493 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
494 returned on a previous call to GetNextRootBridge().
499 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
500 IN OUT EFI_HANDLE
*RootBridgeHandle
503 BOOLEAN NoRootBridge
;
505 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
506 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
509 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
510 List
= HostBridgeInstance
->Head
.ForwardLink
;
513 while (List
!= &HostBridgeInstance
->Head
) {
514 NoRootBridge
= FALSE
;
515 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
516 if (*RootBridgeHandle
== NULL
) {
518 // Return the first Root Bridge Handle of the Host Bridge
520 *RootBridgeHandle
= RootBridgeInstance
->Handle
;
523 if (*RootBridgeHandle
== RootBridgeInstance
->Handle
) {
527 List
= List
->ForwardLink
;
528 if (List
!=&HostBridgeInstance
->Head
) {
529 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
530 *RootBridgeHandle
= RootBridgeInstance
->Handle
;
533 return EFI_NOT_FOUND
;
538 List
= List
->ForwardLink
;
542 return EFI_NOT_FOUND
;
544 return EFI_INVALID_PARAMETER
;
549 Returns the allocation attributes of a PCI root bridge.
551 The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
552 from one PCI root bridge to another. These attributes are different from the decode-related
553 attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
554 RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
555 handles of all the root bridges that are associated with this host bridge must be obtained by calling
556 GetNextRootBridge(). The attributes are static in the sense that they do not change during or
557 after the enumeration process. The hardware may provide mechanisms to change the attributes on
558 the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
559 installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
560 "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
561 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
562 include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
564 Attribute Description
565 ------------------------------------ ----------------------------------------------------------------------
566 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
567 windows for nonprefetchable and prefetchable memory. A PCI bus
568 driver needs to include requests for prefetchable memory in the
569 nonprefetchable memory pool.
571 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
572 windows. If this bit is not set, the PCI bus driver needs to include
573 requests for a 64-bit memory address in the corresponding 32-bit
576 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
577 @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
578 EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
579 @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
581 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
582 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
583 @retval EFI_SUCCESS Success to get attribute of interested root bridge.
589 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
590 IN EFI_HANDLE RootBridgeHandle
,
591 OUT UINT64
*Attributes
595 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
596 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
598 if (Attributes
== NULL
) {
599 return EFI_INVALID_PARAMETER
;
602 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
603 List
= HostBridgeInstance
->Head
.ForwardLink
;
605 while (List
!= &HostBridgeInstance
->Head
) {
606 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
607 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
608 *Attributes
= RootBridgeInstance
->RootBridgeAttrib
;
611 List
= List
->ForwardLink
;
615 // RootBridgeHandle is not an EFI_HANDLE
616 // that was returned on a previous call to GetNextRootBridge()
618 return EFI_INVALID_PARAMETER
;
622 Sets up the specified PCI root bridge for the bus enumeration process.
624 This member function sets up the root bridge for bus enumeration and returns the PCI bus range
625 over which the search should be performed in ACPI 2.0 resource descriptor format.
627 @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
628 @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
629 @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
631 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
632 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
633 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
639 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
640 IN EFI_HANDLE RootBridgeHandle
,
641 OUT VOID
**Configuration
645 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
646 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
652 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
653 List
= HostBridgeInstance
->Head
.ForwardLink
;
655 while (List
!= &HostBridgeInstance
->Head
) {
656 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
657 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
659 // Set up the Root Bridge for Bus Enumeration
661 BusStart
= RootBridgeInstance
->BusBase
;
662 BusEnd
= RootBridgeInstance
->BusLimit
;
664 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
667 Buffer
= AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR
));
668 if (Buffer
== NULL
) {
669 return EFI_OUT_OF_RESOURCES
;
672 Temp
= (UINT8
*)Buffer
;
674 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->Desc
= 0x8A;
675 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->Len
= 0x2B;
676 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->ResType
= 2;
677 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->GenFlag
= 0;
678 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->SpecificFlag
= 0;
679 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrSpaceGranularity
= 0;
680 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrRangeMin
= BusStart
;
681 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrRangeMax
= 0;
682 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrTranslationOffset
= 0;
683 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Temp
)->AddrLen
= BusEnd
- BusStart
+ 1;
685 Temp
= Temp
+ sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
686 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Desc
= 0x79;
687 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Checksum
= 0x0;
689 *Configuration
= Buffer
;
692 List
= List
->ForwardLink
;
695 return EFI_INVALID_PARAMETER
;
699 Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
701 This member function programs the specified PCI root bridge to decode the bus range that is
702 specified by the input parameter Configuration.
703 The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
705 @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
706 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
707 @param[in] Configuration The pointer to the PCI bus resource descriptor
709 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
710 @retval EFI_INVALID_PARAMETER Configuration is NULL.
711 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
712 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
713 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
715 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
716 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
717 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
718 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
719 @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
725 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
726 IN EFI_HANDLE RootBridgeHandle
,
727 IN VOID
*Configuration
731 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
732 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
738 if (Configuration
== NULL
) {
739 return EFI_INVALID_PARAMETER
;
745 // Check the Configuration is valid
747 if(*Ptr
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
748 return EFI_INVALID_PARAMETER
;
751 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Ptr
)->ResType
!= 2) {
752 return EFI_INVALID_PARAMETER
;
755 Ptr
+= sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
756 if (*Ptr
!= ACPI_END_TAG_DESCRIPTOR
) {
757 return EFI_INVALID_PARAMETER
;
760 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
761 List
= HostBridgeInstance
->Head
.ForwardLink
;
765 while (List
!= &HostBridgeInstance
->Head
) {
766 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
767 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
768 BusStart
= (UINTN
)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Ptr
)->AddrRangeMin
;
769 BusLen
= (UINTN
)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Ptr
)->AddrLen
;
770 BusEnd
= BusStart
+ BusLen
- 1;
772 if (BusStart
> BusEnd
) {
773 return EFI_INVALID_PARAMETER
;
776 if ((BusStart
< RootBridgeInstance
->BusBase
) || (BusEnd
> RootBridgeInstance
->BusLimit
)) {
777 return EFI_INVALID_PARAMETER
;
781 // Update the Bus Range
783 RootBridgeInstance
->ResAllocNode
[TypeBus
].Base
= BusStart
;
784 RootBridgeInstance
->ResAllocNode
[TypeBus
].Length
= BusLen
;
785 RootBridgeInstance
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
788 // Program the Root Bridge Hardware
794 List
= List
->ForwardLink
;
797 return EFI_INVALID_PARAMETER
;
802 Submits the I/O and memory resource requirements for the specified PCI root bridge.
804 This function is used to submit all the I/O and memory resources that are required by the specified
805 PCI root bridge. The input parameter Configuration is used to specify the following:
806 - The various types of resources that are required
807 - The associated lengths in terms of ACPI 2.0 resource descriptor format
809 @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
810 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
811 @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
813 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
814 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
815 @retval EFI_INVALID_PARAMETER Configuration is NULL.
816 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
817 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
818 not supported by this PCI root bridge. This error will happen if the caller
819 did not combine resources according to Attributes that were returned by
820 GetAllocAttributes().
821 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
822 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
823 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
829 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
830 IN EFI_HANDLE RootBridgeHandle
,
831 IN VOID
*Configuration
835 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
836 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
838 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ptr
;
843 // Check the input parameter: Configuration
845 if (Configuration
== NULL
) {
846 return EFI_INVALID_PARAMETER
;
849 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
850 List
= HostBridgeInstance
->Head
.ForwardLink
;
852 Temp
= (UINT8
*)Configuration
;
853 while ( *Temp
== 0x8A) {
854 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) ;
857 return EFI_INVALID_PARAMETER
;
860 Temp
= (UINT8
*)Configuration
;
861 while (List
!= &HostBridgeInstance
->Head
) {
862 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
863 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
864 while ( *Temp
== 0x8A) {
865 ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
868 // Check Address Length
870 if (ptr
->AddrLen
> 0xffffffff) {
871 return EFI_INVALID_PARAMETER
;
875 // Check address range alignment
877 if (ptr
->AddrRangeMax
>= 0xffffffff || ptr
->AddrRangeMax
!= (GetPowerOfTwo64 (ptr
->AddrRangeMax
+ 1) - 1)) {
878 return EFI_INVALID_PARAMETER
;
881 switch (ptr
->ResType
) {
886 // Check invalid Address Sapce Granularity
888 if (ptr
->AddrSpaceGranularity
!= 32) {
889 return EFI_INVALID_PARAMETER
;
893 // check the memory resource request is supported by PCI root bridge
895 if (RootBridgeInstance
->RootBridgeAttrib
== EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
&&
896 ptr
->SpecificFlag
== 0x06) {
897 return EFI_INVALID_PARAMETER
;
900 AddrLen
= ptr
->AddrLen
;
901 Alignment
= ptr
->AddrRangeMax
;
902 if (ptr
->AddrSpaceGranularity
== 32) {
903 if (ptr
->SpecificFlag
== 0x06) {
907 RootBridgeInstance
->ResAllocNode
[TypePMem32
].Status
= ResSubmitted
;
909 RootBridgeInstance
->ResAllocNode
[TypeMem32
].Length
= AddrLen
;
910 RootBridgeInstance
->ResAllocNode
[TypeMem32
].Alignment
= Alignment
;
911 RootBridgeInstance
->ResAllocNode
[TypeMem32
].Status
= ResRequested
;
912 HostBridgeInstance
->ResourceSubmited
= TRUE
;
916 if (ptr
->AddrSpaceGranularity
== 64) {
917 if (ptr
->SpecificFlag
== 0x06) {
918 RootBridgeInstance
->ResAllocNode
[TypePMem64
].Status
= ResSubmitted
;
920 RootBridgeInstance
->ResAllocNode
[TypeMem64
].Status
= ResSubmitted
;
926 AddrLen
= (UINTN
)ptr
->AddrLen
;
927 Alignment
= (UINTN
)ptr
->AddrRangeMax
;
928 RootBridgeInstance
->ResAllocNode
[TypeIo
].Length
= AddrLen
;
929 RootBridgeInstance
->ResAllocNode
[TypeIo
].Alignment
= Alignment
;
930 RootBridgeInstance
->ResAllocNode
[TypeIo
].Status
= ResRequested
;
931 HostBridgeInstance
->ResourceSubmited
= TRUE
;
938 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) ;
944 List
= List
->ForwardLink
;
947 return EFI_INVALID_PARAMETER
;
951 Returns the proposed resource settings for the specified PCI root bridge.
953 This member function returns the proposed resource settings for the specified PCI root bridge. The
954 proposed resource settings are prepared when NotifyPhase() is called with a Phase of
955 EfiPciHostBridgeAllocateResources. The output parameter Configuration
956 specifies the following:
957 - The various types of resources, excluding bus resources, that are allocated
958 - The associated lengths in terms of ACPI 2.0 resource descriptor format
960 @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
961 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
962 @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
964 @retval EFI_SUCCESS The requested parameters were returned.
965 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
966 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
967 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
972 GetProposedResources(
973 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
974 IN EFI_HANDLE RootBridgeHandle
,
975 OUT VOID
**Configuration
979 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
980 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
985 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ptr
;
991 // Get the Host Bridge Instance from the resource allocation protocol
993 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
994 List
= HostBridgeInstance
->Head
.ForwardLink
;
997 // Enumerate the root bridges in this host bridge
999 while (List
!= &HostBridgeInstance
->Head
) {
1000 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
1001 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
1002 for (Index
= 0; Index
< TypeBus
; Index
++) {
1003 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
!= ResNone
) {
1009 return EFI_INVALID_PARAMETER
;
1012 Buffer
= AllocateZeroPool (Number
* sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR
));
1013 if (Buffer
== NULL
) {
1014 return EFI_OUT_OF_RESOURCES
;
1018 for (Index
= 0; Index
< TypeBus
; Index
++) {
1019 if (RootBridgeInstance
->ResAllocNode
[Index
].Status
!= ResNone
) {
1020 ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1021 ResStatus
= RootBridgeInstance
->ResAllocNode
[Index
].Status
;
1033 ptr
->SpecificFlag
= 0;
1034 ptr
->AddrRangeMin
= RootBridgeInstance
->ResAllocNode
[Index
].Base
;
1035 ptr
->AddrRangeMax
= 0;
1036 ptr
->AddrTranslationOffset
= \
1037 (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: EFI_RESOURCE_LESS
;
1038 ptr
->AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
1049 ptr
->SpecificFlag
= 0;
1050 ptr
->AddrSpaceGranularity
= 32;
1051 ptr
->AddrRangeMin
= RootBridgeInstance
->ResAllocNode
[Index
].Base
;
1052 ptr
->AddrRangeMax
= 0;
1053 ptr
->AddrTranslationOffset
= \
1054 (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: EFI_RESOURCE_LESS
;
1055 ptr
->AddrLen
= RootBridgeInstance
->ResAllocNode
[Index
].Length
;
1060 // Prefetch memory 32
1066 ptr
->SpecificFlag
= 6;
1067 ptr
->AddrSpaceGranularity
= 32;
1068 ptr
->AddrRangeMin
= 0;
1069 ptr
->AddrRangeMax
= 0;
1070 ptr
->AddrTranslationOffset
= EFI_RESOURCE_NONEXISTENT
;
1082 ptr
->SpecificFlag
= 0;
1083 ptr
->AddrSpaceGranularity
= 64;
1084 ptr
->AddrRangeMin
= 0;
1085 ptr
->AddrRangeMax
= 0;
1086 ptr
->AddrTranslationOffset
= EFI_RESOURCE_NONEXISTENT
;
1092 // Prefetch memory 64
1098 ptr
->SpecificFlag
= 6;
1099 ptr
->AddrSpaceGranularity
= 64;
1100 ptr
->AddrRangeMin
= 0;
1101 ptr
->AddrRangeMax
= 0;
1102 ptr
->AddrTranslationOffset
= EFI_RESOURCE_NONEXISTENT
;
1107 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1111 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Desc
= 0x79;
1112 ((EFI_ACPI_END_TAG_DESCRIPTOR
*)Temp
)->Checksum
= 0x0;
1114 *Configuration
= Buffer
;
1119 List
= List
->ForwardLink
;
1122 return EFI_INVALID_PARAMETER
;
1126 Update attribute for PCI root bridge for specifc device.
1128 @param RootBridge Point to PCI root bridge.
1129 @param PciAddress The specific device PCI address
1133 UpdateRootBridgeAttributes (
1134 IN PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
,
1135 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
1139 PCI_TYPE01 PciConfigurationHeader
;
1143 // Read the PCI Configuration Header for the device
1145 Status
= RootBridge
->Io
.Pci
.Read (
1151 PciAddress
.Function
,
1154 sizeof (PciConfigurationHeader
) / sizeof (UINT16
),
1155 &PciConfigurationHeader
1157 if (EFI_ERROR (Status
)) {
1161 Attributes
= RootBridge
->Attributes
;
1164 // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
1166 if (PciConfigurationHeader
.Hdr
.Command
& 0x20) {
1167 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
1171 // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
1173 if (IS_PCI_BRIDGE(&PciConfigurationHeader
)) {
1175 // Look at the PPB Configuration for legacy decoding attributes
1177 if (PciConfigurationHeader
.Bridge
.BridgeControl
& 0x04) {
1178 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
1179 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
1181 if (PciConfigurationHeader
.Bridge
.BridgeControl
& 0x08) {
1182 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
1183 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
1184 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
1188 // See if the PCI device is an IDE controller
1190 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x01 &&
1191 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ) {
1192 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x80) {
1193 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
1194 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
1196 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x01) {
1197 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
1199 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x04) {
1200 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
1205 // See if the PCI device is a legacy VGA controller
1207 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x00 &&
1208 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ) {
1209 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
1210 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
1211 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
1215 // See if the PCI device is a standard VGA controller
1217 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x03 &&
1218 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x00 ) {
1219 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
1220 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
1221 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
1225 RootBridge
->Attributes
= Attributes
;
1226 RootBridge
->Supports
= Attributes
;
1230 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1231 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1232 PCI controllers before enumeration.
1234 This function is called during the PCI enumeration process. No specific action is expected from this
1235 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1238 @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1239 @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
1240 InstallProtocolInterface() in the UEFI 2.0 Specification.
1241 @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
1242 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
1243 configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
1244 the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
1245 @param Phase The phase of the PCI device enumeration.
1247 @retval EFI_SUCCESS The requested parameters were returned.
1248 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1249 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1250 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1251 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1252 not enumerate this device, including its child devices if it is a PCI-to-PCI
1258 PreprocessController (
1259 IN
struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1260 IN EFI_HANDLE RootBridgeHandle
,
1261 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1262 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1265 PCI_HOST_BRIDGE_INSTANCE
*HostBridgeInstance
;
1266 PCI_ROOT_BRIDGE_INSTANCE
*RootBridgeInstance
;
1269 HostBridgeInstance
= INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This
);
1270 List
= HostBridgeInstance
->Head
.ForwardLink
;
1273 // Enumerate the root bridges in this host bridge
1275 while (List
!= &HostBridgeInstance
->Head
) {
1276 RootBridgeInstance
= DRIVER_INSTANCE_FROM_LIST_ENTRY (List
);
1277 if (RootBridgeHandle
== RootBridgeInstance
->Handle
) {
1278 UpdateRootBridgeAttributes (
1284 List
= List
->ForwardLink
;
1287 return EFI_INVALID_PARAMETER
;