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