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