]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Print resource allocation/bar programming when PciBus driver does PCI BUS enumeration.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciLib.c
CommitLineData
9060e3ec 1/** @file\r
2 Internal library implementation for PCI Bus module.\r
3\r
8db6a82c 4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
9060e3ec 6are licensed 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 "PciBus.h"\r
16\r
8db6a82c
RN
17GLOBAL_REMOVE_IF_UNREFERENCED\r
18CHAR16 *mBarTypeStr[] = {\r
19 L"Unknow",\r
20 L" Io16",\r
21 L" Io32",\r
22 L" Mem32",\r
23 L"PMem32",\r
24 L" Mem64",\r
25 L"PMem64",\r
26 L" Io",\r
27 L" Mem",\r
28 L"Unknow"\r
29 };\r
9060e3ec 30\r
31/**\r
32 Retrieve the PCI Card device BAR information via PciIo interface.\r
33\r
34 @param PciIoDevice PCI Card device instance.\r
35\r
36**/\r
37VOID\r
38GetBackPcCardBar (\r
39 IN PCI_IO_DEVICE *PciIoDevice\r
40 )\r
41{\r
42 UINT32 Address;\r
43\r
44 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
45 return;\r
46 }\r
47\r
48 //\r
49 // Read PciBar information from the bar register\r
50 //\r
51 if (!gFullEnumeration) {\r
52 Address = 0;\r
53 PciIoDevice->PciIo.Pci.Read (\r
54 &(PciIoDevice->PciIo),\r
55 EfiPciIoWidthUint32,\r
56 PCI_CARD_MEMORY_BASE_0,\r
57 1,\r
58 &Address\r
59 );\r
60\r
61 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);\r
62 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
63 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
64\r
65 Address = 0;\r
66 PciIoDevice->PciIo.Pci.Read (\r
67 &(PciIoDevice->PciIo),\r
68 EfiPciIoWidthUint32,\r
69 PCI_CARD_MEMORY_BASE_1,\r
70 1,\r
71 &Address\r
72 );\r
73 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);\r
74 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
75 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
76\r
77 Address = 0;\r
78 PciIoDevice->PciIo.Pci.Read (\r
79 &(PciIoDevice->PciIo),\r
80 EfiPciIoWidthUint32,\r
81 PCI_CARD_IO_BASE_0_LOWER,\r
82 1,\r
83 &Address\r
84 );\r
85 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
86 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
87 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
88\r
89 Address = 0;\r
90 PciIoDevice->PciIo.Pci.Read (\r
91 &(PciIoDevice->PciIo),\r
92 EfiPciIoWidthUint32,\r
93 PCI_CARD_IO_BASE_1_LOWER,\r
94 1,\r
95 &Address\r
96 );\r
97 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
98 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
99 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
100\r
101 }\r
102\r
103 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
104 GetResourcePaddingForHpb (PciIoDevice);\r
105 }\r
106}\r
107\r
108/**\r
109 Remove rejected pci device from specific root bridge\r
110 handle.\r
111\r
112 @param RootBridgeHandle Specific parent root bridge handle.\r
113 @param Bridge Bridge device instance.\r
114\r
115**/\r
116VOID\r
117RemoveRejectedPciDevices (\r
118 IN EFI_HANDLE RootBridgeHandle,\r
119 IN PCI_IO_DEVICE *Bridge\r
120 )\r
121{\r
122 PCI_IO_DEVICE *Temp;\r
123 LIST_ENTRY *CurrentLink;\r
124 LIST_ENTRY *LastLink;\r
125\r
126 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
127 return;\r
128 }\r
129\r
130 CurrentLink = Bridge->ChildList.ForwardLink;\r
131\r
132 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
133\r
134 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
135\r
136 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
137 //\r
138 // Remove rejected devices recusively\r
139 //\r
140 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
141 } else {\r
142 //\r
143 // Skip rejection for all PPBs, while detect rejection for others\r
144 //\r
145 if (IsPciDeviceRejected (Temp)) {\r
146\r
147 //\r
148 // For P2C, remove all devices on it\r
149 //\r
150 if (!IsListEmpty (&Temp->ChildList)) {\r
151 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
152 }\r
153\r
154 //\r
155 // Finally remove itself\r
156 //\r
157 LastLink = CurrentLink->BackLink;\r
158 RemoveEntryList (CurrentLink);\r
159 FreePciDevice (Temp);\r
160\r
161 CurrentLink = LastLink;\r
162 }\r
163 }\r
164\r
165 CurrentLink = CurrentLink->ForwardLink;\r
166 }\r
167}\r
168\r
8db6a82c
RN
169/**\r
170 Dump the resourc map of the bridge device.\r
171\r
172 @param[in] BridgeResource Resource descriptor of the bridge device.\r
173**/\r
174VOID\r
175DumpBridgeResource (\r
176 IN PCI_RESOURCE_NODE *BridgeResource\r
177 )\r
178{\r
179 LIST_ENTRY *Link;\r
180 PCI_RESOURCE_NODE *Resource;\r
181 PCI_BAR *Bar;\r
182\r
183 if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {\r
184 DEBUG ((\r
185 EFI_D_INFO, "Type = %s; Base = 0x%x;\tLength = 0x%x;\tAlignment = 0x%x\n",\r
186 mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],\r
187 BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,\r
188 BridgeResource->Length, BridgeResource->Alignment\r
189 ));\r
190 for ( Link = BridgeResource->ChildList.ForwardLink\r
191 ; Link != &BridgeResource->ChildList\r
192 ; Link = Link->ForwardLink\r
193 ) {\r
194 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
195 if (Resource->ResourceUsage == PciResUsageTypical) {\r
196 Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;\r
197 DEBUG ((\r
198 EFI_D_INFO, " Base = 0x%x;\tLength = 0x%x;\tAlignment = 0x%x;\tOwner = %s ",\r
199 Bar[Resource->Bar].BaseAddress, Resource->Length, Resource->Alignment,\r
200 IS_PCI_BRIDGE (&Resource->PciDev->Pci) ? L"PPB" :\r
201 IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :\r
202 L"PCI"\r
203 ));\r
204\r
205 if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||\r
206 (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||\r
207 (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))\r
208 ) {\r
209 //\r
210 // The resource requirement comes from the device itself.\r
211 //\r
212 DEBUG ((\r
213 EFI_D_INFO, " [%02x|%02x|%02x:%02x]\n",\r
214 Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,\r
215 Resource->PciDev->FunctionNumber, Bar[Resource->Bar].Offset\r
216 ));\r
217 } else {\r
218 //\r
219 // The resource requirement comes from the subordinate devices.\r
220 //\r
221 DEBUG ((\r
222 EFI_D_INFO, " [%02x|%02x|%02x:**]\n",\r
223 Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,\r
224 Resource->PciDev->FunctionNumber\r
225 ));\r
226 }\r
227 } else {\r
228 DEBUG ((EFI_D_INFO, " Padding:Length = 0x%x;\tAlignment = 0x%x\n", Resource->Length, Resource->Alignment));\r
229 }\r
230 }\r
231 }\r
232}\r
233\r
234/**\r
235 Find the corresponding resource node for the Device in child list of BridgeResource.\r
236 \r
237 @param[in] Device Pointer to PCI_IO_DEVICE.\r
238 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.\r
239 \r
240 @return !NULL The corresponding resource node for the Device.\r
241 @return NULL No corresponding resource node for the Device.\r
242**/\r
243PCI_RESOURCE_NODE *\r
244FindResourceNode (\r
245 IN PCI_IO_DEVICE *Device,\r
246 IN PCI_RESOURCE_NODE *BridgeResource\r
247 )\r
248{\r
249 LIST_ENTRY *Link;\r
250 PCI_RESOURCE_NODE *Resource;\r
251\r
252 for ( Link = BridgeResource->ChildList.ForwardLink\r
253 ; Link != &BridgeResource->ChildList\r
254 ; Link = Link->ForwardLink\r
255 ) {\r
256 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
257 if (Resource->PciDev == Device) {\r
258 return Resource;\r
259 }\r
260 }\r
261\r
262 return NULL;\r
263}\r
264\r
265/**\r
266 Dump the resource map of all the devices under Bridge.\r
267 \r
268 @param[in] Bridge Bridge device instance.\r
269 @param[in] IoNode IO resource descriptor for the bridge device.\r
270 @param[in] Mem32Node Mem32 resource descriptor for the bridge device.\r
271 @param[in] PMem32Node PMem32 resource descriptor for the bridge device.\r
272 @param[in] Mem64Node Mem64 resource descriptor for the bridge device.\r
273 @param[in] PMem64Node PMem64 resource descriptor for the bridge device.\r
274**/\r
275VOID\r
276DumpResourceMap (\r
277 IN PCI_IO_DEVICE *Bridge,\r
278 IN PCI_RESOURCE_NODE *IoNode,\r
279 IN PCI_RESOURCE_NODE *Mem32Node,\r
280 IN PCI_RESOURCE_NODE *PMem32Node,\r
281 IN PCI_RESOURCE_NODE *Mem64Node,\r
282 IN PCI_RESOURCE_NODE *PMem64Node\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286 LIST_ENTRY *Link;\r
287 PCI_IO_DEVICE *Device;\r
288 PCI_RESOURCE_NODE *ChildIoNode;\r
289 PCI_RESOURCE_NODE *ChildMem32Node;\r
290 PCI_RESOURCE_NODE *ChildPMem32Node;\r
291 PCI_RESOURCE_NODE *ChildMem64Node;\r
292 PCI_RESOURCE_NODE *ChildPMem64Node;\r
293 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *ToText;\r
294 CHAR16 *Str;\r
295\r
296 DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));\r
297\r
298 Status = gBS->OpenProtocol (\r
299 Bridge->Handle,\r
300 &gEfiPciRootBridgeIoProtocolGuid,\r
301 NULL,\r
302 NULL,\r
303 NULL,\r
304 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
305 );\r
306 if (EFI_ERROR (Status)) {\r
307 DEBUG ((\r
308 EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n",\r
309 Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber\r
310 ));\r
311 } else {\r
312 Status = gBS->LocateProtocol (\r
313 &gEfiDevicePathToTextProtocolGuid,\r
314 NULL,\r
315 (VOID **) &ToText\r
316 );\r
317 Str = NULL;\r
318 if (!EFI_ERROR (Status)) {\r
319 Str = ToText->ConvertDevicePathToText (\r
320 DevicePathFromHandle (Bridge->Handle),\r
321 FALSE,\r
322 FALSE\r
323 );\r
324 }\r
325 DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));\r
326 if (Str != NULL) {\r
327 FreePool (Str);\r
328 }\r
329 }\r
330\r
331 DumpBridgeResource (IoNode);\r
332 DumpBridgeResource (Mem32Node);\r
333 DumpBridgeResource (PMem32Node);\r
334 DumpBridgeResource (Mem64Node);\r
335 DumpBridgeResource (PMem64Node);\r
336 DEBUG ((EFI_D_INFO, "\n"));\r
337\r
338 for ( Link = Bridge->ChildList.ForwardLink\r
339 ; Link != &Bridge->ChildList\r
340 ; Link = Link->ForwardLink\r
341 ) {\r
342 Device = PCI_IO_DEVICE_FROM_LINK (Link);\r
343 if (IS_PCI_BRIDGE (&Device->Pci)) {\r
344\r
345 ChildIoNode = (IoNode == NULL ? NULL : FindResourceNode (Device, IoNode));\r
346 ChildMem32Node = (Mem32Node == NULL ? NULL : FindResourceNode (Device, Mem32Node));\r
347 ChildPMem32Node = (PMem32Node == NULL ? NULL : FindResourceNode (Device, PMem32Node));\r
348 ChildMem64Node = (Mem64Node == NULL ? NULL : FindResourceNode (Device, Mem64Node));\r
349 ChildPMem64Node = (PMem64Node == NULL ? NULL : FindResourceNode (Device, PMem64Node));\r
350\r
351 DumpResourceMap (\r
352 Device,\r
353 ChildIoNode,\r
354 ChildMem32Node,\r
355 ChildPMem32Node,\r
356 ChildMem64Node,\r
357 ChildPMem64Node\r
358 );\r
359 }\r
360 }\r
361}\r
362\r
9060e3ec 363/**\r
364 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
365\r
366 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
367\r
368 @retval EFI_SUCCESS Successfully finished resource allocation.\r
369 @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
370 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
371 @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
372\r
373 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
374\r
375**/\r
376EFI_STATUS\r
377PciHostBridgeResourceAllocator (\r
378 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
379 )\r
380{\r
381 PCI_IO_DEVICE *RootBridgeDev;\r
382 EFI_HANDLE RootBridgeHandle;\r
383 VOID *AcpiConfig;\r
384 EFI_STATUS Status;\r
385 UINT64 IoBase;\r
386 UINT64 Mem32Base;\r
387 UINT64 PMem32Base;\r
388 UINT64 Mem64Base;\r
389 UINT64 PMem64Base;\r
390 UINT64 IoResStatus;\r
391 UINT64 Mem32ResStatus;\r
392 UINT64 PMem32ResStatus;\r
393 UINT64 Mem64ResStatus;\r
394 UINT64 PMem64ResStatus;\r
395 UINT64 MaxOptionRomSize;\r
396 PCI_RESOURCE_NODE *IoBridge;\r
397 PCI_RESOURCE_NODE *Mem32Bridge;\r
398 PCI_RESOURCE_NODE *PMem32Bridge;\r
399 PCI_RESOURCE_NODE *Mem64Bridge;\r
400 PCI_RESOURCE_NODE *PMem64Bridge;\r
401 PCI_RESOURCE_NODE IoPool;\r
402 PCI_RESOURCE_NODE Mem32Pool;\r
403 PCI_RESOURCE_NODE PMem32Pool;\r
404 PCI_RESOURCE_NODE Mem64Pool;\r
405 PCI_RESOURCE_NODE PMem64Pool;\r
406 BOOLEAN ReAllocate;\r
407 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
408 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
409\r
410 //\r
411 // Reallocate flag\r
412 //\r
413 ReAllocate = FALSE;\r
414\r
415 //\r
416 // It may try several times if the resource allocation fails\r
417 //\r
418 while (TRUE) {\r
419 //\r
420 // Initialize resource pool\r
421 //\r
422 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
423 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
424 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
425 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
426 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
427\r
428 RootBridgeDev = NULL;\r
429 RootBridgeHandle = 0;\r
430\r
431 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
432 //\r
433 // Get Root Bridge Device by handle\r
434 //\r
435 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
436\r
437 if (RootBridgeDev == NULL) {\r
438 return EFI_NOT_FOUND;\r
439 }\r
440\r
441 //\r
442 // Create the entire system resource map from the information collected by\r
443 // enumerator. Several resource tree was created\r
444 //\r
445\r
1ef26783 446 //\r
447 // If non-stardard PCI Bridge I/O window alignment is supported,\r
448 // set I/O aligment to minimum possible alignment for root bridge.\r
449 //\r
9060e3ec 450 IoBridge = CreateResourceNode (\r
451 RootBridgeDev,\r
452 0,\r
1ef26783 453 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,\r
8db6a82c 454 RB_IO_RANGE,\r
9060e3ec 455 PciBarTypeIo16,\r
456 PciResUsageTypical\r
457 );\r
458\r
459 Mem32Bridge = CreateResourceNode (\r
460 RootBridgeDev,\r
461 0,\r
462 0xFFFFF,\r
8db6a82c 463 RB_MEM32_RANGE,\r
9060e3ec 464 PciBarTypeMem32,\r
465 PciResUsageTypical\r
466 );\r
467\r
468 PMem32Bridge = CreateResourceNode (\r
469 RootBridgeDev,\r
470 0,\r
471 0xFFFFF,\r
8db6a82c 472 RB_PMEM32_RANGE,\r
9060e3ec 473 PciBarTypePMem32,\r
474 PciResUsageTypical\r
475 );\r
476\r
477 Mem64Bridge = CreateResourceNode (\r
478 RootBridgeDev,\r
479 0,\r
480 0xFFFFF,\r
8db6a82c 481 RB_MEM64_RANGE,\r
9060e3ec 482 PciBarTypeMem64,\r
483 PciResUsageTypical\r
484 );\r
485\r
486 PMem64Bridge = CreateResourceNode (\r
487 RootBridgeDev,\r
488 0,\r
489 0xFFFFF,\r
8db6a82c 490 RB_PMEM64_RANGE,\r
9060e3ec 491 PciBarTypePMem64,\r
492 PciResUsageTypical\r
493 );\r
494\r
495 //\r
496 // Create resourcemap by going through all the devices subject to this root bridge\r
497 //\r
498 CreateResourceMap (\r
499 RootBridgeDev,\r
500 IoBridge,\r
501 Mem32Bridge,\r
502 PMem32Bridge,\r
503 Mem64Bridge,\r
504 PMem64Bridge\r
505 );\r
506\r
507 //\r
508 // Get the max ROM size that the root bridge can process\r
509 //\r
510 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
511\r
512 //\r
513 // Skip to enlarge the resource request during realloction\r
514 //\r
515 if (!ReAllocate) {\r
516 //\r
517 // Get Max Option Rom size for current root bridge\r
518 //\r
519 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
520\r
521 //\r
522 // Enlarger the mem32 resource to accomdate the option rom\r
523 // if the mem32 resource is not enough to hold the rom\r
524 //\r
525 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
526\r
527 Mem32Bridge->Length = MaxOptionRomSize;\r
528 RootBridgeDev->RomSize = MaxOptionRomSize;\r
529\r
530 //\r
531 // Alignment should be adjusted as well\r
532 //\r
533 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
534 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
535 }\r
536 }\r
537 }\r
538\r
539 //\r
540 // Based on the all the resource tree, contruct ACPI resource node to\r
541 // submit the resource aperture to pci host bridge protocol\r
542 //\r
543 Status = ConstructAcpiResourceRequestor (\r
544 RootBridgeDev,\r
545 IoBridge,\r
546 Mem32Bridge,\r
547 PMem32Bridge,\r
548 Mem64Bridge,\r
549 PMem64Bridge,\r
550 &AcpiConfig\r
551 );\r
552\r
553 //\r
554 // Insert these resource nodes into the database\r
555 //\r
556 InsertResourceNode (&IoPool, IoBridge);\r
557 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
558 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
559 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
560 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
561\r
562 if (Status == EFI_SUCCESS) {\r
563 //\r
564 // Submit the resource requirement\r
565 //\r
566 Status = PciResAlloc->SubmitResources (\r
567 PciResAlloc,\r
568 RootBridgeDev->Handle,\r
569 AcpiConfig\r
570 );\r
571 }\r
572\r
573 //\r
574 // Free acpi resource node\r
575 //\r
576 if (AcpiConfig != NULL) {\r
577 FreePool (AcpiConfig);\r
578 }\r
579\r
580 if (EFI_ERROR (Status)) {\r
581 //\r
582 // Destroy all the resource tree\r
583 //\r
584 DestroyResourceTree (&IoPool);\r
585 DestroyResourceTree (&Mem32Pool);\r
586 DestroyResourceTree (&PMem32Pool);\r
587 DestroyResourceTree (&Mem64Pool);\r
588 DestroyResourceTree (&PMem64Pool);\r
589 return Status;\r
590 }\r
591 }\r
592 //\r
593 // End while, at least one Root Bridge should be found.\r
594 //\r
595 ASSERT (RootBridgeDev != NULL);\r
596\r
597 //\r
598 // Notify platform to start to program the resource\r
599 //\r
600 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
601 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
602 //\r
603 // If Hot Plug is not supported\r
604 //\r
605 if (EFI_ERROR (Status)) {\r
606 //\r
607 // Allocation failed, then return\r
608 //\r
609 return EFI_OUT_OF_RESOURCES;\r
610 }\r
611 //\r
612 // Allocation succeed.\r
613 // Get host bridge handle for status report, and then skip the main while\r
614 //\r
615 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
616\r
617 break;\r
618\r
619 } else {\r
620 //\r
621 // If Hot Plug is supported\r
622 //\r
623 if (!EFI_ERROR (Status)) {\r
624 //\r
625 // Allocation succeed, then continue the following\r
626 //\r
627 break;\r
628 }\r
629\r
630 //\r
631 // If the resource allocation is unsuccessful, free resources on bridge\r
632 //\r
633\r
634 RootBridgeDev = NULL;\r
635 RootBridgeHandle = 0;\r
636\r
637 IoResStatus = EFI_RESOURCE_SATISFIED;\r
638 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
639 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
640 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
641 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
642\r
643 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
644 //\r
645 // Get RootBridg Device by handle\r
646 //\r
647 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
648 if (RootBridgeDev == NULL) {\r
649 return EFI_NOT_FOUND;\r
650 }\r
651\r
652 //\r
653 // Get host bridge handle for status report\r
654 //\r
655 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
656\r
657 //\r
658 // Get acpi resource node for all the resource types\r
659 //\r
660 AcpiConfig = NULL;\r
661\r
662 Status = PciResAlloc->GetProposedResources (\r
663 PciResAlloc,\r
664 RootBridgeDev->Handle,\r
665 &AcpiConfig\r
666 );\r
667\r
668 if (EFI_ERROR (Status)) {\r
669 return Status;\r
670 }\r
671\r
672 if (AcpiConfig != NULL) {\r
673 //\r
674 // Adjust resource allocation policy for each RB\r
675 //\r
676 GetResourceAllocationStatus (\r
677 AcpiConfig,\r
678 &IoResStatus,\r
679 &Mem32ResStatus,\r
680 &PMem32ResStatus,\r
681 &Mem64ResStatus,\r
682 &PMem64ResStatus\r
683 );\r
684 FreePool (AcpiConfig);\r
685 }\r
686 }\r
687 //\r
688 // End while\r
689 //\r
690\r
691 //\r
692 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
693 //\r
694 //\r
695 // It is very difficult to follow the spec here\r
696 // Device path , Bar index can not be get here\r
697 //\r
698 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
699\r
700 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
701 EFI_PROGRESS_CODE,\r
702 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
703 (VOID *) &AllocFailExtendedData,\r
704 sizeof (AllocFailExtendedData)\r
705 );\r
706\r
707 Status = PciHostBridgeAdjustAllocation (\r
708 &IoPool,\r
709 &Mem32Pool,\r
710 &PMem32Pool,\r
711 &Mem64Pool,\r
712 &PMem64Pool,\r
713 IoResStatus,\r
714 Mem32ResStatus,\r
715 PMem32ResStatus,\r
716 Mem64ResStatus,\r
717 PMem64ResStatus\r
718 );\r
719\r
720 //\r
721 // Destroy all the resource tree\r
722 //\r
723 DestroyResourceTree (&IoPool);\r
724 DestroyResourceTree (&Mem32Pool);\r
725 DestroyResourceTree (&PMem32Pool);\r
726 DestroyResourceTree (&Mem64Pool);\r
727 DestroyResourceTree (&PMem64Pool);\r
728\r
729 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
730\r
731 if (EFI_ERROR (Status)) {\r
732 return Status;\r
733 }\r
734\r
735 ReAllocate = TRUE;\r
736 }\r
737 }\r
738 //\r
739 // End main while\r
740 //\r
741\r
742 //\r
743 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
744 //\r
745 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
746 EFI_PROGRESS_CODE,\r
fe91c992 747 EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,\r
9060e3ec 748 (VOID *) &HandleExtendedData,\r
749 sizeof (HandleExtendedData)\r
750 );\r
751\r
752 //\r
753 // Notify pci bus driver starts to program the resource\r
754 //\r
755 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
756\r
757 RootBridgeDev = NULL;\r
758\r
759 RootBridgeHandle = 0;\r
760\r
761 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
762 //\r
763 // Get RootBridg Device by handle\r
764 //\r
765 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
766\r
767 if (RootBridgeDev == NULL) {\r
768 return EFI_NOT_FOUND;\r
769 }\r
770\r
771 //\r
772 // Get acpi resource node for all the resource types\r
773 //\r
774 AcpiConfig = NULL;\r
775 Status = PciResAlloc->GetProposedResources (\r
776 PciResAlloc,\r
777 RootBridgeDev->Handle,\r
778 &AcpiConfig\r
779 );\r
780\r
781 if (EFI_ERROR (Status)) {\r
782 return Status;\r
783 }\r
784\r
785 //\r
786 // Get the resource base by interpreting acpi resource node\r
787 //\r
788 //\r
789 GetResourceBase (\r
790 AcpiConfig,\r
791 &IoBase,\r
792 &Mem32Base,\r
793 &PMem32Base,\r
794 &Mem64Base,\r
795 &PMem64Base\r
796 );\r
797\r
798 //\r
799 // Process option rom for this root bridge\r
800 //\r
801 ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
802\r
803 //\r
804 // Create the entire system resource map from the information collected by\r
805 // enumerator. Several resource tree was created\r
806 //\r
8db6a82c
RN
807 IoBridge = FindResourceNode (RootBridgeDev, &IoPool);\r
808 Mem32Bridge = FindResourceNode (RootBridgeDev, &Mem32Pool);\r
809 PMem32Bridge = FindResourceNode (RootBridgeDev, &PMem32Pool);\r
810 Mem64Bridge = FindResourceNode (RootBridgeDev, &Mem64Pool);\r
811 PMem64Bridge = FindResourceNode (RootBridgeDev, &PMem64Pool);\r
9060e3ec 812\r
813 //\r
814 // Program IO resources\r
815 //\r
816 ProgramResource (\r
817 IoBase,\r
818 IoBridge\r
819 );\r
820\r
821 //\r
822 // Program Mem32 resources\r
823 //\r
824 ProgramResource (\r
825 Mem32Base,\r
826 Mem32Bridge\r
827 );\r
828\r
829 //\r
830 // Program PMem32 resources\r
831 //\r
832 ProgramResource (\r
833 PMem32Base,\r
834 PMem32Bridge\r
835 );\r
836\r
837 //\r
838 // Program Mem64 resources\r
839 //\r
840 ProgramResource (\r
841 Mem64Base,\r
842 Mem64Bridge\r
843 );\r
844\r
845 //\r
846 // Program PMem64 resources\r
847 //\r
848 ProgramResource (\r
849 PMem64Base,\r
850 PMem64Bridge\r
851 );\r
852\r
8db6a82c
RN
853 IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase;\r
854 Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;\r
855 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
856 Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;\r
857 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
858\r
859 //\r
860 // Dump the resource map for current root bridge\r
861 //\r
862 DEBUG_CODE (\r
863 DumpResourceMap (\r
864 RootBridgeDev,\r
865 IoBridge,\r
866 Mem32Bridge,\r
867 PMem32Bridge,\r
868 Mem64Bridge,\r
869 PMem64Bridge\r
870 );\r
871 );\r
872\r
9060e3ec 873 FreePool (AcpiConfig);\r
874 }\r
875\r
876 //\r
877 // Destroy all the resource tree\r
878 //\r
879 DestroyResourceTree (&IoPool);\r
880 DestroyResourceTree (&Mem32Pool);\r
881 DestroyResourceTree (&PMem32Pool);\r
882 DestroyResourceTree (&Mem64Pool);\r
883 DestroyResourceTree (&PMem64Pool);\r
884\r
885 //\r
886 // Notify the resource allocation phase is to end\r
887 //\r
888 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
889\r
890 return EFI_SUCCESS;\r
891}\r
892\r
893/**\r
894 Scan pci bus and assign bus number to the given PCI bus system.\r
895\r
896 @param Bridge Bridge device instance.\r
897 @param StartBusNumber start point.\r
898 @param SubBusNumber Point to sub bus number.\r
899 @param PaddedBusRange Customized bus number.\r
900\r
901 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
902 @retval other Some error occurred when scanning pci bus.\r
903\r
904 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
905\r
906**/\r
907EFI_STATUS\r
908PciScanBus (\r
909 IN PCI_IO_DEVICE *Bridge,\r
910 IN UINT8 StartBusNumber,\r
911 OUT UINT8 *SubBusNumber,\r
912 OUT UINT8 *PaddedBusRange\r
913 )\r
914{\r
915 EFI_STATUS Status;\r
916 PCI_TYPE00 Pci;\r
917 UINT8 Device;\r
918 UINT8 Func;\r
919 UINT64 Address;\r
920 UINTN SecondBus;\r
921 UINT16 Register;\r
922 UINTN HpIndex;\r
923 PCI_IO_DEVICE *PciDevice;\r
924 EFI_EVENT Event;\r
925 EFI_HPC_STATE State;\r
926 UINT64 PciAddress;\r
927 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
928 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
929 UINT16 BusRange;\r
930 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
931 BOOLEAN BusPadding;\r
932 UINT32 TempReservedBusNum;\r
933\r
934 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
935 SecondBus = 0;\r
936 Register = 0;\r
937 State = 0;\r
938 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
939 BusRange = 0;\r
940 BusPadding = FALSE;\r
941 PciDevice = NULL;\r
942 PciAddress = 0;\r
943\r
944 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
945 TempReservedBusNum = 0;\r
946 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
947\r
948 //\r
949 // Check to see whether a pci device is present\r
950 //\r
951 Status = PciDevicePresent (\r
952 PciRootBridgeIo,\r
953 &Pci,\r
954 StartBusNumber,\r
955 Device,\r
956 Func\r
957 );\r
958\r
959 if (EFI_ERROR (Status)) {\r
9060e3ec 960 continue;\r
961 }\r
962\r
d4048391 963 //\r
964 // Get the PCI device information\r
965 //\r
966 Status = PciSearchDevice (\r
967 Bridge,\r
968 &Pci,\r
969 StartBusNumber,\r
970 Device,\r
971 Func,\r
972 &PciDevice\r
973 );\r
9060e3ec 974\r
d4048391 975 ASSERT (!EFI_ERROR (Status));\r
9060e3ec 976\r
d4048391 977 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 978\r
d4048391 979 if (!IS_PCI_BRIDGE (&Pci)) {\r
980 //\r
981 // PCI bridges will be called later\r
982 // Here just need for PCI device or PCI to cardbus controller\r
983 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
984 //\r
985 PreprocessController (\r
986 PciDevice,\r
987 PciDevice->BusNumber,\r
988 PciDevice->DeviceNumber,\r
989 PciDevice->FunctionNumber,\r
990 EfiPciBeforeChildBusEnumeration\r
991 );\r
992 }\r
9060e3ec 993\r
d4048391 994 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 995 //\r
996 // For Pci Hotplug controller devcie only\r
997 //\r
998 if (gPciHotPlugInit != NULL) {\r
999 //\r
1000 // Check if it is a Hotplug PCI controller\r
1001 //\r
1002 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 1003 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 1004\r
1005 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1006\r
1007 Status = CreateEventForHpc (HpIndex, &Event);\r
1008\r
1009 ASSERT (!EFI_ERROR (Status));\r
1010\r
1011 Status = gPciHotPlugInit->InitializeRootHpc (\r
1012 gPciHotPlugInit,\r
1013 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1014 PciAddress,\r
1015 Event,\r
1016 &State\r
1017 );\r
1018\r
1019 PreprocessController (\r
1020 PciDevice,\r
1021 PciDevice->BusNumber,\r
1022 PciDevice->DeviceNumber,\r
1023 PciDevice->FunctionNumber,\r
1024 EfiPciBeforeChildBusEnumeration\r
1025 );\r
1026 }\r
1027 }\r
1028 }\r
1029 }\r
1030\r
1031 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1032 //\r
1033 // For PPB\r
1034 //\r
1035 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1036 //\r
1037 // If Hot Plug is not supported,\r
1038 // get the bridge information\r
1039 //\r
1040 Status = PciSearchDevice (\r
1041 Bridge,\r
1042 &Pci,\r
1043 StartBusNumber,\r
1044 Device,\r
1045 Func,\r
1046 &PciDevice\r
1047 );\r
1048\r
1049 if (EFI_ERROR (Status)) {\r
1050 return Status;\r
1051 }\r
1052 } else {\r
1053 //\r
1054 // If Hot Plug is supported,\r
1055 // Get the bridge information\r
1056 //\r
1057 BusPadding = FALSE;\r
1058 if (gPciHotPlugInit != NULL) {\r
1059\r
1060 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1061\r
1062 //\r
1063 // If it is initialized, get the padded bus range\r
1064 //\r
1065 Status = gPciHotPlugInit->GetResourcePadding (\r
1066 gPciHotPlugInit,\r
1067 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1068 PciAddress,\r
1069 &State,\r
1070 (VOID **) &Descriptors,\r
1071 &Attributes\r
1072 );\r
1073\r
1074 if (EFI_ERROR (Status)) {\r
1075 return Status;\r
1076 }\r
1077\r
1078 BusRange = 0;\r
1079 Status = PciGetBusRange (\r
1080 &Descriptors,\r
1081 NULL,\r
1082 NULL,\r
1083 &BusRange\r
1084 );\r
1085\r
1086 FreePool (Descriptors);\r
1087\r
1088 if (EFI_ERROR (Status)) {\r
1089 return Status;\r
1090 }\r
1091\r
1092 BusPadding = TRUE;\r
1093 }\r
1094 }\r
1095 }\r
1096\r
1097 //\r
1098 // Add feature to support customized secondary bus number\r
1099 //\r
1100 if (*SubBusNumber == 0) {\r
1101 *SubBusNumber = *PaddedBusRange;\r
1102 *PaddedBusRange = 0;\r
1103 }\r
1104\r
1105 (*SubBusNumber)++;\r
1106 SecondBus = *SubBusNumber;\r
1107\r
1108 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1109 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
1110\r
1111 Status = PciRootBridgeIo->Pci.Write (\r
1112 PciRootBridgeIo,\r
1113 EfiPciWidthUint16,\r
1114 Address,\r
1115 1,\r
1116 &Register\r
1117 );\r
1118\r
1119\r
1120 //\r
1121 // If it is PPB, resursively search down this bridge\r
1122 //\r
1123 if (IS_PCI_BRIDGE (&Pci)) {\r
1124\r
1125 //\r
1126 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1127 // PCI configuration transaction to go through any PPB\r
1128 //\r
1129 Register = 0xFF;\r
1130 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1131 Status = PciRootBridgeIo->Pci.Write (\r
1132 PciRootBridgeIo,\r
1133 EfiPciWidthUint8,\r
1134 Address,\r
1135 1,\r
1136 &Register\r
1137 );\r
1138\r
1139 //\r
1140 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1141 //\r
1142 PreprocessController (\r
1143 PciDevice,\r
1144 PciDevice->BusNumber,\r
1145 PciDevice->DeviceNumber,\r
1146 PciDevice->FunctionNumber,\r
1147 EfiPciBeforeChildBusEnumeration\r
1148 );\r
1149\r
9060e3ec 1150 Status = PciScanBus (\r
1151 PciDevice,\r
1152 (UINT8) (SecondBus),\r
1153 SubBusNumber,\r
1154 PaddedBusRange\r
1155 );\r
1156 if (EFI_ERROR (Status)) {\r
1157 return Status;\r
1158 }\r
1159 }\r
1160\r
1161 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1162 //\r
1163 // Ensure the device is enabled and initialized\r
1164 //\r
1165 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1166 (State & EFI_HPC_STATE_ENABLED) != 0 &&\r
1167 (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
1168 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1169 } else {\r
1170 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
1171 }\r
1172 }\r
1173\r
1174 //\r
1175 // Set the current maximum bus number under the PPB\r
1176 //\r
1177 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1178\r
1179 Status = PciRootBridgeIo->Pci.Write (\r
1180 PciRootBridgeIo,\r
1181 EfiPciWidthUint8,\r
1182 Address,\r
1183 1,\r
1184 SubBusNumber\r
1185 );\r
1186 } else {\r
1187 //\r
1188 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 1189 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1190 //\r
d4048391 1191 if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {\r
9060e3ec 1192 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1193\r
1194 (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);\r
1195 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1196\r
1197 if (Func == 0) {\r
1198 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
1199 } else {\r
1200 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
1201 }\r
1202 }\r
1203 }\r
1204 }\r
1205\r
1206 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1207\r
1208 //\r
1209 // Skip sub functions, this is not a multi function device\r
1210 //\r
1211\r
1212 Func = PCI_MAX_FUNC;\r
1213 }\r
1214 }\r
1215 }\r
1216\r
1217 return EFI_SUCCESS;\r
1218}\r
1219\r
1220/**\r
1221 Process Option Rom on the specified root bridge.\r
1222\r
1223 @param Bridge Pci root bridge device instance.\r
1224\r
1225 @retval EFI_SUCCESS Success process.\r
1226 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1227\r
1228**/\r
1229EFI_STATUS\r
1230PciRootBridgeP2CProcess (\r
1231 IN PCI_IO_DEVICE *Bridge\r
1232 )\r
1233{\r
1234 LIST_ENTRY *CurrentLink;\r
1235 PCI_IO_DEVICE *Temp;\r
1236 EFI_HPC_STATE State;\r
1237 UINT64 PciAddress;\r
1238 EFI_STATUS Status;\r
1239\r
1240 CurrentLink = Bridge->ChildList.ForwardLink;\r
1241\r
1242 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
1243\r
1244 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1245\r
1246 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1247\r
1248 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1249\r
1250 //\r
1251 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1252 //\r
1253 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1254 EFI_PROGRESS_CODE,\r
fe91c992 1255 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
9060e3ec 1256 Temp->DevicePath\r
1257 );\r
1258\r
1259 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1260 Status = gPciHotPlugInit->InitializeRootHpc (\r
1261 gPciHotPlugInit,\r
1262 Temp->DevicePath,\r
1263 PciAddress,\r
1264 NULL,\r
1265 &State\r
1266 );\r
1267\r
1268 if (!EFI_ERROR (Status)) {\r
1269 Status = PciBridgeEnumerator (Temp);\r
1270\r
1271 if (EFI_ERROR (Status)) {\r
1272 return Status;\r
1273 }\r
1274 }\r
1275\r
1276 CurrentLink = CurrentLink->ForwardLink;\r
1277 continue;\r
1278\r
1279 }\r
1280 }\r
1281\r
1282 if (!IsListEmpty (&Temp->ChildList)) {\r
1283 Status = PciRootBridgeP2CProcess (Temp);\r
1284 }\r
1285\r
1286 CurrentLink = CurrentLink->ForwardLink;\r
1287 }\r
1288\r
1289 return EFI_SUCCESS;\r
1290}\r
1291\r
1292/**\r
1293 Process Option Rom on the specified host bridge.\r
1294\r
1295 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1296\r
1297 @retval EFI_SUCCESS Success process.\r
1298 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1299 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1300\r
1301**/\r
1302EFI_STATUS\r
1303PciHostBridgeP2CProcess (\r
1304 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1305 )\r
1306{\r
1307 EFI_HANDLE RootBridgeHandle;\r
1308 PCI_IO_DEVICE *RootBridgeDev;\r
1309 EFI_STATUS Status;\r
1310\r
1311 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1312 return EFI_SUCCESS;\r
1313 }\r
1314\r
1315 RootBridgeHandle = NULL;\r
1316\r
1317 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1318\r
1319 //\r
1320 // Get RootBridg Device by handle\r
1321 //\r
1322 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1323\r
1324 if (RootBridgeDev == NULL) {\r
1325 return EFI_NOT_FOUND;\r
1326 }\r
1327\r
1328 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1329 if (EFI_ERROR (Status)) {\r
1330 return Status;\r
1331 }\r
1332\r
1333 }\r
1334\r
1335 return EFI_SUCCESS;\r
1336}\r
1337\r
1338/**\r
1339 This function is used to enumerate the entire host bridge\r
1340 in a given platform.\r
1341\r
1342 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1343\r
1344 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1345 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1346 @retval other Some error occurred when enumerating the host bridge.\r
1347\r
1348**/\r
1349EFI_STATUS\r
1350PciHostBridgeEnumerator (\r
1351 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1352 )\r
1353{\r
1354 EFI_HANDLE RootBridgeHandle;\r
1355 PCI_IO_DEVICE *RootBridgeDev;\r
1356 EFI_STATUS Status;\r
1357 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1358 UINT16 MinBus;\r
1359 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1360 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1361 UINT8 StartBusNumber;\r
1362 LIST_ENTRY RootBridgeList;\r
1363 LIST_ENTRY *Link;\r
1364\r
1365 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1366 InitializeHotPlugSupport ();\r
1367 }\r
1368\r
1369 InitializeListHead (&RootBridgeList);\r
1370\r
1371 //\r
1372 // Notify the bus allocation phase is about to start\r
1373 //\r
1374 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1375\r
1376 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
1377 RootBridgeHandle = NULL;\r
1378 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1379\r
1380 //\r
1381 // if a root bridge instance is found, create root bridge device for it\r
1382 //\r
1383\r
1384 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1385\r
1386 if (RootBridgeDev == NULL) {\r
1387 return EFI_OUT_OF_RESOURCES;\r
1388 }\r
1389\r
1390 //\r
1391 // Enumerate all the buses under this root bridge\r
1392 //\r
1393 Status = PciRootBridgeEnumerator (\r
1394 PciResAlloc,\r
1395 RootBridgeDev\r
1396 );\r
1397\r
1398 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1399 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1400 } else {\r
1401 DestroyRootBridge (RootBridgeDev);\r
1402 }\r
1403 if (EFI_ERROR (Status)) {\r
1404 return Status;\r
1405 }\r
1406 }\r
1407\r
1408 //\r
1409 // Notify the bus allocation phase is finished for the first time\r
1410 //\r
1411 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1412\r
1413 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1414 //\r
1415 // Reset all assigned PCI bus number in all PPB\r
1416 //\r
1417 RootBridgeHandle = NULL;\r
1418 Link = GetFirstNode (&RootBridgeList);\r
1419 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1420 (!IsNull (&RootBridgeList, Link))) {\r
1421 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1422 //\r
1423 // Get the Bus information\r
1424 //\r
1425 Status = PciResAlloc->StartBusEnumeration (\r
1426 PciResAlloc,\r
1427 RootBridgeHandle,\r
1428 (VOID **) &Configuration\r
1429 );\r
1430 if (EFI_ERROR (Status)) {\r
1431 return Status;\r
1432 }\r
1433\r
1434 //\r
1435 // Get the bus number to start with\r
1436 //\r
1437 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
1438\r
1439 ResetAllPpbBusNumber (\r
1440 RootBridgeDev,\r
1441 StartBusNumber\r
1442 );\r
1443\r
1444 FreePool (Configuration);\r
8063b47b 1445 Link = RemoveEntryList (Link);\r
9060e3ec 1446 DestroyRootBridge (RootBridgeDev);\r
1447 }\r
1448\r
1449 //\r
1450 // Wait for all HPC initialized\r
1451 //\r
1452 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1453\r
1454 if (EFI_ERROR (Status)) {\r
55565b08 1455 DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1456 return Status;\r
1457 }\r
1458\r
1459 //\r
1460 // Notify the bus allocation phase is about to start for the 2nd time\r
1461 //\r
1462 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1463\r
1464 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
1465 RootBridgeHandle = NULL;\r
1466 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1467\r
1468 //\r
1469 // if a root bridge instance is found, create root bridge device for it\r
1470 //\r
1471 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1472\r
1473 if (RootBridgeDev == NULL) {\r
1474 return EFI_OUT_OF_RESOURCES;\r
1475 }\r
1476\r
1477 //\r
1478 // Enumerate all the buses under this root bridge\r
1479 //\r
1480 Status = PciRootBridgeEnumerator (\r
1481 PciResAlloc,\r
1482 RootBridgeDev\r
1483 );\r
1484\r
1485 DestroyRootBridge (RootBridgeDev);\r
1486 if (EFI_ERROR (Status)) {\r
1487 return Status;\r
1488 }\r
1489 }\r
1490\r
1491 //\r
1492 // Notify the bus allocation phase is to end for the 2nd time\r
1493 //\r
1494 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1495 }\r
1496\r
1497 //\r
1498 // Notify the resource allocation phase is to start\r
1499 //\r
1500 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1501\r
1502 RootBridgeHandle = NULL;\r
1503 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1504\r
1505 //\r
1506 // if a root bridge instance is found, create root bridge device for it\r
1507 //\r
1508 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1509\r
1510 if (RootBridgeDev == NULL) {\r
1511 return EFI_OUT_OF_RESOURCES;\r
1512 }\r
1513\r
1514 Status = StartManagingRootBridge (RootBridgeDev);\r
1515\r
1516 if (EFI_ERROR (Status)) {\r
1517 return Status;\r
1518 }\r
1519\r
1520 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1521 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1522\r
1523 if (EFI_ERROR (Status)) {\r
1524 return Status;\r
1525 }\r
1526\r
1527 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1528\r
1529 if (EFI_ERROR (Status)) {\r
1530 return Status;\r
1531 }\r
1532\r
1533 //\r
1534 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1535 // protocol\r
1536 //\r
1537 DetermineRootBridgeAttributes (\r
1538 PciResAlloc,\r
1539 RootBridgeDev\r
1540 );\r
1541\r
1542 //\r
1543 // Collect all the resource information under this root bridge\r
1544 // A database that records all the information about pci device subject to this\r
1545 // root bridge will then be created\r
1546 //\r
1547 Status = PciPciDeviceInfoCollector (\r
1548 RootBridgeDev,\r
1549 (UINT8) MinBus\r
1550 );\r
1551\r
1552 if (EFI_ERROR (Status)) {\r
1553 return Status;\r
1554 }\r
1555\r
1556 InsertRootBridge (RootBridgeDev);\r
1557\r
1558 //\r
1559 // Record the hostbridge handle\r
1560 //\r
1561 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1562 }\r
1563\r
1564 return EFI_SUCCESS;\r
1565}\r