]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg/PciHostBridge: Refine function header comments.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciHostBridge.c
CommitLineData
4a50cf4e
RN
1/** @file\r
2\r
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
4\r
5Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "PciHostBridge.h"\r
17#include "PciRootBridge.h"\r
18#include "PciHostResource.h"\r
19\r
20\r
21EFI_METRONOME_ARCH_PROTOCOL *mMetronome;\r
22EFI_CPU_IO2_PROTOCOL *mCpuIo;\r
23\r
24GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {\r
25 L"Mem", L"I/O", L"Bus"\r
26};\r
27GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {\r
28 L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
29};\r
30\r
31/**\r
32\r
33 Entry point of this driver.\r
34\r
35 @param ImageHandle Image handle of this driver.\r
36 @param SystemTable Pointer to standard EFI system table.\r
37\r
38 @retval EFI_SUCCESS Succeed.\r
39 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.\r
40\r
41**/\r
42EFI_STATUS\r
43EFIAPI\r
44InitializePciHostBridge (\r
45 IN EFI_HANDLE ImageHandle,\r
46 IN EFI_SYSTEM_TABLE *SystemTable\r
47 )\r
48{\r
49 EFI_STATUS Status;\r
50 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
51 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
52 PCI_ROOT_BRIDGE *RootBridges;\r
53 UINTN RootBridgeCount;\r
54 UINTN Index;\r
55 PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];\r
56 UINTN MemApertureIndex;\r
57\r
58 RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);\r
59 if ((RootBridges == NULL) || (RootBridgeCount == 0)) {\r
60 return EFI_UNSUPPORTED;\r
61 }\r
62\r
63 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);\r
64 ASSERT_EFI_ERROR (Status);\r
65 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);\r
66 ASSERT_EFI_ERROR (Status);\r
67\r
68 //\r
69 // Most systems in the world including complex servers have only one Host Bridge.\r
70 //\r
71 HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));\r
72 ASSERT (HostBridge != NULL);\r
73\r
74 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;\r
75 HostBridge->CanRestarted = TRUE;\r
76 InitializeListHead (&HostBridge->RootBridges);\r
77\r
78 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;\r
79 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;\r
80 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;\r
81 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;\r
82 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;\r
83 HostBridge->ResAlloc.SubmitResources = SubmitResources;\r
84 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;\r
85 HostBridge->ResAlloc.PreprocessController = PreprocessController;\r
86\r
87 Status = gBS->InstallMultipleProtocolInterfaces (\r
88 &HostBridge->Handle,\r
89 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,\r
90 NULL\r
91 );\r
92 if (EFI_ERROR (Status)) {\r
93 FreePool (HostBridge);\r
94 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
95 return Status;\r
96 }\r
97\r
98 //\r
99 // Create Root Bridge Device Handle in this Host Bridge\r
100 //\r
101 for (Index = 0; Index < RootBridgeCount; Index++) {\r
102 //\r
103 // Create Root Bridge Handle Instance\r
104 //\r
105 RootBridge = CreateRootBridge (&RootBridges[Index], HostBridge->Handle);\r
106 ASSERT (RootBridge != NULL);\r
107 if (RootBridge == NULL) {\r
108 continue;\r
109 }\r
110\r
111 if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) {\r
112 Status = gDS->AddIoSpace (\r
113 EfiGcdIoTypeIo,\r
114 RootBridges[Index].Io.Base,\r
115 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1\r
116 );\r
117 ASSERT_EFI_ERROR (Status);\r
118 }\r
119\r
120 //\r
121 // Add all the Mem/PMem aperture to GCD\r
122 // Mem/PMem shouldn't overlap with each other\r
123 // Root bridge which needs to combine MEM and PMEM should only report\r
124 // the MEM aperture in Mem\r
125 //\r
126 MemApertures[0] = &RootBridges[Index].Mem;\r
127 MemApertures[1] = &RootBridges[Index].MemAbove4G;\r
128 MemApertures[2] = &RootBridges[Index].PMem;\r
129 MemApertures[3] = &RootBridges[Index].PMemAbove4G;\r
130\r
131 for (MemApertureIndex = 0; MemApertureIndex < sizeof (MemApertures) / sizeof (MemApertures[0]); MemApertureIndex++) {\r
132 if (MemApertures[MemApertureIndex]->Limit > MemApertures[MemApertureIndex]->Base) {\r
133 Status = gDS->AddMemorySpace (\r
134 EfiGcdMemoryTypeMemoryMappedIo,\r
135 MemApertures[MemApertureIndex]->Base,\r
136 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
137 EFI_MEMORY_UC\r
138 );\r
139 ASSERT_EFI_ERROR (Status);\r
140 Status = gDS->SetMemorySpaceAttributes (\r
141 MemApertures[MemApertureIndex]->Base,\r
142 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
143 EFI_MEMORY_UC\r
144 );\r
145 ASSERT_EFI_ERROR (Status);\r
146 }\r
147 }\r
148 //\r
149 // Insert Root Bridge Handle Instance\r
150 //\r
151 Status = gBS->InstallMultipleProtocolInterfaces (\r
152 &RootBridge->Handle,\r
153 &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,\r
154 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,\r
155 NULL\r
156 );\r
157 ASSERT_EFI_ERROR (Status);\r
158 InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);\r
159 }\r
160 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
161 return Status;\r
162}\r
163\r
164/**\r
165 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().\r
166\r
167 @param HostBridge The Host Bridge Instance where the resource adjustment happens.\r
168**/\r
169VOID\r
170ResourceConflict (\r
171 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge\r
172 )\r
173{\r
174 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;\r
175 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
176 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
177 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
178 LIST_ENTRY *Link;\r
179 UINTN RootBridgeCount;\r
180 PCI_RESOURCE_TYPE Index;\r
181 PCI_RES_NODE *ResAllocNode;\r
182\r
183 RootBridgeCount = 0;\r
184 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
185 ; !IsNull (&HostBridge->RootBridges, Link)\r
186 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
187 ) {\r
188 RootBridgeCount++;\r
189 }\r
190\r
191 Resources = AllocatePool (\r
192 RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +\r
193 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
194 );\r
195 ASSERT (Resources != NULL);\r
196\r
197 for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources\r
198 ; !IsNull (&HostBridge->RootBridges, Link)\r
199 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
200 ) {\r
201 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
202 for (Index = TypeIo; Index < TypeMax; Index++) {\r
203 ResAllocNode = &RootBridge->ResAllocNode[Index];\r
204\r
205 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
206 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
207 Descriptor->AddrRangeMin = ResAllocNode->Base;\r
208 Descriptor->AddrRangeMax = ResAllocNode->Alignment;\r
209 Descriptor->AddrLen = ResAllocNode->Length;\r
210 switch (ResAllocNode->Type) {\r
211\r
212 case TypeIo:\r
213 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
214 break;\r
215\r
216 case TypePMem32:\r
217 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
218 case TypeMem32:\r
219 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
220 Descriptor->AddrSpaceGranularity = 32;\r
221 break;\r
222\r
223 case TypePMem64:\r
224 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
225 case TypeMem64:\r
226 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
227 Descriptor->AddrSpaceGranularity = 64;\r
228 break;\r
229\r
230 case TypeBus:\r
231 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
232 break;\r
233\r
234 default:\r
235 break;\r
236 }\r
237\r
238 Descriptor++;\r
239 }\r
240 //\r
241 // Terminate the root bridge resources.\r
242 //\r
243 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
244 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
245 End->Checksum = 0x0;\r
246\r
247 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);\r
248 }\r
249 //\r
250 // Terminate the host bridge resources.\r
251 //\r
252 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
253 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
254 End->Checksum = 0x0;\r
255\r
256 DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));\r
257 PciHostBridgeResourceConflict (HostBridge->Handle, Resources);\r
258 FreePool (Resources);\r
259}\r
260\r
63b90643
RN
261/**\r
262 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment\r
263 from GCD range [BaseAddress, Limit).\r
264\r
265 @param Mmio TRUE for MMIO and FALSE for IO.\r
266 @param Length Length of the resource to allocate.\r
267 @param BitsOfAlignment Alignment of the resource to allocate.\r
268 @param BaseAddress The starting address the allocation is from.\r
269 @param Limit The ending address the allocation is to.\r
270\r
271 @retval The base address of the allocated resource or MAX_UINT64 if allocation\r
272 fails.\r
273**/\r
4a50cf4e
RN
274UINT64\r
275AllocateResource (\r
276 BOOLEAN Mmio,\r
277 UINT64 Length,\r
278 UINTN BitsOfAlignment,\r
279 UINT64 BaseAddress,\r
280 UINT64 Limit\r
281 )\r
282{\r
283 EFI_STATUS Status;\r
284\r
285 if (BaseAddress < Limit) {\r
286 //\r
287 // Have to make sure Aligment is handled since we are doing direct address allocation\r
288 //\r
289 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));\r
290\r
291 while (BaseAddress + Length <= Limit + 1) {\r
292 if (Mmio) {\r
293 Status = gDS->AllocateMemorySpace (\r
294 EfiGcdAllocateAddress,\r
295 EfiGcdMemoryTypeMemoryMappedIo,\r
296 BitsOfAlignment,\r
297 Length,\r
298 &BaseAddress,\r
299 gImageHandle,\r
300 NULL\r
301 );\r
302 } else {\r
303 Status = gDS->AllocateIoSpace (\r
304 EfiGcdAllocateAddress,\r
305 EfiGcdIoTypeIo,\r
306 BitsOfAlignment,\r
307 Length,\r
308 &BaseAddress,\r
309 gImageHandle,\r
310 NULL\r
311 );\r
312 }\r
313\r
314 if (!EFI_ERROR (Status)) {\r
315 return BaseAddress;\r
316 }\r
317 BaseAddress += LShiftU64 (1, BitsOfAlignment);\r
318 }\r
319 }\r
320 return MAX_UINT64;\r
321}\r
63b90643 322\r
4a50cf4e
RN
323/**\r
324\r
325 Enter a certain phase of the PCI enumeration process.\r
326\r
327 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
328 @param Phase The phase during enumeration.\r
329\r
330 @retval EFI_SUCCESS Succeed.\r
331 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.\r
332 @retval EFI_NOT_READY Resources have not been submitted yet.\r
333\r
334**/\r
335EFI_STATUS\r
336EFIAPI\r
337NotifyPhase (\r
338 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
339 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
340 )\r
341{\r
342 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
343 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
344 LIST_ENTRY *Link;\r
345 EFI_PHYSICAL_ADDRESS BaseAddress;\r
346 UINT64 AddrLen;\r
347 UINTN BitsOfAlignment;\r
348 UINT64 Alignment;\r
349 EFI_STATUS Status;\r
350 EFI_STATUS ReturnStatus;\r
351 PCI_RESOURCE_TYPE Index;\r
352 PCI_RESOURCE_TYPE Index1;\r
353 PCI_RESOURCE_TYPE Index2;\r
354 BOOLEAN ResNodeHandled[TypeMax];\r
355 UINT64 MaxAlignment;\r
356\r
357 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
358\r
359 switch (Phase) {\r
360 case EfiPciHostBridgeBeginEnumeration:\r
361 if (!HostBridge->CanRestarted) {\r
362 return EFI_NOT_READY;\r
363 }\r
364 //\r
365 // Reset Root Bridge\r
366 //\r
367 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
368 ; !IsNull (&HostBridge->RootBridges, Link)\r
369 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
370 ) {\r
371 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
372 for (Index = TypeIo; Index < TypeMax; Index++) {\r
373 RootBridge->ResAllocNode[Index].Type = Index;\r
374 RootBridge->ResAllocNode[Index].Base = 0;\r
375 RootBridge->ResAllocNode[Index].Length = 0;\r
376 RootBridge->ResAllocNode[Index].Status = ResNone;\r
377\r
378 RootBridge->ResourceSubmitted = FALSE;\r
379 }\r
380 }\r
381\r
382 HostBridge->CanRestarted = TRUE;\r
383 break;\r
384\r
385 case EfiPciHostBridgeBeginBusAllocation:\r
386 //\r
387 // No specific action is required here, can perform any chipset specific programing\r
388 //\r
389 HostBridge->CanRestarted = FALSE;\r
390 break;\r
391\r
392 case EfiPciHostBridgeEndBusAllocation:\r
393 //\r
394 // No specific action is required here, can perform any chipset specific programing\r
395 //\r
396 break;\r
397\r
398 case EfiPciHostBridgeBeginResourceAllocation:\r
399 //\r
400 // No specific action is required here, can perform any chipset specific programing\r
401 //\r
402 break;\r
403\r
404 case EfiPciHostBridgeAllocateResources:\r
405 ReturnStatus = EFI_SUCCESS;\r
406\r
407 //\r
408 // Make sure the resource for all root bridges has been submitted.\r
409 //\r
410 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
411 ; !IsNull (&HostBridge->RootBridges, Link)\r
412 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
413 ) {\r
414 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
415 if (!RootBridge->ResourceSubmitted) {\r
416 return EFI_NOT_READY;\r
417 }\r
418 }\r
419\r
420 DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));\r
421 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
422 ; !IsNull (&HostBridge->RootBridges, Link)\r
423 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
424 ) {\r
425 for (Index = TypeIo; Index < TypeBus; Index++) {\r
426 ResNodeHandled[Index] = FALSE;\r
427 }\r
428\r
429 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
430 DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));\r
431\r
432 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
433 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {\r
434 ResNodeHandled[Index1] = TRUE;\r
435 } else {\r
436 //\r
437 // Allocate the resource node with max alignment at first\r
438 //\r
439 MaxAlignment = 0;\r
440 Index = TypeMax;\r
441 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {\r
442 if (ResNodeHandled[Index2]) {\r
443 continue;\r
444 }\r
445 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {\r
446 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;\r
447 Index = Index2;\r
448 }\r
449 }\r
450\r
451 ASSERT (Index < TypeMax);\r
452 ResNodeHandled[Index] = TRUE;\r
453 AddrLen = RootBridge->ResAllocNode[Index].Length;\r
454 Alignment = RootBridge->ResAllocNode[Index].Alignment;\r
455 BitsOfAlignment = LowBitSet64 (Alignment + 1);\r
456 BaseAddress = MAX_UINT64;\r
457\r
458 switch (Index) {\r
459 case TypeIo:\r
460 BaseAddress = AllocateResource (\r
461 FALSE,\r
462 RootBridge->ResAllocNode[Index].Length,\r
463 MIN (15, BitsOfAlignment),\r
464 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
465 RootBridge->Io.Limit\r
466 );\r
467 break;\r
468\r
469 case TypeMem64:\r
470 BaseAddress = AllocateResource (\r
471 TRUE,\r
472 RootBridge->ResAllocNode[Index].Length,\r
473 MIN (63, BitsOfAlignment),\r
474 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
475 RootBridge->MemAbove4G.Limit\r
476 );\r
477 if (BaseAddress != MAX_UINT64) {\r
478 break;\r
479 }\r
480 //\r
481 // If memory above 4GB is not available, try memory below 4GB\r
482 //\r
483\r
484 case TypeMem32:\r
485 BaseAddress = AllocateResource (\r
486 TRUE,\r
487 RootBridge->ResAllocNode[Index].Length,\r
488 MIN (31, BitsOfAlignment),\r
489 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
490 RootBridge->Mem.Limit\r
491 );\r
492 break;\r
493\r
494 case TypePMem64:\r
495 BaseAddress = AllocateResource (\r
496 TRUE,\r
497 RootBridge->ResAllocNode[Index].Length,\r
498 MIN (63, BitsOfAlignment),\r
499 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
500 RootBridge->PMemAbove4G.Limit\r
501 );\r
502 if (BaseAddress != MAX_UINT64) {\r
503 break;\r
504 }\r
505 //\r
506 // If memory above 4GB is not available, try memory below 4GB\r
507 //\r
508 case TypePMem32:\r
509 BaseAddress = AllocateResource (\r
510 TRUE,\r
511 RootBridge->ResAllocNode[Index].Length,\r
512 MIN (31, BitsOfAlignment),\r
513 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
514 RootBridge->PMem.Limit\r
515 );\r
516 break;\r
517\r
518 default:\r
519 ASSERT (FALSE);\r
520 break;\r
521 }\r
522\r
523 DEBUG ((DEBUG_INFO, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",\r
524 mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));\r
525 if (BaseAddress != MAX_UINT64) {\r
526 RootBridge->ResAllocNode[Index].Base = BaseAddress;\r
527 RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
528 DEBUG ((DEBUG_INFO, "Success\n"));\r
529 } else {\r
530 ReturnStatus = EFI_OUT_OF_RESOURCES;\r
531 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));\r
532 }\r
533 }\r
534 }\r
535 }\r
536\r
537 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {\r
538 ResourceConflict (HostBridge);\r
539 }\r
540\r
541 //\r
542 // Set resource to zero for nodes where allocation fails\r
543 //\r
544 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
545 ; !IsNull (&HostBridge->RootBridges, Link)\r
546 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
547 ) {\r
548 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
549 for (Index = TypeIo; Index < TypeBus; Index++) {\r
550 if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {\r
551 RootBridge->ResAllocNode[Index].Length = 0;\r
552 }\r
553 }\r
554 }\r
555 return ReturnStatus;\r
556\r
557 case EfiPciHostBridgeSetResources:\r
558 //\r
559 // HostBridgeInstance->CanRestarted = FALSE;\r
560 //\r
561 break;\r
562\r
563 case EfiPciHostBridgeFreeResources:\r
564 //\r
565 // HostBridgeInstance->CanRestarted = FALSE;\r
566 //\r
567 ReturnStatus = EFI_SUCCESS;\r
568 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
569 ; !IsNull (&HostBridge->RootBridges, Link)\r
570 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
571 ) {\r
572 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
573 for (Index = TypeIo; Index < TypeBus; Index++) {\r
574 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {\r
575 switch (Index) {\r
576 case TypeIo:\r
577 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
578 if (EFI_ERROR (Status)) {\r
579 ReturnStatus = Status;\r
580 }\r
581 break;\r
582\r
583 case TypeMem32:\r
584 case TypePMem32:\r
585 case TypeMem64:\r
586 case TypePMem64:\r
587 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
588 if (EFI_ERROR (Status)) {\r
589 ReturnStatus = Status;\r
590 }\r
591 break;\r
592\r
593 default:\r
594 ASSERT (FALSE);\r
595 break;\r
596 }\r
597\r
598 RootBridge->ResAllocNode[Index].Type = Index;\r
599 RootBridge->ResAllocNode[Index].Base = 0;\r
600 RootBridge->ResAllocNode[Index].Length = 0;\r
601 RootBridge->ResAllocNode[Index].Status = ResNone;\r
602 }\r
603 }\r
604\r
605 RootBridge->ResourceSubmitted = FALSE;\r
606 }\r
607\r
608 HostBridge->CanRestarted = TRUE;\r
609 return ReturnStatus;\r
610\r
611 case EfiPciHostBridgeEndResourceAllocation:\r
612 //\r
613 // The resource allocation phase is completed. No specific action is required\r
614 // here. This notification can be used to perform any chipset specific programming.\r
615 //\r
616 break;\r
617\r
618 case EfiPciHostBridgeEndEnumeration:\r
619 //\r
620 // The Host Bridge Enumeration is completed. No specific action is required here.\r
621 // This notification can be used to perform any chipset specific programming.\r
622 //\r
623 break;\r
624\r
625 default:\r
626 return EFI_INVALID_PARAMETER;\r
627 }\r
628\r
629 return EFI_SUCCESS;\r
630}\r
631\r
632/**\r
633\r
634 Return the device handle of the next PCI root bridge that is associated with\r
635 this Host Bridge.\r
636\r
637 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
638 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.\r
639 On input, it holds the RootBridgeHandle returned by the most\r
640 recent call to GetNextRootBridge().The handle for the first\r
641 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
642\r
643 @retval EFI_SUCCESS Succeed.\r
644 @retval EFI_NOT_FOUND Next PCI root bridge not found.\r
645 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.\r
646\r
647**/\r
648EFI_STATUS\r
649EFIAPI\r
650GetNextRootBridge (\r
651 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
652 IN OUT EFI_HANDLE *RootBridgeHandle\r
653 )\r
654{\r
655 BOOLEAN ReturnNext;\r
656 LIST_ENTRY *Link;\r
657 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
658 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
659\r
660 if (RootBridgeHandle == NULL) {\r
661 return EFI_INVALID_PARAMETER;\r
662 }\r
663\r
664 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
665 ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);\r
666\r
667 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
668 ; !IsNull (&HostBridge->RootBridges, Link)\r
669 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
670 ) {\r
671 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
672 if (ReturnNext) {\r
673 *RootBridgeHandle = RootBridge->Handle;\r
674 return EFI_SUCCESS;\r
675 }\r
676\r
677 ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);\r
678 }\r
679\r
680 if (ReturnNext) {\r
681 ASSERT (IsNull (&HostBridge->RootBridges, Link));\r
682 return EFI_NOT_FOUND;\r
683 } else {\r
684 return EFI_INVALID_PARAMETER;\r
685 }\r
686}\r
687\r
688/**\r
689\r
690 Returns the attributes of a PCI Root Bridge.\r
691\r
692 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
693 @param RootBridgeHandle The device handle of the PCI Root Bridge\r
694 that the caller is interested in.\r
695 @param Attributes The pointer to attributes of the PCI Root Bridge.\r
696\r
697 @retval EFI_SUCCESS Succeed.\r
698 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or\r
699 RootBridgeHandle is not an EFI_HANDLE\r
700 that was returned on a previous call to\r
701 GetNextRootBridge().\r
702\r
703**/\r
704EFI_STATUS\r
705EFIAPI\r
706GetAttributes (\r
707 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
708 IN EFI_HANDLE RootBridgeHandle,\r
709 OUT UINT64 *Attributes\r
710 )\r
711{\r
712 LIST_ENTRY *Link;\r
713 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
714 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
715\r
716 if (Attributes == NULL) {\r
717 return EFI_INVALID_PARAMETER;\r
718 }\r
719\r
720 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
721 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
722 ; !IsNull (&HostBridge->RootBridges, Link)\r
723 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
724 ) {\r
725 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
726 if (RootBridgeHandle == RootBridge->Handle) {\r
727 *Attributes = RootBridge->AllocationAttributes;\r
728 return EFI_SUCCESS;\r
729 }\r
730 }\r
731\r
732 return EFI_INVALID_PARAMETER;\r
733}\r
734\r
735/**\r
736\r
737 This is the request from the PCI enumerator to set up\r
738 the specified PCI Root Bridge for bus enumeration process.\r
739\r
740 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
741 @param RootBridgeHandle The PCI Root Bridge to be set up.\r
742 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.\r
743\r
744 @retval EFI_SUCCESS Succeed.\r
745 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
746 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
747\r
748**/\r
749EFI_STATUS\r
750EFIAPI\r
751StartBusEnumeration (\r
752 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
753 IN EFI_HANDLE RootBridgeHandle,\r
754 OUT VOID **Configuration\r
755 )\r
756{\r
757 LIST_ENTRY *Link;\r
758 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
759 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
760 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
761 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
762\r
763 if (Configuration == NULL) {\r
764 return EFI_INVALID_PARAMETER;\r
765 }\r
766\r
767 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
768 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
769 ; !IsNull (&HostBridge->RootBridges, Link)\r
770 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
771 ) {\r
772 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
773 if (RootBridgeHandle == RootBridge->Handle) {\r
774 *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
775 if (*Configuration == NULL) {\r
776 return EFI_OUT_OF_RESOURCES;\r
777 }\r
778\r
779 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;\r
780 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
781 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
782 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
783 Descriptor->GenFlag = 0;\r
784 Descriptor->SpecificFlag = 0;\r
785 Descriptor->AddrSpaceGranularity = 0;\r
786 Descriptor->AddrRangeMin = RootBridge->Bus.Base;\r
787 Descriptor->AddrRangeMax = 0;\r
788 Descriptor->AddrTranslationOffset = 0;\r
789 Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;\r
790\r
791 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
792 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
793 End->Checksum = 0x0;\r
794\r
795 return EFI_SUCCESS;\r
796 }\r
797 }\r
798\r
799 return EFI_INVALID_PARAMETER;\r
800}\r
801\r
802/**\r
803\r
804 This function programs the PCI Root Bridge hardware so that\r
805 it decodes the specified PCI bus range.\r
806\r
807 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
808 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.\r
809 @param Configuration The pointer to the PCI bus resource descriptor.\r
810\r
811 @retval EFI_SUCCESS Succeed.\r
812 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
813\r
814**/\r
815EFI_STATUS\r
816EFIAPI\r
817SetBusNumbers (\r
818 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
819 IN EFI_HANDLE RootBridgeHandle,\r
820 IN VOID *Configuration\r
821 )\r
822{\r
823 LIST_ENTRY *Link;\r
824 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
825 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
826 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
827 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
828 UINTN BusStart;\r
829 UINTN BusEnd;\r
830 UINTN BusLen;\r
831\r
832 if (Configuration == NULL) {\r
833 return EFI_INVALID_PARAMETER;\r
834 }\r
835\r
836 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
837 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
838\r
839 //\r
840 // Check the Configuration is valid\r
841 //\r
842 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||\r
843 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||\r
844 (End->Desc != ACPI_END_TAG_DESCRIPTOR)\r
845 ) {\r
846 return EFI_INVALID_PARAMETER;\r
847 }\r
848\r
849 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
850 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
851 ; !IsNull (&HostBridge->RootBridges, Link)\r
852 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
853 ) {\r
854 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
855 if (RootBridgeHandle == RootBridge->Handle) {\r
856 BusStart = (UINTN) Descriptor->AddrRangeMin;\r
857 BusLen = (UINTN) Descriptor->AddrLen;\r
858 BusEnd = BusStart + BusLen - 1;\r
859\r
860 if (Descriptor->AddrLen == 0) {\r
861 return EFI_INVALID_PARAMETER;\r
862 }\r
863\r
864 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||\r
865 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)\r
866 ) {\r
867 return EFI_INVALID_PARAMETER;\r
868 }\r
869 //\r
870 // Update the Bus Range\r
871 //\r
872 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;\r
873 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;\r
874 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;\r
875 return EFI_SUCCESS;\r
876 }\r
877 }\r
878\r
879 return EFI_INVALID_PARAMETER;\r
880}\r
881\r
882/**\r
883\r
884 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
885\r
886 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
887 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.\r
888 are being submitted.\r
889 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.\r
890\r
891 @retval EFI_SUCCESS Succeed.\r
892 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
893**/\r
894EFI_STATUS\r
895EFIAPI\r
896SubmitResources (\r
897 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
898 IN EFI_HANDLE RootBridgeHandle,\r
899 IN VOID *Configuration\r
900 )\r
901{\r
902 LIST_ENTRY *Link;\r
903 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
904 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
905 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
906 PCI_RESOURCE_TYPE Type;\r
907\r
908 //\r
909 // Check the input parameter: Configuration\r
910 //\r
911 if (Configuration == NULL) {\r
912 return EFI_INVALID_PARAMETER;\r
913 }\r
914\r
915 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
916 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
917 ; !IsNull (&HostBridge->RootBridges, Link)\r
918 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
919 ) {\r
920 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
921 if (RootBridgeHandle == RootBridge->Handle) {\r
922 DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));\r
923 //\r
924 // Check the resource descriptors.\r
925 // If the Configuration includes one or more invalid resource descriptors, all the resource\r
926 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.\r
927 //\r
928 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
929 if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
930 return EFI_INVALID_PARAMETER;\r
931 }\r
932\r
933 DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",\r
934 mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,\r
935 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""\r
936 ));\r
937 DEBUG ((EFI_D_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));\r
938 switch (Descriptor->ResType) {\r
939 case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
940 if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {\r
941 return EFI_INVALID_PARAMETER;\r
942 }\r
943 if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {\r
944 return EFI_INVALID_PARAMETER;\r
945 }\r
946 //\r
947 // If the PCI root bridge does not support separate windows for nonprefetchable and\r
948 // prefetchable memory, then the PCI bus driver needs to include requests for\r
949 // prefetchable memory in the nonprefetchable memory pool.\r
950 //\r
951 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&\r
952 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)\r
953 ) {\r
954 return EFI_INVALID_PARAMETER;\r
955 }\r
956 case ACPI_ADDRESS_SPACE_TYPE_IO:\r
957 //\r
958 // Check aligment, it should be of the form 2^n-1\r
959 //\r
960 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {\r
961 return EFI_INVALID_PARAMETER;\r
962 }\r
963 break;\r
964 default:\r
965 ASSERT (FALSE);\r
966 break;\r
967 }\r
968 }\r
969 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
970 return EFI_INVALID_PARAMETER;\r
971 }\r
972\r
973 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
974 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
975 if (Descriptor->AddrSpaceGranularity == 32) {\r
976 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
977 Type = TypePMem32;\r
978 } else {\r
979 Type = TypeMem32;\r
980 }\r
981 } else {\r
982 ASSERT (Descriptor->AddrSpaceGranularity == 64);\r
983 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
984 Type = TypePMem64;\r
985 } else {\r
986 Type = TypeMem64;\r
987 }\r
988 }\r
989 } else {\r
990 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);\r
991 Type = TypeIo;\r
992 }\r
993 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;\r
994 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;\r
995 RootBridge->ResAllocNode[Type].Status = ResSubmitted;\r
996 }\r
997 RootBridge->ResourceSubmitted = TRUE;\r
998 return EFI_SUCCESS;\r
999 }\r
1000 }\r
1001\r
1002 return EFI_INVALID_PARAMETER;\r
1003}\r
1004\r
1005/**\r
1006\r
1007 This function returns the proposed resource settings for the specified\r
1008 PCI Root Bridge.\r
1009\r
1010 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1011 @param RootBridgeHandle The PCI Root Bridge handle.\r
1012 @param Configuration The pointer to the pointer to the PCI I/O\r
1013 and memory resource descriptor.\r
1014\r
1015 @retval EFI_SUCCESS Succeed.\r
1016 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
1017 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
1018\r
1019**/\r
1020EFI_STATUS\r
1021EFIAPI\r
1022GetProposedResources (\r
1023 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1024 IN EFI_HANDLE RootBridgeHandle,\r
1025 OUT VOID **Configuration\r
1026 )\r
1027{\r
1028 LIST_ENTRY *Link;\r
1029 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1030 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1031 UINTN Index;\r
1032 UINTN Number;\r
1033 VOID *Buffer;\r
1034 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
1035 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
1036 UINT64 ResStatus;\r
1037\r
1038 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1039 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1040 ; !IsNull (&HostBridge->RootBridges, Link)\r
1041 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1042 ) {\r
1043 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1044 if (RootBridgeHandle == RootBridge->Handle) {\r
1045 for (Index = 0, Number = 0; Index < TypeBus; Index++) {\r
1046 if (RootBridge->ResAllocNode[Index].Status != ResNone) {\r
1047 Number++;\r
1048 }\r
1049 }\r
1050\r
1051 Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1052 if (Buffer == NULL) {\r
1053 return EFI_OUT_OF_RESOURCES;\r
1054 }\r
1055\r
1056 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;\r
1057 for (Index = 0; Index < TypeBus; Index++) {\r
1058 ResStatus = RootBridge->ResAllocNode[Index].Status;\r
1059 if (ResStatus != ResNone) {\r
1060 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1061 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;\r
1062 Descriptor->GenFlag = 0;\r
1063 Descriptor->AddrRangeMin = RootBridge->ResAllocNode[Index].Base;\r
1064 Descriptor->AddrRangeMax = 0;\r
1065 Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;\r
1066 Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;\r
1067\r
1068 switch (Index) {\r
1069\r
1070 case TypeIo:\r
1071 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1072 break;\r
1073\r
1074 case TypePMem32:\r
1075 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1076 case TypeMem32:\r
1077 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1078 Descriptor->AddrSpaceGranularity = 32;\r
1079 break;\r
1080\r
1081 case TypePMem64:\r
1082 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1083 case TypeMem64:\r
1084 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1085 Descriptor->AddrSpaceGranularity = 64;\r
1086 break;\r
1087 }\r
1088\r
1089 Descriptor++;\r
1090 }\r
1091 }\r
1092 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
1093 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1094 End->Checksum = 0;\r
1095\r
1096 *Configuration = Buffer;\r
1097\r
1098 return EFI_SUCCESS;\r
1099 }\r
1100 }\r
1101\r
1102 return EFI_INVALID_PARAMETER;\r
1103}\r
1104\r
1105/**\r
1106\r
1107 This function is called for all the PCI controllers that the PCI\r
1108 bus driver finds. Can be used to Preprogram the controller.\r
1109\r
1110 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1111 @param RootBridgeHandle The PCI Root Bridge handle.\r
1112 @param PciAddress Address of the controller on the PCI bus.\r
1113 @param Phase The Phase during resource allocation.\r
1114\r
1115 @retval EFI_SUCCESS Succeed.\r
1116 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
1117\r
1118**/\r
1119EFI_STATUS\r
1120EFIAPI\r
1121PreprocessController (\r
1122 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1123 IN EFI_HANDLE RootBridgeHandle,\r
1124 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
1125 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1126 )\r
1127{\r
1128 LIST_ENTRY *Link;\r
1129 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1130 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1131\r
1132 if ((UINT32) Phase > EfiPciBeforeResourceCollection) {\r
1133 return EFI_INVALID_PARAMETER;\r
1134 }\r
1135\r
1136 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1137 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1138 ; !IsNull (&HostBridge->RootBridges, Link)\r
1139 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1140 ) {\r
1141 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1142 if (RootBridgeHandle == RootBridge->Handle) {\r
1143 return EFI_SUCCESS;\r
1144 }\r
1145 }\r
1146\r
1147 return EFI_INVALID_PARAMETER;\r
1148}\r