]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.c
ArmPkg/CompilerIntrinsicsLib: Add uread, uwrite GCC assembly sources
[mirror_edk2.git] / QuarkPlatformPkg / Pci / Dxe / PciHostBridge / PciHostBridge.c
CommitLineData
b303605e
MK
1/** @file\r
2Pci Host Bridge driver for a simple IIO. There is only one PCI Root Bridge in the system.\r
3Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
4\r
5Copyright (c) 2013-2015 Intel Corporation.\r
6\r
0eb3de2e 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
b303605e
MK
8\r
9\r
10**/\r
11\r
12#include "PciHostBridge.h"\r
13#include <IntelQNCRegs.h>\r
14\r
15//\r
16// We can hardcode the following for a Simple IIO -\r
17// Root Bridge Count within the host bridge\r
18// Root Bridge's device path\r
19// Root Bridge's resource appeture\r
20//\r
21EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[ROOT_BRIDGE_COUNT] = {\r
22 {\r
23 {\r
24 {\r
25 ACPI_DEVICE_PATH,\r
26 ACPI_DP,\r
27 {\r
28 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\r
29 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r
30 }\r
31 },\r
32 EISA_PNP_ID (0x0A03),\r
33 0\r
34 },\r
35 {\r
36 END_DEVICE_PATH_TYPE,\r
37 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
38 {\r
39 END_DEVICE_PATH_LENGTH,\r
40 0\r
41 }\r
42 }\r
43 }\r
44};\r
45\r
46EFI_HANDLE mDriverImageHandle;\r
47PCI_ROOT_BRIDGE_RESOURCE_APERTURE *mResAperture;\r
48\r
49//\r
50// Implementation\r
51//\r
52EFI_STATUS\r
53EFIAPI\r
54InitializePciHostBridge (\r
55 IN EFI_HANDLE ImageHandle,\r
56 IN EFI_SYSTEM_TABLE *SystemTable\r
57 )\r
58/*++\r
59\r
60Routine Description:\r
61\r
62 Entry point of this driver.\r
63\r
64Arguments:\r
65\r
66 ImageHandle - Image handle of this driver.\r
67 SystemTable - Pointer to standard EFI system table.\r
68\r
69Returns:\r
70\r
71 EFI_SUCCESS - Succeed.\r
72 EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol.\r
73\r
74--*/\r
75{\r
76 EFI_STATUS Status;\r
77 UINTN TotalRootBridgeFound;\r
78 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
79 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
80 UINT64 AllocAttributes;\r
81 EFI_PHYSICAL_ADDRESS BaseAddress;\r
82\r
83 PrivateData = NULL;\r
84\r
85 mDriverImageHandle = ImageHandle;\r
86\r
87 //\r
88 // Most systems in the world including complex servers\r
89 // have only one Host Bridge. Create Host Bridge Device Handle\r
90 //\r
91 Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PCI_HOST_BRIDGE_INSTANCE), (VOID **) &HostBridge);\r
92 ASSERT_EFI_ERROR (Status);\r
93 ZeroMem (HostBridge, sizeof (PCI_HOST_BRIDGE_INSTANCE));\r
94\r
95 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;\r
96 HostBridge->RootBridgeCount = 1;\r
97 HostBridge->ResourceSubmited = FALSE;\r
98 HostBridge->CanRestarted = TRUE;\r
99 //\r
100 // InitializeListHead (&HostBridge->Head);\r
101 //\r
102 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;\r
103 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;\r
104 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;\r
105 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;\r
106 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;\r
107 HostBridge->ResAlloc.SubmitResources = SubmitResources;\r
108 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;\r
109 HostBridge->ResAlloc.PreprocessController = PreprocessController;\r
110\r
111 Status = gBS->InstallProtocolInterface (\r
112 &HostBridge->HostBridgeHandle,\r
113 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
114 EFI_NATIVE_INTERFACE,\r
115 &HostBridge->ResAlloc\r
116 );\r
117 if (EFI_ERROR (Status)) {\r
118 gBS->FreePool (HostBridge);\r
119 return EFI_DEVICE_ERROR;\r
120 }\r
121\r
122 Status = gBS->AllocatePool (EfiBootServicesData,\r
123 HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE),\r
124 (VOID **) &mResAperture);\r
125 ASSERT_EFI_ERROR (Status);\r
126 ZeroMem (mResAperture, HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE));\r
127\r
128 DEBUG ((EFI_D_INFO, "Address of resource Aperture: %x\n", mResAperture));\r
129\r
130 //\r
131 // Create Root Bridge Device Handle in this Host Bridge\r
132 //\r
133 InitializeListHead (&HostBridge->Head);\r
134\r
135 TotalRootBridgeFound = 0;\r
136\r
137 Status = gBS->AllocatePool ( EfiBootServicesData,sizeof (PCI_ROOT_BRIDGE_INSTANCE), (VOID **) &PrivateData);\r
138 ASSERT_EFI_ERROR (Status);\r
139 ZeroMem (PrivateData, sizeof (PCI_ROOT_BRIDGE_INSTANCE));\r
140\r
141 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
142 PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[TotalRootBridgeFound];\r
143 AllocAttributes = GetAllocAttributes (TotalRootBridgeFound);\r
144\r
145 SimpleIioRootBridgeConstructor (\r
146 &PrivateData->Io,\r
147 HostBridge->HostBridgeHandle,\r
148 &(mResAperture[TotalRootBridgeFound]),\r
149 AllocAttributes\r
150 );\r
151 //\r
152 // Update Root Bridge with UDS resource information\r
153 //\r
154 PrivateData->Aperture.BusBase = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE;\r
155 PrivateData->Aperture.BusLimit = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT;\r
156 PrivateData->Aperture.Mem32Base = PcdGet32 (PcdPciHostBridgeMemory32Base);\r
157 PrivateData->Aperture.Mem32Limit = PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1);\r
158 PrivateData->Aperture.IoBase = PcdGet16 (PcdPciHostBridgeIoBase);\r
159 PrivateData->Aperture.IoLimit = PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1);\r
160\r
161 DEBUG ((EFI_D_INFO, "PCI Host Bridge BusBase: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE));\r
162 DEBUG ((EFI_D_INFO, "PCI Host Bridge BusLimit: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT));\r
163 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Base: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base)));\r
164 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Limit: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1)));\r
165 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Base: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base)));\r
166 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Limit: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base) + (PcdGet64 (PcdPciHostBridgeMemory64Size) - 1)));\r
167 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoBase: %x\n", PcdGet16 (PcdPciHostBridgeIoBase)));\r
168 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoLimit: %x\n", PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1)));\r
169\r
170 PrivateData->Handle = NULL;\r
171 Status = gBS->InstallMultipleProtocolInterfaces (\r
172 &PrivateData->Handle,\r
173 &gEfiDevicePathProtocolGuid,\r
174 PrivateData->DevicePath,\r
175 &gEfiPciRootBridgeIoProtocolGuid,\r
176 &PrivateData->Io,\r
177 NULL\r
178 );\r
179 ASSERT_EFI_ERROR (Status);\r
180\r
181 InsertTailList (&HostBridge->Head, &PrivateData->Link);\r
182 TotalRootBridgeFound++; // This is a valid rootbridge so imcrement total root bridges found\r
183\r
184 //\r
185 // Add PCIE base into Runtime memory so that it can be reported in E820 table\r
186 //\r
187 Status = gDS->AddMemorySpace (\r
188 EfiGcdMemoryTypeMemoryMappedIo,\r
189 PcdGet64 (PcdPciExpressBaseAddress),\r
190 PcdGet64 (PcdPciExpressSize),\r
191 EFI_MEMORY_RUNTIME | EFI_MEMORY_UC\r
192 );\r
193 ASSERT_EFI_ERROR(Status);\r
194\r
195 BaseAddress = PcdGet64 (PcdPciExpressBaseAddress);\r
196\r
197 Status = gDS->AllocateMemorySpace (\r
198 EfiGcdAllocateAddress,\r
199 EfiGcdMemoryTypeMemoryMappedIo,\r
200 0,\r
201 PcdGet64 (PcdPciExpressSize),\r
202 &BaseAddress,\r
203 ImageHandle,\r
204 NULL\r
205 );\r
206 ASSERT_EFI_ERROR(Status);\r
207\r
208 Status = gDS->SetMemorySpaceAttributes (\r
209 PcdGet64 (PcdPciExpressBaseAddress),\r
210 PcdGet64 (PcdPciExpressSize),\r
211 EFI_MEMORY_RUNTIME\r
212 );\r
213 ASSERT_EFI_ERROR (Status);\r
214\r
215 if (PcdGet16 (PcdPciHostBridgeIoSize) > 0) {\r
216 //\r
217 // At present, we use up the first 4k for fixed ranges like\r
218 // ICH GPIO, ACPI and ISA devices. The first 4k is not\r
219 // tracked through GCD. It should be.\r
220 //\r
221 Status = gDS->AddIoSpace (\r
222 EfiGcdIoTypeIo,\r
223 PcdGet16(PcdPciHostBridgeIoBase),\r
224 PcdGet16(PcdPciHostBridgeIoSize)\r
225 );\r
226 ASSERT_EFI_ERROR (Status);\r
227 }\r
228\r
229 if (PcdGet32(PcdPciHostBridgeMemory32Size) > 0) {\r
230 //\r
231 // Shouldn't the capabilities be UC?\r
232 //\r
233 Status = gDS->AddMemorySpace (\r
234 EfiGcdMemoryTypeMemoryMappedIo,\r
235 PcdGet32(PcdPciHostBridgeMemory32Base),\r
236 PcdGet32(PcdPciHostBridgeMemory32Size),\r
237 0\r
238 );\r
239 ASSERT_EFI_ERROR (Status);\r
240 }\r
241\r
242 return Status;\r
243}\r
244\r
245EFI_STATUS\r
246EFIAPI\r
247NotifyPhase (\r
248 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
249 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
250 )\r
251/*++\r
252\r
253Routine Description:\r
254\r
255 Enter a certain phase of the PCI enumeration process.\r
256\r
257Arguments:\r
258\r
259 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
260 Phase - The phase during enumeration.\r
261\r
262Returns:\r
263\r
264 EFI_SUCCESS - Succeed.\r
265 EFI_INVALID_PARAMETER - Wrong phase parameter passed in.\r
266 EFI_NOT_READY - Resources have not been submitted yet.\r
267\r
268--*/\r
269{\r
270 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
271 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
272 PCI_RESOURCE_TYPE Index;\r
273 EFI_LIST_ENTRY *List;\r
274 EFI_PHYSICAL_ADDRESS BaseAddress;\r
275 UINT64 AddrLen;\r
276 UINTN BitsOfAlignment;\r
277 UINT64 Alignment;\r
278 EFI_STATUS Status;\r
279 EFI_STATUS ReturnStatus;\r
280 PCI_RESOURCE_TYPE Index1;\r
281 PCI_RESOURCE_TYPE Index2;\r
282 BOOLEAN ResNodeHandled[TypeMax];\r
283 UINT64 MaxAlignment;\r
284\r
285 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
286\r
287 switch (Phase) {\r
288 case EfiPciHostBridgeBeginEnumeration:\r
289 if (HostBridgeInstance->CanRestarted) {\r
290 //\r
291 // Reset Root Bridge\r
292 //\r
293 List = HostBridgeInstance->Head.ForwardLink;\r
294\r
295 while (List != &HostBridgeInstance->Head) {\r
296 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
297 for (Index = TypeIo; Index < TypeMax; Index++) {\r
298 RootBridgeInstance->ResAllocNode[Index].Type = Index;\r
299 RootBridgeInstance->ResAllocNode[Index].Base = 0;\r
300 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
301 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;\r
302 } // for\r
303\r
304 List = List->ForwardLink;\r
305 } // while\r
306\r
307 HostBridgeInstance->ResourceSubmited = FALSE;\r
308 HostBridgeInstance->CanRestarted = TRUE;\r
309 } else {\r
310 //\r
311 // Can not restart\r
312 //\r
313 return EFI_NOT_READY;\r
314 } // if\r
315 break;\r
316\r
317 case EfiPciHostBridgeEndEnumeration:\r
318 return EFI_SUCCESS;\r
319 break;\r
320\r
321 case EfiPciHostBridgeBeginBusAllocation:\r
322 //\r
323 // No specific action is required here, can perform any chipset specific programing\r
324 //\r
325 HostBridgeInstance->CanRestarted = FALSE;\r
326 return EFI_SUCCESS;\r
327 break;\r
328\r
329 case EfiPciHostBridgeEndBusAllocation:\r
330 //\r
331 // No specific action is required here, can perform any chipset specific programing\r
332 //\r
333 // HostBridgeInstance->CanRestarted = FALSE;\r
334 //\r
335 return EFI_SUCCESS;\r
336 break;\r
337\r
338 case EfiPciHostBridgeBeginResourceAllocation:\r
339 //\r
340 // No specific action is required here, can perform any chipset specific programing\r
341 //\r
342 // HostBridgeInstance->CanRestarted = FALSE;\r
343 //\r
344 return EFI_SUCCESS;\r
345 break;\r
346\r
347 case EfiPciHostBridgeAllocateResources:\r
348 ReturnStatus = EFI_SUCCESS;\r
349 if (HostBridgeInstance->ResourceSubmited) {\r
350 List = HostBridgeInstance->Head.ForwardLink;\r
351 while (List != &HostBridgeInstance->Head) {\r
352 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
353 ResNodeHandled[Index1] = FALSE;\r
354 }\r
355\r
356 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
357 DEBUG ((EFI_D_INFO, "Address of RootBridgeInstance: %x)\n", RootBridgeInstance));\r
358 DEBUG ((EFI_D_INFO, " Signature: %x\n", RootBridgeInstance->Signature));\r
359 DEBUG ((EFI_D_INFO, " Bus Number Assigned: %x\n", RootBridgeInstance->BusNumberAssigned));\r
360 DEBUG ((EFI_D_INFO, " Bus Scan Count: %x\n", RootBridgeInstance->BusScanCount));\r
361\r
362 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {\r
363 if (RootBridgeInstance->ResAllocNode[Index1].Status == ResNone) {\r
364 ResNodeHandled[Index1] = TRUE;\r
365 } else {\r
366 //\r
367 // Allocate the resource node with max alignment at first\r
368 //\r
369 MaxAlignment = 0;\r
370 Index = TypeMax;\r
371 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {\r
372 if (ResNodeHandled[Index2]) {\r
373 continue;\r
374 }\r
375 if (MaxAlignment <= RootBridgeInstance->ResAllocNode[Index2].Alignment) {\r
376 MaxAlignment = RootBridgeInstance->ResAllocNode[Index2].Alignment;\r
377 Index = Index2;\r
378 }\r
379 } // for\r
380\r
381 if (Index < TypeMax) {\r
382 ResNodeHandled[Index] = TRUE;\r
383 } else {\r
384 ASSERT (FALSE);\r
385 }\r
386\r
387 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;\r
388\r
389 //\r
390 // Get the number of '1' in Alignment.\r
391 //\r
392 for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) {\r
393 Alignment = RShiftU64 (Alignment, 1);\r
394 }\r
395\r
396 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
397 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;\r
398\r
399 DEBUG ((EFI_D_INFO, "\n\nResource Type to assign : %x\n", Index));\r
400 DEBUG ((EFI_D_INFO, " Length to allocate: %x\n", RootBridgeInstance->ResAllocNode[Index].Length));\r
401 DEBUG ((EFI_D_INFO, " Aligment: %x\n", Alignment));\r
402\r
403 switch (Index) {\r
404 case TypeIo:\r
405 if (RootBridgeInstance->Aperture.IoBase < RootBridgeInstance->Aperture.IoLimit) {\r
406 //\r
407 // It is impossible for 0xFFFF Alignment for IO16\r
408 //\r
409 if (BitsOfAlignment >= 16)\r
410 Alignment = 0;\r
411\r
412 BaseAddress = RootBridgeInstance->Aperture.IoBase;\r
413\r
414 //\r
415 // Have to make sure Aligment is handled seeing we are doing direct address allocation\r
416 //\r
417 if ((BaseAddress & ~(Alignment)) != BaseAddress)\r
418 BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));\r
419\r
420 while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.IoLimit + 1) {\r
421\r
422 Status = gDS->AllocateIoSpace ( EfiGcdAllocateAddress, EfiGcdIoTypeIo, BitsOfAlignment,\r
423 AddrLen, &BaseAddress, mDriverImageHandle, NULL );\r
424\r
425 if (!EFI_ERROR (Status)) {\r
426 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;\r
427 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;\r
428 goto TypeIoFound;\r
429 }\r
430\r
431 BaseAddress += (Alignment + 1);\r
432 } // while\r
433\r
434 } // if\r
435\r
436 TypeIoFound:\r
437 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {\r
438 //\r
439 // No Room at the Inn for this resources request\r
440 //\r
441 ReturnStatus = EFI_OUT_OF_RESOURCES;\r
442 } // if\r
443\r
444 break;\r
445\r
446 case TypeMem32:\r
447 if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {\r
448\r
449 BaseAddress = RootBridgeInstance->Aperture.Mem32Base;\r
450 //\r
451 // Have to make sure Aligment is handled seeing we are doing direct address allocation\r
452 //\r
453 if ((BaseAddress & ~(Alignment)) != BaseAddress)\r
454 BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));\r
455\r
456 while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.Mem32Limit + 1) {\r
457\r
458 Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,\r
459 BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);\r
460\r
461 if (!EFI_ERROR (Status)) {\r
462 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;\r
463 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;\r
464 goto TypeMem32Found;\r
465 } // if\r
466\r
467 BaseAddress += (Alignment + 1);\r
468 } // while\r
469 } // if\r
470\r
471 TypeMem32Found:\r
472 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {\r
473 //\r
474 // No Room at the Inn for this resources request\r
475 //\r
476 ReturnStatus = EFI_OUT_OF_RESOURCES;\r
477 }\r
478\r
479 break;\r
480\r
481 case TypePMem32:\r
482 StartTypePMem32:\r
483 if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {\r
484\r
485 BaseAddress = RootBridgeInstance->Aperture.Mem32Limit + 1;\r
486 BaseAddress -= AddrLen;\r
487\r
488 //\r
489 // Have to make sure Aligment is handled seeing we are doing direct address allocation\r
490 //\r
491 if ((BaseAddress & ~(Alignment)) != BaseAddress)\r
492 BaseAddress = ((BaseAddress) & ~(Alignment));\r
493\r
494 while(RootBridgeInstance->Aperture.Mem32Base <= BaseAddress) {\r
495\r
496 DEBUG ((EFI_D_INFO, " Attempting %x allocation at 0x%lx .....", Index, BaseAddress));\r
497 Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,\r
498 BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);\r
499\r
500 if (!EFI_ERROR (Status)) {\r
501 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;\r
502 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;\r
503 DEBUG ((EFI_D_INFO, "... Passed!!\n"));\r
504 goto TypePMem32Found;\r
505 }\r
506 DEBUG ((EFI_D_INFO, "... Failed!!\n"));\r
507 BaseAddress -= (Alignment + 1);\r
508 } // while\r
509 } // if\r
510\r
511 TypePMem32Found:\r
512 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {\r
513 //\r
514 // No Room at the Inn for this resources request\r
515 //\r
516 ReturnStatus = EFI_OUT_OF_RESOURCES;\r
517 }\r
518\r
519 break;\r
520\r
521 case TypeMem64:\r
522 case TypePMem64:\r
523 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {\r
524 //\r
525 // If 64-bit resourcing is not available, then try as PMem32\r
526 //\r
527 goto StartTypePMem32;\r
528 }\r
529\r
530 break;\r
531\r
532 default:\r
533 break;\r
534 } // End switch (Index)\r
535\r
536 DEBUG ((EFI_D_INFO, "Resource Type Assigned: %x\n", Index));\r
537 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {\r
538 DEBUG ((EFI_D_INFO, " Base Address Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Base));\r
539 DEBUG ((EFI_D_INFO, " Length Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Length));\r
540 } else {\r
541 DEBUG ((DEBUG_ERROR, " Resource Allocation failed! There was no room at the inn\n"));\r
542 }\r
543\r
544 }\r
545 }\r
546\r
547 List = List->ForwardLink;\r
548 }\r
549\r
550 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {\r
551 DEBUG ((DEBUG_ERROR, "Resource allocation Failed. Continue booting the system.\n"));\r
552 }\r
553\r
554 //\r
555 // Set resource to zero for nodes where allocation fails\r
556 //\r
557 List = HostBridgeInstance->Head.ForwardLink;\r
558 while (List != &HostBridgeInstance->Head) {\r
559 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
560 for (Index = TypeIo; Index < TypeBus; Index++) {\r
561 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {\r
562 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
563 }\r
564 }\r
565 List = List->ForwardLink;\r
566 }\r
567 return ReturnStatus;\r
568 } else {\r
569 return EFI_NOT_READY;\r
570 }\r
571 //\r
572 // HostBridgeInstance->CanRestarted = FALSE;\r
573 //\r
574 break;\r
575\r
576 case EfiPciHostBridgeSetResources:\r
577 //\r
578 // HostBridgeInstance->CanRestarted = FALSE;\r
579 //\r
580 break;\r
581\r
582 case EfiPciHostBridgeFreeResources:\r
583 //\r
584 // HostBridgeInstance->CanRestarted = FALSE;\r
585 //\r
586 ReturnStatus = EFI_SUCCESS;\r
587 List = HostBridgeInstance->Head.ForwardLink;\r
588 while (List != &HostBridgeInstance->Head) {\r
589 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
590 for (Index = TypeIo; Index < TypeBus; Index++) {\r
591 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {\r
592 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
593 BaseAddress = (EFI_PHYSICAL_ADDRESS) RootBridgeInstance->ResAllocNode[Index].Base;\r
594 switch (Index) {\r
595 case TypeIo:\r
596 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);\r
597 if (EFI_ERROR (Status)) {\r
598 ReturnStatus = Status;\r
599 }\r
600 break;\r
601\r
602 case TypeMem32:\r
603 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);\r
604 if (EFI_ERROR (Status)) {\r
605 ReturnStatus = Status;\r
606 }\r
607 break;\r
608\r
609 case TypePMem32:\r
610 break;\r
611\r
612 case TypeMem64:\r
613 break;\r
614\r
615 case TypePMem64:\r
616 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);\r
617 if (EFI_ERROR (Status)) {\r
618 ReturnStatus = Status;\r
619 }\r
620 break;\r
621\r
622 default:\r
623 break;\r
624 } // end switch (Index)\r
625\r
626 RootBridgeInstance->ResAllocNode[Index].Type = Index;\r
627 RootBridgeInstance->ResAllocNode[Index].Base = 0;\r
628 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
629 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;\r
630 }\r
631 }\r
632\r
633 List = List->ForwardLink;\r
634 }\r
635\r
636 HostBridgeInstance->ResourceSubmited = FALSE;\r
637 HostBridgeInstance->CanRestarted = TRUE;\r
638 return ReturnStatus;\r
639 break;\r
640\r
641 case EfiPciHostBridgeEndResourceAllocation:\r
642 //\r
643 // Resource enumeration is done. Perform any activities that\r
644 // must wait until that time.\r
645 //\r
646 break;\r
647\r
648 default:\r
649 return EFI_INVALID_PARAMETER;\r
650 } // End switch (Phase)\r
651\r
652 return EFI_SUCCESS;\r
653}\r
654\r
655EFI_STATUS\r
656EFIAPI\r
657GetNextRootBridge (\r
658 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
659 IN OUT EFI_HANDLE *RootBridgeHandle\r
660 )\r
661/*++\r
662\r
663Routine Description:\r
664 Return the device handle of the next PCI root bridge that is associated with\r
665 this Host Bridge.\r
666\r
667Arguments:\r
668\r
669 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
670 RootBridgeHandle - Returns the device handle of the next PCI Root Bridge.\r
671 On input, it holds the RootBridgeHandle returned by the most\r
672 recent call to GetNextRootBridge().The handle for the first\r
673 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.\r
674\r
675Returns:\r
676\r
677 EFI_SUCCESS - Succeed.\r
678 EFI_NOT_FOUND - Next PCI root bridge not found.\r
679 EFI_INVALID_PARAMETER - Wrong parameter passed in.\r
680\r
681--*/\r
682{\r
683 BOOLEAN NoRootBridge;\r
684 EFI_LIST_ENTRY *List;\r
685 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
686 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
687\r
688 NoRootBridge = TRUE;\r
689 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
690 List = HostBridgeInstance->Head.ForwardLink;\r
691\r
692 while (List != &HostBridgeInstance->Head) {\r
693 NoRootBridge = FALSE;\r
694 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
695 if (*RootBridgeHandle == NULL) {\r
696 //\r
697 // Return the first Root Bridge Handle of the Host Bridge\r
698 //\r
699 *RootBridgeHandle = RootBridgeInstance->Handle;\r
700 return EFI_SUCCESS;\r
701 } else {\r
702 if (*RootBridgeHandle == RootBridgeInstance->Handle) {\r
703 //\r
704 // Get next if have\r
705 //\r
706 List = List->ForwardLink;\r
707 if (List != &HostBridgeInstance->Head) {\r
708 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
709 *RootBridgeHandle = RootBridgeInstance->Handle;\r
710 return EFI_SUCCESS;\r
711 } else {\r
712 return EFI_NOT_FOUND;\r
713 }\r
714 }\r
715 }\r
716\r
717 List = List->ForwardLink;\r
718 //\r
719 // end while\r
720 //\r
721 }\r
722\r
723 if (NoRootBridge) {\r
724 return EFI_NOT_FOUND;\r
725 } else {\r
726 return EFI_INVALID_PARAMETER;\r
727 }\r
728}\r
729\r
730EFI_STATUS\r
731EFIAPI\r
732GetAttributes (\r
733 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
734 IN EFI_HANDLE RootBridgeHandle,\r
735 OUT UINT64 *Attributes\r
736 )\r
737/*++\r
738\r
739Routine Description:\r
740 Returns the attributes of a PCI Root Bridge.\r
741\r
742Arguments:\r
743\r
744 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
745 RootBridgeHandle - The device handle of the PCI Root Bridge\r
746 that the caller is interested in.\r
747 Attributes - The pointer to attributes of the PCI Root Bridge.\r
748\r
749Returns:\r
750\r
751 EFI_SUCCESS - Succeed.\r
752 EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or\r
753 RootBridgeHandle is not an EFI_HANDLE\r
754 that was returned on a previous call to\r
755 GetNextRootBridge().\r
756\r
757--*/\r
758{\r
759 EFI_LIST_ENTRY *List;\r
760 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
761 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
762\r
763 if (Attributes == NULL) {\r
764 return EFI_INVALID_PARAMETER;\r
765 }\r
766\r
767 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
768 List = HostBridgeInstance->Head.ForwardLink;\r
769\r
770 while (List != &HostBridgeInstance->Head) {\r
771 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
772 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
773 *Attributes = RootBridgeInstance->RootBridgeAllocAttrib;\r
774 return EFI_SUCCESS;\r
775 }\r
776\r
777 List = List->ForwardLink;\r
778 }\r
779 //\r
780 // RootBridgeHandle is not an EFI_HANDLE\r
781 // that was returned on a previous call to GetNextRootBridge()\r
782 //\r
783 return EFI_INVALID_PARAMETER;\r
784}\r
785\r
786EFI_STATUS\r
787EFIAPI\r
788StartBusEnumeration (\r
789 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
790 IN EFI_HANDLE RootBridgeHandle,\r
791 OUT VOID **Configuration\r
792 )\r
793/*++\r
794\r
795Routine Description:\r
796 This is the request from the PCI enumerator to set up\r
797 the specified PCI Root Bridge for bus enumeration process.\r
798\r
799Arguments:\r
800\r
801 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
802 RootBridgeHandle - The PCI Root Bridge to be set up.\r
803 Configuration - Pointer to the pointer to the PCI bus resource descriptor.\r
804\r
805Returns:\r
806\r
807 EFI_SUCCESS - Succeed.\r
808 EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.\r
809 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.\r
810\r
811--*/\r
812{\r
813 EFI_LIST_ENTRY *List;\r
814 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
815 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
816 VOID *Buffer;\r
817 UINT8 *Temp;\r
818 EFI_STATUS Status;\r
819 UINTN BusStart;\r
820 UINTN BusEnd;\r
821 UINT64 BusReserve;\r
822\r
823 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
824 List = HostBridgeInstance->Head.ForwardLink;\r
825\r
826 while (List != &HostBridgeInstance->Head) {\r
827 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
828 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
829 //\r
830 // Set up the Root Bridge for Bus Enumeration\r
831 //\r
832 BusStart = RootBridgeInstance->Aperture.BusBase;\r
833 BusEnd = RootBridgeInstance->Aperture.BusLimit;\r
834 BusReserve = RootBridgeInstance->Aperture.BusReserve;\r
835 //\r
836 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR\r
837 //\r
838 Status = gBS->AllocatePool (\r
839 EfiBootServicesData,\r
840 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
841 &Buffer\r
842 );\r
843 if (EFI_ERROR (Status)) {\r
844 return EFI_OUT_OF_RESOURCES;\r
845 }\r
846\r
847 Temp = (UINT8 *) Buffer;\r
848\r
849 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
850 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len = 0x2B;\r
851 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
852 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->GenFlag = 0;\r
853 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->SpecificFlag = 0;\r
854 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrSpaceGranularity = 0;\r
855 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMin = BusStart;\r
856 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMax = BusReserve;\r
857 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrTranslationOffset = 0;\r
858 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrLen = BusEnd - BusStart + 1;\r
859\r
860 Temp = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
861 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = ACPI_END_TAG_DESCRIPTOR;\r
862 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;\r
863\r
864 *Configuration = Buffer;\r
865 return EFI_SUCCESS;\r
866 }\r
867\r
868 List = List->ForwardLink;\r
869 }\r
870\r
871 return EFI_INVALID_PARAMETER;\r
872}\r
873\r
874EFI_STATUS\r
875EFIAPI\r
876SetBusNumbers (\r
877 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
878 IN EFI_HANDLE RootBridgeHandle,\r
879 IN VOID *Configuration\r
880 )\r
881/*++\r
882\r
883Routine Description:\r
884 This function programs the PCI Root Bridge hardware so that\r
885 it decodes the specified PCI bus range.\r
886\r
887Arguments:\r
888\r
889 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
890 RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed.\r
891 Configuration - The pointer to the PCI bus resource descriptor.\r
892\r
893Returns:\r
894\r
895 EFI_SUCCESS - Succeed.\r
896 EFI_INVALID_PARAMETER - Wrong parameters passed in.\r
897\r
898--*/\r
899{\r
900 EFI_LIST_ENTRY *List;\r
901 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
902 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
903 UINT8 *Ptr;\r
904 UINTN BusStart;\r
905 UINTN BusEnd;\r
906 UINTN BusLen;\r
907\r
908 if (Configuration == NULL) {\r
909 return EFI_INVALID_PARAMETER;\r
910 }\r
911\r
912 Ptr = Configuration;\r
913\r
914 //\r
915 // Check the Configuration is valid\r
916 //\r
917 if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
918 return EFI_INVALID_PARAMETER;\r
919 }\r
920\r
921 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
922 return EFI_INVALID_PARAMETER;\r
923 }\r
924\r
925 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
926 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {\r
927 return EFI_INVALID_PARAMETER;\r
928 }\r
929\r
930 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
931 List = HostBridgeInstance->Head.ForwardLink;\r
932\r
933 Ptr = Configuration;\r
934\r
935 while (List != &HostBridgeInstance->Head) {\r
936 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
937 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
938 BusStart = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrRangeMin;\r
939 BusLen = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrLen;\r
940 BusEnd = BusStart + BusLen - 1;\r
941\r
942 if (BusStart > BusEnd) {\r
943 return EFI_INVALID_PARAMETER;\r
944 }\r
945\r
946 if ((BusStart < RootBridgeInstance->Aperture.BusBase) || (BusEnd > RootBridgeInstance->Aperture.BusLimit)) {\r
947 return EFI_INVALID_PARAMETER;\r
948 }\r
949 //\r
950 // Update the Bus Range\r
951 //\r
952 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;\r
953 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;\r
954 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;\r
955 RootBridgeInstance->BusScanCount++;\r
956 if (RootBridgeInstance->BusScanCount > 0) {\r
957 //\r
958 // Only care about the 2nd PCI bus scanning\r
959 //\r
960 RootBridgeInstance->BusNumberAssigned = TRUE;\r
961 }\r
962\r
963 return EFI_SUCCESS;\r
964 }\r
965\r
966 List = List->ForwardLink;\r
967 }\r
968\r
969 return EFI_INVALID_PARAMETER;\r
970}\r
971\r
972EFI_STATUS\r
973EFIAPI\r
974SubmitResources (\r
975 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
976 IN EFI_HANDLE RootBridgeHandle,\r
977 IN VOID *Configuration\r
978 )\r
979/*++\r
980\r
981Routine Description:\r
982\r
983 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.\r
984\r
985Arguments:\r
986 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
987 RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements.\r
988 are being submitted.\r
989 Configuration - The pointer to the PCI I/O and PCI memory resource descriptor.\r
990\r
991Returns:\r
992\r
993 EFI_SUCCESS - Succeed.\r
994 EFI_INVALID_PARAMETER - Wrong parameters passed in.\r
995\r
996--*/\r
997{\r
998 EFI_LIST_ENTRY *List;\r
999 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1000 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1001 UINT8 *Temp;\r
1002 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;\r
1003 UINT64 AddrLen;\r
1004 UINT64 Alignment;\r
1005 UINT64 Value;\r
1006\r
1007 //\r
1008 // Check the input parameter: Configuration\r
1009 //\r
1010 if (Configuration == NULL) {\r
1011 return EFI_INVALID_PARAMETER;\r
1012 }\r
1013\r
1014 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1015 List = HostBridgeInstance->Head.ForwardLink;\r
1016\r
1017 Temp = (UINT8 *) Configuration;\r
1018 while (List != &HostBridgeInstance->Head) {\r
1019 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1020 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1021 //\r
1022 // Check the resource descriptors.\r
1023 // If the Configuration includes one or more invalid resource descriptors, all the resource\r
1024 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.\r
1025 //\r
1026 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1027 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
1028 DEBUG ((EFI_D_INFO, " ptr->ResType:%x \n",ptr->ResType));\r
1029 DEBUG ((EFI_D_INFO, " ptr->AddrLen:0x%lx AddrRangeMin:0x%lx AddrRangeMax:0x%lx\n\n",ptr->AddrLen,ptr->AddrRangeMin,ptr->AddrRangeMax));\r
1030\r
1031 switch (ptr->ResType) {\r
1032 case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
1033 if (ptr->AddrSpaceGranularity != 32 && ptr->AddrSpaceGranularity != 64) {\r
1034 return EFI_INVALID_PARAMETER;\r
1035 }\r
1036 if (ptr->AddrSpaceGranularity == 32 && ptr->AddrLen > 0xffffffff) {\r
1037 return EFI_INVALID_PARAMETER;\r
1038 }\r
1039 //\r
1040 // If the PCI root bridge does not support separate windows for nonprefetchable and\r
1041 // prefetchable memory, then the PCI bus driver needs to include requests for\r
1042 // prefetchable memory in the nonprefetchable memory pool.\r
1043 //\r
1044 if ((RootBridgeInstance->RootBridgeAllocAttrib & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 &&\r
1045 ((ptr->SpecificFlag & (BIT2 | BIT1)) != 0)) {\r
1046 return EFI_INVALID_PARAMETER;\r
1047 }\r
1048 case ACPI_ADDRESS_SPACE_TYPE_IO:\r
1049 //\r
1050 // Check aligment, it should be of the form 2^n-1\r
1051 //\r
1052 Value = Power2MaxMemory (ptr->AddrRangeMax + 1);\r
1053 if (Value != (ptr->AddrRangeMax + 1)) {\r
1054 CpuDeadLoop();\r
1055 return EFI_INVALID_PARAMETER;\r
1056 }\r
1057 break;\r
1058 case ACPI_ADDRESS_SPACE_TYPE_BUS:\r
1059 default:\r
1060 return EFI_INVALID_PARAMETER;\r
1061 }\r
1062 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;\r
1063 }\r
1064 if (*Temp != ACPI_END_TAG_DESCRIPTOR) {\r
1065 return EFI_INVALID_PARAMETER;\r
1066 }\r
1067\r
1068 Temp = (UINT8 *) Configuration;\r
1069 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1070 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
1071\r
1072 switch (ptr->ResType) {\r
1073 case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
1074 AddrLen = (UINT64) ptr->AddrLen;\r
1075 Alignment = (UINT64) ptr->AddrRangeMax;\r
1076 if (ptr->AddrSpaceGranularity == 32) {\r
1077 if (ptr->SpecificFlag == 0x06) {\r
1078 //\r
1079 // Apply from GCD\r
1080 //\r
1081 RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;\r
1082 } else {\r
1083 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;\r
1084 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;\r
1085 RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;\r
1086 HostBridgeInstance->ResourceSubmited = TRUE;\r
1087 }\r
1088 }\r
1089\r
1090 if (ptr->AddrSpaceGranularity == 64) {\r
1091 if (ptr->SpecificFlag == 0x06) {\r
1092 RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;\r
1093 } else {\r
1094 RootBridgeInstance->ResAllocNode[TypeMem64].Length = AddrLen;\r
1095 RootBridgeInstance->ResAllocNode[TypeMem64].Alignment = Alignment;\r
1096 RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;\r
1097 HostBridgeInstance->ResourceSubmited = TRUE;\r
1098 }\r
1099 }\r
1100 break;\r
1101\r
1102 case ACPI_ADDRESS_SPACE_TYPE_IO:\r
1103 AddrLen = (UINT64) ptr->AddrLen;\r
1104 Alignment = (UINT64) ptr->AddrRangeMax;\r
1105 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;\r
1106 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;\r
1107 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;\r
1108 HostBridgeInstance->ResourceSubmited = TRUE;\r
1109 break;\r
1110\r
1111 default:\r
1112 break;\r
1113 }\r
1114\r
1115 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1116 }\r
1117\r
1118 return EFI_SUCCESS;\r
1119 }\r
1120\r
1121 List = List->ForwardLink;\r
1122 }\r
1123\r
1124 return EFI_INVALID_PARAMETER;\r
1125}\r
1126\r
1127EFI_STATUS\r
1128EFIAPI\r
1129GetProposedResources (\r
1130 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1131 IN EFI_HANDLE RootBridgeHandle,\r
1132 OUT VOID **Configuration\r
1133 )\r
1134/*++\r
1135\r
1136Routine Description:\r
1137 This function returns the proposed resource settings for the specified\r
1138 PCI Root Bridge.\r
1139\r
1140Arguments:\r
1141\r
1142 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1143 RootBridgeHandle - The PCI Root Bridge handle.\r
1144 Configuration - The pointer to the pointer to the PCI I/O\r
1145 and memory resource descriptor.\r
1146\r
1147Returns:\r
1148\r
1149 EFI_SUCCESS - Succeed.\r
1150 EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.\r
1151 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.\r
1152\r
1153--*/\r
1154{\r
1155 EFI_LIST_ENTRY *List;\r
1156 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1157 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1158 UINTN Index;\r
1159 UINTN Number;\r
1160 VOID *Buffer;\r
1161 UINT8 *Temp;\r
1162 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;\r
1163 EFI_STATUS Status;\r
1164 UINT64 ResStatus;\r
1165\r
1166 Buffer = NULL;\r
1167 Number = 0;\r
1168 //\r
1169 // Get the Host Bridge Instance from the resource allocation protocol\r
1170 //\r
1171 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1172 List = HostBridgeInstance->Head.ForwardLink;\r
1173\r
1174 //\r
1175 // Enumerate the root bridges in this host bridge\r
1176 //\r
1177 while (List != &HostBridgeInstance->Head) {\r
1178 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1179 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1180 for (Index = 0; Index < TypeBus; Index++) {\r
1181 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
1182 Number++;\r
1183 }\r
1184 }\r
1185\r
1186 if (Number > 0) {\r
1187 Status = gBS->AllocatePool (\r
1188 EfiBootServicesData,\r
1189 Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
1190 &Buffer\r
1191 );\r
1192\r
1193 if (EFI_ERROR (Status)) {\r
1194 return EFI_OUT_OF_RESOURCES;\r
1195 }\r
1196\r
1197 ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1198 }\r
1199\r
1200 ASSERT (Buffer != NULL);\r
1201 Temp = Buffer;\r
1202 for (Index = 0; Index < TypeBus; Index++) {\r
1203 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
1204 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
1205 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;\r
1206\r
1207 switch (Index) {\r
1208\r
1209 case TypeIo:\r
1210 //\r
1211 // Io\r
1212 //\r
1213 ptr->Desc = 0x8A;\r
1214 ptr->Len = 0x2B;\r
1215 ptr->ResType = 1;\r
1216 ptr->GenFlag = 0;\r
1217 ptr->SpecificFlag = 0;\r
1218 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;\r
1219 ptr->AddrRangeMax = 0;\r
1220 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;\r
1221 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
1222 break;\r
1223\r
1224 case TypeMem32:\r
1225 //\r
1226 // Memory 32\r
1227 //\r
1228 ptr->Desc = 0x8A;\r
1229 ptr->Len = 0x2B;\r
1230 ptr->ResType = 0;\r
1231 ptr->GenFlag = 0;\r
1232 ptr->SpecificFlag = 0;\r
1233 ptr->AddrSpaceGranularity = 32;\r
1234 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;\r
1235 ptr->AddrRangeMax = 0;\r
1236 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;\r
1237 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
1238 break;\r
1239\r
1240 case TypePMem32:\r
1241 //\r
1242 // Prefetch memory 32\r
1243 //\r
1244 ptr->Desc = 0x8A;\r
1245 ptr->Len = 0x2B;\r
1246 ptr->ResType = 0;\r
1247 ptr->GenFlag = 0;\r
1248 ptr->SpecificFlag = 6;\r
1249 ptr->AddrSpaceGranularity = 32;\r
1250 ptr->AddrRangeMin = 0;\r
1251 ptr->AddrRangeMax = 0;\r
1252 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
1253 ptr->AddrLen = 0;\r
1254 break;\r
1255\r
1256 case TypeMem64:\r
1257 //\r
1258 // Memory 64\r
1259 //\r
1260 ptr->Desc = 0x8A;\r
1261 ptr->Len = 0x2B;\r
1262 ptr->ResType = 0;\r
1263 ptr->GenFlag = 0;\r
1264 ptr->SpecificFlag = 0;\r
1265 ptr->AddrSpaceGranularity = 64;\r
1266 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;\r
1267 ptr->AddrRangeMax = 0;\r
1268 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;\r
1269 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
1270 break;\r
1271\r
1272 case TypePMem64:\r
1273 //\r
1274 // Prefetch memory 64\r
1275 //\r
1276 ptr->Desc = 0x8A;\r
1277 ptr->Len = 0x2B;\r
1278 ptr->ResType = 0;\r
1279 ptr->GenFlag = 0;\r
1280 ptr->SpecificFlag = 6;\r
1281 ptr->AddrSpaceGranularity = 64;\r
1282 ptr->AddrRangeMin = 0;\r
1283 ptr->AddrRangeMax = 0;\r
1284 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
1285 ptr->AddrLen = 0;\r
1286 break;\r
1287 }\r
1288\r
1289 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1290 }\r
1291 }\r
1292\r
1293 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = 0x79;\r
1294 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;\r
1295\r
1296 *Configuration = Buffer;\r
1297\r
1298 return EFI_SUCCESS;\r
1299 }\r
1300\r
1301 List = List->ForwardLink;\r
1302 }\r
1303\r
1304 return EFI_INVALID_PARAMETER;\r
1305}\r
1306\r
1307EFI_STATUS\r
1308EFIAPI\r
1309PreprocessController (\r
1310 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1311 IN EFI_HANDLE RootBridgeHandle,\r
1312 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
1313 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1314 )\r
1315/*++\r
1316\r
1317Routine Description:\r
1318 This function is called for all the PCI controllers that the PCI\r
1319 bus driver finds. Can be used to Preprogram the controller.\r
1320\r
1321Arguments:\r
1322\r
1323 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
1324 RootBridgeHandle - The PCI Root Bridge handle.\r
1325 PciAddress - Address of the controller on the PCI bus.\r
1326 Phase - The Phase during resource allocation.\r
1327\r
1328Returns:\r
1329\r
1330 EFI_SUCCESS - Succeed.\r
1331 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.\r
1332\r
1333--*/\r
1334{\r
1335 BOOLEAN RootBridgeFound;\r
1336 EFI_LIST_ENTRY *List;\r
1337 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1338 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1339\r
1340 if (RootBridgeHandle == NULL) {\r
1341 return EFI_INVALID_PARAMETER;\r
1342 }\r
1343\r
1344 RootBridgeFound = FALSE;\r
1345 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1346 List = HostBridgeInstance->Head.ForwardLink;\r
1347\r
1348 while (List != &HostBridgeInstance->Head) {\r
1349 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1350\r
1351 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1352 RootBridgeFound = TRUE;\r
1353 break;\r
1354 }\r
1355 //\r
1356 // Get next if have\r
1357 //\r
1358 List = List->ForwardLink;\r
1359 }\r
1360\r
1361 if (RootBridgeFound == FALSE) {\r
1362 return EFI_INVALID_PARAMETER;\r
1363 }\r
1364\r
1365 return EFI_SUCCESS;\r
1366}\r
1367\r
1368UINT64\r
1369Power2MaxMemory (\r
1370 IN UINT64 MemoryLength\r
1371 )\r
1372/*++\r
1373\r
1374Routine Description:\r
1375\r
1376 Calculate maximum memory length that can be fit to a mtrr.\r
1377\r
1378Arguments:\r
1379\r
1380 MemoryLength - Input memory length.\r
1381\r
1382Returns:\r
1383\r
1384 Returned Maximum length.\r
1385\r
1386--*/\r
1387{\r
1388 UINT64 Result;\r
1389\r
1390 if (RShiftU64 (MemoryLength, 32)) {\r
1391 Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32);\r
1392 } else {\r
1393 Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength);\r
1394 }\r
1395\r
1396 return Result;\r
1397}\r