blob: aa02641d8ae8346d919f5f22db092acea5f2e2b5 [file] [log] [blame]
jljusten21b404d2009-05-27 21:09:52 +00001/** @file
Laszlo Ersek7c7af552015-07-14 12:01:16 +00002 Provides the basic interfaces to abstract a PCI Host Bridge Resource
3 Allocation
jljusten21b404d2009-05-27 21:09:52 +00004
Laszlo Ersek7c7af552015-07-14 12:01:16 +00005 Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
klu218c97f52010-04-12 04:38:44 +00006
Laszlo Ersek7c7af552015-07-14 12:01:16 +00007 This program and the accompanying materials are licensed and made available
8 under the terms and conditions of the BSD License which accompanies this
9 distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
jljusten21b404d2009-05-27 21:09:52 +000011
Laszlo Ersek7c7af552015-07-14 12:01:16 +000012 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15**/
jljusten21b404d2009-05-27 21:09:52 +000016
17#include "PciHostBridge.h"
18
19//
jljusten21b404d2009-05-27 21:09:52 +000020// Hard code: Root Bridge Number within the host bridge
21// Root Bridge's attribute
22// Root Bridge's device path
Laszlo Ersek0b7c6cd2015-02-23 16:02:34 +000023// Root Bridge's resource aperture
jljusten21b404d2009-05-27 21:09:52 +000024//
25UINTN RootBridgeNumber[1] = { 1 };
26
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +000027UINT64 RootBridgeAttribute[1][1] = {
28 { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM }
29};
jljusten21b404d2009-05-27 21:09:52 +000030
31EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
32 {
lzeng14ce68d3b2012-10-11 02:15:23 +000033 {
34 {
35 {
36 ACPI_DEVICE_PATH,
37 ACPI_DP,
38 {
39 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
40 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
41 }
42 },
43 EISA_PNP_ID(0x0A03),
44 0
45 },
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +000046
lzeng14ce68d3b2012-10-11 02:15:23 +000047 {
48 END_DEVICE_PATH_TYPE,
49 END_ENTIRE_DEVICE_PATH_SUBTYPE,
50 {
51 END_DEVICE_PATH_LENGTH,
52 0
53 }
54 }
55 }
jljusten21b404d2009-05-27 21:09:52 +000056 }
57};
58
Laszlo Ersek0b7c6cd2015-02-23 16:02:34 +000059PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1][1] = {
lzeng14ce68d3b2012-10-11 02:15:23 +000060 {{0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}}
jljusten21b404d2009-05-27 21:09:52 +000061};
62
63EFI_HANDLE mDriverImageHandle;
64
65PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
66 PCI_HOST_BRIDGE_SIGNATURE, // Signature
67 NULL, // HostBridgeHandle
68 0, // RootBridgeNumber
69 {NULL, NULL}, // Head
70 FALSE, // ResourceSubiteed
71 TRUE, // CanRestarted
72 {
73 NotifyPhase,
74 GetNextRootBridge,
75 GetAttributes,
76 StartBusEnumeration,
77 SetBusNumbers,
78 SubmitResources,
79 GetProposedResources,
80 PreprocessController
81 }
82};
83
84//
85// Implementation
86//
ydong1024115e42010-09-17 10:42:10 +000087
klu218c97f52010-04-12 04:38:44 +000088/**
89 Entry point of this driver
90
91 @param ImageHandle Handle of driver image
92 @param SystemTable Point to EFI_SYSTEM_TABLE
93
94 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
95 @retval EFI_DEVICE_ERROR Can not install the protocol instance
96 @retval EFI_SUCCESS Success to initialize the Pci host bridge.
97**/
jljusten21b404d2009-05-27 21:09:52 +000098EFI_STATUS
99EFIAPI
100InitializePciHostBridge (
101 IN EFI_HANDLE ImageHandle,
102 IN EFI_SYSTEM_TABLE *SystemTable
103 )
jljusten21b404d2009-05-27 21:09:52 +0000104{
105 EFI_STATUS Status;
106 UINTN Loop1;
107 UINTN Loop2;
108 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
109 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000110
jljusten21b404d2009-05-27 21:09:52 +0000111 mDriverImageHandle = ImageHandle;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000112
jljusten21b404d2009-05-27 21:09:52 +0000113 //
114 // Create Host Bridge Device Handle
115 //
116 for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000117 HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
118 &mPciHostBridgeInstanceTemplate);
jljusten21b404d2009-05-27 21:09:52 +0000119 if (HostBridge == NULL) {
120 return EFI_OUT_OF_RESOURCES;
121 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000122
jljusten21b404d2009-05-27 21:09:52 +0000123 HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
124 InitializeListHead (&HostBridge->Head);
125
126 Status = gBS->InstallMultipleProtocolInterfaces (
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000127 &HostBridge->HostBridgeHandle,
128 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
129 &HostBridge->ResAlloc,
jljusten21b404d2009-05-27 21:09:52 +0000130 NULL
131 );
132 if (EFI_ERROR (Status)) {
133 FreePool (HostBridge);
134 return EFI_DEVICE_ERROR;
135 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000136
jljusten21b404d2009-05-27 21:09:52 +0000137 //
138 // Create Root Bridge Device Handle in this Host Bridge
139 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000140
jljusten21b404d2009-05-27 21:09:52 +0000141 for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
142 PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
143 if (PrivateData == NULL) {
144 return EFI_OUT_OF_RESOURCES;
145 }
146
147 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000148 PrivateData->DevicePath =
149 (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
jljusten21b404d2009-05-27 21:09:52 +0000150
151 RootBridgeConstructor (
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000152 &PrivateData->Io,
153 HostBridge->HostBridgeHandle,
154 RootBridgeAttribute[Loop1][Loop2],
Laszlo Ersek0b7c6cd2015-02-23 16:02:34 +0000155 &mResAperture[Loop1][Loop2]
jljusten21b404d2009-05-27 21:09:52 +0000156 );
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000157
jljusten21b404d2009-05-27 21:09:52 +0000158 Status = gBS->InstallMultipleProtocolInterfaces(
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000159 &PrivateData->Handle,
160 &gEfiDevicePathProtocolGuid,
161 PrivateData->DevicePath,
162 &gEfiPciRootBridgeIoProtocolGuid,
163 &PrivateData->Io,
jljusten21b404d2009-05-27 21:09:52 +0000164 NULL
165 );
166 if (EFI_ERROR (Status)) {
167 FreePool(PrivateData);
168 return EFI_DEVICE_ERROR;
169 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000170
jljusten21b404d2009-05-27 21:09:52 +0000171 InsertTailList (&HostBridge->Head, &PrivateData->Link);
172 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000173 }
jljusten21b404d2009-05-27 21:09:52 +0000174
jljusten21b404d2009-05-27 21:09:52 +0000175 return EFI_SUCCESS;
176}
177
178
klu218c97f52010-04-12 04:38:44 +0000179/**
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000180 These are the notifications from the PCI bus driver that it is about to enter
181 a certain phase of the PCI enumeration process.
klu218c97f52010-04-12 04:38:44 +0000182
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000183 This member function can be used to notify the host bridge driver to perform
184 specific actions, including any chipset-specific initialization, so that the
185 chipset is ready to enter the next phase. Eight notification points are
186 defined at this time. See belows:
klu218c97f52010-04-12 04:38:44 +0000187
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000188 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures
189 and internal data structures. The PCI
190 enumerator should issue this
191 notification before starting a fresh
192 enumeration process. Enumeration
193 cannot be restarted after sending any
194 other notification such as
195 EfiPciHostBridgeBeginBusAllocation.
klu218c97f52010-04-12 04:38:44 +0000196
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000197 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to
198 begin. No specific action is required
199 here. This notification can be used to
200 perform any chipset-specific
201 programming.
klu218c97f52010-04-12 04:38:44 +0000202
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000203 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming
204 phase is complete. No specific action
205 is required here. This notification
206 can be used to perform any
207 chipset-specific programming.
208
209 EfiPciHostBridgeBeginResourceAllocation
210 The resource allocation phase is about
211 to begin. No specific action is
212 required here. This notification can
213 be used to perform any
214 chipset-specific programming.
215
216 EfiPciHostBridgeAllocateResources Allocates resources per previously
217 submitted requests for all the PCI
218 root bridges. These resource settings
219 are returned on the next call to
220 GetProposedResources(). Before calling
221 NotifyPhase() with a Phase of
222 EfiPciHostBridgeAllocateResource, the
223 PCI bus enumerator is responsible for
224 gathering I/O and memory requests for
225 all the PCI root bridges and
226 submitting these requests using
227 SubmitResources(). This function pads
228 the resource amount to suit the root
229 bridge hardware, takes care of
230 dependencies between the PCI root
231 bridges, and calls the Global
232 Coherency Domain (GCD) with the
233 allocation request. In the case of
234 padding, the allocated range could be
235 bigger than what was requested.
236
237 EfiPciHostBridgeSetResources Programs the host bridge hardware to
238 decode previously allocated resources
239 (proposed resources) for all the PCI
240 root bridges. After the hardware is
241 programmed, reassigning resources will
242 not be supported. The bus settings are
243 not affected.
244
245 EfiPciHostBridgeFreeResources Deallocates resources that were
246 previously allocated for all the PCI
247 root bridges and resets the I/O and
248 memory apertures to their initial
249 state. The bus settings are not
250 affected. If the request to allocate
251 resources fails, the PCI enumerator
252 can use this notification to
253 deallocate previous resources, adjust
254 the requests, and retry allocation.
255
256 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is
257 completed. No specific action is
258 required here. This notification can
259 be used to perform any chipsetspecific
260 programming.
261
262 @param[in] This The instance pointer of
263 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
264
265 @param[in] Phase The phase during enumeration
266
267 @retval EFI_NOT_READY This phase cannot be entered at this time. For
268 example, this error is valid for a Phase of
269 EfiPciHostBridgeAllocateResources if
270 SubmitResources() has not been called for one
271 or more PCI root bridges before this call
272
273 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
274 This error is valid for a Phase of
275 EfiPciHostBridgeSetResources.
276
277 @retval EFI_INVALID_PARAMETER Invalid phase parameter
278
279 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
280 lack of resources. This error is valid for a
281 Phase of EfiPciHostBridgeAllocateResources if
282 the previously submitted resource requests
283 cannot be fulfilled or were only partially
284 fulfilled.
285
286 @retval EFI_SUCCESS The notification was accepted without any
287 errors.
klu218c97f52010-04-12 04:38:44 +0000288**/
jljusten21b404d2009-05-27 21:09:52 +0000289EFI_STATUS
290EFIAPI
291NotifyPhase(
292 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
293 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
294 )
jljusten21b404d2009-05-27 21:09:52 +0000295{
296 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
297 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
298 PCI_RESOURCE_TYPE Index;
299 LIST_ENTRY *List;
300 EFI_PHYSICAL_ADDRESS BaseAddress;
301 UINT64 AddrLen;
302 UINTN BitsOfAlignment;
303 EFI_STATUS Status;
304 EFI_STATUS ReturnStatus;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000305
jljusten21b404d2009-05-27 21:09:52 +0000306 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000307
jljusten21b404d2009-05-27 21:09:52 +0000308 switch (Phase) {
309
310 case EfiPciHostBridgeBeginEnumeration:
311 if (HostBridgeInstance->CanRestarted) {
312 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000313 // Reset the Each Root Bridge
jljusten21b404d2009-05-27 21:09:52 +0000314 //
315 List = HostBridgeInstance->Head.ForwardLink;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000316
jljusten21b404d2009-05-27 21:09:52 +0000317 while (List != &HostBridgeInstance->Head) {
318 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
319 for (Index = TypeIo; Index < TypeMax; Index++) {
320 RootBridgeInstance->ResAllocNode[Index].Type = Index;
321 RootBridgeInstance->ResAllocNode[Index].Base = 0;
322 RootBridgeInstance->ResAllocNode[Index].Length = 0;
323 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
324 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000325
jljusten21b404d2009-05-27 21:09:52 +0000326 List = List->ForwardLink;
327 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000328
jljusten21b404d2009-05-27 21:09:52 +0000329 HostBridgeInstance->ResourceSubmited = FALSE;
330 HostBridgeInstance->CanRestarted = TRUE;
331 } else {
332 //
333 // Can not restart
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000334 //
jljusten21b404d2009-05-27 21:09:52 +0000335 return EFI_NOT_READY;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000336 }
jljusten21b404d2009-05-27 21:09:52 +0000337 break;
338
Ruiyu Nicfdb6732013-07-22 07:35:51 +0000339 case EfiPciHostBridgeEndEnumeration:
340 break;
341
jljusten21b404d2009-05-27 21:09:52 +0000342 case EfiPciHostBridgeBeginBusAllocation:
343 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000344 // No specific action is required here, can perform any chipset specific
345 // programing
jljusten21b404d2009-05-27 21:09:52 +0000346 //
347 HostBridgeInstance->CanRestarted = FALSE;
jljusten21b404d2009-05-27 21:09:52 +0000348 break;
349
350 case EfiPciHostBridgeEndBusAllocation:
351 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000352 // No specific action is required here, can perform any chipset specific
353 // programing
jljusten21b404d2009-05-27 21:09:52 +0000354 //
355 //HostBridgeInstance->CanRestarted = FALSE;
jljusten21b404d2009-05-27 21:09:52 +0000356 break;
357
358 case EfiPciHostBridgeBeginResourceAllocation:
359 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000360 // No specific action is required here, can perform any chipset specific
361 // programing
jljusten21b404d2009-05-27 21:09:52 +0000362 //
363 //HostBridgeInstance->CanRestarted = FALSE;
jljusten21b404d2009-05-27 21:09:52 +0000364 break;
365
366 case EfiPciHostBridgeAllocateResources:
367 ReturnStatus = EFI_SUCCESS;
368 if (HostBridgeInstance->ResourceSubmited) {
369 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000370 // Take care of the resource dependencies between the root bridges
jljusten21b404d2009-05-27 21:09:52 +0000371 //
372 List = HostBridgeInstance->Head.ForwardLink;
373
374 while (List != &HostBridgeInstance->Head) {
375 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
376 for (Index = TypeIo; Index < TypeBus; Index++) {
377 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000378
jljusten21b404d2009-05-27 21:09:52 +0000379 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000380
jljusten21b404d2009-05-27 21:09:52 +0000381 //
382 // Get the number of '1' in Alignment.
383 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000384 BitsOfAlignment =
385 (UINTN)(HighBitSet64 (
386 RootBridgeInstance->ResAllocNode[Index].Alignment
387 ) + 1);
388
jljusten21b404d2009-05-27 21:09:52 +0000389 switch (Index) {
390
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000391 case TypeIo:
jljusten21b404d2009-05-27 21:09:52 +0000392 //
393 // It is impossible for this chipset to align 0xFFFF for IO16
394 // So clear it
395 //
396 if (BitsOfAlignment >= 16) {
397 BitsOfAlignment = 0;
398 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000399
jljusten21b404d2009-05-27 21:09:52 +0000400 Status = gDS->AllocateIoSpace (
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000401 EfiGcdAllocateAnySearchBottomUp,
402 EfiGcdIoTypeIo,
jljusten21b404d2009-05-27 21:09:52 +0000403 BitsOfAlignment,
404 AddrLen,
405 &BaseAddress,
406 mDriverImageHandle,
407 NULL
408 );
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000409
jljusten21b404d2009-05-27 21:09:52 +0000410 if (!EFI_ERROR (Status)) {
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000411 RootBridgeInstance->ResAllocNode[Index].Base =
412 (UINTN)BaseAddress;
413 RootBridgeInstance->ResAllocNode[Index].Status =
414 ResAllocated;
jljusten21b404d2009-05-27 21:09:52 +0000415 } else {
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000416 ReturnStatus = Status;
jljusten21b404d2009-05-27 21:09:52 +0000417 if (Status != EFI_OUT_OF_RESOURCES) {
418 RootBridgeInstance->ResAllocNode[Index].Length = 0;
419 }
420 }
421
422 break;
423
424
425 case TypeMem32:
426 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000427 // It is impossible for this chipset to align 0xFFFFFFFF for
428 // Mem32
429 // So clear it
jljusten21b404d2009-05-27 21:09:52 +0000430 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000431
jljusten21b404d2009-05-27 21:09:52 +0000432 if (BitsOfAlignment >= 32) {
433 BitsOfAlignment = 0;
434 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000435
jljusten21b404d2009-05-27 21:09:52 +0000436 Status = gDS->AllocateMemorySpace (
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000437 EfiGcdAllocateAnySearchBottomUp,
438 EfiGcdMemoryTypeMemoryMappedIo,
jljusten21b404d2009-05-27 21:09:52 +0000439 BitsOfAlignment,
440 AddrLen,
441 &BaseAddress,
442 mDriverImageHandle,
443 NULL
444 );
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000445
jljusten21b404d2009-05-27 21:09:52 +0000446 if (!EFI_ERROR (Status)) {
447 // We were able to allocate the PCI memory
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000448 RootBridgeInstance->ResAllocNode[Index].Base =
449 (UINTN)BaseAddress;
450 RootBridgeInstance->ResAllocNode[Index].Status =
451 ResAllocated;
452
jljusten21b404d2009-05-27 21:09:52 +0000453 } else {
454 // Not able to allocate enough PCI memory
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000455 ReturnStatus = Status;
456
jljusten21b404d2009-05-27 21:09:52 +0000457 if (Status != EFI_OUT_OF_RESOURCES) {
458 RootBridgeInstance->ResAllocNode[Index].Length = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000459 }
jljusten21b404d2009-05-27 21:09:52 +0000460 ASSERT (FALSE);
461 }
462 break;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000463
464 case TypePMem32:
465 case TypeMem64:
jljusten21b404d2009-05-27 21:09:52 +0000466 case TypePMem64:
467 ReturnStatus = EFI_ABORTED;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000468 break;
jljusten21b404d2009-05-27 21:09:52 +0000469 default:
470 ASSERT (FALSE);
471 break;
472 }; //end switch
473 }
474 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000475
jljusten21b404d2009-05-27 21:09:52 +0000476 List = List->ForwardLink;
477 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000478
jljusten21b404d2009-05-27 21:09:52 +0000479 return ReturnStatus;
480
481 } else {
482 return EFI_NOT_READY;
483 }
484 break;
485
486 case EfiPciHostBridgeSetResources:
487 break;
488
489 case EfiPciHostBridgeFreeResources:
490 ReturnStatus = EFI_SUCCESS;
491 List = HostBridgeInstance->Head.ForwardLink;
492 while (List != &HostBridgeInstance->Head) {
493 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
494 for (Index = TypeIo; Index < TypeBus; Index++) {
495 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
496 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
497 BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
498 switch (Index) {
499
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000500 case TypeIo:
501 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
jljusten21b404d2009-05-27 21:09:52 +0000502 if (EFI_ERROR (Status)) {
503 ReturnStatus = Status;
504 }
505 break;
506
507 case TypeMem32:
508 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
509 if (EFI_ERROR (Status)) {
510 ReturnStatus = Status;
511 }
512 break;
513
514 case TypePMem32:
515 break;
516
517 case TypeMem64:
518 break;
519
520 case TypePMem64:
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000521 break;
jljusten21b404d2009-05-27 21:09:52 +0000522
523 default:
524 ASSERT (FALSE);
525 break;
526
527 }; //end switch
528 RootBridgeInstance->ResAllocNode[Index].Type = Index;
529 RootBridgeInstance->ResAllocNode[Index].Base = 0;
530 RootBridgeInstance->ResAllocNode[Index].Length = 0;
531 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
532 }
533 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000534
jljusten21b404d2009-05-27 21:09:52 +0000535 List = List->ForwardLink;
536 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000537
jljusten21b404d2009-05-27 21:09:52 +0000538 HostBridgeInstance->ResourceSubmited = FALSE;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000539 HostBridgeInstance->CanRestarted = TRUE;
jljusten21b404d2009-05-27 21:09:52 +0000540 return ReturnStatus;
jljusten21b404d2009-05-27 21:09:52 +0000541
542 case EfiPciHostBridgeEndResourceAllocation:
543 HostBridgeInstance->CanRestarted = FALSE;
544 break;
545
546 default:
547 return EFI_INVALID_PARAMETER;
Ruiyu Nicfdb6732013-07-22 07:35:51 +0000548 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000549
550 return EFI_SUCCESS;
jljusten21b404d2009-05-27 21:09:52 +0000551}
552
klu218c97f52010-04-12 04:38:44 +0000553/**
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000554 Return the device handle of the next PCI root bridge that is associated with
555 this Host Bridge.
klu218c97f52010-04-12 04:38:44 +0000556
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000557 This function is called multiple times to retrieve the device handles of all
558 the PCI root bridges that are associated with this PCI host bridge. Each PCI
559 host bridge is associated with one or more PCI root bridges. On each call,
560 the handle that was returned by the previous call is passed into the
561 interface, and on output the interface returns the device handle of the next
562 PCI root bridge. The caller can use the handle to obtain the instance of the
563 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
564 PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
565 enumerator must enumerate the PCI root bridges in the order that they are
566 returned by this function.
klu218c97f52010-04-12 04:38:44 +0000567
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000568 For D945 implementation, there is only one root bridge in PCI host bridge.
569
570 @param[in] This The instance pointer of
571 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
572
573 @param[in, out] RootBridgeHandle Returns the device handle of the next PCI
574 root bridge.
575
576 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then
577 return the first Rootbridge handle of the
578 specific Host bridge and return EFI_SUCCESS.
579
580 @retval EFI_NOT_FOUND Can not find the any more root bridge in
581 specific host bridge.
582
583 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
584 returned on a previous call to
585 GetNextRootBridge().
klu218c97f52010-04-12 04:38:44 +0000586**/
jljusten21b404d2009-05-27 21:09:52 +0000587EFI_STATUS
588EFIAPI
589GetNextRootBridge(
590 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
591 IN OUT EFI_HANDLE *RootBridgeHandle
592 )
jljusten21b404d2009-05-27 21:09:52 +0000593{
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000594 BOOLEAN NoRootBridge;
595 LIST_ENTRY *List;
jljusten21b404d2009-05-27 21:09:52 +0000596 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
597 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000598
jljusten21b404d2009-05-27 21:09:52 +0000599 NoRootBridge = TRUE;
600 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
601 List = HostBridgeInstance->Head.ForwardLink;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000602
603
jljusten21b404d2009-05-27 21:09:52 +0000604 while (List != &HostBridgeInstance->Head) {
605 NoRootBridge = FALSE;
606 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
607 if (*RootBridgeHandle == NULL) {
608 //
609 // Return the first Root Bridge Handle of the Host Bridge
610 //
611 *RootBridgeHandle = RootBridgeInstance->Handle;
612 return EFI_SUCCESS;
613 } else {
614 if (*RootBridgeHandle == RootBridgeInstance->Handle) {
615 //
616 // Get next if have
617 //
618 List = List->ForwardLink;
619 if (List!=&HostBridgeInstance->Head) {
620 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
621 *RootBridgeHandle = RootBridgeInstance->Handle;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000622 return EFI_SUCCESS;
jljusten21b404d2009-05-27 21:09:52 +0000623 } else {
624 return EFI_NOT_FOUND;
625 }
626 }
627 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000628
jljusten21b404d2009-05-27 21:09:52 +0000629 List = List->ForwardLink;
630 } //end while
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000631
jljusten21b404d2009-05-27 21:09:52 +0000632 if (NoRootBridge) {
633 return EFI_NOT_FOUND;
634 } else {
635 return EFI_INVALID_PARAMETER;
636 }
637}
638
klu218c97f52010-04-12 04:38:44 +0000639/**
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000640 Returns the allocation attributes of a PCI root bridge.
klu218c97f52010-04-12 04:38:44 +0000641
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000642 The function returns the allocation attributes of a specific PCI root bridge.
643 The attributes can vary from one PCI root bridge to another. These attributes
644 are different from the decode-related attributes that are returned by the
645 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
646 RootBridgeHandle parameter is used to specify the instance of the PCI root
647 bridge. The device handles of all the root bridges that are associated with
648 this host bridge must be obtained by calling GetNextRootBridge(). The
649 attributes are static in the sense that they do not change during or after
650 the enumeration process. The hardware may provide mechanisms to change the
651 attributes on the fly, but such changes must be completed before
652 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
653 values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
654 "Related Definitions" below. The caller uses these attributes to combine
655 multiple resource requests.
klu218c97f52010-04-12 04:38:44 +0000656
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000657 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
658 bus enumerator needs to include requests for the prefetchable memory in the
659 nonprefetchable memory pool and not request any prefetchable memory.
klu218c97f52010-04-12 04:38:44 +0000660
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000661 Attribute Description
662 ------------------------------------ ---------------------------------------
663 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root
664 bridge does not support separate
665 windows for nonprefetchable and
666 prefetchable memory. A PCI bus driver
667 needs to include requests for
668 prefetchable memory in the
669 nonprefetchable memory pool.
klu218c97f52010-04-12 04:38:44 +0000670
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000671 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root
672 bridge supports 64-bit memory windows.
673 If this bit is not set, the PCI bus
674 driver needs to include requests for a
675 64-bit memory address in the
676 corresponding 32-bit memory pool.
677
678 @param[in] This The instance pointer of
679 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
680
681 @param[in] RootBridgeHandle The device handle of the PCI root bridge in
682 which the caller is interested. Type
683 EFI_HANDLE is defined in
684 InstallProtocolInterface() in the UEFI 2.0
685 Specification.
686
687 @param[out] Attributes The pointer to attribte of root bridge, it is
688 output parameter
689
690 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
691
692 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
693
694 @retval EFI_SUCCESS Success to get attribute of interested root
695 bridge.
klu218c97f52010-04-12 04:38:44 +0000696**/
jljusten21b404d2009-05-27 21:09:52 +0000697EFI_STATUS
698EFIAPI
699GetAttributes(
700 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
701 IN EFI_HANDLE RootBridgeHandle,
702 OUT UINT64 *Attributes
703 )
jljusten21b404d2009-05-27 21:09:52 +0000704{
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000705 LIST_ENTRY *List;
jljusten21b404d2009-05-27 21:09:52 +0000706 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
707 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000708
jljusten21b404d2009-05-27 21:09:52 +0000709 if (Attributes == NULL) {
710 return EFI_INVALID_PARAMETER;
711 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000712
jljusten21b404d2009-05-27 21:09:52 +0000713 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
714 List = HostBridgeInstance->Head.ForwardLink;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000715
jljusten21b404d2009-05-27 21:09:52 +0000716 while (List != &HostBridgeInstance->Head) {
717 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
718 if (RootBridgeHandle == RootBridgeInstance->Handle) {
719 *Attributes = RootBridgeInstance->RootBridgeAttrib;
720 return EFI_SUCCESS;
721 }
722 List = List->ForwardLink;
723 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000724
jljusten21b404d2009-05-27 21:09:52 +0000725 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000726 // RootBridgeHandle is not an EFI_HANDLE
jljusten21b404d2009-05-27 21:09:52 +0000727 // that was returned on a previous call to GetNextRootBridge()
728 //
729 return EFI_INVALID_PARAMETER;
730}
731
klu218c97f52010-04-12 04:38:44 +0000732/**
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000733 Sets up the specified PCI root bridge for the bus enumeration process.
klu218c97f52010-04-12 04:38:44 +0000734
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000735 This member function sets up the root bridge for bus enumeration and returns
736 the PCI bus range over which the search should be performed in ACPI 2.0
737 resource descriptor format.
klu218c97f52010-04-12 04:38:44 +0000738
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000739 @param[in] This The
740 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
741 instance.
klu218c97f52010-04-12 04:38:44 +0000742
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000743 @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
744
745 @param[out] Configuration Pointer to the pointer to the PCI bus resource
746 descriptor.
747
748 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
749
750 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
751
752 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
klu218c97f52010-04-12 04:38:44 +0000753**/
jljusten21b404d2009-05-27 21:09:52 +0000754EFI_STATUS
755EFIAPI
756StartBusEnumeration(
757 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
758 IN EFI_HANDLE RootBridgeHandle,
759 OUT VOID **Configuration
760 )
jljusten21b404d2009-05-27 21:09:52 +0000761{
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000762 LIST_ENTRY *List;
jljusten21b404d2009-05-27 21:09:52 +0000763 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
764 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
765 VOID *Buffer;
766 UINT8 *Temp;
767 UINT64 BusStart;
768 UINT64 BusEnd;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000769
jljusten21b404d2009-05-27 21:09:52 +0000770 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
771 List = HostBridgeInstance->Head.ForwardLink;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000772
jljusten21b404d2009-05-27 21:09:52 +0000773 while (List != &HostBridgeInstance->Head) {
774 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
775 if (RootBridgeHandle == RootBridgeInstance->Handle) {
776 //
777 // Set up the Root Bridge for Bus Enumeration
778 //
779 BusStart = RootBridgeInstance->BusBase;
780 BusEnd = RootBridgeInstance->BusLimit;
781 //
782 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
783 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000784
785 Buffer = AllocatePool (
786 sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
787 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
788 );
jljusten21b404d2009-05-27 21:09:52 +0000789 if (Buffer == NULL) {
790 return EFI_OUT_OF_RESOURCES;
791 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000792
jljusten21b404d2009-05-27 21:09:52 +0000793 Temp = (UINT8 *)Buffer;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000794
jljusten21b404d2009-05-27 21:09:52 +0000795 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
796 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
797 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000798 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
jljusten21b404d2009-05-27 21:09:52 +0000799 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
800 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
801 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
802 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000803 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
804 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen =
805 BusEnd - BusStart + 1;
806
jljusten21b404d2009-05-27 21:09:52 +0000807 Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000808 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
jljusten21b404d2009-05-27 21:09:52 +0000809 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000810
811 *Configuration = Buffer;
jljusten21b404d2009-05-27 21:09:52 +0000812 return EFI_SUCCESS;
813 }
814 List = List->ForwardLink;
815 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000816
jljusten21b404d2009-05-27 21:09:52 +0000817 return EFI_INVALID_PARAMETER;
818}
819
klu218c97f52010-04-12 04:38:44 +0000820/**
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000821 Programs the PCI root bridge hardware so that it decodes the specified PCI
822 bus range.
klu218c97f52010-04-12 04:38:44 +0000823
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000824 This member function programs the specified PCI root bridge to decode the bus
825 range that is specified by the input parameter Configuration.
826 The bus range information is specified in terms of the ACPI 2.0 resource
827 descriptor format.
klu218c97f52010-04-12 04:38:44 +0000828
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000829 @param[in] This The
830 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
831 instance
klu218c97f52010-04-12 04:38:44 +0000832
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000833 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be
834 programmed
835
836 @param[in] Configuration The pointer to the PCI bus resource descriptor
837
838 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
839 handle.
840
841 @retval EFI_INVALID_PARAMETER Configuration is NULL.
842
843 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
844 2.0 resource descriptor.
845
846 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI
847 2.0 bus resource descriptor.
848
849 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource
850 descriptors other than bus descriptors.
851
852 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid
853 ACPI resource descriptors.
854
855 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this
856 root bridge.
857
858 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this
859 root bridge.
860
861 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
862
863 @retval EFI_SUCCESS The bus range for the PCI root bridge was
864 programmed.
klu218c97f52010-04-12 04:38:44 +0000865**/
jljusten21b404d2009-05-27 21:09:52 +0000866EFI_STATUS
867EFIAPI
868SetBusNumbers(
869 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
870 IN EFI_HANDLE RootBridgeHandle,
871 IN VOID *Configuration
872 )
jljusten21b404d2009-05-27 21:09:52 +0000873{
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000874 LIST_ENTRY *List;
jljusten21b404d2009-05-27 21:09:52 +0000875 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
876 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
877 UINT8 *Ptr;
878 UINTN BusStart;
879 UINTN BusEnd;
880 UINTN BusLen;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000881
jljusten21b404d2009-05-27 21:09:52 +0000882 if (Configuration == NULL) {
883 return EFI_INVALID_PARAMETER;
884 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000885
jljusten21b404d2009-05-27 21:09:52 +0000886 Ptr = Configuration;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000887
jljusten21b404d2009-05-27 21:09:52 +0000888 //
889 // Check the Configuration is valid
890 //
891 if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
892 return EFI_INVALID_PARAMETER;
893 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000894
jljusten21b404d2009-05-27 21:09:52 +0000895 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
896 return EFI_INVALID_PARAMETER;
897 }
898
899 Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
900 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
901 return EFI_INVALID_PARAMETER;
902 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000903
jljusten21b404d2009-05-27 21:09:52 +0000904 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
905 List = HostBridgeInstance->Head.ForwardLink;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000906
jljusten21b404d2009-05-27 21:09:52 +0000907 Ptr = Configuration;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000908
jljusten21b404d2009-05-27 21:09:52 +0000909 while (List != &HostBridgeInstance->Head) {
910 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
911 if (RootBridgeHandle == RootBridgeInstance->Handle) {
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000912 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
913
914 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
915 BusStart = (UINTN)Desc->AddrRangeMin;
916 BusLen = (UINTN)Desc->AddrLen;
jljusten21b404d2009-05-27 21:09:52 +0000917 BusEnd = BusStart + BusLen - 1;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000918
jljusten21b404d2009-05-27 21:09:52 +0000919 if (BusStart > BusEnd) {
920 return EFI_INVALID_PARAMETER;
921 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000922
923 if ((BusStart < RootBridgeInstance->BusBase) ||
924 (BusEnd > RootBridgeInstance->BusLimit)) {
jljusten21b404d2009-05-27 21:09:52 +0000925 return EFI_INVALID_PARAMETER;
926 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000927
jljusten21b404d2009-05-27 21:09:52 +0000928 //
929 // Update the Bus Range
930 //
931 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
932 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
933 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000934
jljusten21b404d2009-05-27 21:09:52 +0000935 //
936 // Program the Root Bridge Hardware
937 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000938
jljusten21b404d2009-05-27 21:09:52 +0000939 return EFI_SUCCESS;
940 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000941
jljusten21b404d2009-05-27 21:09:52 +0000942 List = List->ForwardLink;
943 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +0000944
jljusten21b404d2009-05-27 21:09:52 +0000945 return EFI_INVALID_PARAMETER;
946}
947
948
klu218c97f52010-04-12 04:38:44 +0000949/**
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000950 Submits the I/O and memory resource requirements for the specified PCI root
951 bridge.
klu218c97f52010-04-12 04:38:44 +0000952
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000953 This function is used to submit all the I/O and memory resources that are
954 required by the specified PCI root bridge. The input parameter Configuration
955 is used to specify the following:
956 - The various types of resources that are required
957 - The associated lengths in terms of ACPI 2.0 resource descriptor format
klu218c97f52010-04-12 04:38:44 +0000958
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000959 @param[in] This Pointer to the
960 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
961 instance.
klu218c97f52010-04-12 04:38:44 +0000962
Laszlo Ersek7c7af552015-07-14 12:01:16 +0000963 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory
964 resource requirements are being submitted.
965
966 @param[in] Configuration The pointer to the PCI I/O and PCI memory
967 resource descriptor.
968
969 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI
970 root bridge were accepted.
971
972 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
973 handle.
974
975 @retval EFI_INVALID_PARAMETER Configuration is NULL.
976
977 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
978 2.0 resource descriptor.
979
980 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or
981 more resource types that are not supported by
982 this PCI root bridge. This error will happen
983 if the caller did not combine resources
984 according to Attributes that were returned by
985 GetAllocAttributes().
986
987 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
988
989 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI
990 root bridge.
991
992 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for
993 this PCI root bridge.
klu218c97f52010-04-12 04:38:44 +0000994**/
jljusten21b404d2009-05-27 21:09:52 +0000995EFI_STATUS
996EFIAPI
997SubmitResources(
998 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
999 IN EFI_HANDLE RootBridgeHandle,
1000 IN VOID *Configuration
1001 )
jljusten21b404d2009-05-27 21:09:52 +00001002{
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001003 LIST_ENTRY *List;
jljusten21b404d2009-05-27 21:09:52 +00001004 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1005 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1006 UINT8 *Temp;
ydong1024115e42010-09-17 10:42:10 +00001007 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
jljusten21b404d2009-05-27 21:09:52 +00001008 UINT64 AddrLen;
1009 UINT64 Alignment;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001010
jljusten21b404d2009-05-27 21:09:52 +00001011 //
1012 // Check the input parameter: Configuration
1013 //
1014 if (Configuration == NULL) {
1015 return EFI_INVALID_PARAMETER;
1016 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001017
jljusten21b404d2009-05-27 21:09:52 +00001018 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1019 List = HostBridgeInstance->Head.ForwardLink;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001020
jljusten21b404d2009-05-27 21:09:52 +00001021 Temp = (UINT8 *)Configuration;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001022 while ( *Temp == 0x8A) {
jljusten21b404d2009-05-27 21:09:52 +00001023 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1024 }
1025 if (*Temp != 0x79) {
1026 return EFI_INVALID_PARAMETER;
1027 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001028
jljusten21b404d2009-05-27 21:09:52 +00001029 Temp = (UINT8 *)Configuration;
1030 while (List != &HostBridgeInstance->Head) {
1031 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1032 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1033 while ( *Temp == 0x8A) {
ydong1024115e42010-09-17 10:42:10 +00001034 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
jljusten21b404d2009-05-27 21:09:52 +00001035
1036 //
1037 // Check Address Length
1038 //
ydong1024115e42010-09-17 10:42:10 +00001039 if (Ptr->AddrLen > 0xffffffff) {
jljusten21b404d2009-05-27 21:09:52 +00001040 return EFI_INVALID_PARAMETER;
1041 }
1042
1043 //
1044 // Check address range alignment
1045 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001046 if (Ptr->AddrRangeMax >= 0xffffffff ||
1047 Ptr->AddrRangeMax != (GetPowerOfTwo64 (
1048 Ptr->AddrRangeMax + 1) - 1)) {
jljusten21b404d2009-05-27 21:09:52 +00001049 return EFI_INVALID_PARAMETER;
1050 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001051
ydong1024115e42010-09-17 10:42:10 +00001052 switch (Ptr->ResType) {
jljusten21b404d2009-05-27 21:09:52 +00001053
1054 case 0:
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001055
jljusten21b404d2009-05-27 21:09:52 +00001056 //
1057 // Check invalid Address Sapce Granularity
1058 //
ydong1024115e42010-09-17 10:42:10 +00001059 if (Ptr->AddrSpaceGranularity != 32) {
jljusten21b404d2009-05-27 21:09:52 +00001060 return EFI_INVALID_PARAMETER;
1061 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001062
jljusten21b404d2009-05-27 21:09:52 +00001063 //
1064 // check the memory resource request is supported by PCI root bridge
1065 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001066 if (RootBridgeInstance->RootBridgeAttrib ==
1067 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
1068 Ptr->SpecificFlag == 0x06) {
jljusten21b404d2009-05-27 21:09:52 +00001069 return EFI_INVALID_PARAMETER;
1070 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001071
ydong1024115e42010-09-17 10:42:10 +00001072 AddrLen = Ptr->AddrLen;
1073 Alignment = Ptr->AddrRangeMax;
1074 if (Ptr->AddrSpaceGranularity == 32) {
1075 if (Ptr->SpecificFlag == 0x06) {
jljusten21b404d2009-05-27 21:09:52 +00001076 //
1077 // Apply from GCD
1078 //
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001079 RootBridgeInstance->ResAllocNode[TypePMem32].Status =
1080 ResSubmitted;
jljusten21b404d2009-05-27 21:09:52 +00001081 } else {
1082 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001083 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =
1084 Alignment;
1085 RootBridgeInstance->ResAllocNode[TypeMem32].Status =
1086 ResRequested;
jljusten21b404d2009-05-27 21:09:52 +00001087 HostBridgeInstance->ResourceSubmited = TRUE;
1088 }
1089 }
1090
ydong1024115e42010-09-17 10:42:10 +00001091 if (Ptr->AddrSpaceGranularity == 64) {
1092 if (Ptr->SpecificFlag == 0x06) {
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001093 RootBridgeInstance->ResAllocNode[TypePMem64].Status =
1094 ResSubmitted;
jljusten21b404d2009-05-27 21:09:52 +00001095 } else {
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001096 RootBridgeInstance->ResAllocNode[TypeMem64].Status =
1097 ResSubmitted;
jljusten21b404d2009-05-27 21:09:52 +00001098 }
1099 }
1100 break;
1101
1102 case 1:
ydong1024115e42010-09-17 10:42:10 +00001103 AddrLen = (UINTN) Ptr->AddrLen;
1104 Alignment = (UINTN) Ptr->AddrRangeMax;
jljusten21b404d2009-05-27 21:09:52 +00001105 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
1106 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
1107 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001108 HostBridgeInstance->ResourceSubmited = TRUE;
jljusten21b404d2009-05-27 21:09:52 +00001109 break;
1110
1111 default:
1112 break;
1113 };
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001114
jljusten21b404d2009-05-27 21:09:52 +00001115 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001116 }
1117
jljusten21b404d2009-05-27 21:09:52 +00001118 return EFI_SUCCESS;
1119 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001120
jljusten21b404d2009-05-27 21:09:52 +00001121 List = List->ForwardLink;
1122 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001123
jljusten21b404d2009-05-27 21:09:52 +00001124 return EFI_INVALID_PARAMETER;
1125}
1126
klu218c97f52010-04-12 04:38:44 +00001127/**
1128 Returns the proposed resource settings for the specified PCI root bridge.
1129
Laszlo Ersek7c7af552015-07-14 12:01:16 +00001130 This member function returns the proposed resource settings for the
1131 specified PCI root bridge. The proposed resource settings are prepared when
1132 NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
1133 The output parameter Configuration specifies the following:
1134 - The various types of resources, excluding bus resources, that are
1135 allocated
klu218c97f52010-04-12 04:38:44 +00001136 - The associated lengths in terms of ACPI 2.0 resource descriptor format
1137
Laszlo Ersek7c7af552015-07-14 12:01:16 +00001138 @param[in] This Pointer to the
1139 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1140 instance.
klu218c97f52010-04-12 04:38:44 +00001141
Laszlo Ersek7c7af552015-07-14 12:01:16 +00001142 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is
1143 defined in InstallProtocolInterface() in the
1144 UEFI 2.0 Specification.
1145
1146 @param[out] Configuration The pointer to the pointer to the PCI I/O and
1147 memory resource descriptor.
1148
1149 @retval EFI_SUCCESS The requested parameters were returned.
1150
1151 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1152 handle.
1153
1154 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1155
1156 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1157 lack of resources.
klu218c97f52010-04-12 04:38:44 +00001158**/
jljusten21b404d2009-05-27 21:09:52 +00001159EFI_STATUS
1160EFIAPI
1161GetProposedResources(
1162 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1163 IN EFI_HANDLE RootBridgeHandle,
1164 OUT VOID **Configuration
1165 )
jljusten21b404d2009-05-27 21:09:52 +00001166{
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001167 LIST_ENTRY *List;
jljusten21b404d2009-05-27 21:09:52 +00001168 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1169 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1170 UINTN Index;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001171 UINTN Number;
1172 VOID *Buffer;
jljusten21b404d2009-05-27 21:09:52 +00001173 UINT8 *Temp;
ydong1024115e42010-09-17 10:42:10 +00001174 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
jljusten21b404d2009-05-27 21:09:52 +00001175 UINT64 ResStatus;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001176
jljusten21b404d2009-05-27 21:09:52 +00001177 Buffer = NULL;
1178 Number = 0;
1179 //
1180 // Get the Host Bridge Instance from the resource allocation protocol
1181 //
1182 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1183 List = HostBridgeInstance->Head.ForwardLink;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001184
jljusten21b404d2009-05-27 21:09:52 +00001185 //
1186 // Enumerate the root bridges in this host bridge
1187 //
1188 while (List != &HostBridgeInstance->Head) {
1189 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1190 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1191 for (Index = 0; Index < TypeBus; Index ++) {
1192 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1193 Number ++;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001194 }
jljusten21b404d2009-05-27 21:09:52 +00001195 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001196
jljusten21b404d2009-05-27 21:09:52 +00001197 if (Number == 0) {
1198 return EFI_INVALID_PARAMETER;
1199 }
1200
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001201 Buffer = AllocateZeroPool (
1202 Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
1203 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
1204 );
jljusten21b404d2009-05-27 21:09:52 +00001205 if (Buffer == NULL) {
1206 return EFI_OUT_OF_RESOURCES;
1207 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001208
jljusten21b404d2009-05-27 21:09:52 +00001209 Temp = Buffer;
1210 for (Index = 0; Index < TypeBus; Index ++) {
1211 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
ydong1024115e42010-09-17 10:42:10 +00001212 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
jljusten21b404d2009-05-27 21:09:52 +00001213 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001214
jljusten21b404d2009-05-27 21:09:52 +00001215 switch (Index) {
1216
1217 case TypeIo:
1218 //
1219 // Io
1220 //
ydong1024115e42010-09-17 10:42:10 +00001221 Ptr->Desc = 0x8A;
1222 Ptr->Len = 0x2B;
1223 Ptr->ResType = 1;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001224 Ptr->GenFlag = 0;
ydong1024115e42010-09-17 10:42:10 +00001225 Ptr->SpecificFlag = 0;
1226 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1227 Ptr->AddrRangeMax = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001228 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1229 EFI_RESOURCE_SATISFIED :
1230 EFI_RESOURCE_LESS;
ydong1024115e42010-09-17 10:42:10 +00001231 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
jljusten21b404d2009-05-27 21:09:52 +00001232 break;
1233
1234 case TypeMem32:
1235 //
1236 // Memory 32
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001237 //
ydong1024115e42010-09-17 10:42:10 +00001238 Ptr->Desc = 0x8A;
1239 Ptr->Len = 0x2B;
1240 Ptr->ResType = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001241 Ptr->GenFlag = 0;
ydong1024115e42010-09-17 10:42:10 +00001242 Ptr->SpecificFlag = 0;
1243 Ptr->AddrSpaceGranularity = 32;
1244 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1245 Ptr->AddrRangeMax = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001246 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1247 EFI_RESOURCE_SATISFIED :
1248 EFI_RESOURCE_LESS;
ydong1024115e42010-09-17 10:42:10 +00001249 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
jljusten21b404d2009-05-27 21:09:52 +00001250 break;
1251
1252 case TypePMem32:
1253 //
1254 // Prefetch memory 32
1255 //
ydong1024115e42010-09-17 10:42:10 +00001256 Ptr->Desc = 0x8A;
1257 Ptr->Len = 0x2B;
1258 Ptr->ResType = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001259 Ptr->GenFlag = 0;
ydong1024115e42010-09-17 10:42:10 +00001260 Ptr->SpecificFlag = 6;
1261 Ptr->AddrSpaceGranularity = 32;
1262 Ptr->AddrRangeMin = 0;
1263 Ptr->AddrRangeMax = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001264 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
ydong1024115e42010-09-17 10:42:10 +00001265 Ptr->AddrLen = 0;
jljusten21b404d2009-05-27 21:09:52 +00001266 break;
1267
1268 case TypeMem64:
1269 //
1270 // Memory 64
1271 //
ydong1024115e42010-09-17 10:42:10 +00001272 Ptr->Desc = 0x8A;
1273 Ptr->Len = 0x2B;
1274 Ptr->ResType = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001275 Ptr->GenFlag = 0;
ydong1024115e42010-09-17 10:42:10 +00001276 Ptr->SpecificFlag = 0;
1277 Ptr->AddrSpaceGranularity = 64;
1278 Ptr->AddrRangeMin = 0;
1279 Ptr->AddrRangeMax = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001280 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
ydong1024115e42010-09-17 10:42:10 +00001281 Ptr->AddrLen = 0;
jljusten21b404d2009-05-27 21:09:52 +00001282 break;
1283
1284 case TypePMem64:
1285 //
1286 // Prefetch memory 64
1287 //
ydong1024115e42010-09-17 10:42:10 +00001288 Ptr->Desc = 0x8A;
1289 Ptr->Len = 0x2B;
1290 Ptr->ResType = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001291 Ptr->GenFlag = 0;
ydong1024115e42010-09-17 10:42:10 +00001292 Ptr->SpecificFlag = 6;
1293 Ptr->AddrSpaceGranularity = 64;
1294 Ptr->AddrRangeMin = 0;
1295 Ptr->AddrRangeMax = 0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001296 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
ydong1024115e42010-09-17 10:42:10 +00001297 Ptr->AddrLen = 0;
jljusten21b404d2009-05-27 21:09:52 +00001298 break;
1299 };
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001300
jljusten21b404d2009-05-27 21:09:52 +00001301 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001302 }
jljusten21b404d2009-05-27 21:09:52 +00001303 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001304
1305 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
jljusten21b404d2009-05-27 21:09:52 +00001306 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001307
1308 *Configuration = Buffer;
1309
jljusten21b404d2009-05-27 21:09:52 +00001310 return EFI_SUCCESS;
1311 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001312
jljusten21b404d2009-05-27 21:09:52 +00001313 List = List->ForwardLink;
1314 }
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001315
jljusten21b404d2009-05-27 21:09:52 +00001316 return EFI_INVALID_PARAMETER;
1317}
1318
klu218c97f52010-04-12 04:38:44 +00001319/**
Laszlo Ersek7c7af552015-07-14 12:01:16 +00001320 Provides the hooks from the PCI bus driver to every PCI controller
1321 (device/function) at various stages of the PCI enumeration process that allow
1322 the host bridge driver to preinitialize individual PCI controllers before
1323 enumeration.
klu218c97f52010-04-12 04:38:44 +00001324
Laszlo Ersek7c7af552015-07-14 12:01:16 +00001325 This function is called during the PCI enumeration process. No specific
1326 action is expected from this member function. It allows the host bridge
1327 driver to preinitialize individual PCI controllers before enumeration.
klu218c97f52010-04-12 04:38:44 +00001328
Laszlo Ersek7c7af552015-07-14 12:01:16 +00001329 @param This Pointer to the
1330 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1331 instance.
klu218c97f52010-04-12 04:38:44 +00001332
Laszlo Ersek7c7af552015-07-14 12:01:16 +00001333 @param RootBridgeHandle The associated PCI root bridge handle. Type
1334 EFI_HANDLE is defined in InstallProtocolInterface()
1335 in the UEFI 2.0 Specification.
1336
1337 @param PciAddress The address of the PCI device on the PCI bus. This
1338 address can be passed to the
1339 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
1340 access the PCI configuration space of the device.
1341 See Table 12-1 in the UEFI 2.0 Specification for the
1342 definition of
1343 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
1344
1345 @param Phase The phase of the PCI device enumeration.
1346
1347 @retval EFI_SUCCESS The requested parameters were returned.
1348
1349 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1350 handle.
1351
1352 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined
1353 in
1354 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1355
1356 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1357 The PCI enumerator should not enumerate this
1358 device, including its child devices if it is
1359 a PCI-to-PCI bridge.
klu218c97f52010-04-12 04:38:44 +00001360**/
jljusten21b404d2009-05-27 21:09:52 +00001361EFI_STATUS
1362EFIAPI
1363PreprocessController (
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001364 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1365 IN EFI_HANDLE RootBridgeHandle,
1366 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1367 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
jljusten21b404d2009-05-27 21:09:52 +00001368 )
jljusten21b404d2009-05-27 21:09:52 +00001369{
1370 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1371 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
Laszlo Ersek3d9eddb2015-07-14 12:01:21 +00001372 LIST_ENTRY *List;
jljusten21b404d2009-05-27 21:09:52 +00001373
1374 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1375 List = HostBridgeInstance->Head.ForwardLink;
1376
1377 //
1378 // Enumerate the root bridges in this host bridge
1379 //
1380 while (List != &HostBridgeInstance->Head) {
1381 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1382 if (RootBridgeHandle == RootBridgeInstance->Handle) {
rsun3e0ee9d92010-12-28 10:10:10 +00001383 break;
jljusten21b404d2009-05-27 21:09:52 +00001384 }
1385 List = List->ForwardLink;
1386 }
rsun3e0ee9d92010-12-28 10:10:10 +00001387 if (List == &HostBridgeInstance->Head) {
1388 return EFI_INVALID_PARAMETER;
1389 }
jljusten21b404d2009-05-27 21:09:52 +00001390
rsun33d78c022012-08-28 06:48:28 +00001391 if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
rsun3e0ee9d92010-12-28 10:10:10 +00001392 return EFI_INVALID_PARAMETER;
1393 }
1394
1395 return EFI_SUCCESS;
jljusten21b404d2009-05-27 21:09:52 +00001396}