]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Use %lx to print UINT64 value instead of %x.
[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
980050bc 4Copyright (c) 2006 - 2012, 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
980050bc 185 EFI_D_INFO, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",\r
8db6a82c
RN
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
980050bc 198 EFI_D_INFO, " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s ",\r
8db6a82c
RN
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
980050bc 228 DEBUG ((EFI_D_INFO, " Padding:Length = 0x%lx;\tAlignment = 0x%lx\n", Resource->Length, Resource->Alignment));\r
8db6a82c
RN
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
9995c2e5
RN
813 ASSERT (IoBridge != NULL);\r
814 ASSERT (Mem32Bridge != NULL);\r
815 ASSERT (PMem32Bridge != NULL);\r
816 ASSERT (Mem64Bridge != NULL);\r
817 ASSERT (PMem64Bridge != NULL);\r
818\r
9060e3ec 819 //\r
820 // Program IO resources\r
821 //\r
822 ProgramResource (\r
823 IoBase,\r
824 IoBridge\r
825 );\r
826\r
827 //\r
828 // Program Mem32 resources\r
829 //\r
830 ProgramResource (\r
831 Mem32Base,\r
832 Mem32Bridge\r
833 );\r
834\r
835 //\r
836 // Program PMem32 resources\r
837 //\r
838 ProgramResource (\r
839 PMem32Base,\r
840 PMem32Bridge\r
841 );\r
842\r
843 //\r
844 // Program Mem64 resources\r
845 //\r
846 ProgramResource (\r
847 Mem64Base,\r
848 Mem64Bridge\r
849 );\r
850\r
851 //\r
852 // Program PMem64 resources\r
853 //\r
854 ProgramResource (\r
855 PMem64Base,\r
856 PMem64Bridge\r
857 );\r
858\r
8db6a82c
RN
859 IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase;\r
860 Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;\r
861 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
862 Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;\r
863 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
864\r
865 //\r
866 // Dump the resource map for current root bridge\r
867 //\r
868 DEBUG_CODE (\r
869 DumpResourceMap (\r
870 RootBridgeDev,\r
871 IoBridge,\r
872 Mem32Bridge,\r
873 PMem32Bridge,\r
874 Mem64Bridge,\r
875 PMem64Bridge\r
876 );\r
877 );\r
878\r
9060e3ec 879 FreePool (AcpiConfig);\r
880 }\r
881\r
882 //\r
883 // Destroy all the resource tree\r
884 //\r
885 DestroyResourceTree (&IoPool);\r
886 DestroyResourceTree (&Mem32Pool);\r
887 DestroyResourceTree (&PMem32Pool);\r
888 DestroyResourceTree (&Mem64Pool);\r
889 DestroyResourceTree (&PMem64Pool);\r
890\r
891 //\r
892 // Notify the resource allocation phase is to end\r
893 //\r
894 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
895\r
896 return EFI_SUCCESS;\r
897}\r
898\r
306bbe82 899/**\r
900 Allocate NumberOfBuses buses and return the next available PCI bus number.\r
901\r
902 @param Bridge Bridge device instance.\r
903 @param StartBusNumber Current available PCI bus number.\r
904 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.\r
905 @param NextBusNumber Next available PCI bus number.\r
906\r
907 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number\r
908 is returned in NextBusNumber.\r
909 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.\r
910\r
911**/\r
912EFI_STATUS\r
913PciAllocateBusNumber (\r
914 IN PCI_IO_DEVICE *Bridge,\r
915 IN UINT8 StartBusNumber,\r
916 IN UINT8 NumberOfBuses,\r
917 OUT UINT8 *NextBusNumber\r
918 )\r
919{\r
920 PCI_IO_DEVICE *RootBridge;\r
921 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
922 UINT8 NextNumber;\r
923 UINT64 MaxNumberInRange;\r
924\r
925 //\r
926 // Get PCI Root Bridge device\r
927 //\r
928 RootBridge = Bridge;\r
929 while (RootBridge->Parent != NULL) {\r
930 RootBridge = RootBridge->Parent;\r
931 }\r
932\r
933 //\r
934 // Get next available PCI bus number\r
935 //\r
936 BusNumberRanges = RootBridge->BusNumberRanges;\r
937 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
938 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
939 if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <= MaxNumberInRange) {\r
50bdaa05 940 NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);\r
306bbe82 941 while (NextNumber > MaxNumberInRange) {\r
942 ++BusNumberRanges;\r
943 if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
944 return EFI_OUT_OF_RESOURCES;\r
945 }\r
50bdaa05 946 NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));\r
306bbe82 947 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
948 }\r
949 *NextBusNumber = NextNumber;\r
950 return EFI_SUCCESS;\r
951 }\r
952 BusNumberRanges++;\r
953 }\r
954 return EFI_OUT_OF_RESOURCES;\r
955}\r
956\r
9060e3ec 957/**\r
958 Scan pci bus and assign bus number to the given PCI bus system.\r
959\r
960 @param Bridge Bridge device instance.\r
961 @param StartBusNumber start point.\r
962 @param SubBusNumber Point to sub bus number.\r
963 @param PaddedBusRange Customized bus number.\r
964\r
965 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
966 @retval other Some error occurred when scanning pci bus.\r
967\r
968 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
969\r
970**/\r
971EFI_STATUS\r
972PciScanBus (\r
973 IN PCI_IO_DEVICE *Bridge,\r
974 IN UINT8 StartBusNumber,\r
975 OUT UINT8 *SubBusNumber,\r
976 OUT UINT8 *PaddedBusRange\r
977 )\r
978{\r
979 EFI_STATUS Status;\r
980 PCI_TYPE00 Pci;\r
981 UINT8 Device;\r
982 UINT8 Func;\r
983 UINT64 Address;\r
984 UINTN SecondBus;\r
985 UINT16 Register;\r
986 UINTN HpIndex;\r
987 PCI_IO_DEVICE *PciDevice;\r
988 EFI_EVENT Event;\r
989 EFI_HPC_STATE State;\r
990 UINT64 PciAddress;\r
991 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
992 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
993 UINT16 BusRange;\r
994 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
995 BOOLEAN BusPadding;\r
996 UINT32 TempReservedBusNum;\r
997\r
998 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
999 SecondBus = 0;\r
1000 Register = 0;\r
1001 State = 0;\r
1002 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
1003 BusRange = 0;\r
1004 BusPadding = FALSE;\r
1005 PciDevice = NULL;\r
1006 PciAddress = 0;\r
1007\r
1008 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1009 TempReservedBusNum = 0;\r
1010 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1011\r
1012 //\r
1013 // Check to see whether a pci device is present\r
1014 //\r
1015 Status = PciDevicePresent (\r
1016 PciRootBridgeIo,\r
1017 &Pci,\r
1018 StartBusNumber,\r
1019 Device,\r
1020 Func\r
1021 );\r
1022\r
1023 if (EFI_ERROR (Status)) {\r
9060e3ec 1024 continue;\r
1025 }\r
1026\r
d4048391 1027 //\r
1028 // Get the PCI device information\r
1029 //\r
1030 Status = PciSearchDevice (\r
1031 Bridge,\r
1032 &Pci,\r
1033 StartBusNumber,\r
1034 Device,\r
1035 Func,\r
1036 &PciDevice\r
1037 );\r
9060e3ec 1038\r
d4048391 1039 ASSERT (!EFI_ERROR (Status));\r
9060e3ec 1040\r
d4048391 1041 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 1042\r
d4048391 1043 if (!IS_PCI_BRIDGE (&Pci)) {\r
1044 //\r
1045 // PCI bridges will be called later\r
1046 // Here just need for PCI device or PCI to cardbus controller\r
1047 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1048 //\r
1049 PreprocessController (\r
1050 PciDevice,\r
1051 PciDevice->BusNumber,\r
1052 PciDevice->DeviceNumber,\r
1053 PciDevice->FunctionNumber,\r
1054 EfiPciBeforeChildBusEnumeration\r
1055 );\r
1056 }\r
9060e3ec 1057\r
d4048391 1058 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1059 //\r
1060 // For Pci Hotplug controller devcie only\r
1061 //\r
1062 if (gPciHotPlugInit != NULL) {\r
1063 //\r
1064 // Check if it is a Hotplug PCI controller\r
1065 //\r
1066 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 1067 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 1068\r
1069 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1070\r
1071 Status = CreateEventForHpc (HpIndex, &Event);\r
1072\r
1073 ASSERT (!EFI_ERROR (Status));\r
1074\r
1075 Status = gPciHotPlugInit->InitializeRootHpc (\r
1076 gPciHotPlugInit,\r
1077 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1078 PciAddress,\r
1079 Event,\r
1080 &State\r
1081 );\r
1082\r
1083 PreprocessController (\r
1084 PciDevice,\r
1085 PciDevice->BusNumber,\r
1086 PciDevice->DeviceNumber,\r
1087 PciDevice->FunctionNumber,\r
1088 EfiPciBeforeChildBusEnumeration\r
1089 );\r
1090 }\r
1091 }\r
1092 }\r
1093 }\r
1094\r
1095 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1096 //\r
1097 // For PPB\r
1098 //\r
1099 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1100 //\r
1101 // If Hot Plug is not supported,\r
1102 // get the bridge information\r
1103 //\r
1104 Status = PciSearchDevice (\r
1105 Bridge,\r
1106 &Pci,\r
1107 StartBusNumber,\r
1108 Device,\r
1109 Func,\r
1110 &PciDevice\r
1111 );\r
1112\r
1113 if (EFI_ERROR (Status)) {\r
1114 return Status;\r
1115 }\r
1116 } else {\r
1117 //\r
1118 // If Hot Plug is supported,\r
1119 // Get the bridge information\r
1120 //\r
1121 BusPadding = FALSE;\r
1122 if (gPciHotPlugInit != NULL) {\r
1123\r
1124 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1125\r
1126 //\r
1127 // If it is initialized, get the padded bus range\r
1128 //\r
1129 Status = gPciHotPlugInit->GetResourcePadding (\r
1130 gPciHotPlugInit,\r
1131 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1132 PciAddress,\r
1133 &State,\r
1134 (VOID **) &Descriptors,\r
1135 &Attributes\r
1136 );\r
1137\r
1138 if (EFI_ERROR (Status)) {\r
1139 return Status;\r
1140 }\r
1141\r
1142 BusRange = 0;\r
1143 Status = PciGetBusRange (\r
1144 &Descriptors,\r
1145 NULL,\r
1146 NULL,\r
1147 &BusRange\r
1148 );\r
1149\r
1150 FreePool (Descriptors);\r
1151\r
1152 if (EFI_ERROR (Status)) {\r
1153 return Status;\r
1154 }\r
1155\r
1156 BusPadding = TRUE;\r
1157 }\r
1158 }\r
1159 }\r
1160\r
306bbe82 1161 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
1162 if (EFI_ERROR (Status)) {\r
1163 return Status;\r
9060e3ec 1164 }\r
9060e3ec 1165 SecondBus = *SubBusNumber;\r
1166\r
1167 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1168 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
1169\r
1170 Status = PciRootBridgeIo->Pci.Write (\r
1171 PciRootBridgeIo,\r
1172 EfiPciWidthUint16,\r
1173 Address,\r
1174 1,\r
1175 &Register\r
1176 );\r
1177\r
1178\r
1179 //\r
1180 // If it is PPB, resursively search down this bridge\r
1181 //\r
1182 if (IS_PCI_BRIDGE (&Pci)) {\r
1183\r
1184 //\r
1185 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1186 // PCI configuration transaction to go through any PPB\r
1187 //\r
1188 Register = 0xFF;\r
1189 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1190 Status = PciRootBridgeIo->Pci.Write (\r
1191 PciRootBridgeIo,\r
1192 EfiPciWidthUint8,\r
1193 Address,\r
1194 1,\r
1195 &Register\r
1196 );\r
1197\r
1198 //\r
1199 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1200 //\r
1201 PreprocessController (\r
1202 PciDevice,\r
1203 PciDevice->BusNumber,\r
1204 PciDevice->DeviceNumber,\r
1205 PciDevice->FunctionNumber,\r
1206 EfiPciBeforeChildBusEnumeration\r
1207 );\r
1208\r
9060e3ec 1209 Status = PciScanBus (\r
1210 PciDevice,\r
1211 (UINT8) (SecondBus),\r
1212 SubBusNumber,\r
1213 PaddedBusRange\r
1214 );\r
1215 if (EFI_ERROR (Status)) {\r
1216 return Status;\r
1217 }\r
1218 }\r
1219\r
1220 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1221 //\r
1222 // Ensure the device is enabled and initialized\r
1223 //\r
1224 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1225 (State & EFI_HPC_STATE_ENABLED) != 0 &&\r
1226 (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
1227 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1228 } else {\r
306bbe82 1229 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (BusRange), SubBusNumber);\r
1230 if (EFI_ERROR (Status)) {\r
1231 return Status;\r
1232 }\r
9060e3ec 1233 }\r
1234 }\r
1235\r
1236 //\r
1237 // Set the current maximum bus number under the PPB\r
1238 //\r
1239 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1240\r
1241 Status = PciRootBridgeIo->Pci.Write (\r
1242 PciRootBridgeIo,\r
1243 EfiPciWidthUint8,\r
1244 Address,\r
1245 1,\r
1246 SubBusNumber\r
1247 );\r
1248 } else {\r
1249 //\r
1250 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 1251 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1252 //\r
d4048391 1253 if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {\r
9060e3ec 1254 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1255\r
306bbe82 1256 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);\r
1257 if (EFI_ERROR (Status)) {\r
1258 return Status;\r
1259 }\r
9060e3ec 1260 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1261\r
1262 if (Func == 0) {\r
1263 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
1264 } else {\r
1265 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
1266 }\r
1267 }\r
1268 }\r
1269 }\r
1270\r
1271 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1272\r
1273 //\r
1274 // Skip sub functions, this is not a multi function device\r
1275 //\r
1276\r
1277 Func = PCI_MAX_FUNC;\r
1278 }\r
1279 }\r
1280 }\r
1281\r
1282 return EFI_SUCCESS;\r
1283}\r
1284\r
1285/**\r
1286 Process Option Rom on the specified root bridge.\r
1287\r
1288 @param Bridge Pci root bridge device instance.\r
1289\r
1290 @retval EFI_SUCCESS Success process.\r
1291 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1292\r
1293**/\r
1294EFI_STATUS\r
1295PciRootBridgeP2CProcess (\r
1296 IN PCI_IO_DEVICE *Bridge\r
1297 )\r
1298{\r
1299 LIST_ENTRY *CurrentLink;\r
1300 PCI_IO_DEVICE *Temp;\r
1301 EFI_HPC_STATE State;\r
1302 UINT64 PciAddress;\r
1303 EFI_STATUS Status;\r
1304\r
1305 CurrentLink = Bridge->ChildList.ForwardLink;\r
1306\r
1307 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
1308\r
1309 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1310\r
1311 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1312\r
1313 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1314\r
1315 //\r
1316 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1317 //\r
1318 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1319 EFI_PROGRESS_CODE,\r
fe91c992 1320 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
9060e3ec 1321 Temp->DevicePath\r
1322 );\r
1323\r
1324 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1325 Status = gPciHotPlugInit->InitializeRootHpc (\r
1326 gPciHotPlugInit,\r
1327 Temp->DevicePath,\r
1328 PciAddress,\r
1329 NULL,\r
1330 &State\r
1331 );\r
1332\r
1333 if (!EFI_ERROR (Status)) {\r
1334 Status = PciBridgeEnumerator (Temp);\r
1335\r
1336 if (EFI_ERROR (Status)) {\r
1337 return Status;\r
1338 }\r
1339 }\r
1340\r
1341 CurrentLink = CurrentLink->ForwardLink;\r
1342 continue;\r
1343\r
1344 }\r
1345 }\r
1346\r
1347 if (!IsListEmpty (&Temp->ChildList)) {\r
1348 Status = PciRootBridgeP2CProcess (Temp);\r
1349 }\r
1350\r
1351 CurrentLink = CurrentLink->ForwardLink;\r
1352 }\r
1353\r
1354 return EFI_SUCCESS;\r
1355}\r
1356\r
1357/**\r
1358 Process Option Rom on the specified host bridge.\r
1359\r
1360 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1361\r
1362 @retval EFI_SUCCESS Success process.\r
1363 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1364 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1365\r
1366**/\r
1367EFI_STATUS\r
1368PciHostBridgeP2CProcess (\r
1369 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1370 )\r
1371{\r
1372 EFI_HANDLE RootBridgeHandle;\r
1373 PCI_IO_DEVICE *RootBridgeDev;\r
1374 EFI_STATUS Status;\r
1375\r
1376 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1377 return EFI_SUCCESS;\r
1378 }\r
1379\r
1380 RootBridgeHandle = NULL;\r
1381\r
1382 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1383\r
1384 //\r
1385 // Get RootBridg Device by handle\r
1386 //\r
1387 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1388\r
1389 if (RootBridgeDev == NULL) {\r
1390 return EFI_NOT_FOUND;\r
1391 }\r
1392\r
1393 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1394 if (EFI_ERROR (Status)) {\r
1395 return Status;\r
1396 }\r
1397\r
1398 }\r
1399\r
1400 return EFI_SUCCESS;\r
1401}\r
1402\r
1403/**\r
1404 This function is used to enumerate the entire host bridge\r
1405 in a given platform.\r
1406\r
1407 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1408\r
1409 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1410 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1411 @retval other Some error occurred when enumerating the host bridge.\r
1412\r
1413**/\r
1414EFI_STATUS\r
1415PciHostBridgeEnumerator (\r
1416 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1417 )\r
1418{\r
1419 EFI_HANDLE RootBridgeHandle;\r
1420 PCI_IO_DEVICE *RootBridgeDev;\r
1421 EFI_STATUS Status;\r
1422 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1423 UINT16 MinBus;\r
1424 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1425 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1426 UINT8 StartBusNumber;\r
1427 LIST_ENTRY RootBridgeList;\r
1428 LIST_ENTRY *Link;\r
1429\r
1430 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1431 InitializeHotPlugSupport ();\r
1432 }\r
1433\r
1434 InitializeListHead (&RootBridgeList);\r
1435\r
1436 //\r
1437 // Notify the bus allocation phase is about to start\r
1438 //\r
1439 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1440\r
1441 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
1442 RootBridgeHandle = NULL;\r
1443 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1444\r
1445 //\r
1446 // if a root bridge instance is found, create root bridge device for it\r
1447 //\r
1448\r
1449 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1450\r
1451 if (RootBridgeDev == NULL) {\r
1452 return EFI_OUT_OF_RESOURCES;\r
1453 }\r
1454\r
1455 //\r
1456 // Enumerate all the buses under this root bridge\r
1457 //\r
1458 Status = PciRootBridgeEnumerator (\r
1459 PciResAlloc,\r
1460 RootBridgeDev\r
1461 );\r
1462\r
1463 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1464 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1465 } else {\r
1466 DestroyRootBridge (RootBridgeDev);\r
1467 }\r
1468 if (EFI_ERROR (Status)) {\r
1469 return Status;\r
1470 }\r
1471 }\r
1472\r
1473 //\r
1474 // Notify the bus allocation phase is finished for the first time\r
1475 //\r
1476 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1477\r
1478 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1479 //\r
1480 // Reset all assigned PCI bus number in all PPB\r
1481 //\r
1482 RootBridgeHandle = NULL;\r
1483 Link = GetFirstNode (&RootBridgeList);\r
1484 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1485 (!IsNull (&RootBridgeList, Link))) {\r
1486 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1487 //\r
1488 // Get the Bus information\r
1489 //\r
1490 Status = PciResAlloc->StartBusEnumeration (\r
1491 PciResAlloc,\r
1492 RootBridgeHandle,\r
1493 (VOID **) &Configuration\r
1494 );\r
1495 if (EFI_ERROR (Status)) {\r
1496 return Status;\r
1497 }\r
1498\r
1499 //\r
1500 // Get the bus number to start with\r
1501 //\r
1502 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
1503\r
1504 ResetAllPpbBusNumber (\r
1505 RootBridgeDev,\r
1506 StartBusNumber\r
1507 );\r
1508\r
1509 FreePool (Configuration);\r
8063b47b 1510 Link = RemoveEntryList (Link);\r
9060e3ec 1511 DestroyRootBridge (RootBridgeDev);\r
1512 }\r
1513\r
1514 //\r
1515 // Wait for all HPC initialized\r
1516 //\r
1517 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1518\r
1519 if (EFI_ERROR (Status)) {\r
55565b08 1520 DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1521 return Status;\r
1522 }\r
1523\r
1524 //\r
1525 // Notify the bus allocation phase is about to start for the 2nd time\r
1526 //\r
1527 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1528\r
1529 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
1530 RootBridgeHandle = NULL;\r
1531 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1532\r
1533 //\r
1534 // if a root bridge instance is found, create root bridge device for it\r
1535 //\r
1536 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1537\r
1538 if (RootBridgeDev == NULL) {\r
1539 return EFI_OUT_OF_RESOURCES;\r
1540 }\r
1541\r
1542 //\r
1543 // Enumerate all the buses under this root bridge\r
1544 //\r
1545 Status = PciRootBridgeEnumerator (\r
1546 PciResAlloc,\r
1547 RootBridgeDev\r
1548 );\r
1549\r
1550 DestroyRootBridge (RootBridgeDev);\r
1551 if (EFI_ERROR (Status)) {\r
1552 return Status;\r
1553 }\r
1554 }\r
1555\r
1556 //\r
1557 // Notify the bus allocation phase is to end for the 2nd time\r
1558 //\r
1559 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1560 }\r
1561\r
1562 //\r
1563 // Notify the resource allocation phase is to start\r
1564 //\r
1565 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1566\r
1567 RootBridgeHandle = NULL;\r
1568 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1569\r
1570 //\r
1571 // if a root bridge instance is found, create root bridge device for it\r
1572 //\r
1573 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1574\r
1575 if (RootBridgeDev == NULL) {\r
1576 return EFI_OUT_OF_RESOURCES;\r
1577 }\r
1578\r
1579 Status = StartManagingRootBridge (RootBridgeDev);\r
1580\r
1581 if (EFI_ERROR (Status)) {\r
1582 return Status;\r
1583 }\r
1584\r
1585 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1586 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1587\r
1588 if (EFI_ERROR (Status)) {\r
1589 return Status;\r
1590 }\r
1591\r
1592 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1593\r
1594 if (EFI_ERROR (Status)) {\r
1595 return Status;\r
1596 }\r
1597\r
1598 //\r
1599 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1600 // protocol\r
1601 //\r
1602 DetermineRootBridgeAttributes (\r
1603 PciResAlloc,\r
1604 RootBridgeDev\r
1605 );\r
1606\r
1607 //\r
1608 // Collect all the resource information under this root bridge\r
1609 // A database that records all the information about pci device subject to this\r
1610 // root bridge will then be created\r
1611 //\r
1612 Status = PciPciDeviceInfoCollector (\r
1613 RootBridgeDev,\r
1614 (UINT8) MinBus\r
1615 );\r
1616\r
1617 if (EFI_ERROR (Status)) {\r
1618 return Status;\r
1619 }\r
1620\r
1621 InsertRootBridge (RootBridgeDev);\r
1622\r
1623 //\r
1624 // Record the hostbridge handle\r
1625 //\r
1626 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1627 }\r
1628\r
1629 return EFI_SUCCESS;\r
1630}\r