]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
Fix a bug about the iSCSI DHCP dependency issue.
[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
8db6a82c
RN
293 CHAR16 *Str;\r
294\r
295 DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));\r
296\r
297 Status = gBS->OpenProtocol (\r
298 Bridge->Handle,\r
299 &gEfiPciRootBridgeIoProtocolGuid,\r
300 NULL,\r
301 NULL,\r
302 NULL,\r
303 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
304 );\r
305 if (EFI_ERROR (Status)) {\r
306 DEBUG ((\r
307 EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n",\r
308 Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber\r
309 ));\r
310 } else {\r
863986b3
RN
311 Str = ConvertDevicePathToText (\r
312 DevicePathFromHandle (Bridge->Handle),\r
313 FALSE,\r
314 FALSE\r
315 );\r
8db6a82c
RN
316 DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));\r
317 if (Str != NULL) {\r
318 FreePool (Str);\r
319 }\r
320 }\r
321\r
322 DumpBridgeResource (IoNode);\r
323 DumpBridgeResource (Mem32Node);\r
324 DumpBridgeResource (PMem32Node);\r
325 DumpBridgeResource (Mem64Node);\r
326 DumpBridgeResource (PMem64Node);\r
327 DEBUG ((EFI_D_INFO, "\n"));\r
328\r
329 for ( Link = Bridge->ChildList.ForwardLink\r
330 ; Link != &Bridge->ChildList\r
331 ; Link = Link->ForwardLink\r
332 ) {\r
333 Device = PCI_IO_DEVICE_FROM_LINK (Link);\r
334 if (IS_PCI_BRIDGE (&Device->Pci)) {\r
335\r
336 ChildIoNode = (IoNode == NULL ? NULL : FindResourceNode (Device, IoNode));\r
337 ChildMem32Node = (Mem32Node == NULL ? NULL : FindResourceNode (Device, Mem32Node));\r
338 ChildPMem32Node = (PMem32Node == NULL ? NULL : FindResourceNode (Device, PMem32Node));\r
339 ChildMem64Node = (Mem64Node == NULL ? NULL : FindResourceNode (Device, Mem64Node));\r
340 ChildPMem64Node = (PMem64Node == NULL ? NULL : FindResourceNode (Device, PMem64Node));\r
341\r
342 DumpResourceMap (\r
343 Device,\r
344 ChildIoNode,\r
345 ChildMem32Node,\r
346 ChildPMem32Node,\r
347 ChildMem64Node,\r
348 ChildPMem64Node\r
349 );\r
350 }\r
351 }\r
352}\r
353\r
9060e3ec 354/**\r
355 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
356\r
357 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
358\r
359 @retval EFI_SUCCESS Successfully finished resource allocation.\r
360 @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
361 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
362 @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
363\r
364 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
365\r
366**/\r
367EFI_STATUS\r
368PciHostBridgeResourceAllocator (\r
369 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
370 )\r
371{\r
372 PCI_IO_DEVICE *RootBridgeDev;\r
373 EFI_HANDLE RootBridgeHandle;\r
374 VOID *AcpiConfig;\r
375 EFI_STATUS Status;\r
376 UINT64 IoBase;\r
377 UINT64 Mem32Base;\r
378 UINT64 PMem32Base;\r
379 UINT64 Mem64Base;\r
380 UINT64 PMem64Base;\r
381 UINT64 IoResStatus;\r
382 UINT64 Mem32ResStatus;\r
383 UINT64 PMem32ResStatus;\r
384 UINT64 Mem64ResStatus;\r
385 UINT64 PMem64ResStatus;\r
386 UINT64 MaxOptionRomSize;\r
387 PCI_RESOURCE_NODE *IoBridge;\r
388 PCI_RESOURCE_NODE *Mem32Bridge;\r
389 PCI_RESOURCE_NODE *PMem32Bridge;\r
390 PCI_RESOURCE_NODE *Mem64Bridge;\r
391 PCI_RESOURCE_NODE *PMem64Bridge;\r
392 PCI_RESOURCE_NODE IoPool;\r
393 PCI_RESOURCE_NODE Mem32Pool;\r
394 PCI_RESOURCE_NODE PMem32Pool;\r
395 PCI_RESOURCE_NODE Mem64Pool;\r
396 PCI_RESOURCE_NODE PMem64Pool;\r
397 BOOLEAN ReAllocate;\r
398 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
399 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
400\r
401 //\r
402 // Reallocate flag\r
403 //\r
404 ReAllocate = FALSE;\r
405\r
406 //\r
407 // It may try several times if the resource allocation fails\r
408 //\r
409 while (TRUE) {\r
410 //\r
411 // Initialize resource pool\r
412 //\r
413 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
414 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
415 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
416 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
417 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
418\r
419 RootBridgeDev = NULL;\r
420 RootBridgeHandle = 0;\r
421\r
422 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
423 //\r
424 // Get Root Bridge Device by handle\r
425 //\r
426 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
427\r
428 if (RootBridgeDev == NULL) {\r
429 return EFI_NOT_FOUND;\r
430 }\r
431\r
432 //\r
433 // Create the entire system resource map from the information collected by\r
434 // enumerator. Several resource tree was created\r
435 //\r
436\r
1ef26783 437 //\r
438 // If non-stardard PCI Bridge I/O window alignment is supported,\r
439 // set I/O aligment to minimum possible alignment for root bridge.\r
440 //\r
9060e3ec 441 IoBridge = CreateResourceNode (\r
442 RootBridgeDev,\r
443 0,\r
1ef26783 444 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,\r
8db6a82c 445 RB_IO_RANGE,\r
9060e3ec 446 PciBarTypeIo16,\r
447 PciResUsageTypical\r
448 );\r
449\r
450 Mem32Bridge = CreateResourceNode (\r
451 RootBridgeDev,\r
452 0,\r
453 0xFFFFF,\r
8db6a82c 454 RB_MEM32_RANGE,\r
9060e3ec 455 PciBarTypeMem32,\r
456 PciResUsageTypical\r
457 );\r
458\r
459 PMem32Bridge = CreateResourceNode (\r
460 RootBridgeDev,\r
461 0,\r
462 0xFFFFF,\r
8db6a82c 463 RB_PMEM32_RANGE,\r
9060e3ec 464 PciBarTypePMem32,\r
465 PciResUsageTypical\r
466 );\r
467\r
468 Mem64Bridge = CreateResourceNode (\r
469 RootBridgeDev,\r
470 0,\r
471 0xFFFFF,\r
8db6a82c 472 RB_MEM64_RANGE,\r
9060e3ec 473 PciBarTypeMem64,\r
474 PciResUsageTypical\r
475 );\r
476\r
477 PMem64Bridge = CreateResourceNode (\r
478 RootBridgeDev,\r
479 0,\r
480 0xFFFFF,\r
8db6a82c 481 RB_PMEM64_RANGE,\r
9060e3ec 482 PciBarTypePMem64,\r
483 PciResUsageTypical\r
484 );\r
485\r
486 //\r
487 // Create resourcemap by going through all the devices subject to this root bridge\r
488 //\r
489 CreateResourceMap (\r
490 RootBridgeDev,\r
491 IoBridge,\r
492 Mem32Bridge,\r
493 PMem32Bridge,\r
494 Mem64Bridge,\r
495 PMem64Bridge\r
496 );\r
497\r
498 //\r
499 // Get the max ROM size that the root bridge can process\r
500 //\r
501 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
502\r
503 //\r
504 // Skip to enlarge the resource request during realloction\r
505 //\r
506 if (!ReAllocate) {\r
507 //\r
508 // Get Max Option Rom size for current root bridge\r
509 //\r
510 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
511\r
512 //\r
513 // Enlarger the mem32 resource to accomdate the option rom\r
514 // if the mem32 resource is not enough to hold the rom\r
515 //\r
516 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
517\r
518 Mem32Bridge->Length = MaxOptionRomSize;\r
519 RootBridgeDev->RomSize = MaxOptionRomSize;\r
520\r
521 //\r
522 // Alignment should be adjusted as well\r
523 //\r
524 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
525 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
526 }\r
527 }\r
528 }\r
529\r
530 //\r
531 // Based on the all the resource tree, contruct ACPI resource node to\r
532 // submit the resource aperture to pci host bridge protocol\r
533 //\r
534 Status = ConstructAcpiResourceRequestor (\r
535 RootBridgeDev,\r
536 IoBridge,\r
537 Mem32Bridge,\r
538 PMem32Bridge,\r
539 Mem64Bridge,\r
540 PMem64Bridge,\r
541 &AcpiConfig\r
542 );\r
543\r
544 //\r
545 // Insert these resource nodes into the database\r
546 //\r
547 InsertResourceNode (&IoPool, IoBridge);\r
548 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
549 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
550 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
551 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
552\r
553 if (Status == EFI_SUCCESS) {\r
554 //\r
555 // Submit the resource requirement\r
556 //\r
557 Status = PciResAlloc->SubmitResources (\r
558 PciResAlloc,\r
559 RootBridgeDev->Handle,\r
560 AcpiConfig\r
561 );\r
724f26a9
RN
562 //\r
563 // If SubmitResources returns error, PciBus isn't able to start.\r
564 // It's a fatal error so assertion is added.\r
565 //\r
566 DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));\r
567 ASSERT_EFI_ERROR (Status);\r
9060e3ec 568 }\r
569\r
570 //\r
571 // Free acpi resource node\r
572 //\r
573 if (AcpiConfig != NULL) {\r
574 FreePool (AcpiConfig);\r
575 }\r
576\r
577 if (EFI_ERROR (Status)) {\r
578 //\r
579 // Destroy all the resource tree\r
580 //\r
581 DestroyResourceTree (&IoPool);\r
582 DestroyResourceTree (&Mem32Pool);\r
583 DestroyResourceTree (&PMem32Pool);\r
584 DestroyResourceTree (&Mem64Pool);\r
585 DestroyResourceTree (&PMem64Pool);\r
586 return Status;\r
587 }\r
588 }\r
589 //\r
590 // End while, at least one Root Bridge should be found.\r
591 //\r
592 ASSERT (RootBridgeDev != NULL);\r
593\r
594 //\r
595 // Notify platform to start to program the resource\r
596 //\r
597 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
724f26a9 598 DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));\r
9060e3ec 599 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
600 //\r
601 // If Hot Plug is not supported\r
602 //\r
603 if (EFI_ERROR (Status)) {\r
604 //\r
605 // Allocation failed, then return\r
606 //\r
607 return EFI_OUT_OF_RESOURCES;\r
608 }\r
609 //\r
610 // Allocation succeed.\r
611 // Get host bridge handle for status report, and then skip the main while\r
612 //\r
613 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
614\r
615 break;\r
616\r
617 } else {\r
618 //\r
619 // If Hot Plug is supported\r
620 //\r
621 if (!EFI_ERROR (Status)) {\r
622 //\r
623 // Allocation succeed, then continue the following\r
624 //\r
625 break;\r
626 }\r
627\r
628 //\r
629 // If the resource allocation is unsuccessful, free resources on bridge\r
630 //\r
631\r
632 RootBridgeDev = NULL;\r
633 RootBridgeHandle = 0;\r
634\r
635 IoResStatus = EFI_RESOURCE_SATISFIED;\r
636 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
637 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
638 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
639 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
640\r
641 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
642 //\r
643 // Get RootBridg Device by handle\r
644 //\r
645 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
646 if (RootBridgeDev == NULL) {\r
647 return EFI_NOT_FOUND;\r
648 }\r
649\r
650 //\r
651 // Get host bridge handle for status report\r
652 //\r
653 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
654\r
655 //\r
656 // Get acpi resource node for all the resource types\r
657 //\r
658 AcpiConfig = NULL;\r
659\r
660 Status = PciResAlloc->GetProposedResources (\r
661 PciResAlloc,\r
662 RootBridgeDev->Handle,\r
663 &AcpiConfig\r
664 );\r
665\r
666 if (EFI_ERROR (Status)) {\r
667 return Status;\r
668 }\r
669\r
670 if (AcpiConfig != NULL) {\r
671 //\r
672 // Adjust resource allocation policy for each RB\r
673 //\r
674 GetResourceAllocationStatus (\r
675 AcpiConfig,\r
676 &IoResStatus,\r
677 &Mem32ResStatus,\r
678 &PMem32ResStatus,\r
679 &Mem64ResStatus,\r
680 &PMem64ResStatus\r
681 );\r
682 FreePool (AcpiConfig);\r
683 }\r
684 }\r
685 //\r
686 // End while\r
687 //\r
688\r
689 //\r
690 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
691 //\r
692 //\r
693 // It is very difficult to follow the spec here\r
694 // Device path , Bar index can not be get here\r
695 //\r
696 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
697\r
698 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
699 EFI_PROGRESS_CODE,\r
700 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
701 (VOID *) &AllocFailExtendedData,\r
702 sizeof (AllocFailExtendedData)\r
703 );\r
704\r
705 Status = PciHostBridgeAdjustAllocation (\r
706 &IoPool,\r
707 &Mem32Pool,\r
708 &PMem32Pool,\r
709 &Mem64Pool,\r
710 &PMem64Pool,\r
711 IoResStatus,\r
712 Mem32ResStatus,\r
713 PMem32ResStatus,\r
714 Mem64ResStatus,\r
715 PMem64ResStatus\r
716 );\r
717\r
718 //\r
719 // Destroy all the resource tree\r
720 //\r
721 DestroyResourceTree (&IoPool);\r
722 DestroyResourceTree (&Mem32Pool);\r
723 DestroyResourceTree (&PMem32Pool);\r
724 DestroyResourceTree (&Mem64Pool);\r
725 DestroyResourceTree (&PMem64Pool);\r
726\r
727 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
728\r
729 if (EFI_ERROR (Status)) {\r
730 return Status;\r
731 }\r
732\r
733 ReAllocate = TRUE;\r
734 }\r
735 }\r
736 //\r
737 // End main while\r
738 //\r
739\r
740 //\r
741 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
742 //\r
743 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
744 EFI_PROGRESS_CODE,\r
fe91c992 745 EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,\r
9060e3ec 746 (VOID *) &HandleExtendedData,\r
747 sizeof (HandleExtendedData)\r
748 );\r
749\r
750 //\r
751 // Notify pci bus driver starts to program the resource\r
752 //\r
ea8d98fa
OM
753 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
754\r
755 if (EFI_ERROR (Status)) {\r
756 return Status;\r
757 }\r
9060e3ec 758\r
759 RootBridgeDev = NULL;\r
760\r
761 RootBridgeHandle = 0;\r
762\r
763 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
764 //\r
765 // Get RootBridg Device by handle\r
766 //\r
767 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
768\r
769 if (RootBridgeDev == NULL) {\r
770 return EFI_NOT_FOUND;\r
771 }\r
772\r
773 //\r
774 // Get acpi resource node for all the resource types\r
775 //\r
776 AcpiConfig = NULL;\r
777 Status = PciResAlloc->GetProposedResources (\r
778 PciResAlloc,\r
779 RootBridgeDev->Handle,\r
780 &AcpiConfig\r
781 );\r
782\r
783 if (EFI_ERROR (Status)) {\r
784 return Status;\r
785 }\r
786\r
787 //\r
788 // Get the resource base by interpreting acpi resource node\r
789 //\r
790 //\r
791 GetResourceBase (\r
792 AcpiConfig,\r
793 &IoBase,\r
794 &Mem32Base,\r
795 &PMem32Base,\r
796 &Mem64Base,\r
797 &PMem64Base\r
798 );\r
799\r
800 //\r
801 // Process option rom for this root bridge\r
802 //\r
803 ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
804\r
805 //\r
806 // Create the entire system resource map from the information collected by\r
807 // enumerator. Several resource tree was created\r
808 //\r
8db6a82c
RN
809 IoBridge = FindResourceNode (RootBridgeDev, &IoPool);\r
810 Mem32Bridge = FindResourceNode (RootBridgeDev, &Mem32Pool);\r
811 PMem32Bridge = FindResourceNode (RootBridgeDev, &PMem32Pool);\r
812 Mem64Bridge = FindResourceNode (RootBridgeDev, &Mem64Pool);\r
813 PMem64Bridge = FindResourceNode (RootBridgeDev, &PMem64Pool);\r
9060e3ec 814\r
9995c2e5
RN
815 ASSERT (IoBridge != NULL);\r
816 ASSERT (Mem32Bridge != NULL);\r
817 ASSERT (PMem32Bridge != NULL);\r
818 ASSERT (Mem64Bridge != NULL);\r
819 ASSERT (PMem64Bridge != NULL);\r
820\r
9060e3ec 821 //\r
822 // Program IO resources\r
823 //\r
824 ProgramResource (\r
825 IoBase,\r
826 IoBridge\r
827 );\r
828\r
829 //\r
830 // Program Mem32 resources\r
831 //\r
832 ProgramResource (\r
833 Mem32Base,\r
834 Mem32Bridge\r
835 );\r
836\r
837 //\r
838 // Program PMem32 resources\r
839 //\r
840 ProgramResource (\r
841 PMem32Base,\r
842 PMem32Bridge\r
843 );\r
844\r
845 //\r
846 // Program Mem64 resources\r
847 //\r
848 ProgramResource (\r
849 Mem64Base,\r
850 Mem64Bridge\r
851 );\r
852\r
853 //\r
854 // Program PMem64 resources\r
855 //\r
856 ProgramResource (\r
857 PMem64Base,\r
858 PMem64Bridge\r
859 );\r
860\r
8db6a82c
RN
861 IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase;\r
862 Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;\r
863 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
864 Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;\r
865 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
866\r
867 //\r
868 // Dump the resource map for current root bridge\r
869 //\r
870 DEBUG_CODE (\r
871 DumpResourceMap (\r
872 RootBridgeDev,\r
873 IoBridge,\r
874 Mem32Bridge,\r
875 PMem32Bridge,\r
876 Mem64Bridge,\r
877 PMem64Bridge\r
878 );\r
879 );\r
880\r
9060e3ec 881 FreePool (AcpiConfig);\r
882 }\r
883\r
884 //\r
885 // Destroy all the resource tree\r
886 //\r
887 DestroyResourceTree (&IoPool);\r
888 DestroyResourceTree (&Mem32Pool);\r
889 DestroyResourceTree (&PMem32Pool);\r
890 DestroyResourceTree (&Mem64Pool);\r
891 DestroyResourceTree (&PMem64Pool);\r
892\r
893 //\r
894 // Notify the resource allocation phase is to end\r
895 //\r
ea8d98fa 896 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
9060e3ec 897\r
ea8d98fa 898 return Status;\r
9060e3ec 899}\r
900\r
306bbe82 901/**\r
902 Allocate NumberOfBuses buses and return the next available PCI bus number.\r
903\r
904 @param Bridge Bridge device instance.\r
905 @param StartBusNumber Current available PCI bus number.\r
906 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.\r
907 @param NextBusNumber Next available PCI bus number.\r
908\r
909 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number\r
910 is returned in NextBusNumber.\r
911 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.\r
912\r
913**/\r
914EFI_STATUS\r
915PciAllocateBusNumber (\r
916 IN PCI_IO_DEVICE *Bridge,\r
917 IN UINT8 StartBusNumber,\r
918 IN UINT8 NumberOfBuses,\r
919 OUT UINT8 *NextBusNumber\r
920 )\r
921{\r
922 PCI_IO_DEVICE *RootBridge;\r
923 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
924 UINT8 NextNumber;\r
925 UINT64 MaxNumberInRange;\r
926\r
927 //\r
928 // Get PCI Root Bridge device\r
929 //\r
930 RootBridge = Bridge;\r
931 while (RootBridge->Parent != NULL) {\r
932 RootBridge = RootBridge->Parent;\r
933 }\r
934\r
935 //\r
936 // Get next available PCI bus number\r
937 //\r
938 BusNumberRanges = RootBridge->BusNumberRanges;\r
939 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
940 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
941 if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <= MaxNumberInRange) {\r
50bdaa05 942 NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);\r
306bbe82 943 while (NextNumber > MaxNumberInRange) {\r
944 ++BusNumberRanges;\r
945 if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
946 return EFI_OUT_OF_RESOURCES;\r
947 }\r
50bdaa05 948 NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));\r
306bbe82 949 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
950 }\r
951 *NextBusNumber = NextNumber;\r
952 return EFI_SUCCESS;\r
953 }\r
954 BusNumberRanges++;\r
955 }\r
956 return EFI_OUT_OF_RESOURCES;\r
957}\r
958\r
9060e3ec 959/**\r
960 Scan pci bus and assign bus number to the given PCI bus system.\r
961\r
962 @param Bridge Bridge device instance.\r
963 @param StartBusNumber start point.\r
964 @param SubBusNumber Point to sub bus number.\r
965 @param PaddedBusRange Customized bus number.\r
966\r
967 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
968 @retval other Some error occurred when scanning pci bus.\r
969\r
970 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
971\r
972**/\r
973EFI_STATUS\r
974PciScanBus (\r
975 IN PCI_IO_DEVICE *Bridge,\r
976 IN UINT8 StartBusNumber,\r
977 OUT UINT8 *SubBusNumber,\r
978 OUT UINT8 *PaddedBusRange\r
979 )\r
980{\r
981 EFI_STATUS Status;\r
982 PCI_TYPE00 Pci;\r
983 UINT8 Device;\r
984 UINT8 Func;\r
985 UINT64 Address;\r
986 UINTN SecondBus;\r
987 UINT16 Register;\r
988 UINTN HpIndex;\r
989 PCI_IO_DEVICE *PciDevice;\r
990 EFI_EVENT Event;\r
991 EFI_HPC_STATE State;\r
992 UINT64 PciAddress;\r
993 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
994 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
995 UINT16 BusRange;\r
996 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
997 BOOLEAN BusPadding;\r
998 UINT32 TempReservedBusNum;\r
999\r
1000 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1001 SecondBus = 0;\r
1002 Register = 0;\r
1003 State = 0;\r
1004 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
1005 BusRange = 0;\r
1006 BusPadding = FALSE;\r
1007 PciDevice = NULL;\r
1008 PciAddress = 0;\r
1009\r
1010 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1011 TempReservedBusNum = 0;\r
1012 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1013\r
1014 //\r
1015 // Check to see whether a pci device is present\r
1016 //\r
1017 Status = PciDevicePresent (\r
1018 PciRootBridgeIo,\r
1019 &Pci,\r
1020 StartBusNumber,\r
1021 Device,\r
1022 Func\r
1023 );\r
1024\r
1025 if (EFI_ERROR (Status)) {\r
9060e3ec 1026 continue;\r
1027 }\r
1028\r
d4048391 1029 //\r
1030 // Get the PCI device information\r
1031 //\r
1032 Status = PciSearchDevice (\r
1033 Bridge,\r
1034 &Pci,\r
1035 StartBusNumber,\r
1036 Device,\r
1037 Func,\r
1038 &PciDevice\r
1039 );\r
9060e3ec 1040\r
d4048391 1041 ASSERT (!EFI_ERROR (Status));\r
9060e3ec 1042\r
d4048391 1043 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 1044\r
d4048391 1045 if (!IS_PCI_BRIDGE (&Pci)) {\r
1046 //\r
1047 // PCI bridges will be called later\r
1048 // Here just need for PCI device or PCI to cardbus controller\r
1049 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1050 //\r
1051 PreprocessController (\r
1052 PciDevice,\r
1053 PciDevice->BusNumber,\r
1054 PciDevice->DeviceNumber,\r
1055 PciDevice->FunctionNumber,\r
1056 EfiPciBeforeChildBusEnumeration\r
1057 );\r
1058 }\r
9060e3ec 1059\r
d4048391 1060 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1061 //\r
1062 // For Pci Hotplug controller devcie only\r
1063 //\r
1064 if (gPciHotPlugInit != NULL) {\r
1065 //\r
1066 // Check if it is a Hotplug PCI controller\r
1067 //\r
1068 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 1069 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 1070\r
1071 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1072\r
1073 Status = CreateEventForHpc (HpIndex, &Event);\r
1074\r
1075 ASSERT (!EFI_ERROR (Status));\r
1076\r
1077 Status = gPciHotPlugInit->InitializeRootHpc (\r
1078 gPciHotPlugInit,\r
1079 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1080 PciAddress,\r
1081 Event,\r
1082 &State\r
1083 );\r
1084\r
1085 PreprocessController (\r
1086 PciDevice,\r
1087 PciDevice->BusNumber,\r
1088 PciDevice->DeviceNumber,\r
1089 PciDevice->FunctionNumber,\r
1090 EfiPciBeforeChildBusEnumeration\r
1091 );\r
1092 }\r
1093 }\r
1094 }\r
1095 }\r
1096\r
1097 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1098 //\r
1099 // For PPB\r
1100 //\r
1101 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1102 //\r
1103 // If Hot Plug is not supported,\r
1104 // get the bridge information\r
1105 //\r
1106 Status = PciSearchDevice (\r
1107 Bridge,\r
1108 &Pci,\r
1109 StartBusNumber,\r
1110 Device,\r
1111 Func,\r
1112 &PciDevice\r
1113 );\r
1114\r
1115 if (EFI_ERROR (Status)) {\r
1116 return Status;\r
1117 }\r
1118 } else {\r
1119 //\r
1120 // If Hot Plug is supported,\r
1121 // Get the bridge information\r
1122 //\r
1123 BusPadding = FALSE;\r
1124 if (gPciHotPlugInit != NULL) {\r
1125\r
1126 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1127\r
1128 //\r
1129 // If it is initialized, get the padded bus range\r
1130 //\r
1131 Status = gPciHotPlugInit->GetResourcePadding (\r
1132 gPciHotPlugInit,\r
1133 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1134 PciAddress,\r
1135 &State,\r
1136 (VOID **) &Descriptors,\r
1137 &Attributes\r
1138 );\r
1139\r
1140 if (EFI_ERROR (Status)) {\r
1141 return Status;\r
1142 }\r
1143\r
1144 BusRange = 0;\r
1145 Status = PciGetBusRange (\r
1146 &Descriptors,\r
1147 NULL,\r
1148 NULL,\r
1149 &BusRange\r
1150 );\r
1151\r
1152 FreePool (Descriptors);\r
1153\r
1154 if (EFI_ERROR (Status)) {\r
1155 return Status;\r
1156 }\r
1157\r
1158 BusPadding = TRUE;\r
1159 }\r
1160 }\r
1161 }\r
1162\r
306bbe82 1163 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
1164 if (EFI_ERROR (Status)) {\r
1165 return Status;\r
9060e3ec 1166 }\r
9060e3ec 1167 SecondBus = *SubBusNumber;\r
1168\r
1169 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1170 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
1171\r
1172 Status = PciRootBridgeIo->Pci.Write (\r
1173 PciRootBridgeIo,\r
1174 EfiPciWidthUint16,\r
1175 Address,\r
1176 1,\r
1177 &Register\r
1178 );\r
1179\r
1180\r
1181 //\r
1182 // If it is PPB, resursively search down this bridge\r
1183 //\r
1184 if (IS_PCI_BRIDGE (&Pci)) {\r
1185\r
1186 //\r
1187 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1188 // PCI configuration transaction to go through any PPB\r
1189 //\r
1190 Register = 0xFF;\r
1191 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1192 Status = PciRootBridgeIo->Pci.Write (\r
1193 PciRootBridgeIo,\r
1194 EfiPciWidthUint8,\r
1195 Address,\r
1196 1,\r
1197 &Register\r
1198 );\r
1199\r
1200 //\r
1201 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1202 //\r
1203 PreprocessController (\r
1204 PciDevice,\r
1205 PciDevice->BusNumber,\r
1206 PciDevice->DeviceNumber,\r
1207 PciDevice->FunctionNumber,\r
1208 EfiPciBeforeChildBusEnumeration\r
1209 );\r
1210\r
9060e3ec 1211 Status = PciScanBus (\r
1212 PciDevice,\r
1213 (UINT8) (SecondBus),\r
1214 SubBusNumber,\r
1215 PaddedBusRange\r
1216 );\r
1217 if (EFI_ERROR (Status)) {\r
1218 return Status;\r
1219 }\r
1220 }\r
1221\r
1222 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1223 //\r
1224 // Ensure the device is enabled and initialized\r
1225 //\r
1226 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1227 (State & EFI_HPC_STATE_ENABLED) != 0 &&\r
1228 (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
1229 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1230 } else {\r
306bbe82 1231 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (BusRange), SubBusNumber);\r
1232 if (EFI_ERROR (Status)) {\r
1233 return Status;\r
1234 }\r
9060e3ec 1235 }\r
1236 }\r
1237\r
1238 //\r
1239 // Set the current maximum bus number under the PPB\r
1240 //\r
1241 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1242\r
1243 Status = PciRootBridgeIo->Pci.Write (\r
1244 PciRootBridgeIo,\r
1245 EfiPciWidthUint8,\r
1246 Address,\r
1247 1,\r
1248 SubBusNumber\r
1249 );\r
1250 } else {\r
1251 //\r
1252 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 1253 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1254 //\r
d4048391 1255 if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {\r
9060e3ec 1256 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1257\r
306bbe82 1258 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);\r
1259 if (EFI_ERROR (Status)) {\r
1260 return Status;\r
1261 }\r
9060e3ec 1262 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1263\r
1264 if (Func == 0) {\r
1265 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
1266 } else {\r
1267 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
1268 }\r
1269 }\r
1270 }\r
1271 }\r
1272\r
1273 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1274\r
1275 //\r
1276 // Skip sub functions, this is not a multi function device\r
1277 //\r
1278\r
1279 Func = PCI_MAX_FUNC;\r
1280 }\r
1281 }\r
1282 }\r
1283\r
1284 return EFI_SUCCESS;\r
1285}\r
1286\r
1287/**\r
1288 Process Option Rom on the specified root bridge.\r
1289\r
1290 @param Bridge Pci root bridge device instance.\r
1291\r
1292 @retval EFI_SUCCESS Success process.\r
1293 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1294\r
1295**/\r
1296EFI_STATUS\r
1297PciRootBridgeP2CProcess (\r
1298 IN PCI_IO_DEVICE *Bridge\r
1299 )\r
1300{\r
1301 LIST_ENTRY *CurrentLink;\r
1302 PCI_IO_DEVICE *Temp;\r
1303 EFI_HPC_STATE State;\r
1304 UINT64 PciAddress;\r
1305 EFI_STATUS Status;\r
1306\r
1307 CurrentLink = Bridge->ChildList.ForwardLink;\r
1308\r
1309 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
1310\r
1311 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1312\r
1313 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1314\r
1315 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1316\r
1317 //\r
1318 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1319 //\r
1320 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1321 EFI_PROGRESS_CODE,\r
fe91c992 1322 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
9060e3ec 1323 Temp->DevicePath\r
1324 );\r
1325\r
1326 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1327 Status = gPciHotPlugInit->InitializeRootHpc (\r
1328 gPciHotPlugInit,\r
1329 Temp->DevicePath,\r
1330 PciAddress,\r
1331 NULL,\r
1332 &State\r
1333 );\r
1334\r
1335 if (!EFI_ERROR (Status)) {\r
1336 Status = PciBridgeEnumerator (Temp);\r
1337\r
1338 if (EFI_ERROR (Status)) {\r
1339 return Status;\r
1340 }\r
1341 }\r
1342\r
1343 CurrentLink = CurrentLink->ForwardLink;\r
1344 continue;\r
1345\r
1346 }\r
1347 }\r
1348\r
1349 if (!IsListEmpty (&Temp->ChildList)) {\r
1350 Status = PciRootBridgeP2CProcess (Temp);\r
1351 }\r
1352\r
1353 CurrentLink = CurrentLink->ForwardLink;\r
1354 }\r
1355\r
1356 return EFI_SUCCESS;\r
1357}\r
1358\r
1359/**\r
1360 Process Option Rom on the specified host bridge.\r
1361\r
1362 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1363\r
1364 @retval EFI_SUCCESS Success process.\r
1365 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1366 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1367\r
1368**/\r
1369EFI_STATUS\r
1370PciHostBridgeP2CProcess (\r
1371 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1372 )\r
1373{\r
1374 EFI_HANDLE RootBridgeHandle;\r
1375 PCI_IO_DEVICE *RootBridgeDev;\r
1376 EFI_STATUS Status;\r
1377\r
1378 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1379 return EFI_SUCCESS;\r
1380 }\r
1381\r
1382 RootBridgeHandle = NULL;\r
1383\r
1384 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1385\r
1386 //\r
1387 // Get RootBridg Device by handle\r
1388 //\r
1389 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1390\r
1391 if (RootBridgeDev == NULL) {\r
1392 return EFI_NOT_FOUND;\r
1393 }\r
1394\r
1395 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1396 if (EFI_ERROR (Status)) {\r
1397 return Status;\r
1398 }\r
1399\r
1400 }\r
1401\r
1402 return EFI_SUCCESS;\r
1403}\r
1404\r
1405/**\r
1406 This function is used to enumerate the entire host bridge\r
1407 in a given platform.\r
1408\r
1409 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1410\r
1411 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1412 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1413 @retval other Some error occurred when enumerating the host bridge.\r
1414\r
1415**/\r
1416EFI_STATUS\r
1417PciHostBridgeEnumerator (\r
1418 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1419 )\r
1420{\r
1421 EFI_HANDLE RootBridgeHandle;\r
1422 PCI_IO_DEVICE *RootBridgeDev;\r
1423 EFI_STATUS Status;\r
1424 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1425 UINT16 MinBus;\r
1426 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1427 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1428 UINT8 StartBusNumber;\r
1429 LIST_ENTRY RootBridgeList;\r
1430 LIST_ENTRY *Link;\r
1431\r
1432 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1433 InitializeHotPlugSupport ();\r
1434 }\r
1435\r
1436 InitializeListHead (&RootBridgeList);\r
1437\r
1438 //\r
1439 // Notify the bus allocation phase is about to start\r
1440 //\r
ea8d98fa
OM
1441 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1442\r
1443 if (EFI_ERROR (Status)) {\r
1444 return Status;\r
1445 }\r
9060e3ec 1446\r
1447 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
1448 RootBridgeHandle = NULL;\r
1449 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1450\r
1451 //\r
1452 // if a root bridge instance is found, create root bridge device for it\r
1453 //\r
1454\r
1455 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1456\r
1457 if (RootBridgeDev == NULL) {\r
1458 return EFI_OUT_OF_RESOURCES;\r
1459 }\r
1460\r
1461 //\r
1462 // Enumerate all the buses under this root bridge\r
1463 //\r
1464 Status = PciRootBridgeEnumerator (\r
1465 PciResAlloc,\r
1466 RootBridgeDev\r
1467 );\r
1468\r
1469 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1470 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1471 } else {\r
1472 DestroyRootBridge (RootBridgeDev);\r
1473 }\r
1474 if (EFI_ERROR (Status)) {\r
1475 return Status;\r
1476 }\r
1477 }\r
1478\r
1479 //\r
1480 // Notify the bus allocation phase is finished for the first time\r
1481 //\r
1482 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1483\r
1484 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1485 //\r
1486 // Reset all assigned PCI bus number in all PPB\r
1487 //\r
1488 RootBridgeHandle = NULL;\r
1489 Link = GetFirstNode (&RootBridgeList);\r
1490 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1491 (!IsNull (&RootBridgeList, Link))) {\r
1492 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1493 //\r
1494 // Get the Bus information\r
1495 //\r
1496 Status = PciResAlloc->StartBusEnumeration (\r
1497 PciResAlloc,\r
1498 RootBridgeHandle,\r
1499 (VOID **) &Configuration\r
1500 );\r
1501 if (EFI_ERROR (Status)) {\r
1502 return Status;\r
1503 }\r
1504\r
1505 //\r
1506 // Get the bus number to start with\r
1507 //\r
1508 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
1509\r
1510 ResetAllPpbBusNumber (\r
1511 RootBridgeDev,\r
1512 StartBusNumber\r
1513 );\r
1514\r
1515 FreePool (Configuration);\r
8063b47b 1516 Link = RemoveEntryList (Link);\r
9060e3ec 1517 DestroyRootBridge (RootBridgeDev);\r
1518 }\r
1519\r
1520 //\r
1521 // Wait for all HPC initialized\r
1522 //\r
1523 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1524\r
1525 if (EFI_ERROR (Status)) {\r
55565b08 1526 DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1527 return Status;\r
1528 }\r
1529\r
1530 //\r
1531 // Notify the bus allocation phase is about to start for the 2nd time\r
1532 //\r
ea8d98fa
OM
1533 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1534\r
1535 if (EFI_ERROR (Status)) {\r
1536 return Status;\r
1537 }\r
9060e3ec 1538\r
1539 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
1540 RootBridgeHandle = NULL;\r
1541 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1542\r
1543 //\r
1544 // if a root bridge instance is found, create root bridge device for it\r
1545 //\r
1546 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1547\r
1548 if (RootBridgeDev == NULL) {\r
1549 return EFI_OUT_OF_RESOURCES;\r
1550 }\r
1551\r
1552 //\r
1553 // Enumerate all the buses under this root bridge\r
1554 //\r
1555 Status = PciRootBridgeEnumerator (\r
1556 PciResAlloc,\r
1557 RootBridgeDev\r
1558 );\r
1559\r
1560 DestroyRootBridge (RootBridgeDev);\r
1561 if (EFI_ERROR (Status)) {\r
1562 return Status;\r
1563 }\r
1564 }\r
1565\r
1566 //\r
1567 // Notify the bus allocation phase is to end for the 2nd time\r
1568 //\r
1569 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1570 }\r
1571\r
1572 //\r
1573 // Notify the resource allocation phase is to start\r
1574 //\r
ea8d98fa
OM
1575 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1576\r
1577 if (EFI_ERROR (Status)) {\r
1578 return Status;\r
1579 }\r
9060e3ec 1580\r
1581 RootBridgeHandle = NULL;\r
1582 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1583\r
1584 //\r
1585 // if a root bridge instance is found, create root bridge device for it\r
1586 //\r
1587 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1588\r
1589 if (RootBridgeDev == NULL) {\r
1590 return EFI_OUT_OF_RESOURCES;\r
1591 }\r
1592\r
1593 Status = StartManagingRootBridge (RootBridgeDev);\r
1594\r
1595 if (EFI_ERROR (Status)) {\r
1596 return Status;\r
1597 }\r
1598\r
1599 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1600 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1601\r
1602 if (EFI_ERROR (Status)) {\r
1603 return Status;\r
1604 }\r
1605\r
1606 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1607\r
1608 if (EFI_ERROR (Status)) {\r
1609 return Status;\r
1610 }\r
1611\r
1612 //\r
1613 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1614 // protocol\r
1615 //\r
1616 DetermineRootBridgeAttributes (\r
1617 PciResAlloc,\r
1618 RootBridgeDev\r
1619 );\r
1620\r
1621 //\r
1622 // Collect all the resource information under this root bridge\r
1623 // A database that records all the information about pci device subject to this\r
1624 // root bridge will then be created\r
1625 //\r
1626 Status = PciPciDeviceInfoCollector (\r
1627 RootBridgeDev,\r
1628 (UINT8) MinBus\r
1629 );\r
1630\r
1631 if (EFI_ERROR (Status)) {\r
1632 return Status;\r
1633 }\r
1634\r
1635 InsertRootBridge (RootBridgeDev);\r
1636\r
1637 //\r
1638 // Record the hostbridge handle\r
1639 //\r
1640 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1641 }\r
1642\r
1643 return EFI_SUCCESS;\r
1644}\r