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