1/** @file 2 Internal library implementation for PCI Bus module. 3 4Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> 5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> 6This program and the accompanying materials 7are licensed and made available under the terms and conditions of the BSD License 8which accompanies this distribution. The full text of the license may be found at 9http://opensource.org/licenses/bsd-license.php 10 11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14**/ 15 16#include "PciBus.h" 17 18GLOBAL_REMOVE_IF_UNREFERENCED 19CHAR16 *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**/ 38VOID 39GetBackPcCardBar ( 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**/ 117VOID 118RemoveRejectedPciDevices ( 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**/ 175VOID 176DumpBridgeResource ( 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 = GetFirstNode (&BridgeResource->ChildList) 192 ; !IsNull (&BridgeResource->ChildList, Link) 193 ; Link = GetNextNode (&BridgeResource->ChildList, Link) 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 [%02x|%02x|%02x:", 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 Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber, 205 Resource->PciDev->FunctionNumber 206 )); 207 208 if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) || 209 (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) || 210 (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1)) 211 ) { 212 // 213 // The resource requirement comes from the device itself. 214 // 215 DEBUG ((EFI_D_INFO, "%02x]", Bar[Resource->Bar].Offset)); 216 } else { 217 // 218 // The resource requirement comes from the subordinate devices. 219 // 220 DEBUG ((EFI_D_INFO, "**]")); 221 } 222 } else { 223 DEBUG ((EFI_D_INFO, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource->Length, Resource->Alignment)); 224 } 225 if (BridgeResource->ResType != Resource->ResType) { 226 DEBUG ((EFI_D_INFO, "; Type = %s", mBarTypeStr[MIN (Resource->ResType, PciBarTypeMaxType)])); 227 } 228 DEBUG ((EFI_D_INFO, "\n")); 229 } 230 } 231} 232 233/** 234 Find the corresponding resource node for the Device in child list of BridgeResource. 235 236 @param[in] Device Pointer to PCI_IO_DEVICE. 237 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE. 238 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device. 239 240 @return Count of the resource descriptors returned. 241**/ 242UINTN 243FindResourceNode ( 244 IN PCI_IO_DEVICE *Device, 245 IN PCI_RESOURCE_NODE *BridgeResource, 246 OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL 247 ) 248{ 249 LIST_ENTRY *Link; 250 PCI_RESOURCE_NODE *Resource; 251 UINTN Count; 252 253 Count = 0; 254 for ( Link = BridgeResource->ChildList.ForwardLink 255 ; Link != &BridgeResource->ChildList 256 ; Link = Link->ForwardLink 257 ) { 258 Resource = RESOURCE_NODE_FROM_LINK (Link); 259 if (Resource->PciDev == Device) { 260 if (DeviceResources != NULL) { 261 DeviceResources[Count] = Resource; 262 } 263 Count++; 264 } 265 } 266 267 return Count; 268} 269 270/** 271 Dump the resource map of all the devices under Bridge. 272 273 @param[in] Bridge Bridge device instance. 274 @param[in] Resources Resource descriptors for the bridge device. 275 @param[in] ResourceCount Count of resource descriptors. 276**/ 277VOID 278DumpResourceMap ( 279 IN PCI_IO_DEVICE *Bridge, 280 IN PCI_RESOURCE_NODE **Resources, 281 IN UINTN ResourceCount 282 ) 283{ 284 EFI_STATUS Status; 285 LIST_ENTRY *Link; 286 PCI_IO_DEVICE *Device; 287 UINTN Index; 288 CHAR16 *Str; 289 PCI_RESOURCE_NODE **ChildResources; 290 UINTN ChildResourceCount; 291 292 DEBUG ((EFI_D_INFO, "PciBus: Resource Map for ")); 293 294 Status = gBS->OpenProtocol ( 295 Bridge->Handle, 296 &gEfiPciRootBridgeIoProtocolGuid, 297 NULL, 298 NULL, 299 NULL, 300 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 301 ); 302 if (EFI_ERROR (Status)) { 303 DEBUG (( 304 EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n", 305 Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber 306 )); 307 } else { 308 Str = ConvertDevicePathToText ( 309 DevicePathFromHandle (Bridge->Handle), 310 FALSE, 311 FALSE 312 ); 313 DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L"")); 314 if (Str != NULL) { 315 FreePool (Str); 316 } 317 } 318 319 for (Index = 0; Index < ResourceCount; Index++) { 320 DumpBridgeResource (Resources[Index]); 321 } 322 DEBUG ((EFI_D_INFO, "\n")); 323 324 for ( Link = Bridge->ChildList.ForwardLink 325 ; Link != &Bridge->ChildList 326 ; Link = Link->ForwardLink 327 ) { 328 Device = PCI_IO_DEVICE_FROM_LINK (Link); 329 if (IS_PCI_BRIDGE (&Device->Pci)) { 330 331 ChildResourceCount = 0; 332 for (Index = 0; Index < ResourceCount; Index++) { 333 ChildResourceCount += FindResourceNode (Device, Resources[Index], NULL); 334 } 335 ChildResources = AllocatePool (sizeof (PCI_RESOURCE_NODE *) * ChildResourceCount); 336 ASSERT (ChildResources != NULL); 337 ChildResourceCount = 0; 338 for (Index = 0; Index < ResourceCount; Index++) { 339 ChildResourceCount += FindResourceNode (Device, Resources[Index], &ChildResources[ChildResourceCount]); 340 } 341 342 DumpResourceMap (Device, ChildResources, ChildResourceCount); 343 FreePool (ChildResources); 344 } 345 } 346} 347 348/** 349 Submits the I/O and memory resource requirements for the specified PCI Host Bridge. 350 351 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. 352 353 @retval EFI_SUCCESS Successfully finished resource allocation. 354 @retval EFI_NOT_FOUND Cannot get root bridge instance. 355 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported. 356 @retval other Some error occurred when allocating resources for the PCI Host Bridge. 357 358 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug. 359 360**/ 361EFI_STATUS 362PciHostBridgeResourceAllocator ( 363 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc 364 ) 365{ 366 PCI_IO_DEVICE *RootBridgeDev; 367 EFI_HANDLE RootBridgeHandle; 368 VOID *AcpiConfig; 369 EFI_STATUS Status; 370 UINT64 IoBase; 371 UINT64 Mem32Base; 372 UINT64 PMem32Base; 373 UINT64 Mem64Base; 374 UINT64 PMem64Base; 375 UINT64 IoResStatus; 376 UINT64 Mem32ResStatus; 377 UINT64 PMem32ResStatus; 378 UINT64 Mem64ResStatus; 379 UINT64 PMem64ResStatus; 380 UINT64 MaxOptionRomSize; 381 PCI_RESOURCE_NODE *IoBridge; 382 PCI_RESOURCE_NODE *Mem32Bridge; 383 PCI_RESOURCE_NODE *PMem32Bridge; 384 PCI_RESOURCE_NODE *Mem64Bridge; 385 PCI_RESOURCE_NODE *PMem64Bridge; 386 PCI_RESOURCE_NODE IoPool; 387 PCI_RESOURCE_NODE Mem32Pool; 388 PCI_RESOURCE_NODE PMem32Pool; 389 PCI_RESOURCE_NODE Mem64Pool; 390 PCI_RESOURCE_NODE PMem64Pool; 391 BOOLEAN ReAllocate; 392 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData; 393 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData; 394 395 // 396 // Reallocate flag 397 // 398 ReAllocate = FALSE; 399 400 // 401 // It may try several times if the resource allocation fails 402 // 403 while (TRUE) { 404 // 405 // Initialize resource pool 406 // 407 InitializeResourcePool (&IoPool, PciBarTypeIo16); 408 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32); 409 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32); 410 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64); 411 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64); 412 413 RootBridgeDev = NULL; 414 RootBridgeHandle = 0; 415 416 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { 417 // 418 // Get Root Bridge Device by handle 419 // 420 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); 421 422 if (RootBridgeDev == NULL) { 423 return EFI_NOT_FOUND; 424 } 425 426 // 427 // Create the entire system resource map from the information collected by 428 // enumerator. Several resource tree was created 429 // 430 431 // 432 // If non-standard PCI Bridge I/O window alignment is supported, 433 // set I/O aligment to minimum possible alignment for root bridge. 434 // 435 IoBridge = CreateResourceNode ( 436 RootBridgeDev, 437 0, 438 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF, 439 RB_IO_RANGE, 440 PciBarTypeIo16, 441 PciResUsageTypical 442 ); 443 444 Mem32Bridge = CreateResourceNode ( 445 RootBridgeDev, 446 0, 447 0xFFFFF, 448 RB_MEM32_RANGE, 449 PciBarTypeMem32, 450 PciResUsageTypical 451 ); 452 453 PMem32Bridge = CreateResourceNode ( 454 RootBridgeDev, 455 0, 456 0xFFFFF, 457 RB_PMEM32_RANGE, 458 PciBarTypePMem32, 459 PciResUsageTypical 460 ); 461 462 Mem64Bridge = CreateResourceNode ( 463 RootBridgeDev, 464 0, 465 0xFFFFF, 466 RB_MEM64_RANGE, 467 PciBarTypeMem64, 468 PciResUsageTypical 469 ); 470 471 PMem64Bridge = CreateResourceNode ( 472 RootBridgeDev, 473 0, 474 0xFFFFF, 475 RB_PMEM64_RANGE, 476 PciBarTypePMem64, 477 PciResUsageTypical 478 ); 479 480 // 481 // Create resourcemap by going through all the devices subject to this root bridge 482 // 483 CreateResourceMap ( 484 RootBridgeDev, 485 IoBridge, 486 Mem32Bridge, 487 PMem32Bridge, 488 Mem64Bridge, 489 PMem64Bridge 490 ); 491 492 // 493 // Get the max ROM size that the root bridge can process 494 // 495 RootBridgeDev->RomSize = Mem32Bridge->Length; 496 497 // 498 // Skip to enlarge the resource request during realloction 499 // 500 if (!ReAllocate) { 501 // 502 // Get Max Option Rom size for current root bridge 503 // 504 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev); 505 506 // 507 // Enlarger the mem32 resource to accomdate the option rom 508 // if the mem32 resource is not enough to hold the rom 509 // 510 if (MaxOptionRomSize > Mem32Bridge->Length) { 511 512 Mem32Bridge->Length = MaxOptionRomSize; 513 RootBridgeDev->RomSize = MaxOptionRomSize; 514 515 // 516 // Alignment should be adjusted as well 517 // 518 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) { 519 Mem32Bridge->Alignment = MaxOptionRomSize - 1; 520 } 521 } 522 } 523 524 // 525 // Based on the all the resource tree, construct ACPI resource node to 526 // submit the resource aperture to pci host bridge protocol 527 // 528 Status = ConstructAcpiResourceRequestor ( 529 RootBridgeDev, 530 IoBridge, 531 Mem32Bridge, 532 PMem32Bridge, 533 Mem64Bridge, 534 PMem64Bridge, 535 &AcpiConfig 536 ); 537 538 // 539 // Insert these resource nodes into the database 540 // 541 InsertResourceNode (&IoPool, IoBridge); 542 InsertResourceNode (&Mem32Pool, Mem32Bridge); 543 InsertResourceNode (&PMem32Pool, PMem32Bridge); 544 InsertResourceNode (&Mem64Pool, Mem64Bridge); 545 InsertResourceNode (&PMem64Pool, PMem64Bridge); 546 547 if (Status == EFI_SUCCESS) { 548 // 549 // Submit the resource requirement 550 // 551 Status = PciResAlloc->SubmitResources ( 552 PciResAlloc, 553 RootBridgeDev->Handle, 554 AcpiConfig 555 ); 556 // 557 // If SubmitResources returns error, PciBus isn't able to start. 558 // It's a fatal error so assertion is added. 559 // 560 DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status)); 561 ASSERT_EFI_ERROR (Status); 562 } 563 564 // 565 // Free acpi resource node 566 // 567 if (AcpiConfig != NULL) { 568 FreePool (AcpiConfig); 569 } 570 571 if (EFI_ERROR (Status)) { 572 // 573 // Destroy all the resource tree 574 // 575 DestroyResourceTree (&IoPool); 576 DestroyResourceTree (&Mem32Pool); 577 DestroyResourceTree (&PMem32Pool); 578 DestroyResourceTree (&Mem64Pool); 579 DestroyResourceTree (&PMem64Pool); 580 return Status; 581 } 582 } 583 // 584 // End while, at least one Root Bridge should be found. 585 // 586 ASSERT (RootBridgeDev != NULL); 587 588 // 589 // Notify platform to start to program the resource 590 // 591 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources); 592 DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status)); 593 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { 594 // 595 // If Hot Plug is not supported 596 // 597 if (EFI_ERROR (Status)) { 598 // 599 // Allocation failed, then return 600 // 601 return EFI_OUT_OF_RESOURCES; 602 } 603 // 604 // Allocation succeed. 605 // Get host bridge handle for status report, and then skip the main while 606 // 607 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle; 608 609 break; 610 611 } else { 612 // 613 // If Hot Plug is supported 614 // 615 if (!EFI_ERROR (Status)) { 616 // 617 // Allocation succeed, then continue the following 618 // 619 break; 620 } 621 622 // 623 // If the resource allocation is unsuccessful, free resources on bridge 624 // 625 626 RootBridgeDev = NULL; 627 RootBridgeHandle = 0; 628 629 IoResStatus = EFI_RESOURCE_SATISFIED; 630 Mem32ResStatus = EFI_RESOURCE_SATISFIED; 631 PMem32ResStatus = EFI_RESOURCE_SATISFIED; 632 Mem64ResStatus = EFI_RESOURCE_SATISFIED; 633 PMem64ResStatus = EFI_RESOURCE_SATISFIED; 634 635 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { 636 // 637 // Get RootBridg Device by handle 638 // 639 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); 640 if (RootBridgeDev == NULL) { 641 return EFI_NOT_FOUND; 642 } 643 644 // 645 // Get host bridge handle for status report 646 // 647 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle; 648 649 // 650 // Get acpi resource node for all the resource types 651 // 652 AcpiConfig = NULL; 653 654 Status = PciResAlloc->GetProposedResources ( 655 PciResAlloc, 656 RootBridgeDev->Handle, 657 &AcpiConfig 658 ); 659 660 if (EFI_ERROR (Status)) { 661 return Status; 662 } 663 664 if (AcpiConfig != NULL) { 665 // 666 // Adjust resource allocation policy for each RB 667 // 668 GetResourceAllocationStatus ( 669 AcpiConfig, 670 &IoResStatus, 671 &Mem32ResStatus, 672 &PMem32ResStatus, 673 &Mem64ResStatus, 674 &PMem64ResStatus 675 ); 676 FreePool (AcpiConfig); 677 } 678 } 679 // 680 // End while 681 // 682 683 // 684 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code 685 // 686 // 687 // It is very difficult to follow the spec here 688 // Device path , Bar index can not be get here 689 // 690 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData)); 691 692 REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( 693 EFI_PROGRESS_CODE, 694 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT, 695 (VOID *) &AllocFailExtendedData, 696 sizeof (AllocFailExtendedData) 697 ); 698 699 Status = PciHostBridgeAdjustAllocation ( 700 &IoPool, 701 &Mem32Pool, 702 &PMem32Pool, 703 &Mem64Pool, 704 &PMem64Pool, 705 IoResStatus, 706 Mem32ResStatus, 707 PMem32ResStatus, 708 Mem64ResStatus, 709 PMem64ResStatus 710 ); 711 712 // 713 // Destroy all the resource tree 714 // 715 DestroyResourceTree (&IoPool); 716 DestroyResourceTree (&Mem32Pool); 717 DestroyResourceTree (&PMem32Pool); 718 DestroyResourceTree (&Mem64Pool); 719 DestroyResourceTree (&PMem64Pool); 720 721 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources); 722 723 if (EFI_ERROR (Status)) { 724 return Status; 725 } 726 727 ReAllocate = TRUE; 728 } 729 } 730 // 731 // End main while 732 // 733 734 // 735 // Raise the EFI_IOB_PCI_RES_ALLOC status code 736 // 737 REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( 738 EFI_PROGRESS_CODE, 739 EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC, 740 (VOID *) &HandleExtendedData, 741 sizeof (HandleExtendedData) 742 ); 743 744 // 745 // Notify pci bus driver starts to program the resource 746 // 747 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources); 748 749 if (EFI_ERROR (Status)) { 750 return Status; 751 } 752 753 RootBridgeDev = NULL; 754 755 RootBridgeHandle = 0; 756 757 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { 758 // 759 // Get RootBridg Device by handle 760 // 761 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); 762 763 if (RootBridgeDev == NULL) { 764 return EFI_NOT_FOUND; 765 } 766 767 // 768 // Get acpi resource node for all the resource types 769 // 770 AcpiConfig = NULL; 771 Status = PciResAlloc->GetProposedResources ( 772 PciResAlloc, 773 RootBridgeDev->Handle, 774 &AcpiConfig 775 ); 776 777 if (EFI_ERROR (Status)) { 778 return Status; 779 } 780 781 // 782 // Get the resource base by interpreting acpi resource node 783 // 784 // 785 GetResourceBase ( 786 AcpiConfig, 787 &IoBase, 788 &Mem32Base, 789 &PMem32Base, 790 &Mem64Base, 791 &PMem64Base 792 ); 793 794 // 795 // Process option rom for this root bridge 796 // 797 ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize); 798 799 // 800 // Create the entire system resource map from the information collected by 801 // enumerator. Several resource tree was created 802 // 803 FindResourceNode (RootBridgeDev, &IoPool, &IoBridge); 804 FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge); 805 FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge); 806 FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge); 807 FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge); 808 809 ASSERT (IoBridge != NULL); 810 ASSERT (Mem32Bridge != NULL); 811 ASSERT (PMem32Bridge != NULL); 812 ASSERT (Mem64Bridge != NULL); 813 ASSERT (PMem64Bridge != NULL); 814 815 // 816 // Program IO resources 817 // 818 ProgramResource ( 819 IoBase, 820 IoBridge 821 ); 822 823 // 824 // Program Mem32 resources 825 // 826 ProgramResource ( 827 Mem32Base, 828 Mem32Bridge 829 ); 830 831 // 832 // Program PMem32 resources 833 // 834 ProgramResource ( 835 PMem32Base, 836 PMem32Bridge 837 ); 838 839 // 840 // Program Mem64 resources 841 // 842 ProgramResource ( 843 Mem64Base, 844 Mem64Bridge 845 ); 846 847 // 848 // Program PMem64 resources 849 // 850 ProgramResource ( 851 PMem64Base, 852 PMem64Bridge 853 ); 854 855 IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase; 856 Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base; 857 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base; 858 Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base; 859 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base; 860 861 // 862 // Dump the resource map for current root bridge 863 // 864 DEBUG_CODE ( 865 PCI_RESOURCE_NODE *Resources[5]; 866 Resources[0] = IoBridge; 867 Resources[1] = Mem32Bridge; 868 Resources[2] = PMem32Bridge; 869 Resources[3] = Mem64Bridge; 870 Resources[4] = PMem64Bridge; 871 DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources)); 872 ); 873 874 FreePool (AcpiConfig); 875 } 876 877 // 878 // Destroy all the resource tree 879 // 880 DestroyResourceTree (&IoPool); 881 DestroyResourceTree (&Mem32Pool); 882 DestroyResourceTree (&PMem32Pool); 883 DestroyResourceTree (&Mem64Pool); 884 DestroyResourceTree (&PMem64Pool); 885 886 // 887 // Notify the resource allocation phase is to end 888 // 889 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation); 890 891 return Status; 892} 893 894/** 895 Allocate NumberOfBuses buses and return the next available PCI bus number. 896 897 @param Bridge Bridge device instance. 898 @param StartBusNumber Current available PCI bus number. 899 @param NumberOfBuses Number of buses enumerated below the StartBusNumber. 900 @param NextBusNumber Next available PCI bus number. 901 902 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number 903 is returned in NextBusNumber. 904 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation. 905 906**/ 907EFI_STATUS 908PciAllocateBusNumber ( 909 IN PCI_IO_DEVICE *Bridge, 910 IN UINT8 StartBusNumber, 911 IN UINT8 NumberOfBuses, 912 OUT UINT8 *NextBusNumber 913 ) 914{ 915 PCI_IO_DEVICE *RootBridge; 916 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges; 917 UINT8 NextNumber; 918 UINT64 MaxNumberInRange; 919 920 // 921 // Get PCI Root Bridge device 922 // 923 RootBridge = Bridge; 924 while (RootBridge->Parent != NULL) { 925 RootBridge = RootBridge->Parent; 926 } 927 928 // 929 // Get next available PCI bus number 930 // 931 BusNumberRanges = RootBridge->BusNumberRanges; 932 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) { 933 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1; 934 if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <= MaxNumberInRange) { 935 NextNumber = (UINT8)(StartBusNumber + NumberOfBuses); 936 while (NextNumber > MaxNumberInRange) { 937 ++BusNumberRanges; 938 if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) { 939 return EFI_OUT_OF_RESOURCES; 940 } 941 NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1))); 942 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1; 943 } 944 *NextBusNumber = NextNumber; 945 return EFI_SUCCESS; 946 } 947 BusNumberRanges++; 948 } 949 return EFI_OUT_OF_RESOURCES; 950} 951 952/** 953 Scan pci bus and assign bus number to the given PCI bus system. 954 955 @param Bridge Bridge device instance. 956 @param StartBusNumber start point. 957 @param SubBusNumber Point to sub bus number. 958 @param PaddedBusRange Customized bus number. 959 960 @retval EFI_SUCCESS Successfully scanned and assigned bus number. 961 @retval other Some error occurred when scanning pci bus. 962 963 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug. 964 965**/ 966EFI_STATUS 967PciScanBus ( 968 IN PCI_IO_DEVICE *Bridge, 969 IN UINT8 StartBusNumber, 970 OUT UINT8 *SubBusNumber, 971 OUT UINT8 *PaddedBusRange 972 ) 973{ 974 EFI_STATUS Status; 975 PCI_TYPE00 Pci; 976 UINT8 Device; 977 UINT8 Func; 978 UINT64 Address; 979 UINT8 SecondBus; 980 UINT8 PaddedSubBus; 981 UINT16 Register; 982 UINTN HpIndex; 983 PCI_IO_DEVICE *PciDevice; 984 EFI_EVENT Event; 985 EFI_HPC_STATE State; 986 UINT64 PciAddress; 987 EFI_HPC_PADDING_ATTRIBUTES Attributes; 988 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; 989 UINT16 BusRange; 990 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; 991 BOOLEAN BusPadding; 992 UINT32 TempReservedBusNum; 993 994 PciRootBridgeIo = Bridge->PciRootBridgeIo; 995 SecondBus = 0; 996 Register = 0; 997 State = 0; 998 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0; 999 BusRange = 0; 1000 BusPadding = FALSE; 1001 PciDevice = NULL; 1002 PciAddress = 0; 1003 1004 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { 1005 TempReservedBusNum = 0; 1006 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { 1007 1008 // 1009 // Check to see whether a pci device is present 1010 // 1011 Status = PciDevicePresent ( 1012 PciRootBridgeIo, 1013 &Pci, 1014 StartBusNumber, 1015 Device, 1016 Func 1017 ); 1018 1019 if (EFI_ERROR (Status) && Func == 0) { 1020 // 1021 // go to next device if there is no Function 0 1022 // 1023 break; 1024 } 1025 1026 if (EFI_ERROR (Status)) { 1027 continue; 1028 } 1029 1030 // 1031 // Get the PCI device information 1032 // 1033 Status = PciSearchDevice ( 1034 Bridge, 1035 &Pci, 1036 StartBusNumber, 1037 Device, 1038 Func, 1039 &PciDevice 1040 ); 1041 1042 ASSERT (!EFI_ERROR (Status)); 1043 1044 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0); 1045 1046 if (!IS_PCI_BRIDGE (&Pci)) { 1047 // 1048 // PCI bridges will be called later 1049 // Here just need for PCI device or PCI to cardbus controller 1050 // EfiPciBeforeChildBusEnumeration for PCI Device Node 1051 // 1052 PreprocessController ( 1053 PciDevice, 1054 PciDevice->BusNumber, 1055 PciDevice->DeviceNumber, 1056 PciDevice->FunctionNumber, 1057 EfiPciBeforeChildBusEnumeration 1058 ); 1059 } 1060 1061 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { 1062 // 1063 // For Pci Hotplug controller devcie only 1064 // 1065 if (gPciHotPlugInit != NULL) { 1066 // 1067 // Check if it is a Hotplug PCI controller 1068 // 1069 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) { 1070 gPciRootHpcData[HpIndex].Found = TRUE; 1071 1072 if (!gPciRootHpcData[HpIndex].Initialized) { 1073 1074 Status = CreateEventForHpc (HpIndex, &Event); 1075 1076 ASSERT (!EFI_ERROR (Status)); 1077 1078 Status = gPciHotPlugInit->InitializeRootHpc ( 1079 gPciHotPlugInit, 1080 gPciRootHpcPool[HpIndex].HpcDevicePath, 1081 PciAddress, 1082 Event, 1083 &State 1084 ); 1085 1086 PreprocessController ( 1087 PciDevice, 1088 PciDevice->BusNumber, 1089 PciDevice->DeviceNumber, 1090 PciDevice->FunctionNumber, 1091 EfiPciBeforeChildBusEnumeration 1092 ); 1093 } 1094 } 1095 } 1096 } 1097 1098 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) { 1099 // 1100 // For PPB 1101 // 1102 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { 1103 // 1104 // If Hot Plug is not supported, 1105 // get the bridge information 1106 // 1107 Status = PciSearchDevice ( 1108 Bridge, 1109 &Pci, 1110 StartBusNumber, 1111 Device, 1112 Func, 1113 &PciDevice 1114 ); 1115 1116 if (EFI_ERROR (Status)) { 1117 return Status; 1118 } 1119 } else { 1120 // 1121 // If Hot Plug is supported, 1122 // Get the bridge information 1123 // 1124 BusPadding = FALSE; 1125 if (gPciHotPlugInit != NULL) { 1126 1127 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) { 1128 1129 // 1130 // If it is initialized, get the padded bus range 1131 // 1132 Status = gPciHotPlugInit->GetResourcePadding ( 1133 gPciHotPlugInit, 1134 gPciRootHpcPool[HpIndex].HpbDevicePath, 1135 PciAddress, 1136 &State, 1137 (VOID **) &Descriptors, 1138 &Attributes 1139 ); 1140 1141 if (EFI_ERROR (Status)) { 1142 return Status; 1143 } 1144 1145 BusRange = 0; 1146 Status = PciGetBusRange ( 1147 &Descriptors, 1148 NULL, 1149 NULL, 1150 &BusRange 1151 ); 1152 1153 FreePool (Descriptors); 1154 1155 if (EFI_ERROR (Status)) { 1156 return Status; 1157 } 1158 1159 BusPadding = TRUE; 1160 } 1161 } 1162 } 1163 1164 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber); 1165 if (EFI_ERROR (Status)) { 1166 return Status; 1167 } 1168 SecondBus = *SubBusNumber; 1169 1170 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber); 1171 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET); 1172 1173 Status = PciRootBridgeIo->Pci.Write ( 1174 PciRootBridgeIo, 1175 EfiPciWidthUint16, 1176 Address, 1177 1, 1178 &Register 1179 ); 1180 1181 1182 // 1183 // If it is PPB, resursively search down this bridge 1184 // 1185 if (IS_PCI_BRIDGE (&Pci)) { 1186 1187 // 1188 // Temporarily initialize SubBusNumber to maximum bus number to ensure the 1189 // PCI configuration transaction to go through any PPB 1190 // 1191 Register = 0xFF; 1192 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); 1193 Status = PciRootBridgeIo->Pci.Write ( 1194 PciRootBridgeIo, 1195 EfiPciWidthUint8, 1196 Address, 1197 1, 1198 &Register 1199 ); 1200 1201 // 1202 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige 1203 // 1204 PreprocessController ( 1205 PciDevice, 1206 PciDevice->BusNumber, 1207 PciDevice->DeviceNumber, 1208 PciDevice->FunctionNumber, 1209 EfiPciBeforeChildBusEnumeration 1210 ); 1211 1212 Status = PciScanBus ( 1213 PciDevice, 1214 SecondBus, 1215 SubBusNumber, 1216 PaddedBusRange 1217 ); 1218 if (EFI_ERROR (Status)) { 1219 return Status; 1220 } 1221 } 1222 1223 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) { 1224 // 1225 // Ensure the device is enabled and initialized 1226 // 1227 if ((Attributes == EfiPaddingPciRootBridge) && 1228 (State & EFI_HPC_STATE_ENABLED) != 0 && 1229 (State & EFI_HPC_STATE_INITIALIZED) != 0) { 1230 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) + *PaddedBusRange); 1231 } else { 1232 // 1233 // Reserve the larger one between the actual occupied bus number and padded bus number 1234 // 1235 Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8) (BusRange), &PaddedSubBus); 1236 if (EFI_ERROR (Status)) { 1237 return Status; 1238 } 1239 *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber); 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**/ 1301EFI_STATUS 1302PciRootBridgeP2CProcess ( 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**/ 1374EFI_STATUS 1375PciHostBridgeP2CProcess ( 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**/ 1421EFI_STATUS 1422PciHostBridgeEnumerator ( 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 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation); 1447 1448 if (EFI_ERROR (Status)) { 1449 return Status; 1450 } 1451 1452 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n")); 1453 RootBridgeHandle = NULL; 1454 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { 1455 1456 // 1457 // if a root bridge instance is found, create root bridge device for it 1458 // 1459 1460 RootBridgeDev = CreateRootBridge (RootBridgeHandle); 1461 1462 if (RootBridgeDev == NULL) { 1463 return EFI_OUT_OF_RESOURCES; 1464 } 1465 1466 // 1467 // Enumerate all the buses under this root bridge 1468 // 1469 Status = PciRootBridgeEnumerator ( 1470 PciResAlloc, 1471 RootBridgeDev 1472 ); 1473 1474 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { 1475 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link)); 1476 } else { 1477 DestroyRootBridge (RootBridgeDev); 1478 } 1479 if (EFI_ERROR (Status)) { 1480 return Status; 1481 } 1482 } 1483 1484 // 1485 // Notify the bus allocation phase is finished for the first time 1486 // 1487 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation); 1488 1489 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { 1490 // 1491 // Reset all assigned PCI bus number in all PPB 1492 // 1493 RootBridgeHandle = NULL; 1494 Link = GetFirstNode (&RootBridgeList); 1495 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) && 1496 (!IsNull (&RootBridgeList, Link))) { 1497 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link); 1498 // 1499 // Get the Bus information 1500 // 1501 Status = PciResAlloc->StartBusEnumeration ( 1502 PciResAlloc, 1503 RootBridgeHandle, 1504 (VOID **) &Configuration 1505 ); 1506 if (EFI_ERROR (Status)) { 1507 return Status; 1508 } 1509 1510 // 1511 // Get the bus number to start with 1512 // 1513 StartBusNumber = (UINT8) (Configuration->AddrRangeMin); 1514 1515 ResetAllPpbBusNumber ( 1516 RootBridgeDev, 1517 StartBusNumber 1518 ); 1519 1520 FreePool (Configuration); 1521 Link = RemoveEntryList (Link); 1522 DestroyRootBridge (RootBridgeDev); 1523 } 1524 1525 // 1526 // Wait for all HPC initialized 1527 // 1528 Status = AllRootHPCInitialized (STALL_1_SECOND * 15); 1529 1530 if (EFI_ERROR (Status)) { 1531 DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n")); 1532 return Status; 1533 } 1534 1535 // 1536 // Notify the bus allocation phase is about to start for the 2nd time 1537 // 1538 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation); 1539 1540 if (EFI_ERROR (Status)) { 1541 return Status; 1542 } 1543 1544 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n")); 1545 RootBridgeHandle = NULL; 1546 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { 1547 1548 // 1549 // if a root bridge instance is found, create root bridge device for it 1550 // 1551 RootBridgeDev = CreateRootBridge (RootBridgeHandle); 1552 1553 if (RootBridgeDev == NULL) { 1554 return EFI_OUT_OF_RESOURCES; 1555 } 1556 1557 // 1558 // Enumerate all the buses under this root bridge 1559 // 1560 Status = PciRootBridgeEnumerator ( 1561 PciResAlloc, 1562 RootBridgeDev 1563 ); 1564 1565 DestroyRootBridge (RootBridgeDev); 1566 if (EFI_ERROR (Status)) { 1567 return Status; 1568 } 1569 } 1570 1571 // 1572 // Notify the bus allocation phase is to end for the 2nd time 1573 // 1574 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation); 1575 } 1576 1577 // 1578 // Notify the resource allocation phase is to start 1579 // 1580 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation); 1581 1582 if (EFI_ERROR (Status)) { 1583 return Status; 1584 } 1585 1586 RootBridgeHandle = NULL; 1587 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { 1588 1589 // 1590 // if a root bridge instance is found, create root bridge device for it 1591 // 1592 RootBridgeDev = CreateRootBridge (RootBridgeHandle); 1593 1594 if (RootBridgeDev == NULL) { 1595 return EFI_OUT_OF_RESOURCES; 1596 } 1597 1598 Status = StartManagingRootBridge (RootBridgeDev); 1599 1600 if (EFI_ERROR (Status)) { 1601 return Status; 1602 } 1603 1604 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo; 1605 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); 1606 1607 if (EFI_ERROR (Status)) { 1608 return Status; 1609 } 1610 1611 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL); 1612 1613 if (EFI_ERROR (Status)) { 1614 return Status; 1615 } 1616 1617 // 1618 // Determine root bridge attribute by calling interface of Pcihostbridge 1619 // protocol 1620 // 1621 DetermineRootBridgeAttributes ( 1622 PciResAlloc, 1623 RootBridgeDev 1624 ); 1625 1626 // 1627 // Collect all the resource information under this root bridge 1628 // A database that records all the information about pci device subject to this 1629 // root bridge will then be created 1630 // 1631 Status = PciPciDeviceInfoCollector ( 1632 RootBridgeDev, 1633 (UINT8) MinBus 1634 ); 1635 1636 if (EFI_ERROR (Status)) { 1637 return Status; 1638 } 1639 1640 InsertRootBridge (RootBridgeDev); 1641 1642 // 1643 // Record the hostbridge handle 1644 // 1645 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle); 1646 } 1647 1648 return EFI_SUCCESS; 1649} 1650