]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
ArmPkg/CpuDxe: Moved memory mapping functions that are not architecture specific...
[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
724f26a9 4Copyright (c) 2006 - 2013, 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
724f26a9
RN
571 //\r
572 // If SubmitResources returns error, PciBus isn't able to start.\r
573 // It's a fatal error so assertion is added.\r
574 //\r
575 DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));\r
576 ASSERT_EFI_ERROR (Status);\r
9060e3ec 577 }\r
578\r
579 //\r
580 // Free acpi resource node\r
581 //\r
582 if (AcpiConfig != NULL) {\r
583 FreePool (AcpiConfig);\r
584 }\r
585\r
586 if (EFI_ERROR (Status)) {\r
587 //\r
588 // Destroy all the resource tree\r
589 //\r
590 DestroyResourceTree (&IoPool);\r
591 DestroyResourceTree (&Mem32Pool);\r
592 DestroyResourceTree (&PMem32Pool);\r
593 DestroyResourceTree (&Mem64Pool);\r
594 DestroyResourceTree (&PMem64Pool);\r
595 return Status;\r
596 }\r
597 }\r
598 //\r
599 // End while, at least one Root Bridge should be found.\r
600 //\r
601 ASSERT (RootBridgeDev != NULL);\r
602\r
603 //\r
604 // Notify platform to start to program the resource\r
605 //\r
606 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
724f26a9 607 DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));\r
9060e3ec 608 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
609 //\r
610 // If Hot Plug is not supported\r
611 //\r
612 if (EFI_ERROR (Status)) {\r
613 //\r
614 // Allocation failed, then return\r
615 //\r
616 return EFI_OUT_OF_RESOURCES;\r
617 }\r
618 //\r
619 // Allocation succeed.\r
620 // Get host bridge handle for status report, and then skip the main while\r
621 //\r
622 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
623\r
624 break;\r
625\r
626 } else {\r
627 //\r
628 // If Hot Plug is supported\r
629 //\r
630 if (!EFI_ERROR (Status)) {\r
631 //\r
632 // Allocation succeed, then continue the following\r
633 //\r
634 break;\r
635 }\r
636\r
637 //\r
638 // If the resource allocation is unsuccessful, free resources on bridge\r
639 //\r
640\r
641 RootBridgeDev = NULL;\r
642 RootBridgeHandle = 0;\r
643\r
644 IoResStatus = EFI_RESOURCE_SATISFIED;\r
645 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
646 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
647 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
648 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
649\r
650 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
651 //\r
652 // Get RootBridg Device by handle\r
653 //\r
654 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
655 if (RootBridgeDev == NULL) {\r
656 return EFI_NOT_FOUND;\r
657 }\r
658\r
659 //\r
660 // Get host bridge handle for status report\r
661 //\r
662 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
663\r
664 //\r
665 // Get acpi resource node for all the resource types\r
666 //\r
667 AcpiConfig = NULL;\r
668\r
669 Status = PciResAlloc->GetProposedResources (\r
670 PciResAlloc,\r
671 RootBridgeDev->Handle,\r
672 &AcpiConfig\r
673 );\r
674\r
675 if (EFI_ERROR (Status)) {\r
676 return Status;\r
677 }\r
678\r
679 if (AcpiConfig != NULL) {\r
680 //\r
681 // Adjust resource allocation policy for each RB\r
682 //\r
683 GetResourceAllocationStatus (\r
684 AcpiConfig,\r
685 &IoResStatus,\r
686 &Mem32ResStatus,\r
687 &PMem32ResStatus,\r
688 &Mem64ResStatus,\r
689 &PMem64ResStatus\r
690 );\r
691 FreePool (AcpiConfig);\r
692 }\r
693 }\r
694 //\r
695 // End while\r
696 //\r
697\r
698 //\r
699 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
700 //\r
701 //\r
702 // It is very difficult to follow the spec here\r
703 // Device path , Bar index can not be get here\r
704 //\r
705 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
706\r
707 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
708 EFI_PROGRESS_CODE,\r
709 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
710 (VOID *) &AllocFailExtendedData,\r
711 sizeof (AllocFailExtendedData)\r
712 );\r
713\r
714 Status = PciHostBridgeAdjustAllocation (\r
715 &IoPool,\r
716 &Mem32Pool,\r
717 &PMem32Pool,\r
718 &Mem64Pool,\r
719 &PMem64Pool,\r
720 IoResStatus,\r
721 Mem32ResStatus,\r
722 PMem32ResStatus,\r
723 Mem64ResStatus,\r
724 PMem64ResStatus\r
725 );\r
726\r
727 //\r
728 // Destroy all the resource tree\r
729 //\r
730 DestroyResourceTree (&IoPool);\r
731 DestroyResourceTree (&Mem32Pool);\r
732 DestroyResourceTree (&PMem32Pool);\r
733 DestroyResourceTree (&Mem64Pool);\r
734 DestroyResourceTree (&PMem64Pool);\r
735\r
736 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
737\r
738 if (EFI_ERROR (Status)) {\r
739 return Status;\r
740 }\r
741\r
742 ReAllocate = TRUE;\r
743 }\r
744 }\r
745 //\r
746 // End main while\r
747 //\r
748\r
749 //\r
750 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
751 //\r
752 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
753 EFI_PROGRESS_CODE,\r
fe91c992 754 EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,\r
9060e3ec 755 (VOID *) &HandleExtendedData,\r
756 sizeof (HandleExtendedData)\r
757 );\r
758\r
759 //\r
760 // Notify pci bus driver starts to program the resource\r
761 //\r
762 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
763\r
764 RootBridgeDev = NULL;\r
765\r
766 RootBridgeHandle = 0;\r
767\r
768 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
769 //\r
770 // Get RootBridg Device by handle\r
771 //\r
772 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
773\r
774 if (RootBridgeDev == NULL) {\r
775 return EFI_NOT_FOUND;\r
776 }\r
777\r
778 //\r
779 // Get acpi resource node for all the resource types\r
780 //\r
781 AcpiConfig = NULL;\r
782 Status = PciResAlloc->GetProposedResources (\r
783 PciResAlloc,\r
784 RootBridgeDev->Handle,\r
785 &AcpiConfig\r
786 );\r
787\r
788 if (EFI_ERROR (Status)) {\r
789 return Status;\r
790 }\r
791\r
792 //\r
793 // Get the resource base by interpreting acpi resource node\r
794 //\r
795 //\r
796 GetResourceBase (\r
797 AcpiConfig,\r
798 &IoBase,\r
799 &Mem32Base,\r
800 &PMem32Base,\r
801 &Mem64Base,\r
802 &PMem64Base\r
803 );\r
804\r
805 //\r
806 // Process option rom for this root bridge\r
807 //\r
808 ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
809\r
810 //\r
811 // Create the entire system resource map from the information collected by\r
812 // enumerator. Several resource tree was created\r
813 //\r
8db6a82c
RN
814 IoBridge = FindResourceNode (RootBridgeDev, &IoPool);\r
815 Mem32Bridge = FindResourceNode (RootBridgeDev, &Mem32Pool);\r
816 PMem32Bridge = FindResourceNode (RootBridgeDev, &PMem32Pool);\r
817 Mem64Bridge = FindResourceNode (RootBridgeDev, &Mem64Pool);\r
818 PMem64Bridge = FindResourceNode (RootBridgeDev, &PMem64Pool);\r
9060e3ec 819\r
9995c2e5
RN
820 ASSERT (IoBridge != NULL);\r
821 ASSERT (Mem32Bridge != NULL);\r
822 ASSERT (PMem32Bridge != NULL);\r
823 ASSERT (Mem64Bridge != NULL);\r
824 ASSERT (PMem64Bridge != NULL);\r
825\r
9060e3ec 826 //\r
827 // Program IO resources\r
828 //\r
829 ProgramResource (\r
830 IoBase,\r
831 IoBridge\r
832 );\r
833\r
834 //\r
835 // Program Mem32 resources\r
836 //\r
837 ProgramResource (\r
838 Mem32Base,\r
839 Mem32Bridge\r
840 );\r
841\r
842 //\r
843 // Program PMem32 resources\r
844 //\r
845 ProgramResource (\r
846 PMem32Base,\r
847 PMem32Bridge\r
848 );\r
849\r
850 //\r
851 // Program Mem64 resources\r
852 //\r
853 ProgramResource (\r
854 Mem64Base,\r
855 Mem64Bridge\r
856 );\r
857\r
858 //\r
859 // Program PMem64 resources\r
860 //\r
861 ProgramResource (\r
862 PMem64Base,\r
863 PMem64Bridge\r
864 );\r
865\r
8db6a82c
RN
866 IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase;\r
867 Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;\r
868 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
869 Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;\r
870 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
871\r
872 //\r
873 // Dump the resource map for current root bridge\r
874 //\r
875 DEBUG_CODE (\r
876 DumpResourceMap (\r
877 RootBridgeDev,\r
878 IoBridge,\r
879 Mem32Bridge,\r
880 PMem32Bridge,\r
881 Mem64Bridge,\r
882 PMem64Bridge\r
883 );\r
884 );\r
885\r
9060e3ec 886 FreePool (AcpiConfig);\r
887 }\r
888\r
889 //\r
890 // Destroy all the resource tree\r
891 //\r
892 DestroyResourceTree (&IoPool);\r
893 DestroyResourceTree (&Mem32Pool);\r
894 DestroyResourceTree (&PMem32Pool);\r
895 DestroyResourceTree (&Mem64Pool);\r
896 DestroyResourceTree (&PMem64Pool);\r
897\r
898 //\r
899 // Notify the resource allocation phase is to end\r
900 //\r
901 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
902\r
903 return EFI_SUCCESS;\r
904}\r
905\r
306bbe82 906/**\r
907 Allocate NumberOfBuses buses and return the next available PCI bus number.\r
908\r
909 @param Bridge Bridge device instance.\r
910 @param StartBusNumber Current available PCI bus number.\r
911 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.\r
912 @param NextBusNumber Next available PCI bus number.\r
913\r
914 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number\r
915 is returned in NextBusNumber.\r
916 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.\r
917\r
918**/\r
919EFI_STATUS\r
920PciAllocateBusNumber (\r
921 IN PCI_IO_DEVICE *Bridge,\r
922 IN UINT8 StartBusNumber,\r
923 IN UINT8 NumberOfBuses,\r
924 OUT UINT8 *NextBusNumber\r
925 )\r
926{\r
927 PCI_IO_DEVICE *RootBridge;\r
928 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
929 UINT8 NextNumber;\r
930 UINT64 MaxNumberInRange;\r
931\r
932 //\r
933 // Get PCI Root Bridge device\r
934 //\r
935 RootBridge = Bridge;\r
936 while (RootBridge->Parent != NULL) {\r
937 RootBridge = RootBridge->Parent;\r
938 }\r
939\r
940 //\r
941 // Get next available PCI bus number\r
942 //\r
943 BusNumberRanges = RootBridge->BusNumberRanges;\r
944 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
945 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
946 if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <= MaxNumberInRange) {\r
50bdaa05 947 NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);\r
306bbe82 948 while (NextNumber > MaxNumberInRange) {\r
949 ++BusNumberRanges;\r
950 if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
951 return EFI_OUT_OF_RESOURCES;\r
952 }\r
50bdaa05 953 NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));\r
306bbe82 954 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
955 }\r
956 *NextBusNumber = NextNumber;\r
957 return EFI_SUCCESS;\r
958 }\r
959 BusNumberRanges++;\r
960 }\r
961 return EFI_OUT_OF_RESOURCES;\r
962}\r
963\r
9060e3ec 964/**\r
965 Scan pci bus and assign bus number to the given PCI bus system.\r
966\r
967 @param Bridge Bridge device instance.\r
968 @param StartBusNumber start point.\r
969 @param SubBusNumber Point to sub bus number.\r
970 @param PaddedBusRange Customized bus number.\r
971\r
972 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
973 @retval other Some error occurred when scanning pci bus.\r
974\r
975 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
976\r
977**/\r
978EFI_STATUS\r
979PciScanBus (\r
980 IN PCI_IO_DEVICE *Bridge,\r
981 IN UINT8 StartBusNumber,\r
982 OUT UINT8 *SubBusNumber,\r
983 OUT UINT8 *PaddedBusRange\r
984 )\r
985{\r
986 EFI_STATUS Status;\r
987 PCI_TYPE00 Pci;\r
988 UINT8 Device;\r
989 UINT8 Func;\r
990 UINT64 Address;\r
991 UINTN SecondBus;\r
992 UINT16 Register;\r
993 UINTN HpIndex;\r
994 PCI_IO_DEVICE *PciDevice;\r
995 EFI_EVENT Event;\r
996 EFI_HPC_STATE State;\r
997 UINT64 PciAddress;\r
998 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
999 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1000 UINT16 BusRange;\r
1001 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1002 BOOLEAN BusPadding;\r
1003 UINT32 TempReservedBusNum;\r
1004\r
1005 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1006 SecondBus = 0;\r
1007 Register = 0;\r
1008 State = 0;\r
1009 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
1010 BusRange = 0;\r
1011 BusPadding = FALSE;\r
1012 PciDevice = NULL;\r
1013 PciAddress = 0;\r
1014\r
1015 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1016 TempReservedBusNum = 0;\r
1017 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1018\r
1019 //\r
1020 // Check to see whether a pci device is present\r
1021 //\r
1022 Status = PciDevicePresent (\r
1023 PciRootBridgeIo,\r
1024 &Pci,\r
1025 StartBusNumber,\r
1026 Device,\r
1027 Func\r
1028 );\r
1029\r
1030 if (EFI_ERROR (Status)) {\r
9060e3ec 1031 continue;\r
1032 }\r
1033\r
d4048391 1034 //\r
1035 // Get the PCI device information\r
1036 //\r
1037 Status = PciSearchDevice (\r
1038 Bridge,\r
1039 &Pci,\r
1040 StartBusNumber,\r
1041 Device,\r
1042 Func,\r
1043 &PciDevice\r
1044 );\r
9060e3ec 1045\r
d4048391 1046 ASSERT (!EFI_ERROR (Status));\r
9060e3ec 1047\r
d4048391 1048 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 1049\r
d4048391 1050 if (!IS_PCI_BRIDGE (&Pci)) {\r
1051 //\r
1052 // PCI bridges will be called later\r
1053 // Here just need for PCI device or PCI to cardbus controller\r
1054 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1055 //\r
1056 PreprocessController (\r
1057 PciDevice,\r
1058 PciDevice->BusNumber,\r
1059 PciDevice->DeviceNumber,\r
1060 PciDevice->FunctionNumber,\r
1061 EfiPciBeforeChildBusEnumeration\r
1062 );\r
1063 }\r
9060e3ec 1064\r
d4048391 1065 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1066 //\r
1067 // For Pci Hotplug controller devcie only\r
1068 //\r
1069 if (gPciHotPlugInit != NULL) {\r
1070 //\r
1071 // Check if it is a Hotplug PCI controller\r
1072 //\r
1073 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 1074 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 1075\r
1076 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1077\r
1078 Status = CreateEventForHpc (HpIndex, &Event);\r
1079\r
1080 ASSERT (!EFI_ERROR (Status));\r
1081\r
1082 Status = gPciHotPlugInit->InitializeRootHpc (\r
1083 gPciHotPlugInit,\r
1084 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1085 PciAddress,\r
1086 Event,\r
1087 &State\r
1088 );\r
1089\r
1090 PreprocessController (\r
1091 PciDevice,\r
1092 PciDevice->BusNumber,\r
1093 PciDevice->DeviceNumber,\r
1094 PciDevice->FunctionNumber,\r
1095 EfiPciBeforeChildBusEnumeration\r
1096 );\r
1097 }\r
1098 }\r
1099 }\r
1100 }\r
1101\r
1102 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1103 //\r
1104 // For PPB\r
1105 //\r
1106 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1107 //\r
1108 // If Hot Plug is not supported,\r
1109 // get the bridge information\r
1110 //\r
1111 Status = PciSearchDevice (\r
1112 Bridge,\r
1113 &Pci,\r
1114 StartBusNumber,\r
1115 Device,\r
1116 Func,\r
1117 &PciDevice\r
1118 );\r
1119\r
1120 if (EFI_ERROR (Status)) {\r
1121 return Status;\r
1122 }\r
1123 } else {\r
1124 //\r
1125 // If Hot Plug is supported,\r
1126 // Get the bridge information\r
1127 //\r
1128 BusPadding = FALSE;\r
1129 if (gPciHotPlugInit != NULL) {\r
1130\r
1131 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1132\r
1133 //\r
1134 // If it is initialized, get the padded bus range\r
1135 //\r
1136 Status = gPciHotPlugInit->GetResourcePadding (\r
1137 gPciHotPlugInit,\r
1138 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1139 PciAddress,\r
1140 &State,\r
1141 (VOID **) &Descriptors,\r
1142 &Attributes\r
1143 );\r
1144\r
1145 if (EFI_ERROR (Status)) {\r
1146 return Status;\r
1147 }\r
1148\r
1149 BusRange = 0;\r
1150 Status = PciGetBusRange (\r
1151 &Descriptors,\r
1152 NULL,\r
1153 NULL,\r
1154 &BusRange\r
1155 );\r
1156\r
1157 FreePool (Descriptors);\r
1158\r
1159 if (EFI_ERROR (Status)) {\r
1160 return Status;\r
1161 }\r
1162\r
1163 BusPadding = TRUE;\r
1164 }\r
1165 }\r
1166 }\r
1167\r
306bbe82 1168 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
1169 if (EFI_ERROR (Status)) {\r
1170 return Status;\r
9060e3ec 1171 }\r
9060e3ec 1172 SecondBus = *SubBusNumber;\r
1173\r
1174 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1175 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
1176\r
1177 Status = PciRootBridgeIo->Pci.Write (\r
1178 PciRootBridgeIo,\r
1179 EfiPciWidthUint16,\r
1180 Address,\r
1181 1,\r
1182 &Register\r
1183 );\r
1184\r
1185\r
1186 //\r
1187 // If it is PPB, resursively search down this bridge\r
1188 //\r
1189 if (IS_PCI_BRIDGE (&Pci)) {\r
1190\r
1191 //\r
1192 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1193 // PCI configuration transaction to go through any PPB\r
1194 //\r
1195 Register = 0xFF;\r
1196 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1197 Status = PciRootBridgeIo->Pci.Write (\r
1198 PciRootBridgeIo,\r
1199 EfiPciWidthUint8,\r
1200 Address,\r
1201 1,\r
1202 &Register\r
1203 );\r
1204\r
1205 //\r
1206 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1207 //\r
1208 PreprocessController (\r
1209 PciDevice,\r
1210 PciDevice->BusNumber,\r
1211 PciDevice->DeviceNumber,\r
1212 PciDevice->FunctionNumber,\r
1213 EfiPciBeforeChildBusEnumeration\r
1214 );\r
1215\r
9060e3ec 1216 Status = PciScanBus (\r
1217 PciDevice,\r
1218 (UINT8) (SecondBus),\r
1219 SubBusNumber,\r
1220 PaddedBusRange\r
1221 );\r
1222 if (EFI_ERROR (Status)) {\r
1223 return Status;\r
1224 }\r
1225 }\r
1226\r
1227 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1228 //\r
1229 // Ensure the device is enabled and initialized\r
1230 //\r
1231 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1232 (State & EFI_HPC_STATE_ENABLED) != 0 &&\r
1233 (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
1234 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1235 } else {\r
306bbe82 1236 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (BusRange), SubBusNumber);\r
1237 if (EFI_ERROR (Status)) {\r
1238 return Status;\r
1239 }\r
9060e3ec 1240 }\r
1241 }\r
1242\r
1243 //\r
1244 // Set the current maximum bus number under the PPB\r
1245 //\r
1246 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1247\r
1248 Status = PciRootBridgeIo->Pci.Write (\r
1249 PciRootBridgeIo,\r
1250 EfiPciWidthUint8,\r
1251 Address,\r
1252 1,\r
1253 SubBusNumber\r
1254 );\r
1255 } else {\r
1256 //\r
1257 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 1258 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1259 //\r
d4048391 1260 if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {\r
9060e3ec 1261 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1262\r
306bbe82 1263 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);\r
1264 if (EFI_ERROR (Status)) {\r
1265 return Status;\r
1266 }\r
9060e3ec 1267 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1268\r
1269 if (Func == 0) {\r
1270 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
1271 } else {\r
1272 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
1273 }\r
1274 }\r
1275 }\r
1276 }\r
1277\r
1278 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1279\r
1280 //\r
1281 // Skip sub functions, this is not a multi function device\r
1282 //\r
1283\r
1284 Func = PCI_MAX_FUNC;\r
1285 }\r
1286 }\r
1287 }\r
1288\r
1289 return EFI_SUCCESS;\r
1290}\r
1291\r
1292/**\r
1293 Process Option Rom on the specified root bridge.\r
1294\r
1295 @param Bridge Pci root bridge device instance.\r
1296\r
1297 @retval EFI_SUCCESS Success process.\r
1298 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1299\r
1300**/\r
1301EFI_STATUS\r
1302PciRootBridgeP2CProcess (\r
1303 IN PCI_IO_DEVICE *Bridge\r
1304 )\r
1305{\r
1306 LIST_ENTRY *CurrentLink;\r
1307 PCI_IO_DEVICE *Temp;\r
1308 EFI_HPC_STATE State;\r
1309 UINT64 PciAddress;\r
1310 EFI_STATUS Status;\r
1311\r
1312 CurrentLink = Bridge->ChildList.ForwardLink;\r
1313\r
1314 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
1315\r
1316 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1317\r
1318 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1319\r
1320 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1321\r
1322 //\r
1323 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1324 //\r
1325 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1326 EFI_PROGRESS_CODE,\r
fe91c992 1327 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
9060e3ec 1328 Temp->DevicePath\r
1329 );\r
1330\r
1331 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1332 Status = gPciHotPlugInit->InitializeRootHpc (\r
1333 gPciHotPlugInit,\r
1334 Temp->DevicePath,\r
1335 PciAddress,\r
1336 NULL,\r
1337 &State\r
1338 );\r
1339\r
1340 if (!EFI_ERROR (Status)) {\r
1341 Status = PciBridgeEnumerator (Temp);\r
1342\r
1343 if (EFI_ERROR (Status)) {\r
1344 return Status;\r
1345 }\r
1346 }\r
1347\r
1348 CurrentLink = CurrentLink->ForwardLink;\r
1349 continue;\r
1350\r
1351 }\r
1352 }\r
1353\r
1354 if (!IsListEmpty (&Temp->ChildList)) {\r
1355 Status = PciRootBridgeP2CProcess (Temp);\r
1356 }\r
1357\r
1358 CurrentLink = CurrentLink->ForwardLink;\r
1359 }\r
1360\r
1361 return EFI_SUCCESS;\r
1362}\r
1363\r
1364/**\r
1365 Process Option Rom on the specified host bridge.\r
1366\r
1367 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1368\r
1369 @retval EFI_SUCCESS Success process.\r
1370 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1371 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1372\r
1373**/\r
1374EFI_STATUS\r
1375PciHostBridgeP2CProcess (\r
1376 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1377 )\r
1378{\r
1379 EFI_HANDLE RootBridgeHandle;\r
1380 PCI_IO_DEVICE *RootBridgeDev;\r
1381 EFI_STATUS Status;\r
1382\r
1383 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1384 return EFI_SUCCESS;\r
1385 }\r
1386\r
1387 RootBridgeHandle = NULL;\r
1388\r
1389 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1390\r
1391 //\r
1392 // Get RootBridg Device by handle\r
1393 //\r
1394 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1395\r
1396 if (RootBridgeDev == NULL) {\r
1397 return EFI_NOT_FOUND;\r
1398 }\r
1399\r
1400 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1401 if (EFI_ERROR (Status)) {\r
1402 return Status;\r
1403 }\r
1404\r
1405 }\r
1406\r
1407 return EFI_SUCCESS;\r
1408}\r
1409\r
1410/**\r
1411 This function is used to enumerate the entire host bridge\r
1412 in a given platform.\r
1413\r
1414 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1415\r
1416 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1417 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1418 @retval other Some error occurred when enumerating the host bridge.\r
1419\r
1420**/\r
1421EFI_STATUS\r
1422PciHostBridgeEnumerator (\r
1423 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1424 )\r
1425{\r
1426 EFI_HANDLE RootBridgeHandle;\r
1427 PCI_IO_DEVICE *RootBridgeDev;\r
1428 EFI_STATUS Status;\r
1429 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1430 UINT16 MinBus;\r
1431 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1432 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1433 UINT8 StartBusNumber;\r
1434 LIST_ENTRY RootBridgeList;\r
1435 LIST_ENTRY *Link;\r
1436\r
1437 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1438 InitializeHotPlugSupport ();\r
1439 }\r
1440\r
1441 InitializeListHead (&RootBridgeList);\r
1442\r
1443 //\r
1444 // Notify the bus allocation phase is about to start\r
1445 //\r
1446 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1447\r
1448 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
1449 RootBridgeHandle = NULL;\r
1450 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1451\r
1452 //\r
1453 // if a root bridge instance is found, create root bridge device for it\r
1454 //\r
1455\r
1456 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1457\r
1458 if (RootBridgeDev == NULL) {\r
1459 return EFI_OUT_OF_RESOURCES;\r
1460 }\r
1461\r
1462 //\r
1463 // Enumerate all the buses under this root bridge\r
1464 //\r
1465 Status = PciRootBridgeEnumerator (\r
1466 PciResAlloc,\r
1467 RootBridgeDev\r
1468 );\r
1469\r
1470 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1471 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1472 } else {\r
1473 DestroyRootBridge (RootBridgeDev);\r
1474 }\r
1475 if (EFI_ERROR (Status)) {\r
1476 return Status;\r
1477 }\r
1478 }\r
1479\r
1480 //\r
1481 // Notify the bus allocation phase is finished for the first time\r
1482 //\r
1483 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1484\r
1485 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1486 //\r
1487 // Reset all assigned PCI bus number in all PPB\r
1488 //\r
1489 RootBridgeHandle = NULL;\r
1490 Link = GetFirstNode (&RootBridgeList);\r
1491 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1492 (!IsNull (&RootBridgeList, Link))) {\r
1493 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1494 //\r
1495 // Get the Bus information\r
1496 //\r
1497 Status = PciResAlloc->StartBusEnumeration (\r
1498 PciResAlloc,\r
1499 RootBridgeHandle,\r
1500 (VOID **) &Configuration\r
1501 );\r
1502 if (EFI_ERROR (Status)) {\r
1503 return Status;\r
1504 }\r
1505\r
1506 //\r
1507 // Get the bus number to start with\r
1508 //\r
1509 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
1510\r
1511 ResetAllPpbBusNumber (\r
1512 RootBridgeDev,\r
1513 StartBusNumber\r
1514 );\r
1515\r
1516 FreePool (Configuration);\r
8063b47b 1517 Link = RemoveEntryList (Link);\r
9060e3ec 1518 DestroyRootBridge (RootBridgeDev);\r
1519 }\r
1520\r
1521 //\r
1522 // Wait for all HPC initialized\r
1523 //\r
1524 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1525\r
1526 if (EFI_ERROR (Status)) {\r
55565b08 1527 DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1528 return Status;\r
1529 }\r
1530\r
1531 //\r
1532 // Notify the bus allocation phase is about to start for the 2nd time\r
1533 //\r
1534 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1535\r
1536 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
1537 RootBridgeHandle = NULL;\r
1538 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1539\r
1540 //\r
1541 // if a root bridge instance is found, create root bridge device for it\r
1542 //\r
1543 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1544\r
1545 if (RootBridgeDev == NULL) {\r
1546 return EFI_OUT_OF_RESOURCES;\r
1547 }\r
1548\r
1549 //\r
1550 // Enumerate all the buses under this root bridge\r
1551 //\r
1552 Status = PciRootBridgeEnumerator (\r
1553 PciResAlloc,\r
1554 RootBridgeDev\r
1555 );\r
1556\r
1557 DestroyRootBridge (RootBridgeDev);\r
1558 if (EFI_ERROR (Status)) {\r
1559 return Status;\r
1560 }\r
1561 }\r
1562\r
1563 //\r
1564 // Notify the bus allocation phase is to end for the 2nd time\r
1565 //\r
1566 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1567 }\r
1568\r
1569 //\r
1570 // Notify the resource allocation phase is to start\r
1571 //\r
1572 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1573\r
1574 RootBridgeHandle = NULL;\r
1575 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1576\r
1577 //\r
1578 // if a root bridge instance is found, create root bridge device for it\r
1579 //\r
1580 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1581\r
1582 if (RootBridgeDev == NULL) {\r
1583 return EFI_OUT_OF_RESOURCES;\r
1584 }\r
1585\r
1586 Status = StartManagingRootBridge (RootBridgeDev);\r
1587\r
1588 if (EFI_ERROR (Status)) {\r
1589 return Status;\r
1590 }\r
1591\r
1592 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1593 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1594\r
1595 if (EFI_ERROR (Status)) {\r
1596 return Status;\r
1597 }\r
1598\r
1599 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1600\r
1601 if (EFI_ERROR (Status)) {\r
1602 return Status;\r
1603 }\r
1604\r
1605 //\r
1606 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1607 // protocol\r
1608 //\r
1609 DetermineRootBridgeAttributes (\r
1610 PciResAlloc,\r
1611 RootBridgeDev\r
1612 );\r
1613\r
1614 //\r
1615 // Collect all the resource information under this root bridge\r
1616 // A database that records all the information about pci device subject to this\r
1617 // root bridge will then be created\r
1618 //\r
1619 Status = PciPciDeviceInfoCollector (\r
1620 RootBridgeDev,\r
1621 (UINT8) MinBus\r
1622 );\r
1623\r
1624 if (EFI_ERROR (Status)) {\r
1625 return Status;\r
1626 }\r
1627\r
1628 InsertRootBridge (RootBridgeDev);\r
1629\r
1630 //\r
1631 // Record the hostbridge handle\r
1632 //\r
1633 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1634 }\r
1635\r
1636 return EFI_SUCCESS;\r
1637}\r