1 /** 2 * Copyright (c) 2014, AppliedMicro Corp. All rights reserved. 3 * Copyright (c) 2016, Hisilicon Limited. All rights reserved. 4 * Copyright (c) 2016, Linaro Limited. All rights reserved. 5 * 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 <Uefi.h> 17 #include <Protocol/EmbeddedGpio.h> 18 #include <Guid/EventGroup.h> 19 #include <Library/UefiBootServicesTableLib.h> 20 #include <Library/UefiRuntimeServicesTableLib.h> 21 #include <Library/OemMiscLib.h> 22 23 #include "PciHostBridge.h" 24 25 UINTN RootBridgeNumber[PCIE_MAX_HOSTBRIDGE] = { PCIE_MAX_ROOTBRIDGE,PCIE_MAX_ROOTBRIDGE }; 26 27 UINT64 RootBridgeAttribute[PCIE_MAX_HOSTBRIDGE][PCIE_MAX_ROOTBRIDGE] = { 28 { //Host Bridge0 29 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 30 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 31 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 32 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 33 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 34 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 35 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 36 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 37 }, 38 { //Host Bridge1 39 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 40 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 41 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 42 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 43 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 44 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 45 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 46 EFI_PCI_HOST_BRIDGE_MEM64_DECODE, 47 } 48 }; 49 50 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[PCIE_MAX_HOSTBRIDGE][PCIE_MAX_ROOTBRIDGE] = { 51 { //Host Bridge0 52 /* Port 0 */ 53 { 54 { 55 { 56 ACPI_DEVICE_PATH, 57 ACPI_DP, 58 { 59 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 60 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 61 } 62 }, 63 EISA_PNP_ID(0x0A03), 64 0 65 }, 66 67 { 68 END_DEVICE_PATH_TYPE, 69 END_ENTIRE_DEVICE_PATH_SUBTYPE, 70 { 71 END_DEVICE_PATH_LENGTH, 72 0 73 } 74 } 75 }, 76 /* Port 1 */ 77 { 78 { 79 { 80 ACPI_DEVICE_PATH, 81 ACPI_DP, 82 { 83 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 84 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 85 } 86 }, 87 EISA_PNP_ID(0x0A04), 88 0 89 }, 90 91 { 92 END_DEVICE_PATH_TYPE, 93 END_ENTIRE_DEVICE_PATH_SUBTYPE, 94 { 95 END_DEVICE_PATH_LENGTH, 96 0 97 } 98 } 99 }, 100 /* Port 2 */ 101 { 102 { 103 { 104 ACPI_DEVICE_PATH, 105 ACPI_DP, 106 { 107 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 108 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 109 } 110 }, 111 EISA_PNP_ID(0x0A05), 112 0 113 }, 114 115 { 116 END_DEVICE_PATH_TYPE, 117 END_ENTIRE_DEVICE_PATH_SUBTYPE, 118 { 119 END_DEVICE_PATH_LENGTH, 120 0 121 } 122 } 123 }, 124 /* Port 3 */ 125 { 126 { 127 { 128 ACPI_DEVICE_PATH, 129 ACPI_DP, 130 { 131 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 132 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 133 } 134 }, 135 EISA_PNP_ID(0x0A06), 136 0 137 }, 138 139 { 140 END_DEVICE_PATH_TYPE, 141 END_ENTIRE_DEVICE_PATH_SUBTYPE, 142 { 143 END_DEVICE_PATH_LENGTH, 144 0 145 } 146 } 147 }, 148 /* Port 4 */ 149 { 150 { 151 { 152 ACPI_DEVICE_PATH, 153 ACPI_DP, 154 { 155 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 156 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 157 } 158 }, 159 EISA_PNP_ID(0x0A07), 160 0 161 }, 162 163 { 164 END_DEVICE_PATH_TYPE, 165 END_ENTIRE_DEVICE_PATH_SUBTYPE, 166 { 167 END_DEVICE_PATH_LENGTH, 168 0 169 } 170 } 171 }, 172 /* Port 5 */ 173 { 174 { 175 { 176 ACPI_DEVICE_PATH, 177 ACPI_DP, 178 { 179 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 180 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 181 } 182 }, 183 EISA_PNP_ID(0x0A08), 184 0 185 }, 186 187 { 188 END_DEVICE_PATH_TYPE, 189 END_ENTIRE_DEVICE_PATH_SUBTYPE, 190 { 191 END_DEVICE_PATH_LENGTH, 192 0 193 } 194 } 195 }, 196 /* Port 6 */ 197 { 198 { 199 { 200 ACPI_DEVICE_PATH, 201 ACPI_DP, 202 { 203 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 204 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 205 } 206 }, 207 EISA_PNP_ID(0x0A09), 208 0 209 }, 210 211 { 212 END_DEVICE_PATH_TYPE, 213 END_ENTIRE_DEVICE_PATH_SUBTYPE, 214 { 215 END_DEVICE_PATH_LENGTH, 216 0 217 } 218 } 219 }, 220 /* Port 7 */ 221 { 222 { 223 { 224 ACPI_DEVICE_PATH, 225 ACPI_DP, 226 { 227 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 228 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 229 } 230 }, 231 EISA_PNP_ID(0x0A0A), 232 0 233 }, 234 235 { 236 END_DEVICE_PATH_TYPE, 237 END_ENTIRE_DEVICE_PATH_SUBTYPE, 238 { 239 END_DEVICE_PATH_LENGTH, 240 0 241 } 242 } 243 } 244 }, 245 { // Host Bridge1 246 /* Port 0 */ 247 { 248 { 249 { 250 ACPI_DEVICE_PATH, 251 ACPI_DP, 252 { 253 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 254 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 255 } 256 }, 257 EISA_PNP_ID(0x0A0B), 258 0 259 }, 260 261 { 262 END_DEVICE_PATH_TYPE, 263 END_ENTIRE_DEVICE_PATH_SUBTYPE, 264 { 265 END_DEVICE_PATH_LENGTH, 266 0 267 } 268 } 269 }, 270 /* Port 1 */ 271 { 272 { 273 { 274 ACPI_DEVICE_PATH, 275 ACPI_DP, 276 { 277 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 278 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 279 } 280 }, 281 EISA_PNP_ID(0x0A0C), 282 0 283 }, 284 285 { 286 END_DEVICE_PATH_TYPE, 287 END_ENTIRE_DEVICE_PATH_SUBTYPE, 288 { 289 END_DEVICE_PATH_LENGTH, 290 0 291 } 292 } 293 }, 294 /* Port 2 */ 295 { 296 { 297 { 298 ACPI_DEVICE_PATH, 299 ACPI_DP, 300 { 301 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 302 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 303 } 304 }, 305 EISA_PNP_ID(0x0A0D), 306 0 307 }, 308 309 { 310 END_DEVICE_PATH_TYPE, 311 END_ENTIRE_DEVICE_PATH_SUBTYPE, 312 { 313 END_DEVICE_PATH_LENGTH, 314 0 315 } 316 } 317 }, 318 /* Port 3 */ 319 { 320 { 321 { 322 ACPI_DEVICE_PATH, 323 ACPI_DP, 324 { 325 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 326 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 327 } 328 }, 329 EISA_PNP_ID(0x0A0E), 330 0 331 }, 332 333 { 334 END_DEVICE_PATH_TYPE, 335 END_ENTIRE_DEVICE_PATH_SUBTYPE, 336 { 337 END_DEVICE_PATH_LENGTH, 338 0 339 } 340 } 341 }, 342 /* Port 4 */ 343 { 344 { 345 { 346 ACPI_DEVICE_PATH, 347 ACPI_DP, 348 { 349 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 350 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 351 } 352 }, 353 EISA_PNP_ID(0x0A0F), 354 0 355 }, 356 357 { 358 END_DEVICE_PATH_TYPE, 359 END_ENTIRE_DEVICE_PATH_SUBTYPE, 360 { 361 END_DEVICE_PATH_LENGTH, 362 0 363 } 364 } 365 }, 366 /* Port 5 */ 367 { 368 { 369 { 370 ACPI_DEVICE_PATH, 371 ACPI_DP, 372 { 373 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 374 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 375 } 376 }, 377 EISA_PNP_ID(0x0A10), 378 0 379 }, 380 381 { 382 END_DEVICE_PATH_TYPE, 383 END_ENTIRE_DEVICE_PATH_SUBTYPE, 384 { 385 END_DEVICE_PATH_LENGTH, 386 0 387 } 388 } 389 }, 390 /* Port 6 */ 391 { 392 { 393 { 394 ACPI_DEVICE_PATH, 395 ACPI_DP, 396 { 397 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 398 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 399 } 400 }, 401 EISA_PNP_ID(0x0A11), 402 0 403 }, 404 405 { 406 END_DEVICE_PATH_TYPE, 407 END_ENTIRE_DEVICE_PATH_SUBTYPE, 408 { 409 END_DEVICE_PATH_LENGTH, 410 0 411 } 412 } 413 }, 414 /* Port 7 */ 415 { 416 { 417 { 418 ACPI_DEVICE_PATH, 419 ACPI_DP, 420 { 421 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), 422 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) 423 } 424 }, 425 EISA_PNP_ID(0x0A12), 426 0 427 }, 428 429 { 430 END_DEVICE_PATH_TYPE, 431 END_ENTIRE_DEVICE_PATH_SUBTYPE, 432 { 433 END_DEVICE_PATH_LENGTH, 434 0 435 } 436 } 437 } 438 } 439 }; 440 441 EFI_HANDLE mDriverImageHandle; 442 443 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = { 444 PCI_HOST_BRIDGE_SIGNATURE, // Signature 445 NULL, // HostBridgeHandle 446 0, // RootBridgeNumber 447 {NULL, NULL}, // Head 448 FALSE, // ResourceSubiteed 449 TRUE, // CanRestarted 450 { 451 NotifyPhase, 452 GetNextRootBridge, 453 GetAttributes, 454 StartBusEnumeration, 455 SetBusNumbers, 456 SubmitResources, 457 GetProposedResources, 458 PreprocessController 459 } 460 }; 461 462 /** 463 Entry point of this driver 464 465 @param ImageHandle Handle of driver image 466 @param SystemTable Point to EFI_SYSTEM_TABLE 467 468 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource 469 @retval EFI_DEVICE_ERROR Can not install the protocol instance 470 @retval EFI_SUCCESS Success to initialize the Pci host bridge. 471 **/ 472 EFI_STATUS 473 EFIAPI 474 InitializePciHostBridge ( 475 IN EFI_HANDLE ImageHandle, 476 IN EFI_SYSTEM_TABLE *SystemTable 477 ) 478 { 479 EFI_STATUS Status; 480 UINTN Loop1; 481 UINTN Loop2; 482 PCI_HOST_BRIDGE_INSTANCE *HostBridge = NULL; 483 PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 484 UINT32 PcieRootBridgeMask; 485 486 if (!OemIsMpBoot()) 487 { 488 PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask); 489 } 490 else 491 { 492 PcieRootBridgeMask = PcdGet32(PcdPcieRootBridgeMask2P); 493 } 494 495 mDriverImageHandle = ImageHandle; 496 // 497 // Create Host Bridge Device Handle 498 // 499 //Each Host Bridge have 8 Root Bridges max, every bits of 0xFF(8 bit) stands for the according PCIe Port 500 //is enable or not 501 for (Loop1 = 0; Loop1 < PCIE_MAX_HOSTBRIDGE; Loop1++) { 502 if (((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) & 0xFF ) == 0) { 503 continue; 504 } 505 506 507 HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate); 508 if (HostBridge == NULL) { 509 return EFI_OUT_OF_RESOURCES; 510 } 511 512 HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1]; 513 InitializeListHead (&HostBridge->Head); 514 515 Status = gBS->InstallMultipleProtocolInterfaces ( 516 &HostBridge->HostBridgeHandle, 517 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc, 518 NULL 519 ); 520 if (EFI_ERROR (Status)) { 521 FreePool (HostBridge); 522 return EFI_DEVICE_ERROR; 523 } 524 525 // 526 // Create Root Bridge Device Handle in this Host Bridge 527 // 528 for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) { 529 if (!(((PcieRootBridgeMask >> (PCIE_MAX_ROOTBRIDGE * Loop1)) >> Loop2 ) & 0x01)) { 530 continue; 531 } 532 533 PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE)); 534 if (PrivateData == NULL) { 535 FreePool (HostBridge); 536 return EFI_OUT_OF_RESOURCES; 537 } 538 PrivateData->Port = Loop2; 539 PrivateData->SocType = PcdGet32(Pcdsoctype); 540 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE; 541 PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2]; 542 543 (VOID)RootBridgeConstructor ( 544 &PrivateData->Io, 545 HostBridge->HostBridgeHandle, 546 RootBridgeAttribute[Loop1][Loop2], 547 &mResAppeture[Loop1][Loop2], 548 Loop1 549 ); 550 551 Status = gBS->InstallMultipleProtocolInterfaces( 552 &PrivateData->Handle, 553 &gEfiDevicePathProtocolGuid, PrivateData->DevicePath, 554 &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io, 555 NULL 556 ); 557 if (EFI_ERROR (Status)) { 558 (VOID)gBS->UninstallMultipleProtocolInterfaces ( 559 HostBridge->HostBridgeHandle, 560 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc, 561 NULL 562 ); 563 FreePool(PrivateData); 564 FreePool (HostBridge); 565 return EFI_DEVICE_ERROR; 566 } 567 // PCI Memory Space 568 Status = gDS->AddMemorySpace ( 569 EfiGcdMemoryTypeMemoryMappedIo, 570 mResAppeture[Loop1][Loop2] .MemBase, 571 mResAppeture[Loop1][Loop2] .MemLimit -mResAppeture[Loop1][Loop2] .MemBase + 1, 572 0 573 ); 574 if (EFI_ERROR (Status)) { 575 DEBUG((EFI_D_ERROR,"PCIE AddMemorySpace Error\n")); 576 } 577 InsertTailList (&HostBridge->Head, &PrivateData->Link); 578 } 579 } 580 581 return EFI_SUCCESS; 582 } 583 584 EFI_STATUS 585 EFIAPI 586 NotifyAllocateMemResources( 587 IN PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance, 588 IN PCI_RESOURCE_TYPE Index, 589 IN OUT UINT64 *AllocatedLenMem 590 ) 591 { 592 EFI_PHYSICAL_ADDRESS BaseAddress; 593 EFI_STATUS ReturnStatus; 594 UINT64 AddrLen; 595 UINTN BitsOfAlignment; 596 597 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 598 PCIE_DEBUG("Addrlen:%llx\n", AddrLen); 599 // Get the number of '1' in Alignment. 600 BitsOfAlignment = (UINTN) (HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1); 601 602 BaseAddress = (RootBridgeInstance->MemBase + *AllocatedLenMem + 603 RootBridgeInstance->ResAllocNode[Index].Alignment) 604 & ~(RootBridgeInstance->ResAllocNode[Index].Alignment); 605 if ((BaseAddress + AddrLen - 1) > RootBridgeInstance->MemLimit) { 606 ReturnStatus = EFI_OUT_OF_RESOURCES; 607 RootBridgeInstance->ResAllocNode[Index].Length = 0; 608 return ReturnStatus; 609 } 610 611 PCIE_DEBUG("(P)Mem32/64 request memory at:%llx\n", BaseAddress); 612 ReturnStatus = gDS->AllocateMemorySpace ( 613 EfiGcdAllocateAddress, 614 EfiGcdMemoryTypeMemoryMappedIo, 615 BitsOfAlignment, 616 AddrLen, 617 &BaseAddress, 618 mDriverImageHandle, 619 NULL 620 ); 621 622 if (!EFI_ERROR (ReturnStatus)) { 623 // We were able to allocate the PCI memory 624 RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress; 625 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; 626 *AllocatedLenMem += AddrLen; 627 PCIE_DEBUG("(P)Mem32/64 resource allocated:%llx\n", BaseAddress); 628 629 } else { 630 // Not able to allocate enough PCI memory 631 if (ReturnStatus != EFI_OUT_OF_RESOURCES) { 632 RootBridgeInstance->ResAllocNode[Index].Length = 0; 633 } 634 } 635 return ReturnStatus; 636 } 637 638 EFI_STATUS 639 EFIAPI 640 NotifyAllocateResources( 641 IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance 642 ) 643 { 644 EFI_STATUS ReturnStatus; 645 LIST_ENTRY *List; 646 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 647 PCI_RESOURCE_TYPE Index; 648 649 ReturnStatus = EFI_SUCCESS; 650 List = HostBridgeInstance->Head.ForwardLink; 651 652 while (List != &HostBridgeInstance->Head) { 653 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 654 655 UINT64 AllocatedLenMem = 0; 656 for (Index = TypeIo; Index < TypeBus; Index++) { 657 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { 658 if(Index == TypeIo) { 659 PCIE_DEBUG("NOT SUPPOER IO RESOURCES ON THIS PLATFORM\n"); 660 } else if ((Index >= TypeMem32) && (Index <= TypePMem64)) { 661 ReturnStatus = NotifyAllocateMemResources(RootBridgeInstance,Index,&AllocatedLenMem); 662 } else { 663 ASSERT (FALSE); 664 } 665 } 666 } 667 668 List = List->ForwardLink; 669 } 670 671 return ReturnStatus; 672 } 673 674 EFI_STATUS 675 EFIAPI 676 NotifyFreeResources( 677 IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance 678 ) 679 { 680 EFI_STATUS ReturnStatus; 681 LIST_ENTRY *List; 682 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 683 PCI_RESOURCE_TYPE Index; 684 UINT64 AddrLen; 685 EFI_PHYSICAL_ADDRESS BaseAddress; 686 687 ReturnStatus = EFI_SUCCESS; 688 List = HostBridgeInstance->Head.ForwardLink; 689 while (List != &HostBridgeInstance->Head) { 690 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 691 for (Index = TypeIo; Index < TypeBus; Index++) { 692 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) { 693 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 694 BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base; 695 696 if(Index <= TypePMem64){ 697 ReturnStatus = gDS->FreeMemorySpace (BaseAddress, AddrLen); 698 }else{ 699 ASSERT (FALSE); 700 } 701 702 RootBridgeInstance->ResAllocNode[Index].Type = Index; 703 RootBridgeInstance->ResAllocNode[Index].Base = 0; 704 RootBridgeInstance->ResAllocNode[Index].Length = 0; 705 RootBridgeInstance->ResAllocNode[Index].Status = ResNone; 706 } 707 } 708 709 List = List->ForwardLink; 710 } 711 712 HostBridgeInstance->ResourceSubmited = FALSE; 713 HostBridgeInstance->CanRestarted = TRUE; 714 return ReturnStatus; 715 716 } 717 718 VOID 719 EFIAPI 720 NotifyBeginEnumeration( 721 IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance 722 ) 723 { 724 LIST_ENTRY *List; 725 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 726 PCI_RESOURCE_TYPE Index; 727 728 // 729 // Reset the Each Root Bridge 730 // 731 List = HostBridgeInstance->Head.ForwardLink; 732 733 while (List != &HostBridgeInstance->Head) { 734 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 735 for (Index = TypeIo; Index < TypeMax; Index++) { 736 RootBridgeInstance->ResAllocNode[Index].Type = Index; 737 RootBridgeInstance->ResAllocNode[Index].Base = 0; 738 RootBridgeInstance->ResAllocNode[Index].Length = 0; 739 RootBridgeInstance->ResAllocNode[Index].Status = ResNone; 740 } 741 742 List = List->ForwardLink; 743 } 744 745 HostBridgeInstance->ResourceSubmited = FALSE; 746 HostBridgeInstance->CanRestarted = TRUE; 747 } 748 749 /** 750 These are the notifications from the PCI bus driver that it is about to enter a certain 751 phase of the PCI enumeration process. 752 753 This member function can be used to notify the host bridge driver to perform specific actions, 754 including any chipset-specific initialization, so that the chipset is ready to enter the next phase. 755 Eight notification points are defined at this time. See belows: 756 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data 757 structures. The PCI enumerator should issue this notification 758 before starting a fresh enumeration process. Enumeration cannot 759 be restarted after sending any other notification such as 760 EfiPciHostBridgeBeginBusAllocation. 761 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is 762 required here. This notification can be used to perform any 763 chipset-specific programming. 764 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No 765 specific action is required here. This notification can be used to 766 perform any chipset-specific programming. 767 EfiPciHostBridgeBeginResourceAllocation 768 The resource allocation phase is about to begin. No specific 769 action is required here. This notification can be used to perform 770 any chipset-specific programming. 771 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI 772 root bridges. These resource settings are returned on the next call to 773 GetProposedResources(). Before calling NotifyPhase() with a Phase of 774 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible 775 for gathering I/O and memory requests for 776 all the PCI root bridges and submitting these requests using 777 SubmitResources(). This function pads the resource amount 778 to suit the root bridge hardware, takes care of dependencies between 779 the PCI root bridges, and calls the Global Coherency Domain (GCD) 780 with the allocation request. In the case of padding, the allocated range 781 could be bigger than what was requested. 782 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated 783 resources (proposed resources) for all the PCI root bridges. After the 784 hardware is programmed, reassigning resources will not be supported. 785 The bus settings are not affected. 786 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI 787 root bridges and resets the I/O and memory apertures to their initial 788 state. The bus settings are not affected. If the request to allocate 789 resources fails, the PCI enumerator can use this notification to 790 deallocate previous resources, adjust the requests, and retry 791 allocation. 792 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is 793 required here. This notification can be used to perform any chipsetspecific 794 programming. 795 796 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL 797 @param[in] Phase The phase during enumeration 798 799 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error 800 is valid for a Phase of EfiPciHostBridgeAllocateResources if 801 SubmitResources() has not been called for one or more 802 PCI root bridges before this call 803 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid 804 for a Phase of EfiPciHostBridgeSetResources. 805 @retval EFI_INVALID_PARAMETER Invalid phase parameter 806 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 807 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the 808 previously submitted resource requests cannot be fulfilled or 809 were only partially fulfilled. 810 @retval EFI_SUCCESS The notification was accepted without any errors. 811 812 **/ 813 EFI_STATUS 814 EFIAPI 815 NotifyPhase( 816 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 817 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase 818 ) 819 { 820 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 821 EFI_STATUS ReturnStatus; 822 823 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 824 ReturnStatus = EFI_SUCCESS; 825 826 switch (Phase) { 827 828 case EfiPciHostBridgeBeginEnumeration: 829 PCIE_DEBUG("Case EfiPciHostBridgeBeginEnumeration\n"); 830 if (HostBridgeInstance->CanRestarted) { 831 NotifyBeginEnumeration(HostBridgeInstance); 832 } else { 833 // 834 // Can not restart 835 // 836 return EFI_NOT_READY; 837 } 838 break; 839 840 case EfiPciHostBridgeEndEnumeration: 841 PCIE_DEBUG("Case EfiPciHostBridgeEndEnumeration\n"); 842 break; 843 844 case EfiPciHostBridgeBeginBusAllocation: 845 PCIE_DEBUG("Case EfiPciHostBridgeBeginBusAllocation\n"); 846 // 847 // No specific action is required here, can perform any chipset specific programing 848 // 849 850 HostBridgeInstance->CanRestarted = FALSE; 851 break; 852 853 case EfiPciHostBridgeEndBusAllocation: 854 PCIE_DEBUG("Case EfiPciHostBridgeEndBusAllocation\n"); 855 // 856 // No specific action is required here, can perform any chipset specific programing 857 // 858 break; 859 860 case EfiPciHostBridgeBeginResourceAllocation: 861 PCIE_DEBUG("Case EfiPciHostBridgeBeginResourceAllocation\n"); 862 // 863 // No specific action is required here, can perform any chipset specific programing 864 // 865 break; 866 867 case EfiPciHostBridgeAllocateResources: 868 PCIE_DEBUG("Case EfiPciHostBridgeAllocateResources\n"); 869 870 if (HostBridgeInstance->ResourceSubmited) { 871 // 872 // Take care of the resource dependencies between the root bridges 873 // 874 ReturnStatus = NotifyAllocateResources(HostBridgeInstance); 875 } else { 876 return EFI_NOT_READY; 877 } 878 //break; 879 880 case EfiPciHostBridgeSetResources: 881 PCIE_DEBUG("Case EfiPciHostBridgeSetResources\n"); 882 break; 883 884 case EfiPciHostBridgeFreeResources: 885 PCIE_DEBUG("Case EfiPciHostBridgeFreeResources\n"); 886 887 ReturnStatus = NotifyFreeResources(HostBridgeInstance); 888 break; 889 890 case EfiPciHostBridgeEndResourceAllocation: 891 PCIE_DEBUG("Case EfiPciHostBridgeEndResourceAllocation\n"); 892 HostBridgeInstance->CanRestarted = FALSE; 893 break; 894 895 default: 896 return EFI_INVALID_PARAMETER; 897 } 898 899 return ReturnStatus; 900 } 901 902 /** 903 Return the device handle of the next PCI root bridge that is associated with this Host Bridge. 904 905 This function is called multiple times to retrieve the device handles of all the PCI root bridges that 906 are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI 907 root bridges. On each call, the handle that was returned by the previous call is passed into the 908 interface, and on output the interface returns the device handle of the next PCI root bridge. The 909 caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL 910 for that root bridge. When there are no more PCI root bridges to report, the interface returns 911 EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they 912 are returned by this function. 913 For D945 implementation, there is only one root bridge in PCI host bridge. 914 915 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL 916 @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge. 917 918 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the 919 specific Host bridge and return EFI_SUCCESS. 920 @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge. 921 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was 922 returned on a previous call to GetNextRootBridge(). 923 **/ 924 EFI_STATUS 925 EFIAPI 926 GetNextRootBridge( 927 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 928 IN OUT EFI_HANDLE *RootBridgeHandle 929 ) 930 { 931 BOOLEAN NoRootBridge; 932 LIST_ENTRY *List; 933 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 934 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 935 936 NoRootBridge = TRUE; 937 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 938 List = HostBridgeInstance->Head.ForwardLink; 939 940 941 while (List != &HostBridgeInstance->Head) { 942 NoRootBridge = FALSE; 943 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 944 if (*RootBridgeHandle == NULL) { 945 // 946 // Return the first Root Bridge Handle of the Host Bridge 947 // 948 *RootBridgeHandle = RootBridgeInstance->Handle; 949 return EFI_SUCCESS; 950 } else { 951 if (*RootBridgeHandle == RootBridgeInstance->Handle) { 952 // 953 // Get next if have 954 // 955 List = List->ForwardLink; 956 if (List!=&HostBridgeInstance->Head) { 957 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 958 *RootBridgeHandle = RootBridgeInstance->Handle; 959 return EFI_SUCCESS; 960 } else { 961 return EFI_NOT_FOUND; 962 } 963 } 964 } 965 966 List = List->ForwardLink; 967 } //end while 968 969 if (NoRootBridge) { 970 return EFI_NOT_FOUND; 971 } else { 972 return EFI_INVALID_PARAMETER; 973 } 974 } 975 976 /** 977 Returns the allocation attributes of a PCI root bridge. 978 979 The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary 980 from one PCI root bridge to another. These attributes are different from the decode-related 981 attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The 982 RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device 983 handles of all the root bridges that are associated with this host bridge must be obtained by calling 984 GetNextRootBridge(). The attributes are static in the sense that they do not change during or 985 after the enumeration process. The hardware may provide mechanisms to change the attributes on 986 the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is 987 installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in 988 "Related Definitions" below. The caller uses these attributes to combine multiple resource requests. 989 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to 990 include requests for the prefetchable memory in the nonprefetchable memory pool and not request any 991 prefetchable memory. 992 Attribute Description 993 ------------------------------------ ---------------------------------------------------------------------- 994 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate 995 windows for nonprefetchable and prefetchable memory. A PCI bus 996 driver needs to include requests for prefetchable memory in the 997 nonprefetchable memory pool. 998 999 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory 1000 windows. If this bit is not set, the PCI bus driver needs to include 1001 requests for a 64-bit memory address in the corresponding 32-bit 1002 memory pool. 1003 1004 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL 1005 @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type 1006 EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. 1007 @param[out] Attributes The pointer to attribte of root bridge, it is output parameter 1008 1009 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL 1010 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid. 1011 @retval EFI_SUCCESS Success to get attribute of interested root bridge. 1012 1013 **/ 1014 EFI_STATUS 1015 EFIAPI 1016 GetAttributes( 1017 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1018 IN EFI_HANDLE RootBridgeHandle, 1019 OUT UINT64 *Attributes 1020 ) 1021 { 1022 LIST_ENTRY *List; 1023 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1024 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1025 1026 if (Attributes == NULL) { 1027 return EFI_INVALID_PARAMETER; 1028 } 1029 1030 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1031 List = HostBridgeInstance->Head.ForwardLink; 1032 1033 while (List != &HostBridgeInstance->Head) { 1034 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1035 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1036 *Attributes = RootBridgeInstance->RootBridgeAttrib; 1037 return EFI_SUCCESS; 1038 } 1039 1040 List = List->ForwardLink; 1041 } 1042 1043 // 1044 // RootBridgeHandle is not an EFI_HANDLE 1045 // that was returned on a previous call to GetNextRootBridge() 1046 // 1047 return EFI_INVALID_PARAMETER; 1048 } 1049 1050 /** 1051 Sets up the specified PCI root bridge for the bus enumeration process. 1052 1053 This member function sets up the root bridge for bus enumeration and returns the PCI bus range 1054 over which the search should be performed in ACPI 2.0 resource descriptor format. 1055 1056 @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance. 1057 @param[in] RootBridgeHandle The PCI Root Bridge to be set up. 1058 @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor. 1059 1060 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle 1061 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag. 1062 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor. 1063 1064 **/ 1065 EFI_STATUS 1066 EFIAPI 1067 StartBusEnumeration( 1068 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1069 IN EFI_HANDLE RootBridgeHandle, 1070 OUT VOID **Configuration 1071 ) 1072 { 1073 LIST_ENTRY *List; 1074 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1075 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1076 VOID *Buffer; 1077 UINT8 *Temp; 1078 UINT64 BusStart; 1079 UINT64 BusEnd; 1080 1081 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1082 List = HostBridgeInstance->Head.ForwardLink; 1083 1084 while (List != &HostBridgeInstance->Head) { 1085 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1086 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1087 // 1088 // Set up the Root Bridge for Bus Enumeration 1089 // 1090 BusStart = RootBridgeInstance->BusBase; 1091 BusEnd = RootBridgeInstance->BusLimit; 1092 // 1093 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR 1094 // 1095 1096 Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)); 1097 if (Buffer == NULL) { 1098 return EFI_OUT_OF_RESOURCES; 1099 } 1100 1101 Temp = (UINT8 *)Buffer; 1102 1103 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A; 1104 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B; 1105 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2; 1106 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0; 1107 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0; 1108 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0; 1109 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart; 1110 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0; 1111 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0; 1112 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1; 1113 1114 Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 1115 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79; 1116 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0; 1117 1118 *Configuration = Buffer; 1119 return EFI_SUCCESS; 1120 } 1121 List = List->ForwardLink; 1122 } 1123 1124 return EFI_INVALID_PARAMETER; 1125 } 1126 1127 /** 1128 Programs the PCI root bridge hardware so that it decodes the specified PCI bus range. 1129 1130 This member function programs the specified PCI root bridge to decode the bus range that is 1131 specified by the input parameter Configuration. 1132 The bus range information is specified in terms of the ACPI 2.0 resource descriptor format. 1133 1134 @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance 1135 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed 1136 @param[in] Configuration The pointer to the PCI bus resource descriptor 1137 1138 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. 1139 @retval EFI_INVALID_PARAMETER Configuration is NULL. 1140 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor. 1141 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor. 1142 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than 1143 bus descriptors. 1144 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors. 1145 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge. 1146 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge. 1147 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. 1148 @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed. 1149 1150 **/ 1151 EFI_STATUS 1152 EFIAPI 1153 SetBusNumbers( 1154 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1155 IN EFI_HANDLE RootBridgeHandle, 1156 IN VOID *Configuration 1157 ) 1158 { 1159 LIST_ENTRY *List; 1160 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1161 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1162 UINT8 *Ptr; 1163 UINTN BusStart; 1164 UINTN BusEnd; 1165 UINTN BusLen; 1166 1167 if (Configuration == NULL) { 1168 return EFI_INVALID_PARAMETER; 1169 } 1170 1171 Ptr = Configuration; 1172 1173 // 1174 // Check the Configuration is valid 1175 // 1176 if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) { 1177 return EFI_INVALID_PARAMETER; 1178 } 1179 1180 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) { 1181 return EFI_INVALID_PARAMETER; 1182 } 1183 1184 Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 1185 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { 1186 return EFI_INVALID_PARAMETER; 1187 } 1188 1189 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1190 List = HostBridgeInstance->Head.ForwardLink; 1191 1192 Ptr = Configuration; 1193 1194 while (List != &HostBridgeInstance->Head) { 1195 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1196 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1197 BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin; 1198 BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen; 1199 BusEnd = BusStart + BusLen - 1; 1200 1201 if (BusStart > BusEnd) { 1202 return EFI_INVALID_PARAMETER; 1203 } 1204 1205 if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) { 1206 return EFI_INVALID_PARAMETER; 1207 } 1208 1209 // 1210 // Update the Bus Range 1211 // 1212 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart; 1213 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen; 1214 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated; 1215 1216 // 1217 // Program the Root Bridge Hardware 1218 // 1219 1220 return EFI_SUCCESS; 1221 } 1222 1223 List = List->ForwardLink; 1224 } 1225 1226 return EFI_INVALID_PARAMETER; 1227 } 1228 1229 VOID 1230 EFIAPI 1231 SubmitGetResourceType( 1232 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr, 1233 OUT UINT64* Index 1234 ) 1235 { 1236 switch (Ptr->ResType) { 1237 case 0: 1238 if (Ptr->AddrSpaceGranularity == 32) { 1239 if (Ptr->SpecificFlag == 0x06) 1240 *Index = TypePMem32; 1241 else 1242 *Index = TypeMem32; 1243 } 1244 1245 if (Ptr->AddrSpaceGranularity == 64) { 1246 if (Ptr->SpecificFlag == 0x06) 1247 *Index = TypePMem64; 1248 else 1249 *Index = TypeMem64; 1250 } 1251 break; 1252 1253 case 1: 1254 *Index = TypeIo; 1255 break; 1256 1257 default: 1258 break; 1259 }; 1260 1261 } 1262 1263 /** 1264 Submits the I/O and memory resource requirements for the specified PCI root bridge. 1265 1266 This function is used to submit all the I/O and memory resources that are required by the specified 1267 PCI root bridge. The input parameter Configuration is used to specify the following: 1268 - The various types of resources that are required 1269 - The associated lengths in terms of ACPI 2.0 resource descriptor format 1270 1271 @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. 1272 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted. 1273 @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor. 1274 1275 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted. 1276 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. 1277 @retval EFI_INVALID_PARAMETER Configuration is NULL. 1278 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor. 1279 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are 1280 not supported by this PCI root bridge. This error will happen if the caller 1281 did not combine resources according to Attributes that were returned by 1282 GetAllocAttributes(). 1283 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid. 1284 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge. 1285 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge. 1286 1287 **/ 1288 EFI_STATUS 1289 EFIAPI 1290 SubmitResources( 1291 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1292 IN EFI_HANDLE RootBridgeHandle, 1293 IN VOID *Configuration 1294 ) 1295 { 1296 LIST_ENTRY *List; 1297 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1298 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1299 UINT8 *Temp; 1300 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; 1301 UINT64 AddrLen; 1302 UINT64 Alignment; 1303 UINTN Index; 1304 1305 PCIE_DEBUG("In SubmitResources\n"); 1306 // 1307 // Check the input parameter: Configuration 1308 // 1309 if (Configuration == NULL) 1310 return EFI_INVALID_PARAMETER; 1311 1312 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1313 List = HostBridgeInstance->Head.ForwardLink; 1314 1315 Temp = (UINT8 *)Configuration; 1316 while ( *Temp == 0x8A) 1317 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; 1318 1319 if (*Temp != 0x79) 1320 return EFI_INVALID_PARAMETER; 1321 1322 Temp = (UINT8 *)Configuration; 1323 while (List != &HostBridgeInstance->Head) { 1324 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1325 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1326 while ( *Temp == 0x8A) { 1327 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ; 1328 PCIE_DEBUG("Ptr->ResType:%d\n", Ptr->ResType); 1329 PCIE_DEBUG("Ptr->Addrlen:%llx\n", Ptr->AddrLen); 1330 PCIE_DEBUG("Ptr->AddrRangeMax:%llx\n", Ptr->AddrRangeMax); 1331 PCIE_DEBUG("Ptr->AddrRangeMin:%llx\n", Ptr->AddrRangeMin); 1332 PCIE_DEBUG("Ptr->SpecificFlag:%llx\n", Ptr->SpecificFlag); 1333 PCIE_DEBUG("Ptr->AddrSpaceGranularity:%d\n", Ptr->AddrSpaceGranularity); 1334 PCIE_DEBUG("RootBridgeInstance->RootBridgeAttrib:%llx\n", RootBridgeInstance->RootBridgeAttrib); 1335 // 1336 // Check address range alignment 1337 // 1338 if (Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) { 1339 return EFI_INVALID_PARAMETER; 1340 } 1341 Index = 0; 1342 SubmitGetResourceType(Ptr,&Index); 1343 AddrLen = (UINTN) Ptr->AddrLen; 1344 Alignment = (UINTN) Ptr->AddrRangeMax; 1345 RootBridgeInstance->ResAllocNode[Index].Length = AddrLen; 1346 RootBridgeInstance->ResAllocNode[Index].Alignment = Alignment; 1347 RootBridgeInstance->ResAllocNode[Index].Status = ResRequested; 1348 HostBridgeInstance->ResourceSubmited = TRUE; 1349 1350 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; 1351 } 1352 1353 return EFI_SUCCESS; 1354 } 1355 1356 List = List->ForwardLink; 1357 } 1358 return EFI_INVALID_PARAMETER; 1359 } 1360 1361 /** 1362 Returns the proposed resource settings for the specified PCI root bridge. 1363 1364 This member function returns the proposed resource settings for the specified PCI root bridge. The 1365 proposed resource settings are prepared when NotifyPhase() is called with a Phase of 1366 EfiPciHostBridgeAllocateResources. The output parameter Configuration 1367 specifies the following: 1368 - The various types of resources, excluding bus resources, that are allocated 1369 - The associated lengths in terms of ACPI 2.0 resource descriptor format 1370 1371 @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. 1372 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. 1373 @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor. 1374 1375 @retval EFI_SUCCESS The requested parameters were returned. 1376 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. 1377 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. 1378 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 1379 1380 **/ 1381 EFI_STATUS 1382 EFIAPI 1383 SetResource( 1384 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance, 1385 VOID *Buffer 1386 1387 ) 1388 { 1389 UINTN Index; 1390 UINT8 *Temp; 1391 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; 1392 UINT64 ResStatus; 1393 1394 Temp = Buffer; 1395 1396 for (Index = 0; Index < TypeBus; Index ++) 1397 { 1398 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { 1399 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ; 1400 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status; 1401 1402 switch (Index) { 1403 1404 case TypeIo: 1405 // 1406 // Io 1407 // 1408 Ptr->Desc = 0x8A; 1409 Ptr->Len = 0x2B; 1410 Ptr->ResType = 1; 1411 Ptr->GenFlag = 0; 1412 Ptr->SpecificFlag = 0; 1413 /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ 1414 Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + 1415 (RootBridgeInstance->MemBase & 0xFFFFFFFF); 1416 Ptr->AddrRangeMax = 0; 1417 Ptr->AddrTranslationOffset = \ 1418 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1419 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1420 break; 1421 1422 case TypeMem32: 1423 // 1424 // Memory 32 1425 // 1426 Ptr->Desc = 0x8A; 1427 Ptr->Len = 0x2B; 1428 Ptr->ResType = 0; 1429 Ptr->GenFlag = 0; 1430 Ptr->SpecificFlag = 0; 1431 Ptr->AddrSpaceGranularity = 32; 1432 /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ 1433 Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + 1434 (RootBridgeInstance->MemBase & 0xFFFFFFFF); 1435 Ptr->AddrRangeMax = 0; 1436 Ptr->AddrTranslationOffset = \ 1437 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1438 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1439 break; 1440 1441 case TypePMem32: 1442 // 1443 // Prefetch memory 32 1444 // 1445 Ptr->Desc = 0x8A; 1446 Ptr->Len = 0x2B; 1447 Ptr->ResType = 0; 1448 Ptr->GenFlag = 0; 1449 Ptr->SpecificFlag = 6; 1450 Ptr->AddrSpaceGranularity = 32; 1451 /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ 1452 Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + 1453 (RootBridgeInstance->MemBase & 0xFFFFFFFF); 1454 Ptr->AddrRangeMax = 0; 1455 Ptr->AddrTranslationOffset = \ 1456 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1457 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1458 break; 1459 1460 case TypeMem64: 1461 // 1462 // Memory 64 1463 // 1464 Ptr->Desc = 0x8A; 1465 Ptr->Len = 0x2B; 1466 Ptr->ResType = 0; 1467 Ptr->GenFlag = 0; 1468 Ptr->SpecificFlag = 0; 1469 Ptr->AddrSpaceGranularity = 64; 1470 /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ 1471 Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + 1472 (RootBridgeInstance->MemBase & 0xFFFFFFFFFFFFFFFF); 1473 Ptr->AddrRangeMax = 0; 1474 Ptr->AddrTranslationOffset = \ 1475 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1476 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1477 break; 1478 1479 case TypePMem64: 1480 // 1481 // Prefetch memory 64 1482 // 1483 Ptr->Desc = 0x8A; 1484 Ptr->Len = 0x2B; 1485 Ptr->ResType = 0; 1486 Ptr->GenFlag = 0; 1487 Ptr->SpecificFlag = 6; 1488 Ptr->AddrSpaceGranularity = 64; 1489 /* This is PCIE Device Bus which start address is the low 32bit of mem base*/ 1490 Ptr->AddrRangeMin = (RootBridgeInstance->ResAllocNode[Index].Base - RootBridgeInstance->MemBase) + 1491 (RootBridgeInstance->MemBase & 0xFFFFFFFFFFFFFFFF); 1492 Ptr->AddrRangeMax = 0; 1493 Ptr->AddrTranslationOffset = \ 1494 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 1495 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; 1496 break; 1497 }; 1498 PCIE_DEBUG("Ptr->ResType:%d\n", Ptr->ResType); 1499 PCIE_DEBUG("Ptr->Addrlen:%llx\n", Ptr->AddrLen); 1500 PCIE_DEBUG("Ptr->AddrRangeMax:%llx\n", Ptr->AddrRangeMax); 1501 PCIE_DEBUG("Ptr->AddrRangeMin:%llx\n", Ptr->AddrRangeMin); 1502 PCIE_DEBUG("Ptr->SpecificFlag:%llx\n", Ptr->SpecificFlag); 1503 PCIE_DEBUG("Ptr->AddrTranslationOffset:%d\n", Ptr->AddrTranslationOffset); 1504 PCIE_DEBUG("Ptr->AddrSpaceGranularity:%d\n", Ptr->AddrSpaceGranularity); 1505 1506 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 1507 } 1508 } 1509 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79; 1510 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0; 1511 1512 return EFI_SUCCESS; 1513 } 1514 /** 1515 Returns the proposed resource settings for the specified PCI root bridge. 1516 1517 This member function returns the proposed resource settings for the specified PCI root bridge. The 1518 proposed resource settings are prepared when NotifyPhase() is called with a Phase of 1519 EfiPciHostBridgeAllocateResources. The output parameter Configuration 1520 specifies the following: 1521 - The various types of resources, excluding bus resources, that are allocated 1522 - The associated lengths in terms of ACPI 2.0 resource descriptor format 1523 1524 @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. 1525 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. 1526 @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor. 1527 1528 @retval EFI_SUCCESS The requested parameters were returned. 1529 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. 1530 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. 1531 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 1532 1533 **/ 1534 EFI_STATUS 1535 EFIAPI 1536 GetProposedResources( 1537 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1538 IN EFI_HANDLE RootBridgeHandle, 1539 OUT VOID **Configuration 1540 ) 1541 { 1542 LIST_ENTRY *List; 1543 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1544 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1545 UINTN Index; 1546 UINTN Number; 1547 VOID *Buffer; 1548 1549 Buffer = NULL; 1550 Number = 0; 1551 1552 PCIE_DEBUG("In GetProposedResources\n"); 1553 // 1554 // Get the Host Bridge Instance from the resource allocation protocol 1555 // 1556 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1557 List = HostBridgeInstance->Head.ForwardLink; 1558 1559 // 1560 // Enumerate the root bridges in this host bridge 1561 // 1562 while (List != &HostBridgeInstance->Head) { 1563 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1564 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1565 for (Index = 0; Index < TypeBus; Index ++) { 1566 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) { 1567 Number ++; 1568 } 1569 } 1570 1571 Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)); 1572 if (Buffer == NULL) { 1573 return EFI_OUT_OF_RESOURCES; 1574 } 1575 1576 (VOID)SetResource(RootBridgeInstance,Buffer); 1577 1578 *Configuration = Buffer; 1579 1580 return EFI_SUCCESS; 1581 } 1582 1583 List = List->ForwardLink; 1584 } 1585 1586 return EFI_INVALID_PARAMETER; 1587 } 1588 1589 /** 1590 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various 1591 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual 1592 PCI controllers before enumeration. 1593 1594 This function is called during the PCI enumeration process. No specific action is expected from this 1595 member function. It allows the host bridge driver to preinitialize individual PCI controllers before 1596 enumeration. 1597 1598 @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. 1599 @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in 1600 InstallProtocolInterface() in the UEFI 2.0 Specification. 1601 @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the 1602 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI 1603 configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for 1604 the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS. 1605 @param Phase The phase of the PCI device enumeration. 1606 1607 @retval EFI_SUCCESS The requested parameters were returned. 1608 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. 1609 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in 1610 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE. 1611 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should 1612 not enumerate this device, including its child devices if it is a PCI-to-PCI 1613 bridge. 1614 1615 **/ 1616 EFI_STATUS 1617 EFIAPI 1618 PreprocessController ( 1619 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 1620 IN EFI_HANDLE RootBridgeHandle, 1621 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, 1622 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase 1623 ) 1624 { 1625 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 1626 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 1627 LIST_ENTRY *List; 1628 1629 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 1630 List = HostBridgeInstance->Head.ForwardLink; 1631 1632 // 1633 // Enumerate the root bridges in this host bridge 1634 // 1635 while (List != &HostBridgeInstance->Head) { 1636 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); 1637 if (RootBridgeHandle == RootBridgeInstance->Handle) { 1638 break; 1639 } 1640 List = List->ForwardLink; 1641 } 1642 if (List == &HostBridgeInstance->Head) { 1643 return EFI_INVALID_PARAMETER; 1644 } 1645 1646 if ((UINT32)Phase > EfiPciBeforeResourceCollection) { 1647 return EFI_INVALID_PARAMETER; 1648 } 1649 1650 return EFI_SUCCESS; 1651 } 1652