]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciHostBridge.c
... / ...
CommitLineData
1/** @file\r
2\r
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
4\r
5Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "PciHostBridge.h"\r
11#include "PciRootBridge.h"\r
12#include "PciHostResource.h"\r
13\r
14EFI_CPU_IO2_PROTOCOL *mCpuIo;\r
15\r
16GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {\r
17 L"Mem", L"I/O", L"Bus"\r
18};\r
19GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {\r
20 L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
21};\r
22\r
23EDKII_IOMMU_PROTOCOL *mIoMmu;\r
24EFI_EVENT mIoMmuEvent;\r
25VOID *mIoMmuRegistration;\r
26\r
27/**\r
28 This routine gets translation offset from a root bridge instance by resource type.\r
29\r
30 @param RootBridge The Root Bridge Instance for the resources.\r
31 @param ResourceType The Resource Type of the translation offset.\r
32\r
33 @retval The Translation Offset of the specified resource.\r
34**/\r
35UINT64\r
36GetTranslationByResourceType (\r
37 IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge,\r
38 IN PCI_RESOURCE_TYPE ResourceType\r
39 )\r
40{\r
41 switch (ResourceType) {\r
42 case TypeIo:\r
43 return RootBridge->Io.Translation;\r
44 case TypeMem32:\r
45 return RootBridge->Mem.Translation;\r
46 case TypePMem32:\r
47 return RootBridge->PMem.Translation;\r
48 case TypeMem64:\r
49 return RootBridge->MemAbove4G.Translation;\r
50 case TypePMem64:\r
51 return RootBridge->PMemAbove4G.Translation;\r
52 case TypeBus:\r
53 return RootBridge->Bus.Translation;\r
54 default:\r
55 ASSERT (FALSE);\r
56 return 0;\r
57 }\r
58}\r
59\r
60/**\r
61 Ensure the compatibility of an IO space descriptor with the IO aperture.\r
62\r
63 The IO space descriptor can come from the GCD IO space map, or it can\r
64 represent a gap between two neighboring IO space descriptors. In the latter\r
65 case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent.\r
66\r
67 If the IO space descriptor already has type EfiGcdIoTypeIo, then no action is\r
68 taken -- it is by definition compatible with the aperture.\r
69\r
70 Otherwise, the intersection of the IO space descriptor is calculated with the\r
71 aperture. If the intersection is the empty set (no overlap), no action is\r
72 taken; the IO space descriptor is compatible with the aperture.\r
73\r
74 Otherwise, the type of the descriptor is investigated again. If the type is\r
75 EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with\r
76 such a type), then an attempt is made to add the intersection as IO space to\r
77 the GCD IO space map. This ensures continuity for the aperture, and the\r
78 descriptor is deemed compatible with the aperture.\r
79\r
80 Otherwise, the IO space descriptor is incompatible with the IO aperture.\r
81\r
82 @param[in] Base Base address of the aperture.\r
83 @param[in] Length Length of the aperture.\r
84 @param[in] Descriptor The descriptor to ensure compatibility with the\r
85 aperture for.\r
86\r
87 @retval EFI_SUCCESS The descriptor is compatible. The GCD IO space\r
88 map may have been updated, for continuity\r
89 within the aperture.\r
90 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.\r
91 @return Error codes from gDS->AddIoSpace().\r
92**/\r
93EFI_STATUS\r
94IntersectIoDescriptor (\r
95 IN UINT64 Base,\r
96 IN UINT64 Length,\r
97 IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor\r
98 )\r
99{\r
100 UINT64 IntersectionBase;\r
101 UINT64 IntersectionEnd;\r
102 EFI_STATUS Status;\r
103\r
104 if (Descriptor->GcdIoType == EfiGcdIoTypeIo) {\r
105 return EFI_SUCCESS;\r
106 }\r
107\r
108 IntersectionBase = MAX (Base, Descriptor->BaseAddress);\r
109 IntersectionEnd = MIN (\r
110 Base + Length,\r
111 Descriptor->BaseAddress + Descriptor->Length\r
112 );\r
113 if (IntersectionBase >= IntersectionEnd) {\r
114 //\r
115 // The descriptor and the aperture don't overlap.\r
116 //\r
117 return EFI_SUCCESS;\r
118 }\r
119\r
120 if (Descriptor->GcdIoType == EfiGcdIoTypeNonExistent) {\r
121 Status = gDS->AddIoSpace (\r
122 EfiGcdIoTypeIo,\r
123 IntersectionBase,\r
124 IntersectionEnd - IntersectionBase\r
125 );\r
126\r
127 DEBUG ((\r
128 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
129 "%a: %a: add [%Lx, %Lx): %r\n",\r
130 gEfiCallerBaseName,\r
131 __FUNCTION__,\r
132 IntersectionBase,\r
133 IntersectionEnd,\r
134 Status\r
135 ));\r
136 return Status;\r
137 }\r
138\r
139 DEBUG ((\r
140 DEBUG_ERROR,\r
141 "%a: %a: desc [%Lx, %Lx) type %u conflicts with "\r
142 "aperture [%Lx, %Lx)\n",\r
143 gEfiCallerBaseName,\r
144 __FUNCTION__,\r
145 Descriptor->BaseAddress,\r
146 Descriptor->BaseAddress + Descriptor->Length,\r
147 (UINT32)Descriptor->GcdIoType,\r
148 Base,\r
149 Base + Length\r
150 ));\r
151 return EFI_INVALID_PARAMETER;\r
152}\r
153\r
154/**\r
155 Add IO space to GCD.\r
156 The routine checks the GCD database and only adds those which are\r
157 not added in the specified range to GCD.\r
158\r
159 @param Base Base address of the IO space.\r
160 @param Length Length of the IO space.\r
161\r
162 @retval EFI_SUCCES The IO space was added successfully.\r
163**/\r
164EFI_STATUS\r
165AddIoSpace (\r
166 IN UINT64 Base,\r
167 IN UINT64 Length\r
168 )\r
169{\r
170 EFI_STATUS Status;\r
171 UINTN Index;\r
172 UINTN NumberOfDescriptors;\r
173 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;\r
174\r
175 Status = gDS->GetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);\r
176 if (EFI_ERROR (Status)) {\r
177 DEBUG ((\r
178 DEBUG_ERROR,\r
179 "%a: %a: GetIoSpaceMap(): %r\n",\r
180 gEfiCallerBaseName,\r
181 __FUNCTION__,\r
182 Status\r
183 ));\r
184 return Status;\r
185 }\r
186\r
187 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
188 Status = IntersectIoDescriptor (Base, Length, &IoSpaceMap[Index]);\r
189 if (EFI_ERROR (Status)) {\r
190 goto FreeIoSpaceMap;\r
191 }\r
192 }\r
193\r
194 DEBUG_CODE_BEGIN ();\r
195 //\r
196 // Make sure there are adjacent descriptors covering [Base, Base + Length).\r
197 // It is possible that they have not been merged; merging can be prevented\r
198 // by allocation.\r
199 //\r
200 UINT64 CheckBase;\r
201 EFI_STATUS CheckStatus;\r
202 EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor;\r
203\r
204 for (CheckBase = Base;\r
205 CheckBase < Base + Length;\r
206 CheckBase = Descriptor.BaseAddress + Descriptor.Length)\r
207 {\r
208 CheckStatus = gDS->GetIoSpaceDescriptor (CheckBase, &Descriptor);\r
209 ASSERT_EFI_ERROR (CheckStatus);\r
210 ASSERT (Descriptor.GcdIoType == EfiGcdIoTypeIo);\r
211 }\r
212\r
213 DEBUG_CODE_END ();\r
214\r
215FreeIoSpaceMap:\r
216 FreePool (IoSpaceMap);\r
217\r
218 return Status;\r
219}\r
220\r
221/**\r
222 Ensure the compatibility of a memory space descriptor with the MMIO aperture.\r
223\r
224 The memory space descriptor can come from the GCD memory space map, or it can\r
225 represent a gap between two neighboring memory space descriptors. In the\r
226 latter case, the GcdMemoryType field is expected to be\r
227 EfiGcdMemoryTypeNonExistent.\r
228\r
229 If the memory space descriptor already has type\r
230 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the\r
231 required capabilities, then no action is taken -- it is by definition\r
232 compatible with the aperture.\r
233\r
234 Otherwise, the intersection of the memory space descriptor is calculated with\r
235 the aperture. If the intersection is the empty set (no overlap), no action is\r
236 taken; the memory space descriptor is compatible with the aperture.\r
237\r
238 Otherwise, the type of the descriptor is investigated again. If the type is\r
239 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with\r
240 such a type), then an attempt is made to add the intersection as MMIO space\r
241 to the GCD memory space map, with the specified capabilities. This ensures\r
242 continuity for the aperture, and the descriptor is deemed compatible with the\r
243 aperture.\r
244\r
245 Otherwise, the memory space descriptor is incompatible with the MMIO\r
246 aperture.\r
247\r
248 @param[in] Base Base address of the aperture.\r
249 @param[in] Length Length of the aperture.\r
250 @param[in] Capabilities Capabilities required by the aperture.\r
251 @param[in] Descriptor The descriptor to ensure compatibility with the\r
252 aperture for.\r
253\r
254 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory\r
255 space map may have been updated, for\r
256 continuity within the aperture.\r
257 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.\r
258 @return Error codes from gDS->AddMemorySpace().\r
259**/\r
260EFI_STATUS\r
261IntersectMemoryDescriptor (\r
262 IN UINT64 Base,\r
263 IN UINT64 Length,\r
264 IN UINT64 Capabilities,\r
265 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor\r
266 )\r
267{\r
268 UINT64 IntersectionBase;\r
269 UINT64 IntersectionEnd;\r
270 EFI_STATUS Status;\r
271\r
272 if ((Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&\r
273 ((Descriptor->Capabilities & Capabilities) == Capabilities))\r
274 {\r
275 return EFI_SUCCESS;\r
276 }\r
277\r
278 IntersectionBase = MAX (Base, Descriptor->BaseAddress);\r
279 IntersectionEnd = MIN (\r
280 Base + Length,\r
281 Descriptor->BaseAddress + Descriptor->Length\r
282 );\r
283 if (IntersectionBase >= IntersectionEnd) {\r
284 //\r
285 // The descriptor and the aperture don't overlap.\r
286 //\r
287 return EFI_SUCCESS;\r
288 }\r
289\r
290 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
291 Status = gDS->AddMemorySpace (\r
292 EfiGcdMemoryTypeMemoryMappedIo,\r
293 IntersectionBase,\r
294 IntersectionEnd - IntersectionBase,\r
295 Capabilities\r
296 );\r
297\r
298 DEBUG ((\r
299 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
300 "%a: %a: add [%Lx, %Lx): %r\n",\r
301 gEfiCallerBaseName,\r
302 __FUNCTION__,\r
303 IntersectionBase,\r
304 IntersectionEnd,\r
305 Status\r
306 ));\r
307 return Status;\r
308 }\r
309\r
310 DEBUG ((\r
311 DEBUG_ERROR,\r
312 "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
313 "with aperture [%Lx, %Lx) cap %Lx\n",\r
314 gEfiCallerBaseName,\r
315 __FUNCTION__,\r
316 Descriptor->BaseAddress,\r
317 Descriptor->BaseAddress + Descriptor->Length,\r
318 (UINT32)Descriptor->GcdMemoryType,\r
319 Descriptor->Capabilities,\r
320 Base,\r
321 Base + Length,\r
322 Capabilities\r
323 ));\r
324 return EFI_INVALID_PARAMETER;\r
325}\r
326\r
327/**\r
328 Add MMIO space to GCD.\r
329 The routine checks the GCD database and only adds those which are\r
330 not added in the specified range to GCD.\r
331\r
332 @param Base Base address of the MMIO space.\r
333 @param Length Length of the MMIO space.\r
334 @param Capabilities Capabilities of the MMIO space.\r
335\r
336 @retval EFI_SUCCES The MMIO space was added successfully.\r
337**/\r
338EFI_STATUS\r
339AddMemoryMappedIoSpace (\r
340 IN UINT64 Base,\r
341 IN UINT64 Length,\r
342 IN UINT64 Capabilities\r
343 )\r
344{\r
345 EFI_STATUS Status;\r
346 UINTN Index;\r
347 UINTN NumberOfDescriptors;\r
348 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
349\r
350 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
351 if (EFI_ERROR (Status)) {\r
352 DEBUG ((\r
353 DEBUG_ERROR,\r
354 "%a: %a: GetMemorySpaceMap(): %r\n",\r
355 gEfiCallerBaseName,\r
356 __FUNCTION__,\r
357 Status\r
358 ));\r
359 return Status;\r
360 }\r
361\r
362 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
363 Status = IntersectMemoryDescriptor (\r
364 Base,\r
365 Length,\r
366 Capabilities,\r
367 &MemorySpaceMap[Index]\r
368 );\r
369 if (EFI_ERROR (Status)) {\r
370 goto FreeMemorySpaceMap;\r
371 }\r
372 }\r
373\r
374 DEBUG_CODE_BEGIN ();\r
375 //\r
376 // Make sure there are adjacent descriptors covering [Base, Base + Length).\r
377 // It is possible that they have not been merged; merging can be prevented\r
378 // by allocation and different capabilities.\r
379 //\r
380 UINT64 CheckBase;\r
381 EFI_STATUS CheckStatus;\r
382 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
383\r
384 for (CheckBase = Base;\r
385 CheckBase < Base + Length;\r
386 CheckBase = Descriptor.BaseAddress + Descriptor.Length)\r
387 {\r
388 CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);\r
389 ASSERT_EFI_ERROR (CheckStatus);\r
390 ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);\r
391 ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);\r
392 }\r
393\r
394 DEBUG_CODE_END ();\r
395\r
396FreeMemorySpaceMap:\r
397 FreePool (MemorySpaceMap);\r
398\r
399 return Status;\r
400}\r
401\r
402/**\r
403 Event notification that is fired when IOMMU protocol is installed.\r
404\r
405 @param Event The Event that is being processed.\r
406 @param Context Event Context.\r
407\r
408**/\r
409VOID\r
410EFIAPI\r
411IoMmuProtocolCallback (\r
412 IN EFI_EVENT Event,\r
413 IN VOID *Context\r
414 )\r
415{\r
416 EFI_STATUS Status;\r
417\r
418 Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);\r
419 if (!EFI_ERROR (Status)) {\r
420 gBS->CloseEvent (mIoMmuEvent);\r
421 }\r
422}\r
423\r
424/**\r
425\r
426 Entry point of this driver.\r
427\r
428 @param ImageHandle Image handle of this driver.\r
429 @param SystemTable Pointer to standard EFI system table.\r
430\r
431 @retval EFI_SUCCESS Succeed.\r
432 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.\r
433\r
434**/\r
435EFI_STATUS\r
436EFIAPI\r
437InitializePciHostBridge (\r
438 IN EFI_HANDLE ImageHandle,\r
439 IN EFI_SYSTEM_TABLE *SystemTable\r
440 )\r
441{\r
442 EFI_STATUS Status;\r
443 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
444 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
445 PCI_ROOT_BRIDGE *RootBridges;\r
446 UINTN RootBridgeCount;\r
447 UINTN Index;\r
448 PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];\r
449 UINTN MemApertureIndex;\r
450 BOOLEAN ResourceAssigned;\r
451 LIST_ENTRY *Link;\r
452 UINT64 HostAddress;\r
453\r
454 RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);\r
455 if ((RootBridges == NULL) || (RootBridgeCount == 0)) {\r
456 return EFI_UNSUPPORTED;\r
457 }\r
458\r
459 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo);\r
460 ASSERT_EFI_ERROR (Status);\r
461\r
462 //\r
463 // Most systems in the world including complex servers have only one Host Bridge.\r
464 //\r
465 HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));\r
466 ASSERT (HostBridge != NULL);\r
467\r
468 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;\r
469 HostBridge->CanRestarted = TRUE;\r
470 InitializeListHead (&HostBridge->RootBridges);\r
471 ResourceAssigned = FALSE;\r
472\r
473 //\r
474 // Create Root Bridge Device Handle in this Host Bridge\r
475 //\r
476 for (Index = 0; Index < RootBridgeCount; Index++) {\r
477 //\r
478 // Create Root Bridge Handle Instance\r
479 //\r
480 RootBridge = CreateRootBridge (&RootBridges[Index]);\r
481 ASSERT (RootBridge != NULL);\r
482 if (RootBridge == NULL) {\r
483 continue;\r
484 }\r
485\r
486 //\r
487 // Make sure all root bridges share the same ResourceAssigned value.\r
488 //\r
489 if (Index == 0) {\r
490 ResourceAssigned = RootBridges[Index].ResourceAssigned;\r
491 } else {\r
492 ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);\r
493 }\r
494\r
495 if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {\r
496 //\r
497 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.\r
498 // For GCD resource manipulation, we need to use host address.\r
499 //\r
500 HostAddress = TO_HOST_ADDRESS (\r
501 RootBridges[Index].Io.Base,\r
502 RootBridges[Index].Io.Translation\r
503 );\r
504\r
505 Status = AddIoSpace (\r
506 HostAddress,\r
507 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1\r
508 );\r
509 ASSERT_EFI_ERROR (Status);\r
510 if (ResourceAssigned) {\r
511 Status = gDS->AllocateIoSpace (\r
512 EfiGcdAllocateAddress,\r
513 EfiGcdIoTypeIo,\r
514 0,\r
515 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,\r
516 &HostAddress,\r
517 gImageHandle,\r
518 NULL\r
519 );\r
520 ASSERT_EFI_ERROR (Status);\r
521 }\r
522 }\r
523\r
524 //\r
525 // Add all the Mem/PMem aperture to GCD\r
526 // Mem/PMem shouldn't overlap with each other\r
527 // Root bridge which needs to combine MEM and PMEM should only report\r
528 // the MEM aperture in Mem\r
529 //\r
530 MemApertures[0] = &RootBridges[Index].Mem;\r
531 MemApertures[1] = &RootBridges[Index].MemAbove4G;\r
532 MemApertures[2] = &RootBridges[Index].PMem;\r
533 MemApertures[3] = &RootBridges[Index].PMemAbove4G;\r
534\r
535 for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {\r
536 if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {\r
537 //\r
538 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.\r
539 // For GCD resource manipulation, we need to use host address.\r
540 //\r
541 HostAddress = TO_HOST_ADDRESS (\r
542 MemApertures[MemApertureIndex]->Base,\r
543 MemApertures[MemApertureIndex]->Translation\r
544 );\r
545 Status = AddMemoryMappedIoSpace (\r
546 HostAddress,\r
547 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
548 EFI_MEMORY_UC\r
549 );\r
550 ASSERT_EFI_ERROR (Status);\r
551 Status = gDS->SetMemorySpaceAttributes (\r
552 HostAddress,\r
553 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
554 EFI_MEMORY_UC\r
555 );\r
556 if (EFI_ERROR (Status)) {\r
557 DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));\r
558 }\r
559\r
560 if (ResourceAssigned) {\r
561 Status = gDS->AllocateMemorySpace (\r
562 EfiGcdAllocateAddress,\r
563 EfiGcdMemoryTypeMemoryMappedIo,\r
564 0,\r
565 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,\r
566 &HostAddress,\r
567 gImageHandle,\r
568 NULL\r
569 );\r
570 ASSERT_EFI_ERROR (Status);\r
571 }\r
572 }\r
573 }\r
574\r
575 //\r
576 // Insert Root Bridge Handle Instance\r
577 //\r
578 InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);\r
579 }\r
580\r
581 //\r
582 // When resources were assigned, it's not needed to expose\r
583 // PciHostBridgeResourceAllocation protocol.\r
584 //\r
585 if (!ResourceAssigned) {\r
586 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;\r
587 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;\r
588 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;\r
589 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;\r
590 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;\r
591 HostBridge->ResAlloc.SubmitResources = SubmitResources;\r
592 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;\r
593 HostBridge->ResAlloc.PreprocessController = PreprocessController;\r
594\r
595 Status = gBS->InstallMultipleProtocolInterfaces (\r
596 &HostBridge->Handle,\r
597 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
598 &HostBridge->ResAlloc,\r
599 NULL\r
600 );\r
601 ASSERT_EFI_ERROR (Status);\r
602 }\r
603\r
604 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
605 ; !IsNull (&HostBridge->RootBridges, Link)\r
606 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
607 )\r
608 {\r
609 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
610 RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;\r
611\r
612 Status = gBS->InstallMultipleProtocolInterfaces (\r
613 &RootBridge->Handle,\r
614 &gEfiDevicePathProtocolGuid,\r
615 RootBridge->DevicePath,\r
616 &gEfiPciRootBridgeIoProtocolGuid,\r
617 &RootBridge->RootBridgeIo,\r
618 NULL\r
619 );\r
620 ASSERT_EFI_ERROR (Status);\r
621 }\r
622\r
623 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
624\r
625 if (!EFI_ERROR (Status)) {\r
626 mIoMmuEvent = EfiCreateProtocolNotifyEvent (\r
627 &gEdkiiIoMmuProtocolGuid,\r
628 TPL_CALLBACK,\r
629 IoMmuProtocolCallback,\r
630 NULL,\r
631 &mIoMmuRegistration\r
632 );\r
633 }\r
634\r
635 return Status;\r
636}\r
637\r
638/**\r
639 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().\r
640\r
641 @param HostBridge The Host Bridge Instance where the resource adjustment happens.\r
642**/\r
643VOID\r
644ResourceConflict (\r
645 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge\r
646 )\r
647{\r
648 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;\r
649 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
650 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
651 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
652 LIST_ENTRY *Link;\r
653 UINTN RootBridgeCount;\r
654 PCI_RESOURCE_TYPE Index;\r
655 PCI_RES_NODE *ResAllocNode;\r
656\r
657 RootBridgeCount = 0;\r
658 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
659 ; !IsNull (&HostBridge->RootBridges, Link)\r
660 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
661 )\r
662 {\r
663 RootBridgeCount++;\r
664 }\r
665\r
666 Resources = AllocatePool (\r
667 RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +\r
668 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
669 );\r
670 ASSERT (Resources != NULL);\r
671\r
672 for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources\r
673 ; !IsNull (&HostBridge->RootBridges, Link)\r
674 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
675 )\r
676 {\r
677 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
678 for (Index = TypeIo; Index < TypeMax; Index++) {\r
679 ResAllocNode = &RootBridge->ResAllocNode[Index];\r
680\r
681 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
682 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
683 Descriptor->AddrRangeMin = ResAllocNode->Base;\r
684 Descriptor->AddrRangeMax = ResAllocNode->Alignment;\r
685 Descriptor->AddrLen = ResAllocNode->Length;\r
686 Descriptor->SpecificFlag = 0;\r
687 switch (ResAllocNode->Type) {\r
688 case TypeIo:\r
689 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
690 break;\r
691\r
692 case TypePMem32:\r
693 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
694 case TypeMem32:\r
695 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
696 Descriptor->AddrSpaceGranularity = 32;\r
697 break;\r
698\r
699 case TypePMem64:\r
700 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
701 case TypeMem64:\r
702 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
703 Descriptor->AddrSpaceGranularity = 64;\r
704 break;\r
705\r
706 case TypeBus:\r
707 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
708 break;\r
709\r
710 default:\r
711 break;\r
712 }\r
713\r
714 Descriptor++;\r
715 }\r
716\r
717 //\r
718 // Terminate the root bridge resources.\r
719 //\r
720 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;\r
721 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
722 End->Checksum = 0x0;\r
723\r
724 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(End + 1);\r
725 }\r
726\r
727 //\r
728 // Terminate the host bridge resources.\r
729 //\r
730 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;\r
731 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
732 End->Checksum = 0x0;\r
733\r
734 DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));\r
735 PciHostBridgeResourceConflict (HostBridge->Handle, Resources);\r
736 FreePool (Resources);\r
737}\r
738\r
739/**\r
740 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment\r
741 from GCD range [BaseAddress, Limit).\r
742\r
743 @param Mmio TRUE for MMIO and FALSE for IO.\r
744 @param Length Length of the resource to allocate.\r
745 @param BitsOfAlignment Alignment of the resource to allocate.\r
746 @param BaseAddress The starting address the allocation is from.\r
747 @param Limit The ending address the allocation is to.\r
748\r
749 @retval The base address of the allocated resource or MAX_UINT64 if allocation\r
750 fails.\r
751**/\r
752UINT64\r
753AllocateResource (\r
754 BOOLEAN Mmio,\r
755 UINT64 Length,\r
756 UINTN BitsOfAlignment,\r
757 UINT64 BaseAddress,\r
758 UINT64 Limit\r
759 )\r
760{\r
761 EFI_STATUS Status;\r
762\r
763 if (BaseAddress < Limit) {\r
764 //\r
765 // Have to make sure Aligment is handled since we are doing direct address allocation\r
766 // Strictly speaking, alignment requirement should be applied to device\r
767 // address instead of host address which is used in GCD manipulation below,\r
768 // but as we restrict the alignment of Translation to be larger than any BAR\r
769 // alignment in the root bridge, we can simplify the situation and consider\r
770 // the same alignment requirement is also applied to host address.\r
771 //\r
772 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));\r
773\r
774 while (BaseAddress + Length <= Limit + 1) {\r
775 if (Mmio) {\r
776 Status = gDS->AllocateMemorySpace (\r
777 EfiGcdAllocateAddress,\r
778 EfiGcdMemoryTypeMemoryMappedIo,\r
779 BitsOfAlignment,\r
780 Length,\r
781 &BaseAddress,\r
782 gImageHandle,\r
783 NULL\r
784 );\r
785 } else {\r
786 Status = gDS->AllocateIoSpace (\r
787 EfiGcdAllocateAddress,\r
788 EfiGcdIoTypeIo,\r
789 BitsOfAlignment,\r
790 Length,\r
791 &BaseAddress,\r
792 gImageHandle,\r
793 NULL\r
794 );\r
795 }\r
796\r
797 if (!EFI_ERROR (Status)) {\r
798 return BaseAddress;\r
799 }\r
800\r
801 BaseAddress += LShiftU64 (1, BitsOfAlignment);\r
802 }\r
803 }\r
804\r
805 return MAX_UINT64;\r
806}\r
807\r
808/**\r
809\r
810 Enter a certain phase of the PCI enumeration process.\r
811\r
812 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
813 @param Phase The phase during enumeration.\r
814\r
815 @retval EFI_SUCCESS Succeed.\r
816 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.\r
817 @retval EFI_NOT_READY Resources have not been submitted yet.\r
818\r
819**/\r
820EFI_STATUS\r
821EFIAPI\r
822NotifyPhase (\r
823 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
824 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
825 )\r
826{\r
827 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
828 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
829 LIST_ENTRY *Link;\r
830 EFI_PHYSICAL_ADDRESS BaseAddress;\r
831 UINTN BitsOfAlignment;\r
832 UINT64 Alignment;\r
833 EFI_STATUS Status;\r
834 EFI_STATUS ReturnStatus;\r
835 PCI_RESOURCE_TYPE Index;\r
836 PCI_RESOURCE_TYPE Index1;\r
837 PCI_RESOURCE_TYPE Index2;\r
838 BOOLEAN ResNodeHandled[TypeMax];\r
839 UINT64 MaxAlignment;\r
840 UINT64 Translation;\r
841\r
842 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
843\r
844 switch (Phase) {\r
845 case EfiPciHostBridgeBeginEnumeration:\r
846 if (!HostBridge->CanRestarted) {\r
847 return EFI_NOT_READY;\r
848 }\r
849\r
850 //\r
851 // Reset Root Bridge\r
852 //\r
853 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
854 ; !IsNull (&HostBridge->RootBridges, Link)\r
855 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
856 )\r
857 {\r
858 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
859 for (Index = TypeIo; Index < TypeMax; Index++) {\r
860 RootBridge->ResAllocNode[Index].Type = Index;\r
861 RootBridge->ResAllocNode[Index].Base = 0;\r
862 RootBridge->ResAllocNode[Index].Length = 0;\r
863 RootBridge->ResAllocNode[Index].Status = ResNone;\r
864\r
865 RootBridge->ResourceSubmitted = FALSE;\r
866 }\r
867 }\r
868\r
869 HostBridge->CanRestarted = TRUE;\r
870 break;\r
871\r
872 case EfiPciHostBridgeBeginBusAllocation:\r
873 //\r
874 // No specific action is required here, can perform any chipset specific programing\r
875 //\r
876 HostBridge->CanRestarted = FALSE;\r
877 break;\r
878\r
879 case EfiPciHostBridgeEndBusAllocation:\r
880 //\r
881 // No specific action is required here, can perform any chipset specific programing\r
882 //\r
883 break;\r
884\r
885 case EfiPciHostBridgeBeginResourceAllocation:\r
886 //\r
887 // No specific action is required here, can perform any chipset specific programing\r
888 //\r
889 break;\r
890\r
891 case EfiPciHostBridgeAllocateResources:\r
892 ReturnStatus = EFI_SUCCESS;\r
893\r
894 //\r
895 // Make sure the resource for all root bridges has been submitted.\r
896 //\r
897 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
898 ; !IsNull (&HostBridge->RootBridges, Link)\r
899 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
900 )\r
901 {\r
902 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
903 if (!RootBridge->ResourceSubmitted) {\r
904 return EFI_NOT_READY;\r
905 }\r
906 }\r
907\r
908 DEBUG ((DEBUG_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));\r
909 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
910 ; !IsNull (&HostBridge->RootBridges, Link)\r
911 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
912 )\r
913 {\r
914 for (Index = TypeIo; Index < TypeBus; Index++) {\r
915 ResNodeHandled[Index] = FALSE;\r
916 }\r
917\r
918 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
919 DEBUG ((DEBUG_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));\r
920\r
921 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
922 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {\r
923 ResNodeHandled[Index1] = TRUE;\r
924 } else {\r
925 //\r
926 // Allocate the resource node with max alignment at first\r
927 //\r
928 MaxAlignment = 0;\r
929 Index = TypeMax;\r
930 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {\r
931 if (ResNodeHandled[Index2]) {\r
932 continue;\r
933 }\r
934\r
935 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {\r
936 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;\r
937 Index = Index2;\r
938 }\r
939 }\r
940\r
941 ASSERT (Index < TypeMax);\r
942 ResNodeHandled[Index] = TRUE;\r
943 Alignment = RootBridge->ResAllocNode[Index].Alignment;\r
944 BitsOfAlignment = LowBitSet64 (Alignment + 1);\r
945 BaseAddress = MAX_UINT64;\r
946\r
947 //\r
948 // RESTRICTION: To simplify the situation, we require the alignment of\r
949 // Translation must be larger than any BAR alignment in the same root\r
950 // bridge, so that resource allocation alignment can be applied to\r
951 // both device address and host address.\r
952 //\r
953 Translation = GetTranslationByResourceType (RootBridge, Index);\r
954 if ((Translation & Alignment) != 0) {\r
955 DEBUG ((\r
956 DEBUG_ERROR,\r
957 "[%a:%d] Translation %lx is not aligned to %lx!\n",\r
958 __FUNCTION__,\r
959 DEBUG_LINE_NUMBER,\r
960 Translation,\r
961 Alignment\r
962 ));\r
963 ASSERT ((Translation & Alignment) == 0);\r
964 //\r
965 // This may be caused by too large alignment or too small\r
966 // Translation; pick the 1st possibility and return out of resource,\r
967 // which can also go thru the same process for out of resource\r
968 // outside the loop.\r
969 //\r
970 ReturnStatus = EFI_OUT_OF_RESOURCES;\r
971 continue;\r
972 }\r
973\r
974 switch (Index) {\r
975 case TypeIo:\r
976 //\r
977 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.\r
978 // For AllocateResource is manipulating GCD resource, we need to use\r
979 // host address here.\r
980 //\r
981 BaseAddress = AllocateResource (\r
982 FALSE,\r
983 RootBridge->ResAllocNode[Index].Length,\r
984 MIN (15, BitsOfAlignment),\r
985 TO_HOST_ADDRESS (\r
986 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),\r
987 RootBridge->Io.Translation\r
988 ),\r
989 TO_HOST_ADDRESS (\r
990 RootBridge->Io.Limit,\r
991 RootBridge->Io.Translation\r
992 )\r
993 );\r
994 break;\r
995\r
996 case TypeMem64:\r
997 BaseAddress = AllocateResource (\r
998 TRUE,\r
999 RootBridge->ResAllocNode[Index].Length,\r
1000 MIN (63, BitsOfAlignment),\r
1001 TO_HOST_ADDRESS (\r
1002 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),\r
1003 RootBridge->MemAbove4G.Translation\r
1004 ),\r
1005 TO_HOST_ADDRESS (\r
1006 RootBridge->MemAbove4G.Limit,\r
1007 RootBridge->MemAbove4G.Translation\r
1008 )\r
1009 );\r
1010 if (BaseAddress != MAX_UINT64) {\r
1011 break;\r
1012 }\r
1013\r
1014 //\r
1015 // If memory above 4GB is not available, try memory below 4GB\r
1016 //\r
1017\r
1018 case TypeMem32:\r
1019 BaseAddress = AllocateResource (\r
1020 TRUE,\r
1021 RootBridge->ResAllocNode[Index].Length,\r
1022 MIN (31, BitsOfAlignment),\r
1023 TO_HOST_ADDRESS (\r
1024 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),\r
1025 RootBridge->Mem.Translation\r
1026 ),\r
1027 TO_HOST_ADDRESS (\r
1028 RootBridge->Mem.Limit,\r
1029 RootBridge->Mem.Translation\r
1030 )\r
1031 );\r
1032 break;\r
1033\r
1034 case TypePMem64:\r
1035 BaseAddress = AllocateResource (\r
1036 TRUE,\r
1037 RootBridge->ResAllocNode[Index].Length,\r
1038 MIN (63, BitsOfAlignment),\r
1039 TO_HOST_ADDRESS (\r
1040 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),\r
1041 RootBridge->PMemAbove4G.Translation\r
1042 ),\r
1043 TO_HOST_ADDRESS (\r
1044 RootBridge->PMemAbove4G.Limit,\r
1045 RootBridge->PMemAbove4G.Translation\r
1046 )\r
1047 );\r
1048 if (BaseAddress != MAX_UINT64) {\r
1049 break;\r
1050 }\r
1051\r
1052 //\r
1053 // If memory above 4GB is not available, try memory below 4GB\r
1054 //\r
1055 case TypePMem32:\r
1056 BaseAddress = AllocateResource (\r
1057 TRUE,\r
1058 RootBridge->ResAllocNode[Index].Length,\r
1059 MIN (31, BitsOfAlignment),\r
1060 TO_HOST_ADDRESS (\r
1061 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),\r
1062 RootBridge->PMem.Translation\r
1063 ),\r
1064 TO_HOST_ADDRESS (\r
1065 RootBridge->PMem.Limit,\r
1066 RootBridge->PMem.Translation\r
1067 )\r
1068 );\r
1069 break;\r
1070\r
1071 default:\r
1072 ASSERT (FALSE);\r
1073 break;\r
1074 }\r
1075\r
1076 DEBUG ((\r
1077 DEBUG_INFO,\r
1078 " %s: Base/Length/Alignment = %lx/%lx/%lx - ",\r
1079 mPciResourceTypeStr[Index],\r
1080 BaseAddress,\r
1081 RootBridge->ResAllocNode[Index].Length,\r
1082 Alignment\r
1083 ));\r
1084 if (BaseAddress != MAX_UINT64) {\r
1085 RootBridge->ResAllocNode[Index].Base = BaseAddress;\r
1086 RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
1087 DEBUG ((DEBUG_INFO, "Success\n"));\r
1088 } else {\r
1089 ReturnStatus = EFI_OUT_OF_RESOURCES;\r
1090 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));\r
1091 }\r
1092 }\r
1093 }\r
1094 }\r
1095\r
1096 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {\r
1097 ResourceConflict (HostBridge);\r
1098 }\r
1099\r
1100 //\r
1101 // Set resource to zero for nodes where allocation fails\r
1102 //\r
1103 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1104 ; !IsNull (&HostBridge->RootBridges, Link)\r
1105 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1106 )\r
1107 {\r
1108 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1109 for (Index = TypeIo; Index < TypeBus; Index++) {\r
1110 if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {\r
1111 RootBridge->ResAllocNode[Index].Length = 0;\r
1112 }\r
1113 }\r
1114 }\r
1115\r
1116 return ReturnStatus;\r
1117\r
1118 case EfiPciHostBridgeSetResources:\r
1119 //\r
1120 // HostBridgeInstance->CanRestarted = FALSE;\r
1121 //\r
1122 break;\r
1123\r
1124 case EfiPciHostBridgeFreeResources:\r
1125 //\r
1126 // HostBridgeInstance->CanRestarted = FALSE;\r
1127 //\r
1128 ReturnStatus = EFI_SUCCESS;\r
1129 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1130 ; !IsNull (&HostBridge->RootBridges, Link)\r
1131 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1132 )\r
1133 {\r
1134 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1135 for (Index = TypeIo; Index < TypeBus; Index++) {\r
1136 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {\r
1137 switch (Index) {\r
1138 case TypeIo:\r
1139 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
1140 if (EFI_ERROR (Status)) {\r
1141 ReturnStatus = Status;\r
1142 }\r
1143\r
1144 break;\r
1145\r
1146 case TypeMem32:\r
1147 case TypePMem32:\r
1148 case TypeMem64:\r
1149 case TypePMem64:\r
1150 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);\r
1151 if (EFI_ERROR (Status)) {\r
1152 ReturnStatus = Status;\r
1153 }\r
1154\r
1155 break;\r
1156\r
1157 default:\r
1158 ASSERT (FALSE);\r
1159 break;\r
1160 }\r
1161\r
1162 RootBridge->ResAllocNode[Index].Type = Index;\r
1163 RootBridge->ResAllocNode[Index].Base = 0;\r
1164 RootBridge->ResAllocNode[Index].Length = 0;\r
1165 RootBridge->ResAllocNode[Index].Status = ResNone;\r
1166 }\r
1167 }\r
1168\r
1169 RootBridge->ResourceSubmitted = FALSE;\r
1170 }\r
1171\r
1172 HostBridge->CanRestarted = TRUE;\r
1173 return ReturnStatus;\r
1174\r
1175 case EfiPciHostBridgeEndResourceAllocation:\r
1176 //\r
1177 // The resource allocation phase is completed. No specific action is required\r
1178 // here. This notification can be used to perform any chipset specific programming.\r
1179 //\r
1180 break;\r
1181\r
1182 case EfiPciHostBridgeEndEnumeration:\r
1183 //\r
1184 // The Host Bridge Enumeration is completed. No specific action is required here.\r
1185 // This notification can be used to perform any chipset specific programming.\r
1186 //\r
1187 break;\r
1188\r
1189 default:\r
1190 return EFI_INVALID_PARAMETER;\r
1191 }\r
1192\r
1193 return EFI_SUCCESS;\r
1194}\r
1195\r
1196/**\r
1197\r
1198 Return the device handle of the next PCI root bridge that is associated with\r
1199 this Host Bridge.\r
1200\r
1201 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1202 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.\r
1203 On input, it holds the RootBridgeHandle returned by the most\r
1204 recent call to GetNextRootBridge().The handle for the first\r
1205 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
1206\r
1207 @retval EFI_SUCCESS Succeed.\r
1208 @retval EFI_NOT_FOUND Next PCI root bridge not found.\r
1209 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.\r
1210\r
1211**/\r
1212EFI_STATUS\r
1213EFIAPI\r
1214GetNextRootBridge (\r
1215 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1216 IN OUT EFI_HANDLE *RootBridgeHandle\r
1217 )\r
1218{\r
1219 BOOLEAN ReturnNext;\r
1220 LIST_ENTRY *Link;\r
1221 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1222 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1223\r
1224 if (RootBridgeHandle == NULL) {\r
1225 return EFI_INVALID_PARAMETER;\r
1226 }\r
1227\r
1228 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1229 ReturnNext = (BOOLEAN)(*RootBridgeHandle == NULL);\r
1230\r
1231 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1232 ; !IsNull (&HostBridge->RootBridges, Link)\r
1233 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1234 )\r
1235 {\r
1236 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1237 if (ReturnNext) {\r
1238 *RootBridgeHandle = RootBridge->Handle;\r
1239 return EFI_SUCCESS;\r
1240 }\r
1241\r
1242 ReturnNext = (BOOLEAN)(*RootBridgeHandle == RootBridge->Handle);\r
1243 }\r
1244\r
1245 if (ReturnNext) {\r
1246 ASSERT (IsNull (&HostBridge->RootBridges, Link));\r
1247 return EFI_NOT_FOUND;\r
1248 } else {\r
1249 return EFI_INVALID_PARAMETER;\r
1250 }\r
1251}\r
1252\r
1253/**\r
1254\r
1255 Returns the attributes of a PCI Root Bridge.\r
1256\r
1257 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1258 @param RootBridgeHandle The device handle of the PCI Root Bridge\r
1259 that the caller is interested in.\r
1260 @param Attributes The pointer to attributes of the PCI Root Bridge.\r
1261\r
1262 @retval EFI_SUCCESS Succeed.\r
1263 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or\r
1264 RootBridgeHandle is not an EFI_HANDLE\r
1265 that was returned on a previous call to\r
1266 GetNextRootBridge().\r
1267\r
1268**/\r
1269EFI_STATUS\r
1270EFIAPI\r
1271GetAttributes (\r
1272 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1273 IN EFI_HANDLE RootBridgeHandle,\r
1274 OUT UINT64 *Attributes\r
1275 )\r
1276{\r
1277 LIST_ENTRY *Link;\r
1278 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1279 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1280\r
1281 if (Attributes == NULL) {\r
1282 return EFI_INVALID_PARAMETER;\r
1283 }\r
1284\r
1285 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1286 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1287 ; !IsNull (&HostBridge->RootBridges, Link)\r
1288 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1289 )\r
1290 {\r
1291 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1292 if (RootBridgeHandle == RootBridge->Handle) {\r
1293 *Attributes = RootBridge->AllocationAttributes;\r
1294 return EFI_SUCCESS;\r
1295 }\r
1296 }\r
1297\r
1298 return EFI_INVALID_PARAMETER;\r
1299}\r
1300\r
1301/**\r
1302\r
1303 This is the request from the PCI enumerator to set up\r
1304 the specified PCI Root Bridge for bus enumeration process.\r
1305\r
1306 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1307 @param RootBridgeHandle The PCI Root Bridge to be set up.\r
1308 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.\r
1309\r
1310 @retval EFI_SUCCESS Succeed.\r
1311 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
1312 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
1313\r
1314**/\r
1315EFI_STATUS\r
1316EFIAPI\r
1317StartBusEnumeration (\r
1318 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1319 IN EFI_HANDLE RootBridgeHandle,\r
1320 OUT VOID **Configuration\r
1321 )\r
1322{\r
1323 LIST_ENTRY *Link;\r
1324 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1325 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1326 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
1327 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
1328\r
1329 if (Configuration == NULL) {\r
1330 return EFI_INVALID_PARAMETER;\r
1331 }\r
1332\r
1333 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1334 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1335 ; !IsNull (&HostBridge->RootBridges, Link)\r
1336 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1337 )\r
1338 {\r
1339 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1340 if (RootBridgeHandle == RootBridge->Handle) {\r
1341 *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1342 if (*Configuration == NULL) {\r
1343 return EFI_OUT_OF_RESOURCES;\r
1344 }\r
1345\r
1346 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)*Configuration;\r
1347 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1348 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1349 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
1350 Descriptor->GenFlag = 0;\r
1351 Descriptor->SpecificFlag = 0;\r
1352 Descriptor->AddrSpaceGranularity = 0;\r
1353 Descriptor->AddrRangeMin = RootBridge->Bus.Base;\r
1354 Descriptor->AddrRangeMax = 0;\r
1355 Descriptor->AddrTranslationOffset = 0;\r
1356 Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;\r
1357\r
1358 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Descriptor + 1);\r
1359 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1360 End->Checksum = 0x0;\r
1361\r
1362 return EFI_SUCCESS;\r
1363 }\r
1364 }\r
1365\r
1366 return EFI_INVALID_PARAMETER;\r
1367}\r
1368\r
1369/**\r
1370\r
1371 This function programs the PCI Root Bridge hardware so that\r
1372 it decodes the specified PCI bus range.\r
1373\r
1374 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1375 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.\r
1376 @param Configuration The pointer to the PCI bus resource descriptor.\r
1377\r
1378 @retval EFI_SUCCESS Succeed.\r
1379 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
1380\r
1381**/\r
1382EFI_STATUS\r
1383EFIAPI\r
1384SetBusNumbers (\r
1385 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1386 IN EFI_HANDLE RootBridgeHandle,\r
1387 IN VOID *Configuration\r
1388 )\r
1389{\r
1390 LIST_ENTRY *Link;\r
1391 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1392 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1393 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
1394 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
1395\r
1396 if (Configuration == NULL) {\r
1397 return EFI_INVALID_PARAMETER;\r
1398 }\r
1399\r
1400 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;\r
1401 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Descriptor + 1);\r
1402\r
1403 //\r
1404 // Check the Configuration is valid\r
1405 //\r
1406 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||\r
1407 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||\r
1408 (End->Desc != ACPI_END_TAG_DESCRIPTOR)\r
1409 )\r
1410 {\r
1411 return EFI_INVALID_PARAMETER;\r
1412 }\r
1413\r
1414 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1415 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1416 ; !IsNull (&HostBridge->RootBridges, Link)\r
1417 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1418 )\r
1419 {\r
1420 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1421 if (RootBridgeHandle == RootBridge->Handle) {\r
1422 if (Descriptor->AddrLen == 0) {\r
1423 return EFI_INVALID_PARAMETER;\r
1424 }\r
1425\r
1426 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||\r
1427 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)\r
1428 )\r
1429 {\r
1430 return EFI_INVALID_PARAMETER;\r
1431 }\r
1432\r
1433 //\r
1434 // Update the Bus Range\r
1435 //\r
1436 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;\r
1437 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;\r
1438 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;\r
1439 return EFI_SUCCESS;\r
1440 }\r
1441 }\r
1442\r
1443 return EFI_INVALID_PARAMETER;\r
1444}\r
1445\r
1446/**\r
1447\r
1448 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
1449\r
1450 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1451 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.\r
1452 are being submitted.\r
1453 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.\r
1454\r
1455 @retval EFI_SUCCESS Succeed.\r
1456 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.\r
1457**/\r
1458EFI_STATUS\r
1459EFIAPI\r
1460SubmitResources (\r
1461 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1462 IN EFI_HANDLE RootBridgeHandle,\r
1463 IN VOID *Configuration\r
1464 )\r
1465{\r
1466 LIST_ENTRY *Link;\r
1467 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1468 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1469 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
1470 PCI_RESOURCE_TYPE Type;\r
1471\r
1472 //\r
1473 // Check the input parameter: Configuration\r
1474 //\r
1475 if (Configuration == NULL) {\r
1476 return EFI_INVALID_PARAMETER;\r
1477 }\r
1478\r
1479 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1480 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1481 ; !IsNull (&HostBridge->RootBridges, Link)\r
1482 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1483 )\r
1484 {\r
1485 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1486 if (RootBridgeHandle == RootBridge->Handle) {\r
1487 DEBUG ((DEBUG_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));\r
1488 //\r
1489 // Check the resource descriptors.\r
1490 // If the Configuration includes one or more invalid resource descriptors, all the resource\r
1491 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.\r
1492 //\r
1493 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
1494 if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
1495 return EFI_INVALID_PARAMETER;\r
1496 }\r
1497\r
1498 DEBUG ((\r
1499 DEBUG_INFO,\r
1500 " %s: Granularity/SpecificFlag = %ld / %02x%s\n",\r
1501 mAcpiAddressSpaceTypeStr[Descriptor->ResType],\r
1502 Descriptor->AddrSpaceGranularity,\r
1503 Descriptor->SpecificFlag,\r
1504 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""\r
1505 ));\r
1506 DEBUG ((DEBUG_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));\r
1507 switch (Descriptor->ResType) {\r
1508 case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
1509 if ((Descriptor->AddrSpaceGranularity != 32) && (Descriptor->AddrSpaceGranularity != 64)) {\r
1510 return EFI_INVALID_PARAMETER;\r
1511 }\r
1512\r
1513 if ((Descriptor->AddrSpaceGranularity == 32) && (Descriptor->AddrLen >= SIZE_4GB)) {\r
1514 return EFI_INVALID_PARAMETER;\r
1515 }\r
1516\r
1517 //\r
1518 // If the PCI root bridge does not support separate windows for nonprefetchable and\r
1519 // prefetchable memory, then the PCI bus driver needs to include requests for\r
1520 // prefetchable memory in the nonprefetchable memory pool.\r
1521 //\r
1522 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&\r
1523 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)\r
1524 )\r
1525 {\r
1526 return EFI_INVALID_PARAMETER;\r
1527 }\r
1528\r
1529 case ACPI_ADDRESS_SPACE_TYPE_IO:\r
1530 //\r
1531 // Check aligment, it should be of the form 2^n-1\r
1532 //\r
1533 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {\r
1534 return EFI_INVALID_PARAMETER;\r
1535 }\r
1536\r
1537 break;\r
1538 default:\r
1539 ASSERT (FALSE);\r
1540 break;\r
1541 }\r
1542 }\r
1543\r
1544 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1545 return EFI_INVALID_PARAMETER;\r
1546 }\r
1547\r
1548 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
1549 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
1550 if (Descriptor->AddrSpaceGranularity == 32) {\r
1551 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
1552 Type = TypePMem32;\r
1553 } else {\r
1554 Type = TypeMem32;\r
1555 }\r
1556 } else {\r
1557 ASSERT (Descriptor->AddrSpaceGranularity == 64);\r
1558 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {\r
1559 Type = TypePMem64;\r
1560 } else {\r
1561 Type = TypeMem64;\r
1562 }\r
1563 }\r
1564 } else {\r
1565 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);\r
1566 Type = TypeIo;\r
1567 }\r
1568\r
1569 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;\r
1570 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;\r
1571 RootBridge->ResAllocNode[Type].Status = ResSubmitted;\r
1572 }\r
1573\r
1574 RootBridge->ResourceSubmitted = TRUE;\r
1575 return EFI_SUCCESS;\r
1576 }\r
1577 }\r
1578\r
1579 return EFI_INVALID_PARAMETER;\r
1580}\r
1581\r
1582/**\r
1583\r
1584 This function returns the proposed resource settings for the specified\r
1585 PCI Root Bridge.\r
1586\r
1587 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1588 @param RootBridgeHandle The PCI Root Bridge handle.\r
1589 @param Configuration The pointer to the pointer to the PCI I/O\r
1590 and memory resource descriptor.\r
1591\r
1592 @retval EFI_SUCCESS Succeed.\r
1593 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.\r
1594 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
1595\r
1596**/\r
1597EFI_STATUS\r
1598EFIAPI\r
1599GetProposedResources (\r
1600 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1601 IN EFI_HANDLE RootBridgeHandle,\r
1602 OUT VOID **Configuration\r
1603 )\r
1604{\r
1605 LIST_ENTRY *Link;\r
1606 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1607 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1608 UINTN Index;\r
1609 UINTN Number;\r
1610 VOID *Buffer;\r
1611 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
1612 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
1613 UINT64 ResStatus;\r
1614\r
1615 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1616 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1617 ; !IsNull (&HostBridge->RootBridges, Link)\r
1618 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1619 )\r
1620 {\r
1621 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1622 if (RootBridgeHandle == RootBridge->Handle) {\r
1623 for (Index = 0, Number = 0; Index < TypeBus; Index++) {\r
1624 if (RootBridge->ResAllocNode[Index].Status != ResNone) {\r
1625 Number++;\r
1626 }\r
1627 }\r
1628\r
1629 Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1630 if (Buffer == NULL) {\r
1631 return EFI_OUT_OF_RESOURCES;\r
1632 }\r
1633\r
1634 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Buffer;\r
1635 for (Index = 0; Index < TypeBus; Index++) {\r
1636 ResStatus = RootBridge->ResAllocNode[Index].Status;\r
1637 if (ResStatus != ResNone) {\r
1638 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1639 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1640 Descriptor->GenFlag = 0;\r
1641 //\r
1642 // AddrRangeMin in Resource Descriptor here should be device address\r
1643 // instead of host address, or else PCI bus driver cannot set correct\r
1644 // address into PCI BAR registers.\r
1645 // Base in ResAllocNode is a host address, so conversion is needed.\r
1646 //\r
1647 Descriptor->AddrRangeMin = TO_DEVICE_ADDRESS (\r
1648 RootBridge->ResAllocNode[Index].Base,\r
1649 GetTranslationByResourceType (RootBridge, Index)\r
1650 );\r
1651 Descriptor->AddrRangeMax = 0;\r
1652 Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;\r
1653 Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;\r
1654\r
1655 switch (Index) {\r
1656 case TypeIo:\r
1657 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1658 break;\r
1659\r
1660 case TypePMem32:\r
1661 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1662 case TypeMem32:\r
1663 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1664 Descriptor->AddrSpaceGranularity = 32;\r
1665 break;\r
1666\r
1667 case TypePMem64:\r
1668 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
1669 case TypeMem64:\r
1670 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1671 Descriptor->AddrSpaceGranularity = 64;\r
1672 break;\r
1673 }\r
1674\r
1675 Descriptor++;\r
1676 }\r
1677 }\r
1678\r
1679 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;\r
1680 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1681 End->Checksum = 0;\r
1682\r
1683 *Configuration = Buffer;\r
1684\r
1685 return EFI_SUCCESS;\r
1686 }\r
1687 }\r
1688\r
1689 return EFI_INVALID_PARAMETER;\r
1690}\r
1691\r
1692/**\r
1693\r
1694 This function is called for all the PCI controllers that the PCI\r
1695 bus driver finds. Can be used to Preprogram the controller.\r
1696\r
1697 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1698 @param RootBridgeHandle The PCI Root Bridge handle.\r
1699 @param PciAddress Address of the controller on the PCI bus.\r
1700 @param Phase The Phase during resource allocation.\r
1701\r
1702 @retval EFI_SUCCESS Succeed.\r
1703 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.\r
1704\r
1705**/\r
1706EFI_STATUS\r
1707EFIAPI\r
1708PreprocessController (\r
1709 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1710 IN EFI_HANDLE RootBridgeHandle,\r
1711 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
1712 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1713 )\r
1714{\r
1715 LIST_ENTRY *Link;\r
1716 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
1717 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
1718\r
1719 if ((UINT32)Phase > EfiPciBeforeResourceCollection) {\r
1720 return EFI_INVALID_PARAMETER;\r
1721 }\r
1722\r
1723 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);\r
1724 for (Link = GetFirstNode (&HostBridge->RootBridges)\r
1725 ; !IsNull (&HostBridge->RootBridges, Link)\r
1726 ; Link = GetNextNode (&HostBridge->RootBridges, Link)\r
1727 )\r
1728 {\r
1729 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);\r
1730 if (RootBridgeHandle == RootBridge->Handle) {\r
1731 return EFI_SUCCESS;\r
1732 }\r
1733 }\r
1734\r
1735 return EFI_INVALID_PARAMETER;\r
1736}\r