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