]> git.proxmox.com Git - mirror_edk2.git/blame - PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
ShellPkg/UefiDpLib: Fix a memory leak issue in Dp.
[mirror_edk2.git] / PcAtChipsetPkg / PciHostBridgeDxe / PciHostBridge.c
CommitLineData
21b404d1 1/** @file\r
7c7af556
LE
2 Provides the basic interfaces to abstract a PCI Host Bridge Resource\r
3 Allocation\r
21b404d1 4\r
7c7af556 5 Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\r
18c97f53 6\r
7c7af556
LE
7 This program and the accompanying materials are licensed and made available\r
8 under the terms and conditions of the BSD License which accompanies this\r
9 distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
21b404d1 11\r
7c7af556
LE
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
21b404d1 16\r
17#include "PciHostBridge.h"\r
18\r
21b404d1 19//\r
20// Hard code: Root Bridge Number within the host bridge\r
21// Root Bridge's attribute\r
22// Root Bridge's device path\r
0b7c6cd4 23// Root Bridge's resource aperture\r
21b404d1 24//\r
25UINTN RootBridgeNumber[1] = { 1 };\r
26\r
3d9eddb1
LE
27UINT64 RootBridgeAttribute[1][1] = {\r
28 { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM }\r
29};\r
21b404d1 30\r
31EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {\r
32 {\r
ce68d3bc
SZ
33 {\r
34 {\r
35 {\r
36 ACPI_DEVICE_PATH,\r
37 ACPI_DP,\r
38 {\r
39 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),\r
40 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)\r
41 }\r
42 },\r
43 EISA_PNP_ID(0x0A03),\r
44 0\r
45 },\r
3d9eddb1 46\r
ce68d3bc
SZ
47 {\r
48 END_DEVICE_PATH_TYPE,\r
49 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
50 {\r
51 END_DEVICE_PATH_LENGTH,\r
52 0\r
53 }\r
54 }\r
55 }\r
21b404d1 56 }\r
57};\r
58\r
0b7c6cd4 59PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1][1] = {\r
ce68d3bc 60 {{0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}}\r
21b404d1 61};\r
62\r
63EFI_HANDLE mDriverImageHandle;\r
64\r
65PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {\r
66 PCI_HOST_BRIDGE_SIGNATURE, // Signature\r
67 NULL, // HostBridgeHandle\r
68 0, // RootBridgeNumber\r
69 {NULL, NULL}, // Head\r
70 FALSE, // ResourceSubiteed\r
71 TRUE, // CanRestarted\r
72 {\r
73 NotifyPhase,\r
74 GetNextRootBridge,\r
75 GetAttributes,\r
76 StartBusEnumeration,\r
77 SetBusNumbers,\r
78 SubmitResources,\r
79 GetProposedResources,\r
80 PreprocessController\r
81 }\r
82};\r
83\r
84//\r
85// Implementation\r
86//\r
24115e44 87\r
18c97f53 88/**\r
89 Entry point of this driver\r
90\r
91 @param ImageHandle Handle of driver image\r
92 @param SystemTable Point to EFI_SYSTEM_TABLE\r
93\r
94 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource\r
95 @retval EFI_DEVICE_ERROR Can not install the protocol instance\r
96 @retval EFI_SUCCESS Success to initialize the Pci host bridge.\r
97**/\r
21b404d1 98EFI_STATUS\r
99EFIAPI\r
100InitializePciHostBridge (\r
101 IN EFI_HANDLE ImageHandle,\r
102 IN EFI_SYSTEM_TABLE *SystemTable\r
103 )\r
21b404d1 104{\r
105 EFI_STATUS Status;\r
106 UINTN Loop1;\r
107 UINTN Loop2;\r
108 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
109 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
3d9eddb1 110\r
21b404d1 111 mDriverImageHandle = ImageHandle;\r
3d9eddb1 112\r
21b404d1 113 //\r
114 // Create Host Bridge Device Handle\r
115 //\r
116 for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {\r
3d9eddb1
LE
117 HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),\r
118 &mPciHostBridgeInstanceTemplate);\r
21b404d1 119 if (HostBridge == NULL) {\r
120 return EFI_OUT_OF_RESOURCES;\r
121 }\r
3d9eddb1 122\r
21b404d1 123 HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];\r
124 InitializeListHead (&HostBridge->Head);\r
125\r
126 Status = gBS->InstallMultipleProtocolInterfaces (\r
3d9eddb1
LE
127 &HostBridge->HostBridgeHandle,\r
128 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
129 &HostBridge->ResAlloc,\r
21b404d1 130 NULL\r
131 );\r
132 if (EFI_ERROR (Status)) {\r
133 FreePool (HostBridge);\r
134 return EFI_DEVICE_ERROR;\r
135 }\r
3d9eddb1 136\r
21b404d1 137 //\r
138 // Create Root Bridge Device Handle in this Host Bridge\r
139 //\r
3d9eddb1 140\r
21b404d1 141 for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {\r
142 PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));\r
143 if (PrivateData == NULL) {\r
144 return EFI_OUT_OF_RESOURCES;\r
145 }\r
146\r
147 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
3d9eddb1
LE
148 PrivateData->DevicePath =\r
149 (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];\r
21b404d1 150\r
151 RootBridgeConstructor (\r
3d9eddb1
LE
152 &PrivateData->Io,\r
153 HostBridge->HostBridgeHandle,\r
154 RootBridgeAttribute[Loop1][Loop2],\r
0b7c6cd4 155 &mResAperture[Loop1][Loop2]\r
21b404d1 156 );\r
3d9eddb1 157\r
21b404d1 158 Status = gBS->InstallMultipleProtocolInterfaces(\r
3d9eddb1
LE
159 &PrivateData->Handle,\r
160 &gEfiDevicePathProtocolGuid,\r
161 PrivateData->DevicePath,\r
162 &gEfiPciRootBridgeIoProtocolGuid,\r
163 &PrivateData->Io,\r
21b404d1 164 NULL\r
165 );\r
166 if (EFI_ERROR (Status)) {\r
167 FreePool(PrivateData);\r
168 return EFI_DEVICE_ERROR;\r
169 }\r
3d9eddb1 170\r
21b404d1 171 InsertTailList (&HostBridge->Head, &PrivateData->Link);\r
172 }\r
3d9eddb1 173 }\r
21b404d1 174\r
21b404d1 175 return EFI_SUCCESS;\r
176}\r
177\r
178\r
18c97f53 179/**\r
7c7af556
LE
180 These are the notifications from the PCI bus driver that it is about to enter\r
181 a certain phase of the PCI enumeration process.\r
182\r
183 This member function can be used to notify the host bridge driver to perform\r
184 specific actions, including any chipset-specific initialization, so that the\r
185 chipset is ready to enter the next phase. Eight notification points are\r
186 defined at this time. See belows:\r
187\r
188 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures\r
189 and internal data structures. The PCI\r
190 enumerator should issue this\r
191 notification before starting a fresh\r
192 enumeration process. Enumeration\r
193 cannot be restarted after sending any\r
194 other notification such as\r
195 EfiPciHostBridgeBeginBusAllocation.\r
196\r
197 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to\r
198 begin. No specific action is required\r
199 here. This notification can be used to\r
200 perform any chipset-specific\r
201 programming.\r
202\r
203 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming\r
204 phase is complete. No specific action\r
205 is required here. This notification\r
206 can be used to perform any\r
207 chipset-specific programming.\r
208\r
209 EfiPciHostBridgeBeginResourceAllocation\r
210 The resource allocation phase is about\r
211 to begin. No specific action is\r
212 required here. This notification can\r
213 be used to perform any\r
214 chipset-specific programming.\r
215\r
216 EfiPciHostBridgeAllocateResources Allocates resources per previously\r
217 submitted requests for all the PCI\r
218 root bridges. These resource settings\r
219 are returned on the next call to\r
220 GetProposedResources(). Before calling\r
221 NotifyPhase() with a Phase of\r
222 EfiPciHostBridgeAllocateResource, the\r
223 PCI bus enumerator is responsible for\r
224 gathering I/O and memory requests for\r
225 all the PCI root bridges and\r
226 submitting these requests using\r
227 SubmitResources(). This function pads\r
228 the resource amount to suit the root\r
229 bridge hardware, takes care of\r
230 dependencies between the PCI root\r
231 bridges, and calls the Global\r
232 Coherency Domain (GCD) with the\r
233 allocation request. In the case of\r
234 padding, the allocated range could be\r
235 bigger than what was requested.\r
236\r
237 EfiPciHostBridgeSetResources Programs the host bridge hardware to\r
238 decode previously allocated resources\r
239 (proposed resources) for all the PCI\r
240 root bridges. After the hardware is\r
241 programmed, reassigning resources will\r
242 not be supported. The bus settings are\r
243 not affected.\r
244\r
245 EfiPciHostBridgeFreeResources Deallocates resources that were\r
246 previously allocated for all the PCI\r
247 root bridges and resets the I/O and\r
248 memory apertures to their initial\r
249 state. The bus settings are not\r
250 affected. If the request to allocate\r
251 resources fails, the PCI enumerator\r
252 can use this notification to\r
253 deallocate previous resources, adjust\r
254 the requests, and retry allocation.\r
255\r
256 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is\r
257 completed. No specific action is\r
258 required here. This notification can\r
259 be used to perform any chipsetspecific\r
260 programming.\r
261\r
262 @param[in] This The instance pointer of\r
263 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
264\r
265 @param[in] Phase The phase during enumeration\r
266\r
267 @retval EFI_NOT_READY This phase cannot be entered at this time. For\r
268 example, this error is valid for a Phase of\r
269 EfiPciHostBridgeAllocateResources if\r
270 SubmitResources() has not been called for one\r
271 or more PCI root bridges before this call\r
272\r
273 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.\r
274 This error is valid for a Phase of\r
275 EfiPciHostBridgeSetResources.\r
276\r
277 @retval EFI_INVALID_PARAMETER Invalid phase parameter\r
278\r
279 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
280 lack of resources. This error is valid for a\r
281 Phase of EfiPciHostBridgeAllocateResources if\r
282 the previously submitted resource requests\r
283 cannot be fulfilled or were only partially\r
284 fulfilled.\r
285\r
286 @retval EFI_SUCCESS The notification was accepted without any\r
287 errors.\r
18c97f53 288**/\r
21b404d1 289EFI_STATUS\r
290EFIAPI\r
291NotifyPhase(\r
292 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
293 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
294 )\r
21b404d1 295{\r
296 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
297 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
298 PCI_RESOURCE_TYPE Index;\r
299 LIST_ENTRY *List;\r
300 EFI_PHYSICAL_ADDRESS BaseAddress;\r
301 UINT64 AddrLen;\r
302 UINTN BitsOfAlignment;\r
303 EFI_STATUS Status;\r
304 EFI_STATUS ReturnStatus;\r
3d9eddb1 305\r
21b404d1 306 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
3d9eddb1 307\r
21b404d1 308 switch (Phase) {\r
309\r
310 case EfiPciHostBridgeBeginEnumeration:\r
311 if (HostBridgeInstance->CanRestarted) {\r
312 //\r
3d9eddb1 313 // Reset the Each Root Bridge\r
21b404d1 314 //\r
315 List = HostBridgeInstance->Head.ForwardLink;\r
3d9eddb1 316\r
21b404d1 317 while (List != &HostBridgeInstance->Head) {\r
318 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
319 for (Index = TypeIo; Index < TypeMax; Index++) {\r
320 RootBridgeInstance->ResAllocNode[Index].Type = Index;\r
321 RootBridgeInstance->ResAllocNode[Index].Base = 0;\r
322 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
323 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;\r
324 }\r
3d9eddb1 325\r
21b404d1 326 List = List->ForwardLink;\r
327 }\r
3d9eddb1 328\r
21b404d1 329 HostBridgeInstance->ResourceSubmited = FALSE;\r
330 HostBridgeInstance->CanRestarted = TRUE;\r
331 } else {\r
332 //\r
333 // Can not restart\r
3d9eddb1 334 //\r
21b404d1 335 return EFI_NOT_READY;\r
3d9eddb1 336 }\r
21b404d1 337 break;\r
338\r
cfdb6737
RN
339 case EfiPciHostBridgeEndEnumeration:\r
340 break;\r
341\r
21b404d1 342 case EfiPciHostBridgeBeginBusAllocation:\r
343 //\r
3d9eddb1
LE
344 // No specific action is required here, can perform any chipset specific\r
345 // programing\r
21b404d1 346 //\r
347 HostBridgeInstance->CanRestarted = FALSE;\r
21b404d1 348 break;\r
349\r
350 case EfiPciHostBridgeEndBusAllocation:\r
351 //\r
3d9eddb1
LE
352 // No specific action is required here, can perform any chipset specific\r
353 // programing\r
21b404d1 354 //\r
355 //HostBridgeInstance->CanRestarted = FALSE;\r
21b404d1 356 break;\r
357\r
358 case EfiPciHostBridgeBeginResourceAllocation:\r
359 //\r
3d9eddb1
LE
360 // No specific action is required here, can perform any chipset specific\r
361 // programing\r
21b404d1 362 //\r
363 //HostBridgeInstance->CanRestarted = FALSE;\r
21b404d1 364 break;\r
365\r
366 case EfiPciHostBridgeAllocateResources:\r
367 ReturnStatus = EFI_SUCCESS;\r
368 if (HostBridgeInstance->ResourceSubmited) {\r
369 //\r
3d9eddb1 370 // Take care of the resource dependencies between the root bridges\r
21b404d1 371 //\r
372 List = HostBridgeInstance->Head.ForwardLink;\r
373\r
374 while (List != &HostBridgeInstance->Head) {\r
375 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
376 for (Index = TypeIo; Index < TypeBus; Index++) {\r
377 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
3d9eddb1 378\r
21b404d1 379 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
3d9eddb1 380\r
21b404d1 381 //\r
382 // Get the number of '1' in Alignment.\r
383 //\r
3d9eddb1
LE
384 BitsOfAlignment =\r
385 (UINTN)(HighBitSet64 (\r
386 RootBridgeInstance->ResAllocNode[Index].Alignment\r
387 ) + 1);\r
388\r
21b404d1 389 switch (Index) {\r
390\r
3d9eddb1 391 case TypeIo:\r
21b404d1 392 //\r
393 // It is impossible for this chipset to align 0xFFFF for IO16\r
394 // So clear it\r
395 //\r
396 if (BitsOfAlignment >= 16) {\r
397 BitsOfAlignment = 0;\r
398 }\r
3d9eddb1 399\r
21b404d1 400 Status = gDS->AllocateIoSpace (\r
3d9eddb1
LE
401 EfiGcdAllocateAnySearchBottomUp,\r
402 EfiGcdIoTypeIo,\r
21b404d1 403 BitsOfAlignment,\r
404 AddrLen,\r
405 &BaseAddress,\r
406 mDriverImageHandle,\r
407 NULL\r
408 );\r
3d9eddb1 409\r
21b404d1 410 if (!EFI_ERROR (Status)) {\r
3d9eddb1
LE
411 RootBridgeInstance->ResAllocNode[Index].Base =\r
412 (UINTN)BaseAddress;\r
413 RootBridgeInstance->ResAllocNode[Index].Status =\r
414 ResAllocated;\r
21b404d1 415 } else {\r
3d9eddb1 416 ReturnStatus = Status;\r
21b404d1 417 if (Status != EFI_OUT_OF_RESOURCES) {\r
418 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
419 }\r
420 }\r
421\r
422 break;\r
423\r
424\r
425 case TypeMem32:\r
426 //\r
3d9eddb1
LE
427 // It is impossible for this chipset to align 0xFFFFFFFF for\r
428 // Mem32\r
429 // So clear it\r
21b404d1 430 //\r
3d9eddb1 431\r
21b404d1 432 if (BitsOfAlignment >= 32) {\r
433 BitsOfAlignment = 0;\r
434 }\r
3d9eddb1 435\r
21b404d1 436 Status = gDS->AllocateMemorySpace (\r
3d9eddb1
LE
437 EfiGcdAllocateAnySearchBottomUp,\r
438 EfiGcdMemoryTypeMemoryMappedIo,\r
21b404d1 439 BitsOfAlignment,\r
440 AddrLen,\r
441 &BaseAddress,\r
442 mDriverImageHandle,\r
443 NULL\r
444 );\r
3d9eddb1 445\r
21b404d1 446 if (!EFI_ERROR (Status)) {\r
447 // We were able to allocate the PCI memory\r
3d9eddb1
LE
448 RootBridgeInstance->ResAllocNode[Index].Base =\r
449 (UINTN)BaseAddress;\r
450 RootBridgeInstance->ResAllocNode[Index].Status =\r
451 ResAllocated;\r
452\r
21b404d1 453 } else {\r
454 // Not able to allocate enough PCI memory\r
3d9eddb1
LE
455 ReturnStatus = Status;\r
456\r
21b404d1 457 if (Status != EFI_OUT_OF_RESOURCES) {\r
458 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
3d9eddb1 459 }\r
21b404d1 460 ASSERT (FALSE);\r
461 }\r
462 break;\r
3d9eddb1
LE
463\r
464 case TypePMem32:\r
465 case TypeMem64:\r
21b404d1 466 case TypePMem64:\r
467 ReturnStatus = EFI_ABORTED;\r
3d9eddb1 468 break;\r
21b404d1 469 default:\r
470 ASSERT (FALSE);\r
471 break;\r
472 }; //end switch\r
473 }\r
474 }\r
3d9eddb1 475\r
21b404d1 476 List = List->ForwardLink;\r
477 }\r
3d9eddb1 478\r
21b404d1 479 return ReturnStatus;\r
480\r
481 } else {\r
482 return EFI_NOT_READY;\r
483 }\r
484 break;\r
485\r
486 case EfiPciHostBridgeSetResources:\r
487 break;\r
488\r
489 case EfiPciHostBridgeFreeResources:\r
490 ReturnStatus = EFI_SUCCESS;\r
491 List = HostBridgeInstance->Head.ForwardLink;\r
492 while (List != &HostBridgeInstance->Head) {\r
493 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
494 for (Index = TypeIo; Index < TypeBus; Index++) {\r
495 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {\r
496 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
497 BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;\r
498 switch (Index) {\r
499\r
3d9eddb1
LE
500 case TypeIo:\r
501 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);\r
21b404d1 502 if (EFI_ERROR (Status)) {\r
503 ReturnStatus = Status;\r
504 }\r
505 break;\r
506\r
507 case TypeMem32:\r
508 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);\r
509 if (EFI_ERROR (Status)) {\r
510 ReturnStatus = Status;\r
511 }\r
512 break;\r
513\r
514 case TypePMem32:\r
515 break;\r
516\r
517 case TypeMem64:\r
518 break;\r
519\r
520 case TypePMem64:\r
3d9eddb1 521 break;\r
21b404d1 522\r
523 default:\r
524 ASSERT (FALSE);\r
525 break;\r
526\r
527 }; //end switch\r
528 RootBridgeInstance->ResAllocNode[Index].Type = Index;\r
529 RootBridgeInstance->ResAllocNode[Index].Base = 0;\r
530 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
531 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;\r
532 }\r
533 }\r
3d9eddb1 534\r
21b404d1 535 List = List->ForwardLink;\r
536 }\r
3d9eddb1 537\r
21b404d1 538 HostBridgeInstance->ResourceSubmited = FALSE;\r
3d9eddb1 539 HostBridgeInstance->CanRestarted = TRUE;\r
21b404d1 540 return ReturnStatus;\r
21b404d1 541\r
542 case EfiPciHostBridgeEndResourceAllocation:\r
543 HostBridgeInstance->CanRestarted = FALSE;\r
544 break;\r
545\r
546 default:\r
547 return EFI_INVALID_PARAMETER;\r
cfdb6737 548 }\r
3d9eddb1
LE
549\r
550 return EFI_SUCCESS;\r
21b404d1 551}\r
552\r
18c97f53 553/**\r
7c7af556
LE
554 Return the device handle of the next PCI root bridge that is associated with\r
555 this Host Bridge.\r
556\r
557 This function is called multiple times to retrieve the device handles of all\r
558 the PCI root bridges that are associated with this PCI host bridge. Each PCI\r
559 host bridge is associated with one or more PCI root bridges. On each call,\r
560 the handle that was returned by the previous call is passed into the\r
561 interface, and on output the interface returns the device handle of the next\r
562 PCI root bridge. The caller can use the handle to obtain the instance of the\r
563 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more\r
564 PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI\r
565 enumerator must enumerate the PCI root bridges in the order that they are\r
566 returned by this function.\r
567\r
568 For D945 implementation, there is only one root bridge in PCI host bridge.\r
569\r
570 @param[in] This The instance pointer of\r
571 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
572\r
573 @param[in, out] RootBridgeHandle Returns the device handle of the next PCI\r
574 root bridge.\r
575\r
576 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then\r
577 return the first Rootbridge handle of the\r
578 specific Host bridge and return EFI_SUCCESS.\r
579\r
580 @retval EFI_NOT_FOUND Can not find the any more root bridge in\r
581 specific host bridge.\r
582\r
583 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was\r
584 returned on a previous call to\r
585 GetNextRootBridge().\r
18c97f53 586**/\r
21b404d1 587EFI_STATUS\r
588EFIAPI\r
589GetNextRootBridge(\r
590 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
591 IN OUT EFI_HANDLE *RootBridgeHandle\r
592 )\r
21b404d1 593{\r
3d9eddb1
LE
594 BOOLEAN NoRootBridge;\r
595 LIST_ENTRY *List;\r
21b404d1 596 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
597 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
3d9eddb1 598\r
21b404d1 599 NoRootBridge = TRUE;\r
600 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
601 List = HostBridgeInstance->Head.ForwardLink;\r
3d9eddb1
LE
602\r
603\r
21b404d1 604 while (List != &HostBridgeInstance->Head) {\r
605 NoRootBridge = FALSE;\r
606 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
607 if (*RootBridgeHandle == NULL) {\r
608 //\r
609 // Return the first Root Bridge Handle of the Host Bridge\r
610 //\r
611 *RootBridgeHandle = RootBridgeInstance->Handle;\r
612 return EFI_SUCCESS;\r
613 } else {\r
614 if (*RootBridgeHandle == RootBridgeInstance->Handle) {\r
615 //\r
616 // Get next if have\r
617 //\r
618 List = List->ForwardLink;\r
619 if (List!=&HostBridgeInstance->Head) {\r
620 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
621 *RootBridgeHandle = RootBridgeInstance->Handle;\r
3d9eddb1 622 return EFI_SUCCESS;\r
21b404d1 623 } else {\r
624 return EFI_NOT_FOUND;\r
625 }\r
626 }\r
627 }\r
3d9eddb1 628\r
21b404d1 629 List = List->ForwardLink;\r
630 } //end while\r
3d9eddb1 631\r
21b404d1 632 if (NoRootBridge) {\r
633 return EFI_NOT_FOUND;\r
634 } else {\r
635 return EFI_INVALID_PARAMETER;\r
636 }\r
637}\r
638\r
18c97f53 639/**\r
7c7af556
LE
640 Returns the allocation attributes of a PCI root bridge.\r
641\r
642 The function returns the allocation attributes of a specific PCI root bridge.\r
643 The attributes can vary from one PCI root bridge to another. These attributes\r
644 are different from the decode-related attributes that are returned by the\r
645 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The\r
646 RootBridgeHandle parameter is used to specify the instance of the PCI root\r
647 bridge. The device handles of all the root bridges that are associated with\r
648 this host bridge must be obtained by calling GetNextRootBridge(). The\r
649 attributes are static in the sense that they do not change during or after\r
650 the enumeration process. The hardware may provide mechanisms to change the\r
651 attributes on the fly, but such changes must be completed before\r
652 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted\r
653 values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in\r
654 "Related Definitions" below. The caller uses these attributes to combine\r
655 multiple resource requests.\r
656\r
657 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI\r
658 bus enumerator needs to include requests for the prefetchable memory in the\r
659 nonprefetchable memory pool and not request any prefetchable memory.\r
660\r
661 Attribute Description\r
662 ------------------------------------ ---------------------------------------\r
663 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root\r
664 bridge does not support separate\r
665 windows for nonprefetchable and\r
666 prefetchable memory. A PCI bus driver\r
667 needs to include requests for\r
668 prefetchable memory in the\r
669 nonprefetchable memory pool.\r
670\r
671 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root\r
672 bridge supports 64-bit memory windows.\r
673 If this bit is not set, the PCI bus\r
674 driver needs to include requests for a\r
675 64-bit memory address in the\r
676 corresponding 32-bit memory pool.\r
677\r
678 @param[in] This The instance pointer of\r
679 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
680\r
681 @param[in] RootBridgeHandle The device handle of the PCI root bridge in\r
682 which the caller is interested. Type\r
683 EFI_HANDLE is defined in\r
684 InstallProtocolInterface() in the UEFI 2.0\r
685 Specification.\r
686\r
687 @param[out] Attributes The pointer to attribte of root bridge, it is\r
688 output parameter\r
689\r
690 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL\r
691\r
692 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.\r
693\r
694 @retval EFI_SUCCESS Success to get attribute of interested root\r
695 bridge.\r
18c97f53 696**/\r
21b404d1 697EFI_STATUS\r
698EFIAPI\r
699GetAttributes(\r
700 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
701 IN EFI_HANDLE RootBridgeHandle,\r
702 OUT UINT64 *Attributes\r
703 )\r
21b404d1 704{\r
3d9eddb1 705 LIST_ENTRY *List;\r
21b404d1 706 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
707 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
3d9eddb1 708\r
21b404d1 709 if (Attributes == NULL) {\r
710 return EFI_INVALID_PARAMETER;\r
711 }\r
3d9eddb1 712\r
21b404d1 713 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
714 List = HostBridgeInstance->Head.ForwardLink;\r
3d9eddb1 715\r
21b404d1 716 while (List != &HostBridgeInstance->Head) {\r
717 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
718 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
719 *Attributes = RootBridgeInstance->RootBridgeAttrib;\r
720 return EFI_SUCCESS;\r
721 }\r
722 List = List->ForwardLink;\r
723 }\r
3d9eddb1 724\r
21b404d1 725 //\r
3d9eddb1 726 // RootBridgeHandle is not an EFI_HANDLE\r
21b404d1 727 // that was returned on a previous call to GetNextRootBridge()\r
728 //\r
729 return EFI_INVALID_PARAMETER;\r
730}\r
731\r
18c97f53 732/**\r
7c7af556 733 Sets up the specified PCI root bridge for the bus enumeration process.\r
18c97f53 734\r
7c7af556
LE
735 This member function sets up the root bridge for bus enumeration and returns\r
736 the PCI bus range over which the search should be performed in ACPI 2.0\r
737 resource descriptor format.\r
18c97f53 738\r
7c7af556
LE
739 @param[in] This The\r
740 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
741 instance.\r
742\r
743 @param[in] RootBridgeHandle The PCI Root Bridge to be set up.\r
744\r
745 @param[out] Configuration Pointer to the pointer to the PCI bus resource\r
746 descriptor.\r
747\r
748 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle\r
749\r
750 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.\r
18c97f53 751\r
7c7af556 752 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.\r
18c97f53 753**/\r
21b404d1 754EFI_STATUS\r
755EFIAPI\r
756StartBusEnumeration(\r
757 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
758 IN EFI_HANDLE RootBridgeHandle,\r
759 OUT VOID **Configuration\r
760 )\r
21b404d1 761{\r
3d9eddb1 762 LIST_ENTRY *List;\r
21b404d1 763 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
764 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
765 VOID *Buffer;\r
766 UINT8 *Temp;\r
767 UINT64 BusStart;\r
768 UINT64 BusEnd;\r
3d9eddb1 769\r
21b404d1 770 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
771 List = HostBridgeInstance->Head.ForwardLink;\r
3d9eddb1 772\r
21b404d1 773 while (List != &HostBridgeInstance->Head) {\r
774 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
775 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
776 //\r
777 // Set up the Root Bridge for Bus Enumeration\r
778 //\r
779 BusStart = RootBridgeInstance->BusBase;\r
780 BusEnd = RootBridgeInstance->BusLimit;\r
781 //\r
782 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR\r
783 //\r
3d9eddb1
LE
784\r
785 Buffer = AllocatePool (\r
786 sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +\r
787 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)\r
788 );\r
21b404d1 789 if (Buffer == NULL) {\r
790 return EFI_OUT_OF_RESOURCES;\r
791 }\r
3d9eddb1 792\r
21b404d1 793 Temp = (UINT8 *)Buffer;\r
3d9eddb1 794\r
21b404d1 795 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;\r
796 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;\r
797 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;\r
3d9eddb1 798 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;\r
21b404d1 799 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;\r
800 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;\r
801 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;\r
802 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;\r
3d9eddb1
LE
803 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;\r
804 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen =\r
805 BusEnd - BusStart + 1;\r
806\r
21b404d1 807 Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
3d9eddb1 808 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;\r
21b404d1 809 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;\r
3d9eddb1
LE
810\r
811 *Configuration = Buffer;\r
21b404d1 812 return EFI_SUCCESS;\r
813 }\r
814 List = List->ForwardLink;\r
815 }\r
3d9eddb1 816\r
21b404d1 817 return EFI_INVALID_PARAMETER;\r
818}\r
819\r
18c97f53 820/**\r
7c7af556
LE
821 Programs the PCI root bridge hardware so that it decodes the specified PCI\r
822 bus range.\r
18c97f53 823\r
7c7af556
LE
824 This member function programs the specified PCI root bridge to decode the bus\r
825 range that is specified by the input parameter Configuration.\r
826 The bus range information is specified in terms of the ACPI 2.0 resource\r
827 descriptor format.\r
18c97f53 828\r
7c7af556
LE
829 @param[in] This The\r
830 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
831 instance\r
832\r
833 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be\r
834 programmed\r
835\r
836 @param[in] Configuration The pointer to the PCI bus resource descriptor\r
837\r
838 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge\r
839 handle.\r
840\r
841 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
842\r
843 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI\r
844 2.0 resource descriptor.\r
845\r
846 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI\r
847 2.0 bus resource descriptor.\r
848\r
849 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource\r
850 descriptors other than bus descriptors.\r
851\r
852 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid\r
853 ACPI resource descriptors.\r
854\r
855 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this\r
856 root bridge.\r
18c97f53 857\r
7c7af556
LE
858 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this\r
859 root bridge.\r
860\r
861 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.\r
862\r
863 @retval EFI_SUCCESS The bus range for the PCI root bridge was\r
864 programmed.\r
18c97f53 865**/\r
21b404d1 866EFI_STATUS\r
867EFIAPI\r
868SetBusNumbers(\r
869 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
870 IN EFI_HANDLE RootBridgeHandle,\r
871 IN VOID *Configuration\r
872 )\r
21b404d1 873{\r
3d9eddb1 874 LIST_ENTRY *List;\r
21b404d1 875 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
876 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
877 UINT8 *Ptr;\r
878 UINTN BusStart;\r
879 UINTN BusEnd;\r
880 UINTN BusLen;\r
3d9eddb1 881\r
21b404d1 882 if (Configuration == NULL) {\r
883 return EFI_INVALID_PARAMETER;\r
884 }\r
3d9eddb1 885\r
21b404d1 886 Ptr = Configuration;\r
3d9eddb1 887\r
21b404d1 888 //\r
889 // Check the Configuration is valid\r
890 //\r
891 if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
892 return EFI_INVALID_PARAMETER;\r
893 }\r
3d9eddb1 894\r
21b404d1 895 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {\r
896 return EFI_INVALID_PARAMETER;\r
897 }\r
898\r
899 Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
900 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {\r
901 return EFI_INVALID_PARAMETER;\r
902 }\r
3d9eddb1 903\r
21b404d1 904 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
905 List = HostBridgeInstance->Head.ForwardLink;\r
3d9eddb1 906\r
21b404d1 907 Ptr = Configuration;\r
3d9eddb1 908\r
21b404d1 909 while (List != &HostBridgeInstance->Head) {\r
910 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
911 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
3d9eddb1
LE
912 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
913\r
914 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;\r
915 BusStart = (UINTN)Desc->AddrRangeMin;\r
916 BusLen = (UINTN)Desc->AddrLen;\r
21b404d1 917 BusEnd = BusStart + BusLen - 1;\r
3d9eddb1 918\r
21b404d1 919 if (BusStart > BusEnd) {\r
920 return EFI_INVALID_PARAMETER;\r
921 }\r
3d9eddb1
LE
922\r
923 if ((BusStart < RootBridgeInstance->BusBase) ||\r
924 (BusEnd > RootBridgeInstance->BusLimit)) {\r
21b404d1 925 return EFI_INVALID_PARAMETER;\r
926 }\r
3d9eddb1 927\r
21b404d1 928 //\r
929 // Update the Bus Range\r
930 //\r
931 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;\r
932 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;\r
933 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;\r
3d9eddb1 934\r
21b404d1 935 //\r
936 // Program the Root Bridge Hardware\r
937 //\r
3d9eddb1 938\r
21b404d1 939 return EFI_SUCCESS;\r
940 }\r
3d9eddb1 941\r
21b404d1 942 List = List->ForwardLink;\r
943 }\r
3d9eddb1 944\r
21b404d1 945 return EFI_INVALID_PARAMETER;\r
946}\r
947\r
948\r
18c97f53 949/**\r
7c7af556
LE
950 Submits the I/O and memory resource requirements for the specified PCI root\r
951 bridge.\r
18c97f53 952\r
7c7af556
LE
953 This function is used to submit all the I/O and memory resources that are\r
954 required by the specified PCI root bridge. The input parameter Configuration\r
955 is used to specify the following:\r
956 - The various types of resources that are required\r
957 - The associated lengths in terms of ACPI 2.0 resource descriptor format\r
18c97f53 958\r
7c7af556
LE
959 @param[in] This Pointer to the\r
960 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
961 instance.\r
962\r
963 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory\r
964 resource requirements are being submitted.\r
965\r
966 @param[in] Configuration The pointer to the PCI I/O and PCI memory\r
967 resource descriptor.\r
968\r
969 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI\r
970 root bridge were accepted.\r
971\r
972 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge\r
973 handle.\r
974\r
975 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
976\r
977 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI\r
978 2.0 resource descriptor.\r
979\r
980 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or\r
981 more resource types that are not supported by\r
982 this PCI root bridge. This error will happen\r
983 if the caller did not combine resources\r
984 according to Attributes that were returned by\r
985 GetAllocAttributes().\r
18c97f53 986\r
7c7af556
LE
987 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.\r
988\r
989 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI\r
990 root bridge.\r
991\r
992 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for\r
993 this PCI root bridge.\r
18c97f53 994**/\r
21b404d1 995EFI_STATUS\r
996EFIAPI\r
997SubmitResources(\r
998 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
999 IN EFI_HANDLE RootBridgeHandle,\r
1000 IN VOID *Configuration\r
1001 )\r
21b404d1 1002{\r
3d9eddb1 1003 LIST_ENTRY *List;\r
21b404d1 1004 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1005 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1006 UINT8 *Temp;\r
24115e44 1007 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
21b404d1 1008 UINT64 AddrLen;\r
1009 UINT64 Alignment;\r
3d9eddb1 1010\r
21b404d1 1011 //\r
1012 // Check the input parameter: Configuration\r
1013 //\r
1014 if (Configuration == NULL) {\r
1015 return EFI_INVALID_PARAMETER;\r
1016 }\r
3d9eddb1 1017\r
21b404d1 1018 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1019 List = HostBridgeInstance->Head.ForwardLink;\r
3d9eddb1 1020\r
21b404d1 1021 Temp = (UINT8 *)Configuration;\r
3d9eddb1 1022 while ( *Temp == 0x8A) {\r
21b404d1 1023 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;\r
1024 }\r
1025 if (*Temp != 0x79) {\r
1026 return EFI_INVALID_PARAMETER;\r
1027 }\r
3d9eddb1 1028\r
21b404d1 1029 Temp = (UINT8 *)Configuration;\r
1030 while (List != &HostBridgeInstance->Head) {\r
1031 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1032 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1033 while ( *Temp == 0x8A) {\r
24115e44 1034 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;\r
21b404d1 1035\r
1036 //\r
1037 // Check Address Length\r
1038 //\r
24115e44 1039 if (Ptr->AddrLen > 0xffffffff) {\r
21b404d1 1040 return EFI_INVALID_PARAMETER;\r
1041 }\r
1042\r
1043 //\r
1044 // Check address range alignment\r
1045 //\r
3d9eddb1
LE
1046 if (Ptr->AddrRangeMax >= 0xffffffff ||\r
1047 Ptr->AddrRangeMax != (GetPowerOfTwo64 (\r
1048 Ptr->AddrRangeMax + 1) - 1)) {\r
21b404d1 1049 return EFI_INVALID_PARAMETER;\r
1050 }\r
3d9eddb1 1051\r
24115e44 1052 switch (Ptr->ResType) {\r
21b404d1 1053\r
1054 case 0:\r
3d9eddb1 1055\r
21b404d1 1056 //\r
1057 // Check invalid Address Sapce Granularity\r
1058 //\r
24115e44 1059 if (Ptr->AddrSpaceGranularity != 32) {\r
21b404d1 1060 return EFI_INVALID_PARAMETER;\r
1061 }\r
3d9eddb1 1062\r
21b404d1 1063 //\r
1064 // check the memory resource request is supported by PCI root bridge\r
1065 //\r
3d9eddb1
LE
1066 if (RootBridgeInstance->RootBridgeAttrib ==\r
1067 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&\r
1068 Ptr->SpecificFlag == 0x06) {\r
21b404d1 1069 return EFI_INVALID_PARAMETER;\r
1070 }\r
3d9eddb1 1071\r
24115e44
ED
1072 AddrLen = Ptr->AddrLen;\r
1073 Alignment = Ptr->AddrRangeMax;\r
1074 if (Ptr->AddrSpaceGranularity == 32) {\r
1075 if (Ptr->SpecificFlag == 0x06) {\r
21b404d1 1076 //\r
1077 // Apply from GCD\r
1078 //\r
3d9eddb1
LE
1079 RootBridgeInstance->ResAllocNode[TypePMem32].Status =\r
1080 ResSubmitted;\r
21b404d1 1081 } else {\r
1082 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;\r
3d9eddb1
LE
1083 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =\r
1084 Alignment;\r
1085 RootBridgeInstance->ResAllocNode[TypeMem32].Status =\r
1086 ResRequested;\r
21b404d1 1087 HostBridgeInstance->ResourceSubmited = TRUE;\r
1088 }\r
1089 }\r
1090\r
24115e44
ED
1091 if (Ptr->AddrSpaceGranularity == 64) {\r
1092 if (Ptr->SpecificFlag == 0x06) {\r
3d9eddb1
LE
1093 RootBridgeInstance->ResAllocNode[TypePMem64].Status =\r
1094 ResSubmitted;\r
21b404d1 1095 } else {\r
3d9eddb1
LE
1096 RootBridgeInstance->ResAllocNode[TypeMem64].Status =\r
1097 ResSubmitted;\r
21b404d1 1098 }\r
1099 }\r
1100 break;\r
1101\r
1102 case 1:\r
24115e44
ED
1103 AddrLen = (UINTN) Ptr->AddrLen;\r
1104 Alignment = (UINTN) Ptr->AddrRangeMax;\r
21b404d1 1105 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;\r
1106 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;\r
1107 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;\r
3d9eddb1 1108 HostBridgeInstance->ResourceSubmited = TRUE;\r
21b404d1 1109 break;\r
1110\r
1111 default:\r
1112 break;\r
1113 };\r
3d9eddb1 1114\r
21b404d1 1115 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;\r
3d9eddb1
LE
1116 }\r
1117\r
21b404d1 1118 return EFI_SUCCESS;\r
1119 }\r
3d9eddb1 1120\r
21b404d1 1121 List = List->ForwardLink;\r
1122 }\r
3d9eddb1 1123\r
21b404d1 1124 return EFI_INVALID_PARAMETER;\r
1125}\r
1126\r
18c97f53 1127/**\r
1128 Returns the proposed resource settings for the specified PCI root bridge.\r
1129\r
7c7af556
LE
1130 This member function returns the proposed resource settings for the\r
1131 specified PCI root bridge. The proposed resource settings are prepared when\r
1132 NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.\r
1133 The output parameter Configuration specifies the following:\r
1134 - The various types of resources, excluding bus resources, that are\r
1135 allocated\r
18c97f53 1136 - The associated lengths in terms of ACPI 2.0 resource descriptor format\r
1137\r
7c7af556
LE
1138 @param[in] This Pointer to the\r
1139 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
1140 instance.\r
1141\r
1142 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is\r
1143 defined in InstallProtocolInterface() in the\r
1144 UEFI 2.0 Specification.\r
1145\r
1146 @param[out] Configuration The pointer to the pointer to the PCI I/O and\r
1147 memory resource descriptor.\r
1148\r
18c97f53 1149 @retval EFI_SUCCESS The requested parameters were returned.\r
7c7af556
LE
1150\r
1151 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge\r
1152 handle.\r
1153\r
18c97f53 1154 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.\r
18c97f53 1155\r
7c7af556
LE
1156 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
1157 lack of resources.\r
18c97f53 1158**/\r
21b404d1 1159EFI_STATUS\r
1160EFIAPI\r
1161GetProposedResources(\r
1162 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1163 IN EFI_HANDLE RootBridgeHandle,\r
1164 OUT VOID **Configuration\r
1165 )\r
21b404d1 1166{\r
3d9eddb1 1167 LIST_ENTRY *List;\r
21b404d1 1168 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1169 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1170 UINTN Index;\r
3d9eddb1
LE
1171 UINTN Number;\r
1172 VOID *Buffer;\r
21b404d1 1173 UINT8 *Temp;\r
24115e44 1174 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
21b404d1 1175 UINT64 ResStatus;\r
3d9eddb1 1176\r
21b404d1 1177 Buffer = NULL;\r
1178 Number = 0;\r
1179 //\r
1180 // Get the Host Bridge Instance from the resource allocation protocol\r
1181 //\r
1182 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1183 List = HostBridgeInstance->Head.ForwardLink;\r
3d9eddb1 1184\r
21b404d1 1185 //\r
1186 // Enumerate the root bridges in this host bridge\r
1187 //\r
1188 while (List != &HostBridgeInstance->Head) {\r
1189 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1190 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1191 for (Index = 0; Index < TypeBus; Index ++) {\r
1192 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
1193 Number ++;\r
3d9eddb1 1194 }\r
21b404d1 1195 }\r
3d9eddb1 1196\r
21b404d1 1197 if (Number == 0) {\r
1198 return EFI_INVALID_PARAMETER;\r
1199 }\r
1200\r
3d9eddb1
LE
1201 Buffer = AllocateZeroPool (\r
1202 Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +\r
1203 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)\r
1204 );\r
21b404d1 1205 if (Buffer == NULL) {\r
1206 return EFI_OUT_OF_RESOURCES;\r
1207 }\r
3d9eddb1 1208\r
21b404d1 1209 Temp = Buffer;\r
1210 for (Index = 0; Index < TypeBus; Index ++) {\r
1211 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
24115e44 1212 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;\r
21b404d1 1213 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;\r
3d9eddb1 1214\r
21b404d1 1215 switch (Index) {\r
1216\r
1217 case TypeIo:\r
1218 //\r
1219 // Io\r
1220 //\r
24115e44
ED
1221 Ptr->Desc = 0x8A;\r
1222 Ptr->Len = 0x2B;\r
1223 Ptr->ResType = 1;\r
3d9eddb1 1224 Ptr->GenFlag = 0;\r
24115e44
ED
1225 Ptr->SpecificFlag = 0;\r
1226 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;\r
1227 Ptr->AddrRangeMax = 0;\r
3d9eddb1
LE
1228 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?\r
1229 EFI_RESOURCE_SATISFIED :\r
1230 EFI_RESOURCE_LESS;\r
24115e44 1231 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
21b404d1 1232 break;\r
1233\r
1234 case TypeMem32:\r
1235 //\r
1236 // Memory 32\r
3d9eddb1 1237 //\r
24115e44
ED
1238 Ptr->Desc = 0x8A;\r
1239 Ptr->Len = 0x2B;\r
1240 Ptr->ResType = 0;\r
3d9eddb1 1241 Ptr->GenFlag = 0;\r
24115e44
ED
1242 Ptr->SpecificFlag = 0;\r
1243 Ptr->AddrSpaceGranularity = 32;\r
1244 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;\r
1245 Ptr->AddrRangeMax = 0;\r
3d9eddb1
LE
1246 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?\r
1247 EFI_RESOURCE_SATISFIED :\r
1248 EFI_RESOURCE_LESS;\r
24115e44 1249 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
21b404d1 1250 break;\r
1251\r
1252 case TypePMem32:\r
1253 //\r
1254 // Prefetch memory 32\r
1255 //\r
24115e44
ED
1256 Ptr->Desc = 0x8A;\r
1257 Ptr->Len = 0x2B;\r
1258 Ptr->ResType = 0;\r
3d9eddb1 1259 Ptr->GenFlag = 0;\r
24115e44
ED
1260 Ptr->SpecificFlag = 6;\r
1261 Ptr->AddrSpaceGranularity = 32;\r
1262 Ptr->AddrRangeMin = 0;\r
1263 Ptr->AddrRangeMax = 0;\r
3d9eddb1 1264 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
24115e44 1265 Ptr->AddrLen = 0;\r
21b404d1 1266 break;\r
1267\r
1268 case TypeMem64:\r
1269 //\r
1270 // Memory 64\r
1271 //\r
24115e44
ED
1272 Ptr->Desc = 0x8A;\r
1273 Ptr->Len = 0x2B;\r
1274 Ptr->ResType = 0;\r
3d9eddb1 1275 Ptr->GenFlag = 0;\r
24115e44
ED
1276 Ptr->SpecificFlag = 0;\r
1277 Ptr->AddrSpaceGranularity = 64;\r
1278 Ptr->AddrRangeMin = 0;\r
1279 Ptr->AddrRangeMax = 0;\r
3d9eddb1 1280 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
24115e44 1281 Ptr->AddrLen = 0;\r
21b404d1 1282 break;\r
1283\r
1284 case TypePMem64:\r
1285 //\r
1286 // Prefetch memory 64\r
1287 //\r
24115e44
ED
1288 Ptr->Desc = 0x8A;\r
1289 Ptr->Len = 0x2B;\r
1290 Ptr->ResType = 0;\r
3d9eddb1 1291 Ptr->GenFlag = 0;\r
24115e44
ED
1292 Ptr->SpecificFlag = 6;\r
1293 Ptr->AddrSpaceGranularity = 64;\r
1294 Ptr->AddrRangeMin = 0;\r
1295 Ptr->AddrRangeMax = 0;\r
3d9eddb1 1296 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
24115e44 1297 Ptr->AddrLen = 0;\r
21b404d1 1298 break;\r
1299 };\r
3d9eddb1 1300\r
21b404d1 1301 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
3d9eddb1 1302 }\r
21b404d1 1303 }\r
3d9eddb1
LE
1304\r
1305 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;\r
21b404d1 1306 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;\r
3d9eddb1
LE
1307\r
1308 *Configuration = Buffer;\r
1309\r
21b404d1 1310 return EFI_SUCCESS;\r
1311 }\r
3d9eddb1 1312\r
21b404d1 1313 List = List->ForwardLink;\r
1314 }\r
3d9eddb1 1315\r
21b404d1 1316 return EFI_INVALID_PARAMETER;\r
1317}\r
1318\r
18c97f53 1319/**\r
7c7af556
LE
1320 Provides the hooks from the PCI bus driver to every PCI controller\r
1321 (device/function) at various stages of the PCI enumeration process that allow\r
1322 the host bridge driver to preinitialize individual PCI controllers before\r
1323 enumeration.\r
1324\r
1325 This function is called during the PCI enumeration process. No specific\r
1326 action is expected from this member function. It allows the host bridge\r
1327 driver to preinitialize individual PCI controllers before enumeration.\r
1328\r
1329 @param This Pointer to the\r
1330 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
1331 instance.\r
1332\r
1333 @param RootBridgeHandle The associated PCI root bridge handle. Type\r
1334 EFI_HANDLE is defined in InstallProtocolInterface()\r
1335 in the UEFI 2.0 Specification.\r
1336\r
1337 @param PciAddress The address of the PCI device on the PCI bus. This\r
1338 address can be passed to the\r
1339 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to\r
1340 access the PCI configuration space of the device.\r
1341 See Table 12-1 in the UEFI 2.0 Specification for the\r
1342 definition of\r
1343 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.\r
1344\r
1345 @param Phase The phase of the PCI device enumeration.\r
1346\r
1347 @retval EFI_SUCCESS The requested parameters were returned.\r
1348\r
1349 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge\r
1350 handle.\r
1351\r
1352 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined\r
1353 in\r
1354 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.\r
1355\r
1356 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.\r
1357 The PCI enumerator should not enumerate this\r
1358 device, including its child devices if it is\r
1359 a PCI-to-PCI bridge.\r
18c97f53 1360**/\r
21b404d1 1361EFI_STATUS\r
1362EFIAPI\r
1363PreprocessController (\r
3d9eddb1
LE
1364 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1365 IN EFI_HANDLE RootBridgeHandle,\r
1366 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
1367 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
21b404d1 1368 )\r
21b404d1 1369{\r
1370 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1371 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
3d9eddb1 1372 LIST_ENTRY *List;\r
21b404d1 1373\r
1374 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1375 List = HostBridgeInstance->Head.ForwardLink;\r
1376\r
1377 //\r
1378 // Enumerate the root bridges in this host bridge\r
1379 //\r
1380 while (List != &HostBridgeInstance->Head) {\r
1381 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1382 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
e0ee9d93 1383 break;\r
21b404d1 1384 }\r
1385 List = List->ForwardLink;\r
1386 }\r
e0ee9d93 1387 if (List == &HostBridgeInstance->Head) {\r
1388 return EFI_INVALID_PARAMETER;\r
1389 }\r
21b404d1 1390\r
3d78c020 1391 if ((UINT32)Phase > EfiPciBeforeResourceCollection) {\r
e0ee9d93 1392 return EFI_INVALID_PARAMETER;\r
1393 }\r
1394\r
1395 return EFI_SUCCESS;\r
21b404d1 1396}\r