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