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