1 /** @file 2 PCI emumeration support functions implementation for PCI Bus module. 3 4 Copyright (c) 2006 - 2016, 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 extern CHAR16 *mBarTypeStr[]; 19 20 /** 21 This routine is used to check whether the pci device is present. 22 23 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. 24 @param Pci Output buffer for PCI device configuration space. 25 @param Bus PCI bus NO. 26 @param Device PCI device NO. 27 @param Func PCI Func NO. 28 29 @retval EFI_NOT_FOUND PCI device not present. 30 @retval EFI_SUCCESS PCI device is found. 31 32 **/ 33 EFI_STATUS 34 PciDevicePresent ( 35 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 36 OUT PCI_TYPE00 *Pci, 37 IN UINT8 Bus, 38 IN UINT8 Device, 39 IN UINT8 Func 40 ) 41 { 42 UINT64 Address; 43 EFI_STATUS Status; 44 45 // 46 // Create PCI address map in terms of Bus, Device and Func 47 // 48 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0); 49 50 // 51 // Read the Vendor ID register 52 // 53 Status = PciRootBridgeIo->Pci.Read ( 54 PciRootBridgeIo, 55 EfiPciWidthUint32, 56 Address, 57 1, 58 Pci 59 ); 60 61 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) { 62 // 63 // Read the entire config header for the device 64 // 65 Status = PciRootBridgeIo->Pci.Read ( 66 PciRootBridgeIo, 67 EfiPciWidthUint32, 68 Address, 69 sizeof (PCI_TYPE00) / sizeof (UINT32), 70 Pci 71 ); 72 73 return EFI_SUCCESS; 74 } 75 76 return EFI_NOT_FOUND; 77 } 78 79 /** 80 Collect all the resource information under this root bridge. 81 82 A database that records all the information about pci device subject to this 83 root bridge will then be created. 84 85 @param Bridge Parent bridge instance. 86 @param StartBusNumber Bus number of begining. 87 88 @retval EFI_SUCCESS PCI device is found. 89 @retval other Some error occurred when reading PCI bridge information. 90 91 **/ 92 EFI_STATUS 93 PciPciDeviceInfoCollector ( 94 IN PCI_IO_DEVICE *Bridge, 95 IN UINT8 StartBusNumber 96 ) 97 { 98 EFI_STATUS Status; 99 PCI_TYPE00 Pci; 100 UINT8 Device; 101 UINT8 Func; 102 UINT8 SecBus; 103 PCI_IO_DEVICE *PciIoDevice; 104 EFI_PCI_IO_PROTOCOL *PciIo; 105 106 Status = EFI_SUCCESS; 107 SecBus = 0; 108 109 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { 110 111 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { 112 113 // 114 // Check to see whether PCI device is present 115 // 116 Status = PciDevicePresent ( 117 Bridge->PciRootBridgeIo, 118 &Pci, 119 (UINT8) StartBusNumber, 120 (UINT8) Device, 121 (UINT8) Func 122 ); 123 124 if (EFI_ERROR (Status) && Func == 0) { 125 // 126 // go to next device if there is no Function 0 127 // 128 break; 129 } 130 131 if (!EFI_ERROR (Status)) { 132 133 // 134 // Call back to host bridge function 135 // 136 PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection); 137 138 // 139 // Collect all the information about the PCI device discovered 140 // 141 Status = PciSearchDevice ( 142 Bridge, 143 &Pci, 144 (UINT8) StartBusNumber, 145 Device, 146 Func, 147 &PciIoDevice 148 ); 149 150 // 151 // Recursively scan PCI busses on the other side of PCI-PCI bridges 152 // 153 // 154 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) { 155 156 // 157 // If it is PPB, we need to get the secondary bus to continue the enumeration 158 // 159 PciIo = &(PciIoDevice->PciIo); 160 161 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus); 162 163 if (EFI_ERROR (Status)) { 164 return Status; 165 } 166 167 // 168 // Ensure secondary bus number is greater than the primary bus number to avoid 169 // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE 170 // 171 if (SecBus <= StartBusNumber) { 172 break; 173 } 174 175 // 176 // Get resource padding for PPB 177 // 178 GetResourcePaddingPpb (PciIoDevice); 179 180 // 181 // Deep enumerate the next level bus 182 // 183 Status = PciPciDeviceInfoCollector ( 184 PciIoDevice, 185 (UINT8) (SecBus) 186 ); 187 188 } 189 190 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { 191 192 // 193 // Skip sub functions, this is not a multi function device 194 // 195 Func = PCI_MAX_FUNC; 196 } 197 } 198 199 } 200 } 201 202 return EFI_SUCCESS; 203 } 204 205 /** 206 Seach required device and create PCI device instance. 207 208 @param Bridge Parent bridge instance. 209 @param Pci Input PCI device information block. 210 @param Bus PCI bus NO. 211 @param Device PCI device NO. 212 @param Func PCI func NO. 213 @param PciDevice Output of searched PCI device instance. 214 215 @retval EFI_SUCCESS Successfully created PCI device instance. 216 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information. 217 218 **/ 219 EFI_STATUS 220 PciSearchDevice ( 221 IN PCI_IO_DEVICE *Bridge, 222 IN PCI_TYPE00 *Pci, 223 IN UINT8 Bus, 224 IN UINT8 Device, 225 IN UINT8 Func, 226 OUT PCI_IO_DEVICE **PciDevice 227 ) 228 { 229 PCI_IO_DEVICE *PciIoDevice; 230 231 PciIoDevice = NULL; 232 233 DEBUG (( 234 EFI_D_INFO, 235 "PciBus: Discovered %s @ [%02x|%02x|%02x]\n", 236 IS_PCI_BRIDGE (Pci) ? L"PPB" : 237 IS_CARDBUS_BRIDGE (Pci) ? L"P2C" : 238 L"PCI", 239 Bus, Device, Func 240 )); 241 242 if (!IS_PCI_BRIDGE (Pci)) { 243 244 if (IS_CARDBUS_BRIDGE (Pci)) { 245 PciIoDevice = GatherP2CInfo ( 246 Bridge, 247 Pci, 248 Bus, 249 Device, 250 Func 251 ); 252 if ((PciIoDevice != NULL) && gFullEnumeration) { 253 InitializeP2C (PciIoDevice); 254 } 255 } else { 256 257 // 258 // Create private data for Pci Device 259 // 260 PciIoDevice = GatherDeviceInfo ( 261 Bridge, 262 Pci, 263 Bus, 264 Device, 265 Func 266 ); 267 268 } 269 270 } else { 271 272 // 273 // Create private data for PPB 274 // 275 PciIoDevice = GatherPpbInfo ( 276 Bridge, 277 Pci, 278 Bus, 279 Device, 280 Func 281 ); 282 283 // 284 // Special initialization for PPB including making the PPB quiet 285 // 286 if ((PciIoDevice != NULL) && gFullEnumeration) { 287 InitializePpb (PciIoDevice); 288 } 289 } 290 291 if (PciIoDevice == NULL) { 292 return EFI_OUT_OF_RESOURCES; 293 } 294 295 // 296 // Update the bar information for this PCI device so as to support some specific device 297 // 298 UpdatePciInfo (PciIoDevice); 299 300 if (PciIoDevice->DevicePath == NULL) { 301 return EFI_OUT_OF_RESOURCES; 302 } 303 304 // 305 // Detect this function has option rom 306 // 307 if (gFullEnumeration) { 308 309 if (!IS_CARDBUS_BRIDGE (Pci)) { 310 311 GetOpRomInfo (PciIoDevice); 312 313 } 314 315 ResetPowerManagementFeature (PciIoDevice); 316 317 } 318 319 // 320 // Insert it into a global tree for future reference 321 // 322 InsertPciDevice (Bridge, PciIoDevice); 323 324 // 325 // Determine PCI device attributes 326 // 327 328 if (PciDevice != NULL) { 329 *PciDevice = PciIoDevice; 330 } 331 332 return EFI_SUCCESS; 333 } 334 335 /** 336 Dump the PPB padding resource information. 337 338 @param PciIoDevice PCI IO instance. 339 @param ResourceType The desired resource type to dump. 340 PciBarTypeUnknown means to dump all types of resources. 341 **/ 342 VOID 343 DumpPpbPaddingResource ( 344 IN PCI_IO_DEVICE *PciIoDevice, 345 IN PCI_BAR_TYPE ResourceType 346 ) 347 { 348 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor; 349 PCI_BAR_TYPE Type; 350 351 if (PciIoDevice->ResourcePaddingDescriptors == NULL) { 352 return; 353 } 354 355 if (ResourceType == PciBarTypeIo16 || ResourceType == PciBarTypeIo32) { 356 ResourceType = PciBarTypeIo; 357 } 358 359 for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) { 360 361 Type = PciBarTypeUnknown; 362 if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) { 363 Type = PciBarTypeIo; 364 } else if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { 365 366 if (Descriptor->AddrSpaceGranularity == 32) { 367 // 368 // prefechable 369 // 370 if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) { 371 Type = PciBarTypePMem32; 372 } 373 374 // 375 // Non-prefechable 376 // 377 if (Descriptor->SpecificFlag == 0) { 378 Type = PciBarTypeMem32; 379 } 380 } 381 382 if (Descriptor->AddrSpaceGranularity == 64) { 383 // 384 // prefechable 385 // 386 if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) { 387 Type = PciBarTypePMem64; 388 } 389 390 // 391 // Non-prefechable 392 // 393 if (Descriptor->SpecificFlag == 0) { 394 Type = PciBarTypeMem64; 395 } 396 } 397 } 398 399 if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) { 400 DEBUG (( 401 EFI_D_INFO, 402 " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n", 403 mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen 404 )); 405 } 406 } 407 408 } 409 410 /** 411 Dump the PCI BAR information. 412 413 @param PciIoDevice PCI IO instance. 414 **/ 415 VOID 416 DumpPciBars ( 417 IN PCI_IO_DEVICE *PciIoDevice 418 ) 419 { 420 UINTN Index; 421 422 for (Index = 0; Index < PCI_MAX_BAR; Index++) { 423 if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) { 424 continue; 425 } 426 427 DEBUG (( 428 EFI_D_INFO, 429 " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n", 430 Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)], 431 PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset 432 )); 433 } 434 435 for (Index = 0; Index < PCI_MAX_BAR; Index++) { 436 if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) { 437 continue; 438 } 439 440 DEBUG (( 441 EFI_D_INFO, 442 " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n", 443 Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)], 444 PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice->VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset 445 )); 446 } 447 DEBUG ((EFI_D_INFO, "\n")); 448 } 449 450 /** 451 Create PCI device instance for PCI device. 452 453 @param Bridge Parent bridge instance. 454 @param Pci Input PCI device information block. 455 @param Bus PCI device Bus NO. 456 @param Device PCI device Device NO. 457 @param Func PCI device's func NO. 458 459 @return Created PCI device instance. 460 461 **/ 462 PCI_IO_DEVICE * 463 GatherDeviceInfo ( 464 IN PCI_IO_DEVICE *Bridge, 465 IN PCI_TYPE00 *Pci, 466 IN UINT8 Bus, 467 IN UINT8 Device, 468 IN UINT8 Func 469 ) 470 { 471 UINTN Offset; 472 UINTN BarIndex; 473 PCI_IO_DEVICE *PciIoDevice; 474 475 PciIoDevice = CreatePciIoDevice ( 476 Bridge, 477 Pci, 478 Bus, 479 Device, 480 Func 481 ); 482 483 if (PciIoDevice == NULL) { 484 return NULL; 485 } 486 487 // 488 // If it is a full enumeration, disconnect the device in advance 489 // 490 if (gFullEnumeration) { 491 492 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); 493 494 } 495 496 // 497 // Start to parse the bars 498 // 499 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) { 500 Offset = PciParseBar (PciIoDevice, Offset, BarIndex); 501 } 502 503 // 504 // Parse the SR-IOV VF bars 505 // 506 if (PcdGetBool (PcdSrIovSupport) && PciIoDevice->SrIovCapabilityOffset != 0) { 507 for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0; 508 Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5; 509 BarIndex++) { 510 511 ASSERT (BarIndex < PCI_MAX_BAR); 512 Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex); 513 } 514 } 515 516 DEBUG_CODE (DumpPciBars (PciIoDevice);); 517 return PciIoDevice; 518 } 519 520 /** 521 Create PCI device instance for PCI-PCI bridge. 522 523 @param Bridge Parent bridge instance. 524 @param Pci Input PCI device information block. 525 @param Bus PCI device Bus NO. 526 @param Device PCI device Device NO. 527 @param Func PCI device's func NO. 528 529 @return Created PCI device instance. 530 531 **/ 532 PCI_IO_DEVICE * 533 GatherPpbInfo ( 534 IN PCI_IO_DEVICE *Bridge, 535 IN PCI_TYPE00 *Pci, 536 IN UINT8 Bus, 537 IN UINT8 Device, 538 IN UINT8 Func 539 ) 540 { 541 PCI_IO_DEVICE *PciIoDevice; 542 EFI_STATUS Status; 543 UINT8 Value; 544 EFI_PCI_IO_PROTOCOL *PciIo; 545 UINT8 Temp; 546 UINT32 PMemBaseLimit; 547 UINT16 PrefetchableMemoryBase; 548 UINT16 PrefetchableMemoryLimit; 549 550 PciIoDevice = CreatePciIoDevice ( 551 Bridge, 552 Pci, 553 Bus, 554 Device, 555 Func 556 ); 557 558 if (PciIoDevice == NULL) { 559 return NULL; 560 } 561 562 if (gFullEnumeration) { 563 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); 564 565 // 566 // Initalize the bridge control register 567 // 568 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED); 569 570 } 571 572 // 573 // PPB can have two BARs 574 // 575 if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) { 576 // 577 // Not 64-bit bar 578 // 579 PciParseBar (PciIoDevice, 0x14, PPB_BAR_1); 580 } 581 582 PciIo = &PciIoDevice->PciIo; 583 584 // 585 // Test whether it support 32 decode or not 586 // 587 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); 588 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); 589 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); 590 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); 591 592 if (Value != 0) { 593 if ((Value & 0x01) != 0) { 594 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED; 595 } else { 596 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED; 597 } 598 } 599 600 // 601 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes 602 // PCI bridge supporting non-standard I/O window alignment less than 4K. 603 // 604 605 PciIoDevice->BridgeIoAlignment = 0xFFF; 606 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) { 607 // 608 // Check any bits of bit 3-1 of I/O Base Register are writable. 609 // if so, it is assumed non-standard I/O window alignment is supported by this bridge. 610 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed. 611 // 612 Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1)); 613 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); 614 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); 615 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); 616 Value = (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1)); 617 switch (Value) { 618 case BIT3: 619 PciIoDevice->BridgeIoAlignment = 0x7FF; 620 break; 621 case BIT3 | BIT2: 622 PciIoDevice->BridgeIoAlignment = 0x3FF; 623 break; 624 case BIT3 | BIT2 | BIT1: 625 PciIoDevice->BridgeIoAlignment = 0x1FF; 626 break; 627 } 628 } 629 630 Status = BarExisted ( 631 PciIoDevice, 632 0x24, 633 NULL, 634 &PMemBaseLimit 635 ); 636 637 // 638 // Test if it supports 64 memory or not 639 // 640 // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit 641 // registers: 642 // 0 - the bridge supports only 32 bit addresses. 643 // 1 - the bridge supports 64-bit addresses. 644 // 645 PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff); 646 PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16); 647 if (!EFI_ERROR (Status) && 648 (PrefetchableMemoryBase & 0x000f) == 0x0001 && 649 (PrefetchableMemoryLimit & 0x000f) == 0x0001) { 650 Status = BarExisted ( 651 PciIoDevice, 652 0x28, 653 NULL, 654 NULL 655 ); 656 657 if (!EFI_ERROR (Status)) { 658 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; 659 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED; 660 } else { 661 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; 662 } 663 } 664 665 // 666 // Memory 32 code is required for ppb 667 // 668 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED; 669 670 GetResourcePaddingPpb (PciIoDevice); 671 672 DEBUG_CODE ( 673 DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown); 674 DumpPciBars (PciIoDevice); 675 ); 676 677 return PciIoDevice; 678 } 679 680 681 /** 682 Create PCI device instance for PCI Card bridge device. 683 684 @param Bridge Parent bridge instance. 685 @param Pci Input PCI device information block. 686 @param Bus PCI device Bus NO. 687 @param Device PCI device Device NO. 688 @param Func PCI device's func NO. 689 690 @return Created PCI device instance. 691 692 **/ 693 PCI_IO_DEVICE * 694 GatherP2CInfo ( 695 IN PCI_IO_DEVICE *Bridge, 696 IN PCI_TYPE00 *Pci, 697 IN UINT8 Bus, 698 IN UINT8 Device, 699 IN UINT8 Func 700 ) 701 { 702 PCI_IO_DEVICE *PciIoDevice; 703 704 PciIoDevice = CreatePciIoDevice ( 705 Bridge, 706 Pci, 707 Bus, 708 Device, 709 Func 710 ); 711 712 if (PciIoDevice == NULL) { 713 return NULL; 714 } 715 716 if (gFullEnumeration) { 717 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); 718 719 // 720 // Initalize the bridge control register 721 // 722 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED); 723 } 724 725 // 726 // P2C only has one bar that is in 0x10 727 // 728 PciParseBar (PciIoDevice, 0x10, P2C_BAR_0); 729 730 // 731 // Read PciBar information from the bar register 732 // 733 GetBackPcCardBar (PciIoDevice); 734 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED | 735 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED | 736 EFI_BRIDGE_IO32_DECODE_SUPPORTED; 737 738 DEBUG_CODE (DumpPciBars (PciIoDevice);); 739 740 return PciIoDevice; 741 } 742 743 /** 744 Create device path for pci deivce. 745 746 @param ParentDevicePath Parent bridge's path. 747 @param PciIoDevice Pci device instance. 748 749 @return Device path protocol instance for specific pci device. 750 751 **/ 752 EFI_DEVICE_PATH_PROTOCOL * 753 CreatePciDevicePath ( 754 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, 755 IN PCI_IO_DEVICE *PciIoDevice 756 ) 757 { 758 759 PCI_DEVICE_PATH PciNode; 760 761 // 762 // Create PCI device path 763 // 764 PciNode.Header.Type = HARDWARE_DEVICE_PATH; 765 PciNode.Header.SubType = HW_PCI_DP; 766 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode)); 767 768 PciNode.Device = PciIoDevice->DeviceNumber; 769 PciNode.Function = PciIoDevice->FunctionNumber; 770 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header); 771 772 return PciIoDevice->DevicePath; 773 } 774 775 /** 776 Check whether the PCI IOV VF bar is existed or not. 777 778 @param PciIoDevice A pointer to the PCI_IO_DEVICE. 779 @param Offset The offset. 780 @param BarLengthValue The bar length value returned. 781 @param OriginalBarValue The original bar value returned. 782 783 @retval EFI_NOT_FOUND The bar doesn't exist. 784 @retval EFI_SUCCESS The bar exist. 785 786 **/ 787 EFI_STATUS 788 VfBarExisted ( 789 IN PCI_IO_DEVICE *PciIoDevice, 790 IN UINTN Offset, 791 OUT UINT32 *BarLengthValue, 792 OUT UINT32 *OriginalBarValue 793 ) 794 { 795 EFI_PCI_IO_PROTOCOL *PciIo; 796 UINT32 OriginalValue; 797 UINT32 Value; 798 EFI_TPL OldTpl; 799 800 // 801 // Ensure it is called properly 802 // 803 ASSERT (PciIoDevice->SrIovCapabilityOffset != 0); 804 if (PciIoDevice->SrIovCapabilityOffset == 0) { 805 return EFI_NOT_FOUND; 806 } 807 808 PciIo = &PciIoDevice->PciIo; 809 810 // 811 // Preserve the original value 812 // 813 814 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue); 815 816 // 817 // Raise TPL to high level to disable timer interrupt while the BAR is probed 818 // 819 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); 820 821 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne); 822 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value); 823 824 // 825 // Write back the original value 826 // 827 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue); 828 829 // 830 // Restore TPL to its original level 831 // 832 gBS->RestoreTPL (OldTpl); 833 834 if (BarLengthValue != NULL) { 835 *BarLengthValue = Value; 836 } 837 838 if (OriginalBarValue != NULL) { 839 *OriginalBarValue = OriginalValue; 840 } 841 842 if (Value == 0) { 843 return EFI_NOT_FOUND; 844 } else { 845 return EFI_SUCCESS; 846 } 847 } 848 849 /** 850 Check whether the bar is existed or not. 851 852 @param PciIoDevice A pointer to the PCI_IO_DEVICE. 853 @param Offset The offset. 854 @param BarLengthValue The bar length value returned. 855 @param OriginalBarValue The original bar value returned. 856 857 @retval EFI_NOT_FOUND The bar doesn't exist. 858 @retval EFI_SUCCESS The bar exist. 859 860 **/ 861 EFI_STATUS 862 BarExisted ( 863 IN PCI_IO_DEVICE *PciIoDevice, 864 IN UINTN Offset, 865 OUT UINT32 *BarLengthValue, 866 OUT UINT32 *OriginalBarValue 867 ) 868 { 869 EFI_PCI_IO_PROTOCOL *PciIo; 870 UINT32 OriginalValue; 871 UINT32 Value; 872 EFI_TPL OldTpl; 873 874 PciIo = &PciIoDevice->PciIo; 875 876 // 877 // Preserve the original value 878 // 879 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); 880 881 // 882 // Raise TPL to high level to disable timer interrupt while the BAR is probed 883 // 884 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); 885 886 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne); 887 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value); 888 889 // 890 // Write back the original value 891 // 892 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); 893 894 // 895 // Restore TPL to its original level 896 // 897 gBS->RestoreTPL (OldTpl); 898 899 if (BarLengthValue != NULL) { 900 *BarLengthValue = Value; 901 } 902 903 if (OriginalBarValue != NULL) { 904 *OriginalBarValue = OriginalValue; 905 } 906 907 if (Value == 0) { 908 return EFI_NOT_FOUND; 909 } else { 910 return EFI_SUCCESS; 911 } 912 } 913 914 /** 915 Test whether the device can support given attributes. 916 917 @param PciIoDevice Pci device instance. 918 @param Command Input command register value, and 919 returned supported register value. 920 @param BridgeControl Inout bridge control value for PPB or P2C, and 921 returned supported bridge control value. 922 @param OldCommand Returned and stored old command register offset. 923 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C. 924 925 **/ 926 VOID 927 PciTestSupportedAttribute ( 928 IN PCI_IO_DEVICE *PciIoDevice, 929 IN OUT UINT16 *Command, 930 IN OUT UINT16 *BridgeControl, 931 OUT UINT16 *OldCommand, 932 OUT UINT16 *OldBridgeControl 933 ) 934 { 935 EFI_TPL OldTpl; 936 937 // 938 // Preserve the original value 939 // 940 PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand); 941 942 // 943 // Raise TPL to high level to disable timer interrupt while the BAR is probed 944 // 945 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); 946 947 PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command); 948 PCI_READ_COMMAND_REGISTER (PciIoDevice, Command); 949 950 // 951 // Write back the original value 952 // 953 PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand); 954 955 // 956 // Restore TPL to its original level 957 // 958 gBS->RestoreTPL (OldTpl); 959 960 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { 961 962 // 963 // Preserve the original value 964 // 965 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl); 966 967 // 968 // Raise TPL to high level to disable timer interrupt while the BAR is probed 969 // 970 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); 971 972 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl); 973 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl); 974 975 // 976 // Write back the original value 977 // 978 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl); 979 980 // 981 // Restore TPL to its original level 982 // 983 gBS->RestoreTPL (OldTpl); 984 985 } else { 986 *OldBridgeControl = 0; 987 *BridgeControl = 0; 988 } 989 } 990 991 /** 992 Set the supported or current attributes of a PCI device. 993 994 @param PciIoDevice Structure pointer for PCI device. 995 @param Command Command register value. 996 @param BridgeControl Bridge control value for PPB or P2C. 997 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES. 998 999 **/ 1000 VOID 1001 PciSetDeviceAttribute ( 1002 IN PCI_IO_DEVICE *PciIoDevice, 1003 IN UINT16 Command, 1004 IN UINT16 BridgeControl, 1005 IN UINTN Option 1006 ) 1007 { 1008 UINT64 Attributes; 1009 1010 Attributes = 0; 1011 1012 if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) { 1013 Attributes |= EFI_PCI_IO_ATTRIBUTE_IO; 1014 } 1015 1016 if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) { 1017 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY; 1018 } 1019 1020 if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) { 1021 Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER; 1022 } 1023 1024 if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) { 1025 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; 1026 } 1027 1028 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) { 1029 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO; 1030 } 1031 1032 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) { 1033 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO; 1034 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; 1035 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; 1036 } 1037 1038 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) { 1039 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16; 1040 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16; 1041 } 1042 1043 if (Option == EFI_SET_SUPPORTS) { 1044 1045 Attributes |= (UINT64) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | 1046 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | 1047 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE | 1048 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE | 1049 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM | 1050 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE); 1051 1052 if (IS_PCI_LPC (&PciIoDevice->Pci)) { 1053 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO; 1054 Attributes |= (mReserveIsaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO : \ 1055 (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16); 1056 } 1057 1058 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { 1059 // 1060 // For bridge, it should support IDE attributes 1061 // 1062 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO; 1063 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO; 1064 1065 if (mReserveVgaAliases) { 1066 Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \ 1067 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16); 1068 } else { 1069 Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \ 1070 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO); 1071 } 1072 } else { 1073 1074 if (IS_PCI_IDE (&PciIoDevice->Pci)) { 1075 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO; 1076 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO; 1077 } 1078 1079 if (IS_PCI_VGA (&PciIoDevice->Pci)) { 1080 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; 1081 Attributes |= (mReserveVgaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO : \ 1082 (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16); 1083 } 1084 } 1085 1086 PciIoDevice->Supports = Attributes; 1087 PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \ 1088 EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \ 1089 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER ); 1090 1091 } else { 1092 // 1093 // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were 1094 // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller. 1095 // When this attribute is set, the PCI option ROM described by the RomImage and RomSize 1096 // fields is not from the the ROM BAR of the PCI controller. 1097 // 1098 if (!PciIoDevice->EmbeddedRom) { 1099 Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM; 1100 } 1101 PciIoDevice->Attributes = Attributes; 1102 } 1103 } 1104 1105 /** 1106 Determine if the device can support Fast Back to Back attribute. 1107 1108 @param PciIoDevice Pci device instance. 1109 @param StatusIndex Status register value. 1110 1111 @retval EFI_SUCCESS This device support Fast Back to Back attribute. 1112 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute. 1113 1114 **/ 1115 EFI_STATUS 1116 GetFastBackToBackSupport ( 1117 IN PCI_IO_DEVICE *PciIoDevice, 1118 IN UINT8 StatusIndex 1119 ) 1120 { 1121 EFI_PCI_IO_PROTOCOL *PciIo; 1122 EFI_STATUS Status; 1123 UINT32 StatusRegister; 1124 1125 // 1126 // Read the status register 1127 // 1128 PciIo = &PciIoDevice->PciIo; 1129 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister); 1130 if (EFI_ERROR (Status)) { 1131 return EFI_UNSUPPORTED; 1132 } 1133 1134 // 1135 // Check the Fast B2B bit 1136 // 1137 if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) { 1138 return EFI_SUCCESS; 1139 } else { 1140 return EFI_UNSUPPORTED; 1141 } 1142 } 1143 1144 /** 1145 Process the option ROM for all the children of the specified parent PCI device. 1146 It can only be used after the first full Option ROM process. 1147 1148 @param PciIoDevice Pci device instance. 1149 1150 **/ 1151 VOID 1152 ProcessOptionRomLight ( 1153 IN PCI_IO_DEVICE *PciIoDevice 1154 ) 1155 { 1156 PCI_IO_DEVICE *Temp; 1157 LIST_ENTRY *CurrentLink; 1158 1159 // 1160 // For RootBridge, PPB , P2C, go recursively to traverse all its children 1161 // 1162 CurrentLink = PciIoDevice->ChildList.ForwardLink; 1163 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) { 1164 1165 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 1166 1167 if (!IsListEmpty (&Temp->ChildList)) { 1168 ProcessOptionRomLight (Temp); 1169 } 1170 1171 PciRomGetImageMapping (Temp); 1172 1173 // 1174 // The OpRom has already been processed in the first round 1175 // 1176 Temp->AllOpRomProcessed = TRUE; 1177 1178 CurrentLink = CurrentLink->ForwardLink; 1179 } 1180 } 1181 1182 /** 1183 Determine the related attributes of all devices under a Root Bridge. 1184 1185 @param PciIoDevice PCI device instance. 1186 1187 **/ 1188 EFI_STATUS 1189 DetermineDeviceAttribute ( 1190 IN PCI_IO_DEVICE *PciIoDevice 1191 ) 1192 { 1193 UINT16 Command; 1194 UINT16 BridgeControl; 1195 UINT16 OldCommand; 1196 UINT16 OldBridgeControl; 1197 BOOLEAN FastB2BSupport; 1198 PCI_IO_DEVICE *Temp; 1199 LIST_ENTRY *CurrentLink; 1200 EFI_STATUS Status; 1201 1202 // 1203 // For Root Bridge, just copy it by RootBridgeIo proctocol 1204 // so as to keep consistent with the actual attribute 1205 // 1206 if (PciIoDevice->Parent == NULL) { 1207 Status = PciIoDevice->PciRootBridgeIo->GetAttributes ( 1208 PciIoDevice->PciRootBridgeIo, 1209 &PciIoDevice->Supports, 1210 &PciIoDevice->Attributes 1211 ); 1212 if (EFI_ERROR (Status)) { 1213 return Status; 1214 } 1215 // 1216 // Assume the PCI Root Bridge supports DAC 1217 // 1218 PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE | 1219 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM | 1220 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE); 1221 1222 } else { 1223 1224 // 1225 // Set the attributes to be checked for common PCI devices and PPB or P2C 1226 // Since some devices only support part of them, it is better to set the 1227 // attribute according to its command or bridge control register 1228 // 1229 Command = EFI_PCI_COMMAND_IO_SPACE | 1230 EFI_PCI_COMMAND_MEMORY_SPACE | 1231 EFI_PCI_COMMAND_BUS_MASTER | 1232 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1233 1234 BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16; 1235 1236 // 1237 // Test whether the device can support attributes above 1238 // 1239 PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl); 1240 1241 // 1242 // Set the supported attributes for specified PCI device 1243 // 1244 PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS); 1245 1246 // 1247 // Set the current attributes for specified PCI device 1248 // 1249 PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES); 1250 1251 // 1252 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL 1253 // 1254 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE); 1255 } 1256 1257 FastB2BSupport = TRUE; 1258 1259 // 1260 // P2C can not support FB2B on the secondary side 1261 // 1262 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { 1263 FastB2BSupport = FALSE; 1264 } 1265 1266 // 1267 // For RootBridge, PPB , P2C, go recursively to traverse all its children 1268 // 1269 CurrentLink = PciIoDevice->ChildList.ForwardLink; 1270 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) { 1271 1272 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 1273 Status = DetermineDeviceAttribute (Temp); 1274 if (EFI_ERROR (Status)) { 1275 return Status; 1276 } 1277 // 1278 // Detect Fast Bact to Bact support for the device under the bridge 1279 // 1280 Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET); 1281 if (FastB2BSupport && EFI_ERROR (Status)) { 1282 FastB2BSupport = FALSE; 1283 } 1284 1285 CurrentLink = CurrentLink->ForwardLink; 1286 } 1287 // 1288 // Set or clear Fast Back to Back bit for the whole bridge 1289 // 1290 if (!IsListEmpty (&PciIoDevice->ChildList)) { 1291 1292 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { 1293 1294 Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET); 1295 1296 if (EFI_ERROR (Status) || (!FastB2BSupport)) { 1297 FastB2BSupport = FALSE; 1298 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK); 1299 } else { 1300 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK); 1301 } 1302 } 1303 1304 CurrentLink = PciIoDevice->ChildList.ForwardLink; 1305 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) { 1306 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); 1307 if (FastB2BSupport) { 1308 PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK); 1309 } else { 1310 PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK); 1311 } 1312 1313 CurrentLink = CurrentLink->ForwardLink; 1314 } 1315 } 1316 // 1317 // End for IsListEmpty 1318 // 1319 return EFI_SUCCESS; 1320 } 1321 1322 /** 1323 This routine is used to update the bar information for those incompatible PCI device. 1324 1325 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated 1326 Bar information. 1327 1328 @retval EFI_SUCCESS Successfully updated bar information. 1329 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list. 1330 1331 **/ 1332 EFI_STATUS 1333 UpdatePciInfo ( 1334 IN OUT PCI_IO_DEVICE *PciIoDevice 1335 ) 1336 { 1337 EFI_STATUS Status; 1338 UINTN BarIndex; 1339 UINTN BarEndIndex; 1340 BOOLEAN SetFlag; 1341 VOID *Configuration; 1342 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; 1343 1344 Configuration = NULL; 1345 Status = EFI_SUCCESS; 1346 1347 if (gIncompatiblePciDeviceSupport == NULL) { 1348 // 1349 // It can only be supported after the Incompatible PCI Device 1350 // Support Protocol has been installed 1351 // 1352 Status = gBS->LocateProtocol ( 1353 &gEfiIncompatiblePciDeviceSupportProtocolGuid, 1354 NULL, 1355 (VOID **) &gIncompatiblePciDeviceSupport 1356 ); 1357 } 1358 if (Status == EFI_SUCCESS) { 1359 // 1360 // Check whether the device belongs to incompatible devices from protocol or not 1361 // If it is , then get its special requirement in the ACPI table 1362 // 1363 Status = gIncompatiblePciDeviceSupport->CheckDevice ( 1364 gIncompatiblePciDeviceSupport, 1365 PciIoDevice->Pci.Hdr.VendorId, 1366 PciIoDevice->Pci.Hdr.DeviceId, 1367 PciIoDevice->Pci.Hdr.RevisionID, 1368 PciIoDevice->Pci.Device.SubsystemVendorID, 1369 PciIoDevice->Pci.Device.SubsystemID, 1370 &Configuration 1371 ); 1372 1373 } 1374 1375 if (EFI_ERROR (Status) || Configuration == NULL ) { 1376 return EFI_UNSUPPORTED; 1377 } 1378 1379 // 1380 // Update PCI device information from the ACPI table 1381 // 1382 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; 1383 1384 while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) { 1385 1386 if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) { 1387 // 1388 // The format is not support 1389 // 1390 break; 1391 } 1392 1393 BarIndex = (UINTN) Ptr->AddrTranslationOffset; 1394 BarEndIndex = BarIndex; 1395 1396 // 1397 // Update all the bars in the device 1398 // 1399 if (BarIndex == PCI_BAR_ALL) { 1400 BarIndex = 0; 1401 BarEndIndex = PCI_MAX_BAR - 1; 1402 } 1403 1404 if (BarIndex > PCI_MAX_BAR) { 1405 Ptr++; 1406 continue; 1407 } 1408 1409 for (; BarIndex <= BarEndIndex; BarIndex++) { 1410 SetFlag = FALSE; 1411 switch (Ptr->ResType) { 1412 case ACPI_ADDRESS_SPACE_TYPE_MEM: 1413 1414 // 1415 // Make sure the bar is memory type 1416 // 1417 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) { 1418 SetFlag = TRUE; 1419 1420 // 1421 // Ignored if granularity is 0. 1422 // Ignored if PCI BAR is I/O or 32-bit memory. 1423 // If PCI BAR is 64-bit memory and granularity is 32, then 1424 // the PCI BAR resource is allocated below 4GB. 1425 // If PCI BAR is 64-bit memory and granularity is 64, then 1426 // the PCI BAR resource is allocated above 4GB. 1427 // 1428 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) { 1429 switch (Ptr->AddrSpaceGranularity) { 1430 case 32: 1431 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32; 1432 case 64: 1433 PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE; 1434 break; 1435 default: 1436 break; 1437 } 1438 } 1439 1440 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) { 1441 switch (Ptr->AddrSpaceGranularity) { 1442 case 32: 1443 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32; 1444 case 64: 1445 PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE; 1446 break; 1447 default: 1448 break; 1449 } 1450 } 1451 } 1452 break; 1453 1454 case ACPI_ADDRESS_SPACE_TYPE_IO: 1455 1456 // 1457 // Make sure the bar is IO type 1458 // 1459 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) { 1460 SetFlag = TRUE; 1461 } 1462 break; 1463 } 1464 1465 if (SetFlag) { 1466 1467 // 1468 // Update the new alignment for the device 1469 // 1470 SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax); 1471 1472 // 1473 // Update the new length for the device 1474 // 1475 if (Ptr->AddrLen != PCI_BAR_NOCHANGE) { 1476 PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen; 1477 } 1478 } 1479 } 1480 1481 Ptr++; 1482 } 1483 1484 FreePool (Configuration); 1485 1486 return EFI_SUCCESS; 1487 } 1488 1489 /** 1490 This routine will update the alignment with the new alignment. 1491 1492 @param Alignment Input Old alignment. Output updated alignment. 1493 @param NewAlignment New alignment. 1494 1495 **/ 1496 VOID 1497 SetNewAlign ( 1498 IN OUT UINT64 *Alignment, 1499 IN UINT64 NewAlignment 1500 ) 1501 { 1502 UINT64 OldAlignment; 1503 UINTN ShiftBit; 1504 1505 // 1506 // The new alignment is the same as the original, 1507 // so skip it 1508 // 1509 if (NewAlignment == PCI_BAR_OLD_ALIGN) { 1510 return ; 1511 } 1512 // 1513 // Check the validity of the parameter 1514 // 1515 if (NewAlignment != PCI_BAR_EVEN_ALIGN && 1516 NewAlignment != PCI_BAR_SQUAD_ALIGN && 1517 NewAlignment != PCI_BAR_DQUAD_ALIGN ) { 1518 *Alignment = NewAlignment; 1519 return ; 1520 } 1521 1522 OldAlignment = (*Alignment) + 1; 1523 ShiftBit = 0; 1524 1525 // 1526 // Get the first non-zero hex value of the length 1527 // 1528 while ((OldAlignment & 0x0F) == 0x00) { 1529 OldAlignment = RShiftU64 (OldAlignment, 4); 1530 ShiftBit += 4; 1531 } 1532 1533 // 1534 // Adjust the alignment to even, quad or double quad boundary 1535 // 1536 if (NewAlignment == PCI_BAR_EVEN_ALIGN) { 1537 if ((OldAlignment & 0x01) != 0) { 1538 OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01); 1539 } 1540 } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) { 1541 if ((OldAlignment & 0x03) != 0) { 1542 OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03); 1543 } 1544 } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) { 1545 if ((OldAlignment & 0x07) != 0) { 1546 OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07); 1547 } 1548 } 1549 1550 // 1551 // Update the old value 1552 // 1553 NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1; 1554 *Alignment = NewAlignment; 1555 1556 return ; 1557 } 1558 1559 /** 1560 Parse PCI IOV VF bar information and fill them into PCI device instance. 1561 1562 @param PciIoDevice Pci device instance. 1563 @param Offset Bar offset. 1564 @param BarIndex Bar index. 1565 1566 @return Next bar offset. 1567 1568 **/ 1569 UINTN 1570 PciIovParseVfBar ( 1571 IN PCI_IO_DEVICE *PciIoDevice, 1572 IN UINTN Offset, 1573 IN UINTN BarIndex 1574 ) 1575 { 1576 UINT32 Value; 1577 UINT32 OriginalValue; 1578 UINT32 Mask; 1579 EFI_STATUS Status; 1580 1581 // 1582 // Ensure it is called properly 1583 // 1584 ASSERT (PciIoDevice->SrIovCapabilityOffset != 0); 1585 if (PciIoDevice->SrIovCapabilityOffset == 0) { 1586 return 0; 1587 } 1588 1589 OriginalValue = 0; 1590 Value = 0; 1591 1592 Status = VfBarExisted ( 1593 PciIoDevice, 1594 Offset, 1595 &Value, 1596 &OriginalValue 1597 ); 1598 1599 if (EFI_ERROR (Status)) { 1600 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0; 1601 PciIoDevice->VfPciBar[BarIndex].Length = 0; 1602 PciIoDevice->VfPciBar[BarIndex].Alignment = 0; 1603 1604 // 1605 // Scan all the BARs anyway 1606 // 1607 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset; 1608 return Offset + 4; 1609 } 1610 1611 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset; 1612 if ((Value & 0x01) != 0) { 1613 // 1614 // Device I/Os. Impossible 1615 // 1616 ASSERT (FALSE); 1617 return Offset + 4; 1618 1619 } else { 1620 1621 Mask = 0xfffffff0; 1622 1623 PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask; 1624 1625 switch (Value & 0x07) { 1626 1627 // 1628 //memory space; anywhere in 32 bit address space 1629 // 1630 case 0x00: 1631 if ((Value & 0x08) != 0) { 1632 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32; 1633 } else { 1634 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32; 1635 } 1636 1637 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1; 1638 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1; 1639 1640 // 1641 // Adjust Length 1642 // 1643 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs); 1644 // 1645 // Adjust Alignment 1646 // 1647 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) { 1648 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1; 1649 } 1650 1651 break; 1652 1653 // 1654 // memory space; anywhere in 64 bit address space 1655 // 1656 case 0x04: 1657 if ((Value & 0x08) != 0) { 1658 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64; 1659 } else { 1660 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64; 1661 } 1662 1663 // 1664 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar 1665 // is regarded as an extension for the first bar. As a result 1666 // the sizing will be conducted on combined 64 bit value 1667 // Here just store the masked first 32bit value for future size 1668 // calculation 1669 // 1670 PciIoDevice->VfPciBar[BarIndex].Length = Value & Mask; 1671 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1; 1672 1673 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) { 1674 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1; 1675 } 1676 1677 // 1678 // Increment the offset to point to next DWORD 1679 // 1680 Offset += 4; 1681 1682 Status = VfBarExisted ( 1683 PciIoDevice, 1684 Offset, 1685 &Value, 1686 &OriginalValue 1687 ); 1688 1689 if (EFI_ERROR (Status)) { 1690 return Offset + 4; 1691 } 1692 1693 // 1694 // Fix the length to support some spefic 64 bit BAR 1695 // 1696 Value |= ((UINT32) -1 << HighBitSet32 (Value)); 1697 1698 // 1699 // Calculate the size of 64bit bar 1700 // 1701 PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32); 1702 1703 PciIoDevice->VfPciBar[BarIndex].Length = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32); 1704 PciIoDevice->VfPciBar[BarIndex].Length = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1; 1705 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1; 1706 1707 // 1708 // Adjust Length 1709 // 1710 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs); 1711 // 1712 // Adjust Alignment 1713 // 1714 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) { 1715 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1; 1716 } 1717 1718 break; 1719 1720 // 1721 // reserved 1722 // 1723 default: 1724 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown; 1725 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1; 1726 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1; 1727 1728 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) { 1729 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1; 1730 } 1731 1732 break; 1733 } 1734 } 1735 1736 // 1737 // Check the length again so as to keep compatible with some special bars 1738 // 1739 if (PciIoDevice->VfPciBar[BarIndex].Length == 0) { 1740 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown; 1741 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0; 1742 PciIoDevice->VfPciBar[BarIndex].Alignment = 0; 1743 } 1744 1745 // 1746 // Increment number of bar 1747 // 1748 return Offset + 4; 1749 } 1750 1751 /** 1752 Parse PCI bar information and fill them into PCI device instance. 1753 1754 @param PciIoDevice Pci device instance. 1755 @param Offset Bar offset. 1756 @param BarIndex Bar index. 1757 1758 @return Next bar offset. 1759 1760 **/ 1761 UINTN 1762 PciParseBar ( 1763 IN PCI_IO_DEVICE *PciIoDevice, 1764 IN UINTN Offset, 1765 IN UINTN BarIndex 1766 ) 1767 { 1768 UINT32 Value; 1769 UINT32 OriginalValue; 1770 UINT32 Mask; 1771 EFI_STATUS Status; 1772 1773 OriginalValue = 0; 1774 Value = 0; 1775 1776 Status = BarExisted ( 1777 PciIoDevice, 1778 Offset, 1779 &Value, 1780 &OriginalValue 1781 ); 1782 1783 if (EFI_ERROR (Status)) { 1784 PciIoDevice->PciBar[BarIndex].BaseAddress = 0; 1785 PciIoDevice->PciBar[BarIndex].Length = 0; 1786 PciIoDevice->PciBar[BarIndex].Alignment = 0; 1787 1788 // 1789 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway 1790 // 1791 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; 1792 return Offset + 4; 1793 } 1794 1795 PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE; 1796 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; 1797 if ((Value & 0x01) != 0) { 1798 // 1799 // Device I/Os 1800 // 1801 Mask = 0xfffffffc; 1802 1803 if ((Value & 0xFFFF0000) != 0) { 1804 // 1805 // It is a IO32 bar 1806 // 1807 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32; 1808 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1); 1809 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1810 1811 } else { 1812 // 1813 // It is a IO16 bar 1814 // 1815 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16; 1816 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1); 1817 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1818 1819 } 1820 // 1821 // Workaround. Some platforms inplement IO bar with 0 length 1822 // Need to treat it as no-bar 1823 // 1824 if (PciIoDevice->PciBar[BarIndex].Length == 0) { 1825 PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0; 1826 } 1827 1828 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; 1829 1830 } else { 1831 1832 Mask = 0xfffffff0; 1833 1834 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; 1835 1836 switch (Value & 0x07) { 1837 1838 // 1839 //memory space; anywhere in 32 bit address space 1840 // 1841 case 0x00: 1842 if ((Value & 0x08) != 0) { 1843 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32; 1844 } else { 1845 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32; 1846 } 1847 1848 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; 1849 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) { 1850 // 1851 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O 1852 // 1853 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1); 1854 } else { 1855 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1856 } 1857 break; 1858 1859 // 1860 // memory space; anywhere in 64 bit address space 1861 // 1862 case 0x04: 1863 if ((Value & 0x08) != 0) { 1864 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64; 1865 } else { 1866 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64; 1867 } 1868 1869 // 1870 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar 1871 // is regarded as an extension for the first bar. As a result 1872 // the sizing will be conducted on combined 64 bit value 1873 // Here just store the masked first 32bit value for future size 1874 // calculation 1875 // 1876 PciIoDevice->PciBar[BarIndex].Length = Value & Mask; 1877 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1878 1879 // 1880 // Increment the offset to point to next DWORD 1881 // 1882 Offset += 4; 1883 1884 Status = BarExisted ( 1885 PciIoDevice, 1886 Offset, 1887 &Value, 1888 &OriginalValue 1889 ); 1890 1891 if (EFI_ERROR (Status)) { 1892 // 1893 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again 1894 // 1895 if (PciIoDevice->PciBar[BarIndex].Length == 0) { 1896 // 1897 // some device implement MMIO bar with 0 length, need to treat it as no-bar 1898 // 1899 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; 1900 return Offset + 4; 1901 } 1902 } 1903 1904 // 1905 // Fix the length to support some spefic 64 bit BAR 1906 // 1907 if (Value == 0) { 1908 DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n")); 1909 Value = (UINT32) -1; 1910 } else { 1911 Value |= ((UINT32)(-1) << HighBitSet32 (Value)); 1912 } 1913 1914 // 1915 // Calculate the size of 64bit bar 1916 // 1917 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32); 1918 1919 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32); 1920 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1; 1921 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) { 1922 // 1923 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O 1924 // 1925 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1); 1926 } else { 1927 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1928 } 1929 1930 break; 1931 1932 // 1933 // reserved 1934 // 1935 default: 1936 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; 1937 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; 1938 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) { 1939 // 1940 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O 1941 // 1942 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1); 1943 } else { 1944 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1945 } 1946 break; 1947 } 1948 } 1949 1950 // 1951 // Check the length again so as to keep compatible with some special bars 1952 // 1953 if (PciIoDevice->PciBar[BarIndex].Length == 0) { 1954 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; 1955 PciIoDevice->PciBar[BarIndex].BaseAddress = 0; 1956 PciIoDevice->PciBar[BarIndex].Alignment = 0; 1957 } 1958 1959 // 1960 // Increment number of bar 1961 // 1962 return Offset + 4; 1963 } 1964 1965 /** 1966 This routine is used to initialize the bar of a PCI device. 1967 1968 @param PciIoDevice Pci device instance. 1969 1970 @note It can be called typically when a device is going to be rejected. 1971 1972 **/ 1973 VOID 1974 InitializePciDevice ( 1975 IN PCI_IO_DEVICE *PciIoDevice 1976 ) 1977 { 1978 EFI_PCI_IO_PROTOCOL *PciIo; 1979 UINT8 Offset; 1980 1981 PciIo = &(PciIoDevice->PciIo); 1982 1983 // 1984 // Put all the resource apertures 1985 // Resource base is set to all ones so as to indicate its resource 1986 // has not been alloacted 1987 // 1988 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) { 1989 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne); 1990 } 1991 } 1992 1993 /** 1994 This routine is used to initialize the bar of a PCI-PCI Bridge device. 1995 1996 @param PciIoDevice PCI-PCI bridge device instance. 1997 1998 **/ 1999 VOID 2000 InitializePpb ( 2001 IN PCI_IO_DEVICE *PciIoDevice 2002 ) 2003 { 2004 EFI_PCI_IO_PROTOCOL *PciIo; 2005 2006 PciIo = &(PciIoDevice->PciIo); 2007 2008 // 2009 // Put all the resource apertures including IO16 2010 // Io32, pMem32, pMem64 to quiescent state 2011 // Resource base all ones, Resource limit all zeros 2012 // 2013 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); 2014 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero); 2015 2016 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne); 2017 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero); 2018 2019 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne); 2020 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero); 2021 2022 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne); 2023 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero); 2024 2025 // 2026 // Don't support use io32 as for now 2027 // 2028 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne); 2029 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero); 2030 2031 // 2032 // Force Interrupt line to zero for cards that come up randomly 2033 // 2034 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); 2035 } 2036 2037 /** 2038 This routine is used to initialize the bar of a PCI Card Bridge device. 2039 2040 @param PciIoDevice PCI Card bridge device. 2041 2042 **/ 2043 VOID 2044 InitializeP2C ( 2045 IN PCI_IO_DEVICE *PciIoDevice 2046 ) 2047 { 2048 EFI_PCI_IO_PROTOCOL *PciIo; 2049 2050 PciIo = &(PciIoDevice->PciIo); 2051 2052 // 2053 // Put all the resource apertures including IO16 2054 // Io32, pMem32, pMem64 to quiescent state( 2055 // Resource base all ones, Resource limit all zeros 2056 // 2057 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne); 2058 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero); 2059 2060 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne); 2061 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero); 2062 2063 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne); 2064 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero); 2065 2066 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne); 2067 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero); 2068 2069 // 2070 // Force Interrupt line to zero for cards that come up randomly 2071 // 2072 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); 2073 } 2074 2075 /** 2076 Create and initiliaze general PCI I/O device instance for 2077 PCI device/bridge device/hotplug bridge device. 2078 2079 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. 2080 @param Pci Input Pci information block. 2081 @param Bus Device Bus NO. 2082 @param Device Device device NO. 2083 @param Func Device func NO. 2084 2085 @return Instance of PCI device. NULL means no instance created. 2086 2087 **/ 2088 PCI_IO_DEVICE * 2089 CreatePciIoDevice ( 2090 IN PCI_IO_DEVICE *Bridge, 2091 IN PCI_TYPE00 *Pci, 2092 IN UINT8 Bus, 2093 IN UINT8 Device, 2094 IN UINT8 Func 2095 ) 2096 { 2097 PCI_IO_DEVICE *PciIoDevice; 2098 EFI_PCI_IO_PROTOCOL *PciIo; 2099 EFI_STATUS Status; 2100 2101 PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE)); 2102 if (PciIoDevice == NULL) { 2103 return NULL; 2104 } 2105 2106 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE; 2107 PciIoDevice->Handle = NULL; 2108 PciIoDevice->PciRootBridgeIo = Bridge->PciRootBridgeIo; 2109 PciIoDevice->DevicePath = NULL; 2110 PciIoDevice->BusNumber = Bus; 2111 PciIoDevice->DeviceNumber = Device; 2112 PciIoDevice->FunctionNumber = Func; 2113 PciIoDevice->Decodes = 0; 2114 2115 if (gFullEnumeration) { 2116 PciIoDevice->Allocated = FALSE; 2117 } else { 2118 PciIoDevice->Allocated = TRUE; 2119 } 2120 2121 PciIoDevice->Registered = FALSE; 2122 PciIoDevice->Attributes = 0; 2123 PciIoDevice->Supports = 0; 2124 PciIoDevice->BusOverride = FALSE; 2125 PciIoDevice->AllOpRomProcessed = FALSE; 2126 2127 PciIoDevice->IsPciExp = FALSE; 2128 2129 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01)); 2130 2131 // 2132 // Initialize the PCI I/O instance structure 2133 // 2134 InitializePciIoInstance (PciIoDevice); 2135 InitializePciDriverOverrideInstance (PciIoDevice); 2136 InitializePciLoadFile2 (PciIoDevice); 2137 PciIo = &PciIoDevice->PciIo; 2138 2139 // 2140 // Create a device path for this PCI device and store it into its private data 2141 // 2142 CreatePciDevicePath ( 2143 Bridge->DevicePath, 2144 PciIoDevice 2145 ); 2146 2147 // 2148 // Detect if PCI Express Device 2149 // 2150 PciIoDevice->PciExpressCapabilityOffset = 0; 2151 Status = LocateCapabilityRegBlock ( 2152 PciIoDevice, 2153 EFI_PCI_CAPABILITY_ID_PCIEXP, 2154 &PciIoDevice->PciExpressCapabilityOffset, 2155 NULL 2156 ); 2157 if (!EFI_ERROR (Status)) { 2158 PciIoDevice->IsPciExp = TRUE; 2159 } 2160 2161 if (PcdGetBool (PcdAriSupport)) { 2162 // 2163 // Check if the device is an ARI device. 2164 // 2165 Status = LocatePciExpressCapabilityRegBlock ( 2166 PciIoDevice, 2167 EFI_PCIE_CAPABILITY_ID_ARI, 2168 &PciIoDevice->AriCapabilityOffset, 2169 NULL 2170 ); 2171 if (!EFI_ERROR (Status)) { 2172 // 2173 // We need to enable ARI feature before calculate BusReservation, 2174 // because FirstVFOffset and VFStride may change after that. 2175 // 2176 EFI_PCI_IO_PROTOCOL *ParentPciIo; 2177 UINT32 Data32; 2178 2179 // 2180 // Check if its parent supports ARI forwarding. 2181 // 2182 ParentPciIo = &Bridge->PciIo; 2183 ParentPciIo->Pci.Read ( 2184 ParentPciIo, 2185 EfiPciIoWidthUint32, 2186 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, 2187 1, 2188 &Data32 2189 ); 2190 if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) { 2191 // 2192 // ARI forward support in bridge, so enable it. 2193 // 2194 ParentPciIo->Pci.Read ( 2195 ParentPciIo, 2196 EfiPciIoWidthUint32, 2197 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 2198 1, 2199 &Data32 2200 ); 2201 if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) { 2202 Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING; 2203 ParentPciIo->Pci.Write ( 2204 ParentPciIo, 2205 EfiPciIoWidthUint32, 2206 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 2207 1, 2208 &Data32 2209 ); 2210 DEBUG (( 2211 EFI_D_INFO, 2212 " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n", 2213 Bridge->BusNumber, 2214 Bridge->DeviceNumber, 2215 Bridge->FunctionNumber 2216 )); 2217 } 2218 } 2219 2220 DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset)); 2221 } 2222 } 2223 2224 // 2225 // Initialization for SR-IOV 2226 // 2227 2228 if (PcdGetBool (PcdSrIovSupport)) { 2229 Status = LocatePciExpressCapabilityRegBlock ( 2230 PciIoDevice, 2231 EFI_PCIE_CAPABILITY_ID_SRIOV, 2232 &PciIoDevice->SrIovCapabilityOffset, 2233 NULL 2234 ); 2235 if (!EFI_ERROR (Status)) { 2236 UINT32 SupportedPageSize; 2237 UINT16 VFStride; 2238 UINT16 FirstVFOffset; 2239 UINT16 Data16; 2240 UINT32 PFRid; 2241 UINT32 LastVF; 2242 2243 // 2244 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device. 2245 // 2246 if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != 0) { 2247 PciIo->Pci.Read ( 2248 PciIo, 2249 EfiPciIoWidthUint16, 2250 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 2251 1, 2252 &Data16 2253 ); 2254 Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY; 2255 PciIo->Pci.Write ( 2256 PciIo, 2257 EfiPciIoWidthUint16, 2258 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 2259 1, 2260 &Data16 2261 ); 2262 } 2263 2264 // 2265 // Calculate SystemPageSize 2266 // 2267 2268 PciIo->Pci.Read ( 2269 PciIo, 2270 EfiPciIoWidthUint32, 2271 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE, 2272 1, 2273 &SupportedPageSize 2274 ); 2275 PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize); 2276 ASSERT (PciIoDevice->SystemPageSize != 0); 2277 2278 PciIo->Pci.Write ( 2279 PciIo, 2280 EfiPciIoWidthUint32, 2281 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE, 2282 1, 2283 &PciIoDevice->SystemPageSize 2284 ); 2285 // 2286 // Adjust SystemPageSize for Alignment usage later 2287 // 2288 PciIoDevice->SystemPageSize <<= 12; 2289 2290 // 2291 // Calculate BusReservation for PCI IOV 2292 // 2293 2294 // 2295 // Read First FirstVFOffset, InitialVFs, and VFStride 2296 // 2297 PciIo->Pci.Read ( 2298 PciIo, 2299 EfiPciIoWidthUint16, 2300 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF, 2301 1, 2302 &FirstVFOffset 2303 ); 2304 PciIo->Pci.Read ( 2305 PciIo, 2306 EfiPciIoWidthUint16, 2307 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS, 2308 1, 2309 &PciIoDevice->InitialVFs 2310 ); 2311 PciIo->Pci.Read ( 2312 PciIo, 2313 EfiPciIoWidthUint16, 2314 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE, 2315 1, 2316 &VFStride 2317 ); 2318 // 2319 // Calculate LastVF 2320 // 2321 PFRid = EFI_PCI_RID(Bus, Device, Func); 2322 LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride; 2323 2324 // 2325 // Calculate ReservedBusNum for this PF 2326 // 2327 PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1); 2328 2329 DEBUG (( 2330 EFI_D_INFO, 2331 " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n", 2332 SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset 2333 )); 2334 DEBUG (( 2335 EFI_D_INFO, 2336 " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n", 2337 PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset 2338 )); 2339 } 2340 } 2341 2342 if (PcdGetBool (PcdMrIovSupport)) { 2343 Status = LocatePciExpressCapabilityRegBlock ( 2344 PciIoDevice, 2345 EFI_PCIE_CAPABILITY_ID_MRIOV, 2346 &PciIoDevice->MrIovCapabilityOffset, 2347 NULL 2348 ); 2349 if (!EFI_ERROR (Status)) { 2350 DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset)); 2351 } 2352 } 2353 2354 // 2355 // Initialize the reserved resource list 2356 // 2357 InitializeListHead (&PciIoDevice->ReservedResourceList); 2358 2359 // 2360 // Initialize the driver list 2361 // 2362 InitializeListHead (&PciIoDevice->OptionRomDriverList); 2363 2364 // 2365 // Initialize the child list 2366 // 2367 InitializeListHead (&PciIoDevice->ChildList); 2368 2369 return PciIoDevice; 2370 } 2371 2372 /** 2373 This routine is used to enumerate entire pci bus system 2374 in a given platform. 2375 2376 It is only called on the second start on the same Root Bridge. 2377 2378 @param Controller Parent bridge handler. 2379 2380 @retval EFI_SUCCESS PCI enumeration finished successfully. 2381 @retval other Some error occurred when enumerating the pci bus system. 2382 2383 **/ 2384 EFI_STATUS 2385 PciEnumeratorLight ( 2386 IN EFI_HANDLE Controller 2387 ) 2388 { 2389 2390 EFI_STATUS Status; 2391 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; 2392 PCI_IO_DEVICE *RootBridgeDev; 2393 UINT16 MinBus; 2394 UINT16 MaxBus; 2395 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; 2396 2397 MinBus = 0; 2398 MaxBus = PCI_MAX_BUS; 2399 Descriptors = NULL; 2400 2401 // 2402 // If this root bridge has been already enumerated, then return successfully 2403 // 2404 if (GetRootBridgeByHandle (Controller) != NULL) { 2405 return EFI_SUCCESS; 2406 } 2407 2408 // 2409 // Open pci root bridge io protocol 2410 // 2411 Status = gBS->OpenProtocol ( 2412 Controller, 2413 &gEfiPciRootBridgeIoProtocolGuid, 2414 (VOID **) &PciRootBridgeIo, 2415 gPciBusDriverBinding.DriverBindingHandle, 2416 Controller, 2417 EFI_OPEN_PROTOCOL_BY_DRIVER 2418 ); 2419 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 2420 return Status; 2421 } 2422 2423 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); 2424 2425 if (EFI_ERROR (Status)) { 2426 return Status; 2427 } 2428 2429 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) { 2430 2431 // 2432 // Create a device node for root bridge device with a NULL host bridge controller handle 2433 // 2434 RootBridgeDev = CreateRootBridge (Controller); 2435 2436 if (RootBridgeDev == NULL) { 2437 Descriptors++; 2438 continue; 2439 } 2440 2441 // 2442 // Record the root bridgeio protocol 2443 // 2444 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo; 2445 2446 Status = PciPciDeviceInfoCollector ( 2447 RootBridgeDev, 2448 (UINT8) MinBus 2449 ); 2450 2451 if (!EFI_ERROR (Status)) { 2452 2453 // 2454 // Remove those PCI devices which are rejected when full enumeration 2455 // 2456 RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev); 2457 2458 // 2459 // Process option rom light 2460 // 2461 ProcessOptionRomLight (RootBridgeDev); 2462 2463 // 2464 // Determine attributes for all devices under this root bridge 2465 // 2466 DetermineDeviceAttribute (RootBridgeDev); 2467 2468 // 2469 // If successfully, insert the node into device pool 2470 // 2471 InsertRootBridge (RootBridgeDev); 2472 } else { 2473 2474 // 2475 // If unsuccessly, destroy the entire node 2476 // 2477 DestroyRootBridge (RootBridgeDev); 2478 } 2479 2480 Descriptors++; 2481 } 2482 2483 return EFI_SUCCESS; 2484 } 2485 2486 /** 2487 Get bus range from PCI resource descriptor list. 2488 2489 @param Descriptors A pointer to the address space descriptor. 2490 @param MinBus The min bus returned. 2491 @param MaxBus The max bus returned. 2492 @param BusRange The bus range returned. 2493 2494 @retval EFI_SUCCESS Successfully got bus range. 2495 @retval EFI_NOT_FOUND Can not find the specific bus. 2496 2497 **/ 2498 EFI_STATUS 2499 PciGetBusRange ( 2500 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, 2501 OUT UINT16 *MinBus, 2502 OUT UINT16 *MaxBus, 2503 OUT UINT16 *BusRange 2504 ) 2505 { 2506 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) { 2507 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) { 2508 if (MinBus != NULL) { 2509 *MinBus = (UINT16) (*Descriptors)->AddrRangeMin; 2510 } 2511 2512 if (MaxBus != NULL) { 2513 *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax; 2514 } 2515 2516 if (BusRange != NULL) { 2517 *BusRange = (UINT16) (*Descriptors)->AddrLen; 2518 } 2519 2520 return EFI_SUCCESS; 2521 } 2522 2523 (*Descriptors)++; 2524 } 2525 2526 return EFI_NOT_FOUND; 2527 } 2528 2529 /** 2530 This routine can be used to start the root bridge. 2531 2532 @param RootBridgeDev Pci device instance. 2533 2534 @retval EFI_SUCCESS This device started. 2535 @retval other Failed to get PCI Root Bridge I/O protocol. 2536 2537 **/ 2538 EFI_STATUS 2539 StartManagingRootBridge ( 2540 IN PCI_IO_DEVICE *RootBridgeDev 2541 ) 2542 { 2543 EFI_HANDLE RootBridgeHandle; 2544 EFI_STATUS Status; 2545 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; 2546 2547 // 2548 // Get the root bridge handle 2549 // 2550 RootBridgeHandle = RootBridgeDev->Handle; 2551 PciRootBridgeIo = NULL; 2552 2553 // 2554 // Get the pci root bridge io protocol 2555 // 2556 Status = gBS->OpenProtocol ( 2557 RootBridgeHandle, 2558 &gEfiPciRootBridgeIoProtocolGuid, 2559 (VOID **) &PciRootBridgeIo, 2560 gPciBusDriverBinding.DriverBindingHandle, 2561 RootBridgeHandle, 2562 EFI_OPEN_PROTOCOL_BY_DRIVER 2563 ); 2564 2565 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 2566 return Status; 2567 } 2568 2569 // 2570 // Store the PciRootBridgeIo protocol into root bridge private data 2571 // 2572 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo; 2573 2574 return EFI_SUCCESS; 2575 2576 } 2577 2578 /** 2579 This routine can be used to check whether a PCI device should be rejected when light enumeration. 2580 2581 @param PciIoDevice Pci device instance. 2582 2583 @retval TRUE This device should be rejected. 2584 @retval FALSE This device shouldn't be rejected. 2585 2586 **/ 2587 BOOLEAN 2588 IsPciDeviceRejected ( 2589 IN PCI_IO_DEVICE *PciIoDevice 2590 ) 2591 { 2592 EFI_STATUS Status; 2593 UINT32 TestValue; 2594 UINT32 OldValue; 2595 UINT32 Mask; 2596 UINT8 BarOffset; 2597 2598 // 2599 // PPB should be skip! 2600 // 2601 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { 2602 return FALSE; 2603 } 2604 2605 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { 2606 // 2607 // Only test base registers for P2C 2608 // 2609 for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) { 2610 2611 Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC; 2612 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); 2613 if (EFI_ERROR (Status)) { 2614 continue; 2615 } 2616 2617 TestValue = TestValue & Mask; 2618 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { 2619 // 2620 // The bar isn't programed, so it should be rejected 2621 // 2622 return TRUE; 2623 } 2624 } 2625 2626 return FALSE; 2627 } 2628 2629 for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) { 2630 // 2631 // Test PCI devices 2632 // 2633 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); 2634 if (EFI_ERROR (Status)) { 2635 continue; 2636 } 2637 2638 if ((TestValue & 0x01) != 0) { 2639 2640 // 2641 // IO Bar 2642 // 2643 Mask = 0xFFFFFFFC; 2644 TestValue = TestValue & Mask; 2645 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { 2646 return TRUE; 2647 } 2648 2649 } else { 2650 2651 // 2652 // Mem Bar 2653 // 2654 Mask = 0xFFFFFFF0; 2655 TestValue = TestValue & Mask; 2656 2657 if ((TestValue & 0x07) == 0x04) { 2658 2659 // 2660 // Mem64 or PMem64 2661 // 2662 BarOffset += sizeof (UINT32); 2663 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { 2664 2665 // 2666 // Test its high 32-Bit BAR 2667 // 2668 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); 2669 if (TestValue == OldValue) { 2670 return TRUE; 2671 } 2672 } 2673 2674 } else { 2675 2676 // 2677 // Mem32 or PMem32 2678 // 2679 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { 2680 return TRUE; 2681 } 2682 } 2683 } 2684 } 2685 2686 return FALSE; 2687 } 2688 2689 /** 2690 Reset all bus number from specific bridge. 2691 2692 @param Bridge Parent specific bridge. 2693 @param StartBusNumber Start bus number. 2694 2695 **/ 2696 VOID 2697 ResetAllPpbBusNumber ( 2698 IN PCI_IO_DEVICE *Bridge, 2699 IN UINT8 StartBusNumber 2700 ) 2701 { 2702 EFI_STATUS Status; 2703 PCI_TYPE00 Pci; 2704 UINT8 Device; 2705 UINT32 Register; 2706 UINT8 Func; 2707 UINT64 Address; 2708 UINT8 SecondaryBus; 2709 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; 2710 2711 PciRootBridgeIo = Bridge->PciRootBridgeIo; 2712 2713 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { 2714 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { 2715 2716 // 2717 // Check to see whether a pci device is present 2718 // 2719 Status = PciDevicePresent ( 2720 PciRootBridgeIo, 2721 &Pci, 2722 StartBusNumber, 2723 Device, 2724 Func 2725 ); 2726 2727 if (EFI_ERROR (Status) && Func == 0) { 2728 // 2729 // go to next device if there is no Function 0 2730 // 2731 break; 2732 } 2733 2734 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) { 2735 2736 Register = 0; 2737 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18); 2738 Status = PciRootBridgeIo->Pci.Read ( 2739 PciRootBridgeIo, 2740 EfiPciWidthUint32, 2741 Address, 2742 1, 2743 &Register 2744 ); 2745 SecondaryBus = (UINT8)(Register >> 8); 2746 2747 if (SecondaryBus != 0) { 2748 ResetAllPpbBusNumber (Bridge, SecondaryBus); 2749 } 2750 2751 // 2752 // Reset register 18h, 19h, 1Ah on PCI Bridge 2753 // 2754 Register &= 0xFF000000; 2755 Status = PciRootBridgeIo->Pci.Write ( 2756 PciRootBridgeIo, 2757 EfiPciWidthUint32, 2758 Address, 2759 1, 2760 &Register 2761 ); 2762 } 2763 2764 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { 2765 // 2766 // Skip sub functions, this is not a multi function device 2767 // 2768 Func = PCI_MAX_FUNC; 2769 } 2770 } 2771 } 2772 } 2773 2774