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