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