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