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