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