1 /** @file 2 Internal library implementation for PCI Bus module. 3 4 Copyright (c) 2006 - 2015, 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 = 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 **/ 242 UINTN 243 FindResourceNode ( 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 **/ 277 VOID 278 DumpResourceMap ( 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 **/ 361 EFI_STATUS 362 PciHostBridgeResourceAllocator ( 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-stardard 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, contruct 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, sizeof (Resources) / sizeof (Resources[0])); 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 **/ 907 EFI_STATUS 908 PciAllocateBusNumber ( 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 **/ 966 EFI_STATUS 967 PciScanBus ( 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, StartBusNumber, (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 **/ 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 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