]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg: Add generic PciHostBridgeDxe driver.
[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
261UINT64\r
262AllocateResource (\r
263 BOOLEAN Mmio,\r
264 UINT64 Length,\r
265 UINTN BitsOfAlignment,\r
266 UINT64 BaseAddress,\r
267 UINT64 Limit\r
268 )\r
269{\r
270 EFI_STATUS Status;\r
271\r
272 if (BaseAddress < Limit) {\r
273 //\r
274 // Have to make sure Aligment is handled since we are doing direct address allocation\r
275 //\r
276 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));\r
277\r
278 while (BaseAddress + Length <= Limit + 1) {\r
279 if (Mmio) {\r
280 Status = gDS->AllocateMemorySpace (\r
281 EfiGcdAllocateAddress,\r
282 EfiGcdMemoryTypeMemoryMappedIo,\r
283 BitsOfAlignment,\r
284 Length,\r
285 &BaseAddress,\r
286 gImageHandle,\r
287 NULL\r
288 );\r
289 } else {\r
290 Status = gDS->AllocateIoSpace (\r
291 EfiGcdAllocateAddress,\r
292 EfiGcdIoTypeIo,\r
293 BitsOfAlignment,\r
294 Length,\r
295 &BaseAddress,\r
296 gImageHandle,\r
297 NULL\r
298 );\r
299 }\r
300\r
301 if (!EFI_ERROR (Status)) {\r
302 return BaseAddress;\r
303 }\r
304 BaseAddress += LShiftU64 (1, BitsOfAlignment);\r
305 }\r
306 }\r
307 return MAX_UINT64;\r
308}\r
309/**\r
310\r
311 Enter a certain phase of the PCI enumeration process.\r
312\r
313 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
314 @param Phase The phase during enumeration.\r
315\r
316 @retval EFI_SUCCESS Succeed.\r
317 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.\r
318 @retval EFI_NOT_READY Resources have not been submitted yet.\r
319\r
320**/\r
321EFI_STATUS\r
322EFIAPI\r
323NotifyPhase (\r
324 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
325 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
326 )\r
327{\r
328 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
329 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
330 LIST_ENTRY *Link;\r
331 EFI_PHYSICAL_ADDRESS BaseAddress;\r
332 UINT64 AddrLen;\r
333 UINTN BitsOfAlignment;\r
334 UINT64 Alignment;\r
335 EFI_STATUS Status;\r
336 EFI_STATUS ReturnStatus;\r
337 PCI_RESOURCE_TYPE Index;\r
338 PCI_RESOURCE_TYPE Index1;\r
339 PCI_RESOURCE_TYPE Index2;\r
340 BOOLEAN ResNodeHandled[TypeMax];\r
341 UINT64 MaxAlignment;\r
342\r
343 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
344\r
345 switch (Phase) {\r
346 case EfiPciHostBridgeBeginEnumeration:\r
347 if (!HostBridge->CanRestarted) {\r
348 return EFI_NOT_READY;\r
349 }\r
350 //\r
351 // Reset Root Bridge\r
352 //\r
353 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
354 ; !IsNull (&HostBridge->RootBridges, Link)\r
355 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
356 ) {\r
357 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
358 for (Index = TypeIo; Index < TypeMax; Index++) {\r
359 RootBridge->ResAllocNode[Index].Type = Index;\r
360 RootBridge->ResAllocNode[Index].Base = 0;\r
361 RootBridge->ResAllocNode[Index].Length = 0;\r
362 RootBridge->ResAllocNode[Index].Status = ResNone;\r
363\r
364 RootBridge->ResourceSubmitted = FALSE;\r
365 }\r
366 }\r
367\r
368 HostBridge->CanRestarted = TRUE;\r
369 break;\r
370\r
371 case EfiPciHostBridgeBeginBusAllocation:\r
372 //\r
373 // No specific action is required here, can perform any chipset specific programing\r
374 //\r
375 HostBridge->CanRestarted = FALSE;\r
376 break;\r
377\r
378 case EfiPciHostBridgeEndBusAllocation:\r
379 //\r
380 // No specific action is required here, can perform any chipset specific programing\r
381 //\r
382 break;\r
383\r
384 case EfiPciHostBridgeBeginResourceAllocation:\r
385 //\r
386 // No specific action is required here, can perform any chipset specific programing\r
387 //\r
388 break;\r
389\r
390 case EfiPciHostBridgeAllocateResources:\r
391 ReturnStatus = EFI_SUCCESS;\r
392\r
393 //\r
394 // Make sure the resource for all root bridges has been submitted.\r
395 //\r
396 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
397 ; !IsNull (&HostBridge->RootBridges, Link)\r
398 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
399 ) {\r
400 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
401 if (!RootBridge->ResourceSubmitted) {\r
402 return EFI_NOT_READY;\r
403 }\r
404 }\r
405\r
406 DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));\r
407 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
408 ; !IsNull (&HostBridge->RootBridges, Link)\r
409 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
410 ) {\r
411 for (Index = TypeIo; Index < TypeBus; Index++) {\r
412 ResNodeHandled[Index] = FALSE;\r
413 }\r
414\r
415 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
416 DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));\r
417\r
418 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
419 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {\r
420 ResNodeHandled[Index1] = TRUE;\r
421 } else {\r
422 //\r
423 // Allocate the resource node with max alignment at first\r
424 //\r
425 MaxAlignment = 0;\r
426 Index = TypeMax;\r
427 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {\r
428 if (ResNodeHandled[Index2]) {\r
429 continue;\r
430 }\r
431 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {\r
432 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;\r
433 Index = Index2;\r
434 }\r
435 }\r
436\r
437 ASSERT (Index < TypeMax);\r
438 ResNodeHandled[Index] = TRUE;\r
439 AddrLen = RootBridge->ResAllocNode[Index].Length;\r
440 Alignment = RootBridge->ResAllocNode[Index].Alignment;\r
441 BitsOfAlignment = LowBitSet64 (Alignment + 1);\r
442 BaseAddress = MAX_UINT64;\r
443\r
444 switch (Index) {\r
445 case TypeIo:\r
446 BaseAddress = AllocateResource (\r
447 FALSE,\r
448 RootBridge->ResAllocNode[Index].Length,\r
449 MIN (15, BitsOfAlignment),\r
450 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
451 RootBridge->Io.Limit\r
452 );\r
453 break;\r
454\r
455 case TypeMem64:\r
456 BaseAddress = AllocateResource (\r
457 TRUE,\r
458 RootBridge->ResAllocNode[Index].Length,\r
459 MIN (63, BitsOfAlignment),\r
460 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
461 RootBridge->MemAbove4G.Limit\r
462 );\r
463 if (BaseAddress != MAX_UINT64) {\r
464 break;\r
465 }\r
466 //\r
467 // If memory above 4GB is not available, try memory below 4GB\r
468 //\r
469\r
470 case TypeMem32:\r
471 BaseAddress = AllocateResource (\r
472 TRUE,\r
473 RootBridge->ResAllocNode[Index].Length,\r
474 MIN (31, BitsOfAlignment),\r
475 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
476 RootBridge->Mem.Limit\r
477 );\r
478 break;\r
479\r
480 case TypePMem64:\r
481 BaseAddress = AllocateResource (\r
482 TRUE,\r
483 RootBridge->ResAllocNode[Index].Length,\r
484 MIN (63, BitsOfAlignment),\r
485 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
486 RootBridge->PMemAbove4G.Limit\r
487 );\r
488 if (BaseAddress != MAX_UINT64) {\r
489 break;\r
490 }\r
491 //\r
492 // If memory above 4GB is not available, try memory below 4GB\r
493 //\r
494 case TypePMem32:\r
495 BaseAddress = AllocateResource (\r
496 TRUE,\r
497 RootBridge->ResAllocNode[Index].Length,\r
498 MIN (31, BitsOfAlignment),\r
499 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
500 RootBridge->PMem.Limit\r
501 );\r
502 break;\r
503\r
504 default:\r
505 ASSERT (FALSE);\r
506 break;\r
507 }\r
508\r
509 DEBUG ((DEBUG_INFO, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",\r
510 mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));\r
511 if (BaseAddress != MAX_UINT64) {\r
512 RootBridge->ResAllocNode[Index].Base = BaseAddress;\r
513 RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
514 DEBUG ((DEBUG_INFO, "Success\n"));\r
515 } else {\r
516 ReturnStatus = EFI_OUT_OF_RESOURCES;\r
517 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));\r
518 }\r
519 }\r
520 }\r
521 }\r
522\r
523 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {\r
524 ResourceConflict (HostBridge);\r
525 }\r
526\r
527 //\r
528 // Set resource to zero for nodes where allocation fails\r
529 //\r
530 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
531 ; !IsNull (&HostBridge->RootBridges, Link)\r
532 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
533 ) {\r
534 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
535 for (Index = TypeIo; Index < TypeBus; Index++) {\r
536 if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {\r
537 RootBridge->ResAllocNode[Index].Length = 0;\r
538 }\r
539 }\r
540 }\r
541 return ReturnStatus;\r
542\r
543 case EfiPciHostBridgeSetResources:\r
544 //\r
545 // HostBridgeInstance->CanRestarted = FALSE;\r
546 //\r
547 break;\r
548\r
549 case EfiPciHostBridgeFreeResources:\r
550 //\r
551 // HostBridgeInstance->CanRestarted = FALSE;\r
552 //\r
553 ReturnStatus = EFI_SUCCESS;\r
554 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
555 ; !IsNull (&HostBridge->RootBridges, Link)\r
556 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
557 ) {\r
558 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
559 for (Index = TypeIo; Index < TypeBus; Index++) {\r
560 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {\r
561 switch (Index) {\r
562 case TypeIo:\r
563 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
564 if (EFI_ERROR (Status)) {\r
565 ReturnStatus = Status;\r
566 }\r
567 break;\r
568\r
569 case TypeMem32:\r
570 case TypePMem32:\r
571 case TypeMem64:\r
572 case TypePMem64:\r
573 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
574 if (EFI_ERROR (Status)) {\r
575 ReturnStatus = Status;\r
576 }\r
577 break;\r
578\r
579 default:\r
580 ASSERT (FALSE);\r
581 break;\r
582 }\r
583\r
584 RootBridge->ResAllocNode[Index].Type = Index;\r
585 RootBridge->ResAllocNode[Index].Base = 0;\r
586 RootBridge->ResAllocNode[Index].Length = 0;\r
587 RootBridge->ResAllocNode[Index].Status = ResNone;\r
588 }\r
589 }\r
590\r
591 RootBridge->ResourceSubmitted = FALSE;\r
592 }\r
593\r
594 HostBridge->CanRestarted = TRUE;\r
595 return ReturnStatus;\r
596\r
597 case EfiPciHostBridgeEndResourceAllocation:\r
598 //\r
599 // The resource allocation phase is completed. No specific action is required\r
600 // here. This notification can be used to perform any chipset specific programming.\r
601 //\r
602 break;\r
603\r
604 case EfiPciHostBridgeEndEnumeration:\r
605 //\r
606 // The Host Bridge Enumeration is completed. No specific action is required here.\r
607 // This notification can be used to perform any chipset specific programming.\r
608 //\r
609 break;\r
610\r
611 default:\r
612 return EFI_INVALID_PARAMETER;\r
613 }\r
614\r
615 return EFI_SUCCESS;\r
616}\r
617\r
618/**\r
619\r
620 Return the device handle of the next PCI root bridge that is associated with\r
621 this Host Bridge.\r
622\r
623 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
624 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.\r
625 On input, it holds the RootBridgeHandle returned by the most\r
626 recent call to GetNextRootBridge().The handle for the first\r
627 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
628\r
629 @retval EFI_SUCCESS Succeed.\r
630 @retval EFI_NOT_FOUND Next PCI root bridge not found.\r
631 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.\r
632\r
633**/\r
634EFI_STATUS\r
635EFIAPI\r
636GetNextRootBridge (\r
637 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
638 IN OUT EFI_HANDLE *RootBridgeHandle\r
639 )\r
640{\r
641 BOOLEAN ReturnNext;\r
642 LIST_ENTRY *Link;\r
643 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
644 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
645\r
646 if (RootBridgeHandle == NULL) {\r
647 return EFI_INVALID_PARAMETER;\r
648 }\r
649\r
650 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
651 ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);\r
652\r
653 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
654 ; !IsNull (&HostBridge->RootBridges, Link)\r
655 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
656 ) {\r
657 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
658 if (ReturnNext) {\r
659 *RootBridgeHandle = RootBridge->Handle;\r
660 return EFI_SUCCESS;\r
661 }\r
662\r
663 ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);\r
664 }\r
665\r
666 if (ReturnNext) {\r
667 ASSERT (IsNull (&HostBridge->RootBridges, Link));\r
668 return EFI_NOT_FOUND;\r
669 } else {\r
670 return EFI_INVALID_PARAMETER;\r
671 }\r
672}\r
673\r
674/**\r
675\r
676 Returns the attributes of a PCI Root Bridge.\r
677\r
678 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
679 @param RootBridgeHandle The device handle of the PCI Root Bridge\r
680 that the caller is interested in.\r
681 @param Attributes The pointer to attributes of the PCI Root Bridge.\r
682\r
683 @retval EFI_SUCCESS Succeed.\r
684 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or\r
685 RootBridgeHandle is not an EFI_HANDLE\r
686 that was returned on a previous call to\r
687 GetNextRootBridge().\r
688\r
689**/\r
690EFI_STATUS\r
691EFIAPI\r
692GetAttributes (\r
693 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
694 IN EFI_HANDLE RootBridgeHandle,\r
695 OUT UINT64 *Attributes\r
696 )\r
697{\r
698 LIST_ENTRY *Link;\r
699 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
700 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
701\r
702 if (Attributes == NULL) {\r
703 return EFI_INVALID_PARAMETER;\r
704 }\r
705\r
706 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
707 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
708 ; !IsNull (&HostBridge->RootBridges, Link)\r
709 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
710 ) {\r
711 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
712 if (RootBridgeHandle == RootBridge->Handle) {\r
713 *Attributes = RootBridge->AllocationAttributes;\r
714 return EFI_SUCCESS;\r
715 }\r
716 }\r
717\r
718 return EFI_INVALID_PARAMETER;\r
719}\r
720\r
721/**\r
722\r
723 This is the request from the PCI enumerator to set up\r
724 the specified PCI Root Bridge for bus enumeration process.\r
725\r
726 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
727 @param RootBridgeHandle The PCI Root Bridge to be set up.\r
728 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.\r
729\r
730 @retval EFI_SUCCESS Succeed.\r
731 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
732 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
733\r
734**/\r
735EFI_STATUS\r
736EFIAPI\r
737StartBusEnumeration (\r
738 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
739 IN EFI_HANDLE RootBridgeHandle,\r
740 OUT VOID **Configuration\r
741 )\r
742{\r
743 LIST_ENTRY *Link;\r
744 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
745 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
746 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
747 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
748\r
749 if (Configuration == NULL) {\r
750 return EFI_INVALID_PARAMETER;\r
751 }\r
752\r
753 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
754 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
755 ; !IsNull (&HostBridge->RootBridges, Link)\r
756 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
757 ) {\r
758 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
759 if (RootBridgeHandle == RootBridge->Handle) {\r
760 *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
761 if (*Configuration == NULL) {\r
762 return EFI_OUT_OF_RESOURCES;\r
763 }\r
764\r
765 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;\r
766 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
767 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
768 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
769 Descriptor->GenFlag = 0;\r
770 Descriptor->SpecificFlag = 0;\r
771 Descriptor->AddrSpaceGranularity = 0;\r
772 Descriptor->AddrRangeMin = RootBridge->Bus.Base;\r
773 Descriptor->AddrRangeMax = 0;\r
774 Descriptor->AddrTranslationOffset = 0;\r
775 Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;\r
776\r
777 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
778 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
779 End->Checksum = 0x0;\r
780\r
781 return EFI_SUCCESS;\r
782 }\r
783 }\r
784\r
785 return EFI_INVALID_PARAMETER;\r
786}\r
787\r
788/**\r
789\r
790 This function programs the PCI Root Bridge hardware so that\r
791 it decodes the specified PCI bus range.\r
792\r
793 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
794 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.\r
795 @param Configuration The pointer to the PCI bus resource descriptor.\r
796\r
797 @retval EFI_SUCCESS Succeed.\r
798 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
799\r
800**/\r
801EFI_STATUS\r
802EFIAPI\r
803SetBusNumbers (\r
804 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
805 IN EFI_HANDLE RootBridgeHandle,\r
806 IN VOID *Configuration\r
807 )\r
808{\r
809 LIST_ENTRY *Link;\r
810 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
811 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
812 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
813 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
814 UINTN BusStart;\r
815 UINTN BusEnd;\r
816 UINTN BusLen;\r
817\r
818 if (Configuration == NULL) {\r
819 return EFI_INVALID_PARAMETER;\r
820 }\r
821\r
822 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
823 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
824\r
825 //\r
826 // Check the Configuration is valid\r
827 //\r
828 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||\r
829 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||\r
830 (End->Desc != ACPI_END_TAG_DESCRIPTOR)\r
831 ) {\r
832 return EFI_INVALID_PARAMETER;\r
833 }\r
834\r
835 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
836 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
837 ; !IsNull (&HostBridge->RootBridges, Link)\r
838 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
839 ) {\r
840 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
841 if (RootBridgeHandle == RootBridge->Handle) {\r
842 BusStart = (UINTN) Descriptor->AddrRangeMin;\r
843 BusLen = (UINTN) Descriptor->AddrLen;\r
844 BusEnd = BusStart + BusLen - 1;\r
845\r
846 if (Descriptor->AddrLen == 0) {\r
847 return EFI_INVALID_PARAMETER;\r
848 }\r
849\r
850 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||\r
851 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)\r
852 ) {\r
853 return EFI_INVALID_PARAMETER;\r
854 }\r
855 //\r
856 // Update the Bus Range\r
857 //\r
858 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;\r
859 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;\r
860 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;\r
861 return EFI_SUCCESS;\r
862 }\r
863 }\r
864\r
865 return EFI_INVALID_PARAMETER;\r
866}\r
867\r
868/**\r
869\r
870 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
871\r
872 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
873 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.\r
874 are being submitted.\r
875 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.\r
876\r
877 @retval EFI_SUCCESS Succeed.\r
878 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
879**/\r
880EFI_STATUS\r
881EFIAPI\r
882SubmitResources (\r
883 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
884 IN EFI_HANDLE RootBridgeHandle,\r
885 IN VOID *Configuration\r
886 )\r
887{\r
888 LIST_ENTRY *Link;\r
889 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
890 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
891 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
892 PCI_RESOURCE_TYPE Type;\r
893\r
894 //\r
895 // Check the input parameter: Configuration\r
896 //\r
897 if (Configuration == NULL) {\r
898 return EFI_INVALID_PARAMETER;\r
899 }\r
900\r
901 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
902 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
903 ; !IsNull (&HostBridge->RootBridges, Link)\r
904 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
905 ) {\r
906 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
907 if (RootBridgeHandle == RootBridge->Handle) {\r
908 DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));\r
909 //\r
910 // Check the resource descriptors.\r
911 // If the Configuration includes one or more invalid resource descriptors, all the resource\r
912 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.\r
913 //\r
914 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
915 if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
916 return EFI_INVALID_PARAMETER;\r
917 }\r
918\r
919 DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",\r
920 mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,\r
921 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""\r
922 ));\r
923 DEBUG ((EFI_D_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));\r
924 switch (Descriptor->ResType) {\r
925 case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
926 if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {\r
927 return EFI_INVALID_PARAMETER;\r
928 }\r
929 if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {\r
930 return EFI_INVALID_PARAMETER;\r
931 }\r
932 //\r
933 // If the PCI root bridge does not support separate windows for nonprefetchable and\r
934 // prefetchable memory, then the PCI bus driver needs to include requests for\r
935 // prefetchable memory in the nonprefetchable memory pool.\r
936 //\r
937 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&\r
938 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)\r
939 ) {\r
940 return EFI_INVALID_PARAMETER;\r
941 }\r
942 case ACPI_ADDRESS_SPACE_TYPE_IO:\r
943 //\r
944 // Check aligment, it should be of the form 2^n-1\r
945 //\r
946 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {\r
947 return EFI_INVALID_PARAMETER;\r
948 }\r
949 break;\r
950 default:\r
951 ASSERT (FALSE);\r
952 break;\r
953 }\r
954 }\r
955 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
956 return EFI_INVALID_PARAMETER;\r
957 }\r
958\r
959 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
960 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
961 if (Descriptor->AddrSpaceGranularity == 32) {\r
962 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
963 Type = TypePMem32;\r
964 } else {\r
965 Type = TypeMem32;\r
966 }\r
967 } else {\r
968 ASSERT (Descriptor->AddrSpaceGranularity == 64);\r
969 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
970 Type = TypePMem64;\r
971 } else {\r
972 Type = TypeMem64;\r
973 }\r
974 }\r
975 } else {\r
976 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);\r
977 Type = TypeIo;\r
978 }\r
979 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;\r
980 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;\r
981 RootBridge->ResAllocNode[Type].Status = ResSubmitted;\r
982 }\r
983 RootBridge->ResourceSubmitted = TRUE;\r
984 return EFI_SUCCESS;\r
985 }\r
986 }\r
987\r
988 return EFI_INVALID_PARAMETER;\r
989}\r
990\r
991/**\r
992\r
993 This function returns the proposed resource settings for the specified\r
994 PCI Root Bridge.\r
995\r
996 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
997 @param RootBridgeHandle The PCI Root Bridge handle.\r
998 @param Configuration The pointer to the pointer to the PCI I/O\r
999 and memory resource descriptor.\r
1000\r
1001 @retval EFI_SUCCESS Succeed.\r
1002 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
1003 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
1004\r
1005**/\r
1006EFI_STATUS\r
1007EFIAPI\r
1008GetProposedResources (\r
1009 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1010 IN EFI_HANDLE RootBridgeHandle,\r
1011 OUT VOID **Configuration\r
1012 )\r
1013{\r
1014 LIST_ENTRY *Link;\r
1015 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1016 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1017 UINTN Index;\r
1018 UINTN Number;\r
1019 VOID *Buffer;\r
1020 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
1021 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
1022 UINT64 ResStatus;\r
1023\r
1024 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1025 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1026 ; !IsNull (&HostBridge->RootBridges, Link)\r
1027 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1028 ) {\r
1029 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1030 if (RootBridgeHandle == RootBridge->Handle) {\r
1031 for (Index = 0, Number = 0; Index < TypeBus; Index++) {\r
1032 if (RootBridge->ResAllocNode[Index].Status != ResNone) {\r
1033 Number++;\r
1034 }\r
1035 }\r
1036\r
1037 Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1038 if (Buffer == NULL) {\r
1039 return EFI_OUT_OF_RESOURCES;\r
1040 }\r
1041\r
1042 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;\r
1043 for (Index = 0; Index < TypeBus; Index++) {\r
1044 ResStatus = RootBridge->ResAllocNode[Index].Status;\r
1045 if (ResStatus != ResNone) {\r
1046 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1047 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;\r
1048 Descriptor->GenFlag = 0;\r
1049 Descriptor->AddrRangeMin = RootBridge->ResAllocNode[Index].Base;\r
1050 Descriptor->AddrRangeMax = 0;\r
1051 Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;\r
1052 Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;\r
1053\r
1054 switch (Index) {\r
1055\r
1056 case TypeIo:\r
1057 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1058 break;\r
1059\r
1060 case TypePMem32:\r
1061 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1062 case TypeMem32:\r
1063 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1064 Descriptor->AddrSpaceGranularity = 32;\r
1065 break;\r
1066\r
1067 case TypePMem64:\r
1068 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1069 case TypeMem64:\r
1070 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1071 Descriptor->AddrSpaceGranularity = 64;\r
1072 break;\r
1073 }\r
1074\r
1075 Descriptor++;\r
1076 }\r
1077 }\r
1078 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
1079 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1080 End->Checksum = 0;\r
1081\r
1082 *Configuration = Buffer;\r
1083\r
1084 return EFI_SUCCESS;\r
1085 }\r
1086 }\r
1087\r
1088 return EFI_INVALID_PARAMETER;\r
1089}\r
1090\r
1091/**\r
1092\r
1093 This function is called for all the PCI controllers that the PCI\r
1094 bus driver finds. Can be used to Preprogram the controller.\r
1095\r
1096 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1097 @param RootBridgeHandle The PCI Root Bridge handle.\r
1098 @param PciAddress Address of the controller on the PCI bus.\r
1099 @param Phase The Phase during resource allocation.\r
1100\r
1101 @retval EFI_SUCCESS Succeed.\r
1102 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
1103\r
1104**/\r
1105EFI_STATUS\r
1106EFIAPI\r
1107PreprocessController (\r
1108 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1109 IN EFI_HANDLE RootBridgeHandle,\r
1110 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
1111 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1112 )\r
1113{\r
1114 LIST_ENTRY *Link;\r
1115 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1116 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1117\r
1118 if ((UINT32) Phase > EfiPciBeforeResourceCollection) {\r
1119 return EFI_INVALID_PARAMETER;\r
1120 }\r
1121\r
1122 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1123 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1124 ; !IsNull (&HostBridge->RootBridges, Link)\r
1125 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1126 ) {\r
1127 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1128 if (RootBridgeHandle == RootBridge->Handle) {\r
1129 return EFI_SUCCESS;\r
1130 }\r
1131 }\r
1132\r
1133 return EFI_INVALID_PARAMETER;\r
1134}\r