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