1 /*++ 2 3 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR> 4 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 Module Name: 14 15 PciEnumeratorSupport.c 16 17 Abstract: 18 19 PCI Bus Driver 20 21 Revision History 22 23 --*/ 24 25 #include "PciBus.h" 26 27 EFI_STATUS 28 InitializePPB ( 29 IN PCI_IO_DEVICE *PciIoDevice 30 ); 31 32 EFI_STATUS 33 InitializeP2C ( 34 IN PCI_IO_DEVICE *PciIoDevice 35 ); 36 37 PCI_IO_DEVICE* 38 CreatePciIoDevice ( 39 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 40 IN PCI_TYPE00 *Pci, 41 UINT8 Bus, 42 UINT8 Device, 43 UINT8 Func 44 ); 45 46 47 PCI_IO_DEVICE* 48 GatherP2CInfo ( 49 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 50 IN PCI_TYPE00 *Pci, 51 UINT8 Bus, 52 UINT8 Device, 53 UINT8 Func 54 ); 55 56 UINTN 57 PciParseBar ( 58 IN PCI_IO_DEVICE *PciIoDevice, 59 IN UINTN Offset, 60 IN UINTN BarIndex 61 ); 62 63 64 EFI_STATUS 65 PciSearchDevice ( 66 IN PCI_IO_DEVICE *Bridge, 67 PCI_TYPE00 *Pci, 68 UINT8 Bus, 69 UINT8 Device, 70 UINT8 Func, 71 PCI_IO_DEVICE **PciDevice 72 ); 73 74 75 EFI_STATUS 76 DetermineDeviceAttribute ( 77 IN PCI_IO_DEVICE *PciIoDevice 78 ); 79 80 EFI_STATUS 81 BarExisted ( 82 IN PCI_IO_DEVICE *PciIoDevice, 83 IN UINTN Offset, 84 OUT UINT32 *BarLengthValue, 85 OUT UINT32 *OriginalBarValue 86 ); 87 88 89 90 EFI_DEVICE_PATH_PROTOCOL* 91 CreatePciDevicePath( 92 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, 93 IN PCI_IO_DEVICE *PciIoDevice 94 ); 95 96 PCI_IO_DEVICE* 97 GatherDeviceInfo ( 98 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 99 IN PCI_TYPE00 *Pci, 100 UINT8 Bus, 101 UINT8 Device, 102 UINT8 Func 103 ); 104 105 PCI_IO_DEVICE* 106 GatherPPBInfo ( 107 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 108 IN PCI_TYPE00 *Pci, 109 UINT8 Bus, 110 UINT8 Device, 111 UINT8 Func 112 ); 113 114 EFI_STATUS 115 PciDevicePresent ( 116 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 117 PCI_TYPE00 *Pci, 118 UINT8 Bus, 119 UINT8 Device, 120 UINT8 Func 121 ) 122 /*++ 123 124 Routine Description: 125 126 This routine is used to check whether the pci device is present 127 128 Arguments: 129 130 Returns: 131 132 None 133 134 --*/ 135 { 136 UINT64 Address; 137 EFI_STATUS Status; 138 139 // 140 // Create PCI address map in terms of Bus, Device and Func 141 // 142 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0); 143 144 // 145 // Read the Vendor Id register 146 // 147 Status = PciRootBridgeIo->Pci.Read ( 148 PciRootBridgeIo, 149 EfiPciWidthUint32, 150 Address, 151 1, 152 Pci 153 ); 154 155 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) { 156 157 // 158 // Read the entire config header for the device 159 // 160 161 Status = PciRootBridgeIo->Pci.Read ( 162 PciRootBridgeIo, 163 EfiPciWidthUint32, 164 Address, 165 sizeof (PCI_TYPE00) / sizeof (UINT32), 166 Pci 167 ); 168 169 return EFI_SUCCESS; 170 } 171 172 return EFI_NOT_FOUND; 173 } 174 175 EFI_STATUS 176 PciPciDeviceInfoCollector ( 177 IN PCI_IO_DEVICE *Bridge, 178 UINT8 StartBusNumber 179 ) 180 /*++ 181 182 Routine Description: 183 184 Arguments: 185 186 Returns: 187 188 None 189 190 --*/ 191 { 192 EFI_STATUS Status; 193 PCI_TYPE00 Pci; 194 UINT8 Device; 195 UINT8 Func; 196 UINT8 SecBus; 197 PCI_IO_DEVICE *PciIoDevice; 198 EFI_PCI_IO_PROTOCOL *PciIo; 199 200 Status = EFI_SUCCESS; 201 SecBus = 0; 202 PciIoDevice = NULL; 203 204 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { 205 206 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { 207 208 // 209 // Check to see whether PCI device is present 210 // 211 212 Status = PciDevicePresent ( 213 Bridge->PciRootBridgeIo, 214 &Pci, 215 (UINT8) StartBusNumber, 216 (UINT8) Device, 217 (UINT8) Func 218 ); 219 220 if (EFI_ERROR (Status) && Func == 0) { 221 // 222 // go to next device if there is no Function 0 223 // 224 break; 225 } 226 227 if (!EFI_ERROR (Status)) { 228 229 // 230 // Collect all the information about the PCI device discovered 231 // 232 Status = PciSearchDevice ( 233 Bridge, 234 &Pci, 235 (UINT8) StartBusNumber, 236 Device, 237 Func, 238 &PciIoDevice 239 ); 240 241 // 242 // Recursively scan PCI busses on the other side of PCI-PCI bridges 243 // 244 // 245 246 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) { 247 248 // 249 // If it is PPB, we need to get the secondary bus to continue the enumeration 250 // 251 PciIo = &(PciIoDevice->PciIo); 252 253 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus); 254 255 if (EFI_ERROR (Status)) { 256 return Status; 257 } 258 259 // 260 // Deep enumerate the next level bus 261 // 262 Status = PciPciDeviceInfoCollector ( 263 PciIoDevice, 264 (UINT8) (SecBus) 265 ); 266 267 } 268 269 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { 270 271 // 272 // Skip sub functions, this is not a multi function device 273 // 274 Func = PCI_MAX_FUNC; 275 } 276 } 277 278 } 279 } 280 281 return EFI_SUCCESS; 282 } 283 284 EFI_STATUS 285 PciSearchDevice ( 286 IN PCI_IO_DEVICE *Bridge, 287 IN PCI_TYPE00 *Pci, 288 IN UINT8 Bus, 289 IN UINT8 Device, 290 IN UINT8 Func, 291 OUT PCI_IO_DEVICE **PciDevice 292 ) 293 /*++ 294 295 Routine Description: 296 297 Search required device. 298 299 Arguments: 300 301 Bridge - A pointer to the PCI_IO_DEVICE. 302 Pci - A pointer to the PCI_TYPE00. 303 Bus - Bus number. 304 Device - Device number. 305 Func - Function number. 306 PciDevice - The Required pci device. 307 308 Returns: 309 310 Status code. 311 312 --*/ 313 { 314 PCI_IO_DEVICE *PciIoDevice; 315 316 PciIoDevice = NULL; 317 318 if (!IS_PCI_BRIDGE (Pci)) { 319 320 if (IS_CARDBUS_BRIDGE (Pci)) { 321 PciIoDevice = GatherP2CInfo ( 322 Bridge->PciRootBridgeIo, 323 Pci, 324 Bus, 325 Device, 326 Func 327 ); 328 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) { 329 InitializeP2C (PciIoDevice); 330 } 331 } else { 332 333 // 334 // Create private data for Pci Device 335 // 336 PciIoDevice = GatherDeviceInfo ( 337 Bridge->PciRootBridgeIo, 338 Pci, 339 Bus, 340 Device, 341 Func 342 ); 343 344 } 345 346 } else { 347 348 // 349 // Create private data for PPB 350 // 351 PciIoDevice = GatherPPBInfo ( 352 Bridge->PciRootBridgeIo, 353 Pci, 354 Bus, 355 Device, 356 Func 357 ); 358 359 // 360 // Special initialization for PPB including making the PPB quiet 361 // 362 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) { 363 InitializePPB (PciIoDevice); 364 } 365 } 366 367 if (!PciIoDevice) { 368 return EFI_OUT_OF_RESOURCES; 369 } 370 371 // 372 // Create a device path for this PCI device and store it into its private data 373 // 374 CreatePciDevicePath( 375 Bridge->DevicePath, 376 PciIoDevice 377 ); 378 379 // 380 // Detect this function has option rom 381 // 382 if (gFullEnumeration) { 383 384 if (!IS_CARDBUS_BRIDGE (Pci)) { 385 386 GetOpRomInfo (PciIoDevice); 387 388 } 389 390 ResetPowerManagementFeature (PciIoDevice); 391 392 } 393 else { 394 PciRomGetRomResourceFromPciOptionRomTable ( 395 &gPciBusDriverBinding, 396 PciIoDevice->PciRootBridgeIo, 397 PciIoDevice 398 ); 399 } 400 401 402 // 403 // Insert it into a global tree for future reference 404 // 405 InsertPciDevice (Bridge, PciIoDevice); 406 407 // 408 // Determine PCI device attributes 409 // 410 DetermineDeviceAttribute (PciIoDevice); 411 412 if (PciDevice != NULL) { 413 *PciDevice = PciIoDevice; 414 } 415 416 return EFI_SUCCESS; 417 } 418 419 PCI_IO_DEVICE * 420 GatherDeviceInfo ( 421 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 422 IN PCI_TYPE00 *Pci, 423 UINT8 Bus, 424 UINT8 Device, 425 UINT8 Func 426 ) 427 /*++ 428 429 Routine Description: 430 431 Arguments: 432 433 Returns: 434 435 None 436 437 --*/ 438 { 439 UINTN Offset; 440 UINTN BarIndex; 441 PCI_IO_DEVICE *PciIoDevice; 442 443 PciIoDevice = CreatePciIoDevice ( 444 PciRootBridgeIo, 445 Pci, 446 Bus, 447 Device, 448 Func 449 ); 450 451 if (!PciIoDevice) { 452 return NULL; 453 } 454 455 // 456 // If it is a full enumeration, disconnect the device in advance 457 // 458 if (gFullEnumeration) { 459 460 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); 461 462 } 463 464 // 465 // Start to parse the bars 466 // 467 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) { 468 Offset = PciParseBar (PciIoDevice, Offset, BarIndex); 469 } 470 471 return PciIoDevice; 472 } 473 474 PCI_IO_DEVICE * 475 GatherPPBInfo ( 476 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 477 IN PCI_TYPE00 *Pci, 478 UINT8 Bus, 479 UINT8 Device, 480 UINT8 Func 481 ) 482 /*++ 483 484 Routine Description: 485 486 Arguments: 487 488 Returns: 489 490 None 491 492 --*/ 493 { 494 PCI_IO_DEVICE *PciIoDevice; 495 EFI_STATUS Status; 496 UINT8 Value; 497 EFI_PCI_IO_PROTOCOL *PciIo; 498 UINT8 Temp; 499 500 PciIoDevice = CreatePciIoDevice ( 501 PciRootBridgeIo, 502 Pci, 503 Bus, 504 Device, 505 Func 506 ); 507 508 if (!PciIoDevice) { 509 return NULL; 510 } 511 512 if (gFullEnumeration) { 513 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); 514 515 // 516 // Initalize the bridge control register 517 // 518 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED); 519 } 520 521 PciIo = &PciIoDevice->PciIo; 522 523 // 524 // Test whether it support 32 decode or not 525 // 526 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); 527 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); 528 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); 529 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); 530 531 if (Value) { 532 if (Value & 0x01) { 533 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED; 534 } else { 535 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED; 536 } 537 } 538 539 Status = BarExisted ( 540 PciIoDevice, 541 0x24, 542 NULL, 543 NULL 544 ); 545 546 // 547 // test if it supports 64 memory or not 548 // 549 if (!EFI_ERROR (Status)) { 550 551 Status = BarExisted ( 552 PciIoDevice, 553 0x28, 554 NULL, 555 NULL 556 ); 557 558 if (!EFI_ERROR (Status)) { 559 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; 560 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED; 561 } else { 562 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; 563 } 564 } 565 566 // 567 // Memory 32 code is required for ppb 568 // 569 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED; 570 571 return PciIoDevice; 572 } 573 574 PCI_IO_DEVICE * 575 GatherP2CInfo ( 576 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 577 IN PCI_TYPE00 *Pci, 578 UINT8 Bus, 579 UINT8 Device, 580 UINT8 Func 581 ) 582 /*++ 583 584 Routine Description: 585 586 Arguments: 587 588 Returns: 589 590 None 591 592 --*/ 593 { 594 PCI_IO_DEVICE *PciIoDevice; 595 596 PciIoDevice = CreatePciIoDevice ( 597 PciRootBridgeIo, 598 Pci, 599 Bus, 600 Device, 601 Func 602 ); 603 604 if (!PciIoDevice) { 605 return NULL; 606 } 607 608 if (gFullEnumeration) { 609 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); 610 611 // 612 // Initalize the bridge control register 613 // 614 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED); 615 616 } 617 // 618 // P2C only has one bar that is in 0x10 619 // 620 PciParseBar(PciIoDevice, 0x10, 0); 621 622 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED | 623 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED | 624 EFI_BRIDGE_IO32_DECODE_SUPPORTED; 625 626 return PciIoDevice; 627 } 628 629 EFI_DEVICE_PATH_PROTOCOL * 630 CreatePciDevicePath ( 631 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, 632 IN PCI_IO_DEVICE *PciIoDevice 633 ) 634 /*++ 635 636 Routine Description: 637 638 Arguments: 639 640 Returns: 641 642 None 643 644 --*/ 645 { 646 647 PCI_DEVICE_PATH PciNode; 648 649 // 650 // Create PCI device path 651 // 652 PciNode.Header.Type = HARDWARE_DEVICE_PATH; 653 PciNode.Header.SubType = HW_PCI_DP; 654 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode)); 655 656 PciNode.Device = PciIoDevice->DeviceNumber; 657 PciNode.Function = PciIoDevice->FunctionNumber; 658 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header); 659 660 return PciIoDevice->DevicePath; 661 } 662 663 EFI_STATUS 664 BarExisted ( 665 IN PCI_IO_DEVICE *PciIoDevice, 666 IN UINTN Offset, 667 OUT UINT32 *BarLengthValue, 668 OUT UINT32 *OriginalBarValue 669 ) 670 /*++ 671 672 Routine Description: 673 674 Check the bar is existed or not. 675 676 Arguments: 677 678 PciIoDevice - A pointer to the PCI_IO_DEVICE. 679 Offset - The offset. 680 BarLengthValue - The bar length value. 681 OriginalBarValue - The original bar value. 682 683 Returns: 684 685 EFI_NOT_FOUND - The bar don't exist. 686 EFI_SUCCESS - The bar exist. 687 688 --*/ 689 { 690 EFI_PCI_IO_PROTOCOL *PciIo; 691 UINT32 OriginalValue; 692 UINT32 Value; 693 EFI_TPL OldTpl; 694 695 PciIo = &PciIoDevice->PciIo; 696 697 // 698 // Preserve the original value 699 // 700 701 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); 702 703 // 704 // Raise TPL to high level to disable timer interrupt while the BAR is probed 705 // 706 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); 707 708 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne); 709 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value); 710 711 // 712 // Write back the original value 713 // 714 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); 715 716 // 717 // Restore TPL to its original level 718 // 719 gBS->RestoreTPL (OldTpl); 720 721 if (BarLengthValue != NULL) { 722 *BarLengthValue = Value; 723 } 724 725 if (OriginalBarValue != NULL) { 726 *OriginalBarValue = OriginalValue; 727 } 728 729 if (Value == 0) { 730 return EFI_NOT_FOUND; 731 } else { 732 return EFI_SUCCESS; 733 } 734 } 735 736 737 EFI_STATUS 738 DetermineDeviceAttribute ( 739 IN PCI_IO_DEVICE *PciIoDevice 740 ) 741 /*++ 742 743 Routine Description: 744 745 Determine the related attributes of all devices under a Root Bridge 746 747 Arguments: 748 749 Returns: 750 751 None 752 753 --*/ 754 { 755 UINT16 Command; 756 UINT16 BridgeControl; 757 758 Command = 0; 759 760 PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE; 761 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE; 762 763 if (IS_PCI_VGA (&(PciIoDevice->Pci))){ 764 765 // 766 // If the device is VGA, VGA related Attributes are supported 767 // 768 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ; 769 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ; 770 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO ; 771 } 772 773 if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) { 774 // 775 // If the devie is a ISA Bridge, set the two attributes 776 // 777 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO; 778 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO; 779 } 780 781 if (IS_PCI_GFX (&(PciIoDevice->Pci))) { 782 783 // 784 // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 785 // attribute 786 // 787 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ; 788 } 789 790 791 // 792 // If the device is IDE, IDE related attributes are supported 793 // 794 if (IS_PCI_IDE (&(PciIoDevice->Pci))) { 795 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO ; 796 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO ; 797 } 798 799 PciReadCommandRegister(PciIoDevice, &Command); 800 801 802 if (Command & EFI_PCI_COMMAND_IO_SPACE) { 803 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO; 804 } 805 806 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) { 807 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY; 808 } 809 810 if (Command & EFI_PCI_COMMAND_BUS_MASTER) { 811 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER; 812 } 813 814 if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) || 815 IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){ 816 817 // 818 // If it is a PPB, read the Bridge Control Register to determine 819 // the relevant attributes 820 // 821 BridgeControl = 0; 822 PciReadBridgeControlRegister(PciIoDevice, &BridgeControl); 823 824 // 825 // Determine whether the ISA bit is set 826 // If ISA Enable on Bridge is set, the PPB 827 // will block forwarding 0x100-0x3ff for each 1KB in the 828 // first 64KB I/O range. 829 // 830 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) { 831 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO; 832 } 833 834 // 835 // Determine whether the VGA bit is set 836 // If it is set, the bridge is set to decode VGA memory range 837 // and palette register range 838 // 839 if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) { 840 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO; 841 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; 842 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; 843 } 844 845 // 846 // if the palette snoop bit is set, then the brige is set to 847 // decode palette IO write 848 // 849 if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) { 850 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; 851 } 852 } 853 854 return EFI_SUCCESS; 855 } 856 857 UINTN 858 PciParseBar ( 859 IN PCI_IO_DEVICE *PciIoDevice, 860 IN UINTN Offset, 861 IN UINTN BarIndex 862 ) 863 /*++ 864 865 Routine Description: 866 867 Arguments: 868 869 Returns: 870 871 None 872 873 --*/ 874 { 875 UINT32 Value; 876 UINT32 OriginalValue; 877 UINT32 Mask; 878 EFI_STATUS Status; 879 880 OriginalValue = 0; 881 Value = 0; 882 883 Status = BarExisted ( 884 PciIoDevice, 885 Offset, 886 &Value, 887 &OriginalValue 888 ); 889 890 if (EFI_ERROR (Status)) { 891 PciIoDevice->PciBar[BarIndex].BaseAddress = 0; 892 PciIoDevice->PciBar[BarIndex].Length = 0; 893 PciIoDevice->PciBar[BarIndex].Alignment = 0; 894 895 // 896 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway 897 // 898 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; 899 return Offset + 4; 900 } 901 902 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; 903 if (Value & 0x01) { 904 // 905 // Device I/Os 906 // 907 Mask = 0xfffffffc; 908 909 if (Value & 0xFFFF0000) { 910 // 911 // It is a IO32 bar 912 // 913 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32; 914 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1); 915 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 916 917 } else { 918 // 919 // It is a IO16 bar 920 // 921 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16; 922 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1); 923 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 924 925 } 926 // 927 // Workaround. Some platforms inplement IO bar with 0 length 928 // Need to treat it as no-bar 929 // 930 if (PciIoDevice->PciBar[BarIndex].Length == 0) { 931 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; 932 } 933 934 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE; 935 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; 936 937 } else { 938 939 Mask = 0xfffffff0; 940 941 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; 942 943 switch (Value & 0x07) { 944 945 // 946 //memory space; anywhere in 32 bit address space 947 // 948 case 0x00: 949 if (Value & 0x08) { 950 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32; 951 } else { 952 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32; 953 } 954 955 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; 956 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 957 958 break; 959 960 // 961 // memory space; anywhere in 64 bit address space 962 // 963 case 0x04: 964 if (Value & 0x08) { 965 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64; 966 } else { 967 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64; 968 } 969 970 // 971 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar 972 // is regarded as an extension for the first bar. As a result 973 // the sizing will be conducted on combined 64 bit value 974 // Here just store the masked first 32bit value for future size 975 // calculation 976 // 977 PciIoDevice->PciBar[BarIndex].Length = Value & Mask; 978 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 979 980 // 981 // Increment the offset to point to next DWORD 982 // 983 Offset += 4; 984 985 Status = BarExisted ( 986 PciIoDevice, 987 Offset, 988 &Value, 989 &OriginalValue 990 ); 991 992 if (EFI_ERROR (Status)) { 993 return Offset + 4; 994 } 995 996 // 997 // Fix the length to support some spefic 64 bit BAR 998 // 999 Value |= ((UINT32)(-1) << HighBitSet32 (Value)); 1000 1001 // 1002 // Calculate the size of 64bit bar 1003 // 1004 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32); 1005 1006 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32); 1007 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1; 1008 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1009 1010 break; 1011 1012 // 1013 // reserved 1014 // 1015 default: 1016 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; 1017 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; 1018 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; 1019 1020 break; 1021 } 1022 } 1023 1024 // 1025 // Check the length again so as to keep compatible with some special bars 1026 // 1027 if (PciIoDevice->PciBar[BarIndex].Length == 0) { 1028 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; 1029 PciIoDevice->PciBar[BarIndex].BaseAddress = 0; 1030 PciIoDevice->PciBar[BarIndex].Alignment = 0; 1031 } 1032 1033 // 1034 // Increment number of bar 1035 // 1036 return Offset + 4; 1037 } 1038 1039 EFI_STATUS 1040 InitializePPB ( 1041 IN PCI_IO_DEVICE *PciIoDevice 1042 ) 1043 /*++ 1044 1045 Routine Description: 1046 1047 Arguments: 1048 1049 Returns: 1050 1051 None 1052 1053 --*/ 1054 { 1055 EFI_PCI_IO_PROTOCOL *PciIo; 1056 1057 PciIo = &(PciIoDevice->PciIo); 1058 1059 // 1060 // Put all the resource apertures including IO16 1061 // Io32, pMem32, pMem64 to quiescent state 1062 // Resource base all ones, Resource limit all zeros 1063 // 1064 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); 1065 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero); 1066 1067 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne); 1068 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero); 1069 1070 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne); 1071 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero); 1072 1073 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne); 1074 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero); 1075 1076 // 1077 // don't support use io32 as for now 1078 // 1079 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne); 1080 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero); 1081 1082 return EFI_SUCCESS; 1083 } 1084 1085 EFI_STATUS 1086 InitializeP2C ( 1087 IN PCI_IO_DEVICE *PciIoDevice 1088 ) 1089 /*++ 1090 1091 Routine Description: 1092 1093 Arguments: 1094 1095 Returns: 1096 1097 None 1098 1099 --*/ 1100 { 1101 EFI_PCI_IO_PROTOCOL *PciIo; 1102 1103 PciIo = &(PciIoDevice->PciIo); 1104 1105 // 1106 // Put all the resource apertures including IO16 1107 // Io32, pMem32, pMem64 to quiescent state( 1108 // Resource base all ones, Resource limit all zeros 1109 // 1110 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne); 1111 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero); 1112 1113 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne); 1114 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero); 1115 1116 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne); 1117 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero); 1118 1119 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne); 1120 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero); 1121 1122 return EFI_SUCCESS; 1123 } 1124 1125 PCI_IO_DEVICE * 1126 CreatePciIoDevice ( 1127 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, 1128 IN PCI_TYPE00 *Pci, 1129 UINT8 Bus, 1130 UINT8 Device, 1131 UINT8 Func 1132 ) 1133 /*++ 1134 1135 Routine Description: 1136 1137 Arguments: 1138 1139 Returns: 1140 1141 None 1142 1143 --*/ 1144 { 1145 1146 EFI_STATUS Status; 1147 PCI_IO_DEVICE *PciIoDevice; 1148 1149 PciIoDevice = NULL; 1150 1151 Status = gBS->AllocatePool ( 1152 EfiBootServicesData, 1153 sizeof (PCI_IO_DEVICE), 1154 (VOID **) &PciIoDevice 1155 ); 1156 1157 if (EFI_ERROR (Status)) { 1158 return NULL; 1159 } 1160 1161 ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE)); 1162 1163 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE; 1164 PciIoDevice->Handle = NULL; 1165 PciIoDevice->PciRootBridgeIo = PciRootBridgeIo; 1166 PciIoDevice->DevicePath = NULL; 1167 PciIoDevice->BusNumber = Bus; 1168 PciIoDevice->DeviceNumber = Device; 1169 PciIoDevice->FunctionNumber = Func; 1170 PciIoDevice->Decodes = 0; 1171 if (gFullEnumeration) { 1172 PciIoDevice->Allocated = FALSE; 1173 } else { 1174 PciIoDevice->Allocated = TRUE; 1175 } 1176 1177 PciIoDevice->Attributes = 0; 1178 PciIoDevice->Supports = 0; 1179 PciIoDevice->BusOverride = FALSE; 1180 PciIoDevice->IsPciExp = FALSE; 1181 1182 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01)); 1183 1184 // 1185 // Initialize the PCI I/O instance structure 1186 // 1187 1188 Status = InitializePciIoInstance (PciIoDevice); 1189 Status = InitializePciDriverOverrideInstance (PciIoDevice); 1190 1191 if (EFI_ERROR (Status)) { 1192 gBS->FreePool (PciIoDevice); 1193 return NULL; 1194 } 1195 1196 // 1197 // Initialize the reserved resource list 1198 // 1199 InitializeListHead (&PciIoDevice->ReservedResourceList); 1200 1201 // 1202 // Initialize the driver list 1203 // 1204 InitializeListHead (&PciIoDevice->OptionRomDriverList); 1205 1206 // 1207 // Initialize the child list 1208 // 1209 InitializeListHead (&PciIoDevice->ChildList); 1210 1211 return PciIoDevice; 1212 } 1213 1214 EFI_STATUS 1215 PciEnumeratorLight ( 1216 IN EFI_HANDLE Controller 1217 ) 1218 /*++ 1219 1220 Routine Description: 1221 1222 This routine is used to enumerate entire pci bus system 1223 in a given platform 1224 1225 Arguments: 1226 1227 Returns: 1228 1229 None 1230 1231 --*/ 1232 { 1233 1234 EFI_STATUS Status; 1235 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 1236 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; 1237 PCI_IO_DEVICE *RootBridgeDev; 1238 UINT16 MinBus; 1239 UINT16 MaxBus; 1240 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; 1241 1242 MinBus = 0; 1243 MaxBus = PCI_MAX_BUS; 1244 Descriptors = NULL; 1245 1246 // 1247 // If this host bridge has been already enumerated, then return successfully 1248 // 1249 if (RootBridgeExisted (Controller)) { 1250 return EFI_SUCCESS; 1251 } 1252 1253 // 1254 // Open the IO Abstraction(s) needed to perform the supported test 1255 // 1256 Status = gBS->OpenProtocol ( 1257 Controller , 1258 &gEfiDevicePathProtocolGuid, 1259 (VOID **)&ParentDevicePath, 1260 gPciBusDriverBinding.DriverBindingHandle, 1261 Controller, 1262 EFI_OPEN_PROTOCOL_BY_DRIVER 1263 ); 1264 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 1265 return Status; 1266 } 1267 1268 // 1269 // Open pci root bridge io protocol 1270 // 1271 Status = gBS->OpenProtocol ( 1272 Controller, 1273 &gEfiPciRootBridgeIoProtocolGuid, 1274 (VOID **) &PciRootBridgeIo, 1275 gPciBusDriverBinding.DriverBindingHandle, 1276 Controller, 1277 EFI_OPEN_PROTOCOL_BY_DRIVER 1278 ); 1279 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 1280 return Status; 1281 } 1282 1283 // 1284 // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge 1285 // 1286 Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo); 1287 1288 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); 1289 1290 if (EFI_ERROR (Status)) { 1291 return Status; 1292 } 1293 1294 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) { 1295 1296 // 1297 // Create a device node for root bridge device with a NULL host bridge controller handle 1298 // 1299 RootBridgeDev = CreateRootBridge (Controller); 1300 1301 // 1302 // Record the root bridge device path 1303 // 1304 RootBridgeDev->DevicePath = ParentDevicePath; 1305 1306 // 1307 // Record the root bridge io protocol 1308 // 1309 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo; 1310 1311 Status = PciPciDeviceInfoCollector ( 1312 RootBridgeDev, 1313 (UINT8) MinBus 1314 ); 1315 1316 if (!EFI_ERROR (Status)) { 1317 1318 // 1319 // If successfully, insert the node into device pool 1320 // 1321 InsertRootBridge (RootBridgeDev); 1322 } else { 1323 1324 // 1325 // If unsuccessly, destroy the entire node 1326 // 1327 DestroyRootBridge (RootBridgeDev); 1328 } 1329 1330 Descriptors++; 1331 } 1332 1333 return EFI_SUCCESS; 1334 } 1335 1336 EFI_STATUS 1337 PciGetBusRange ( 1338 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, 1339 OUT UINT16 *MinBus, 1340 OUT UINT16 *MaxBus, 1341 OUT UINT16 *BusRange 1342 ) 1343 /*++ 1344 1345 Routine Description: 1346 1347 Get the bus range. 1348 1349 Arguments: 1350 1351 Descriptors - A pointer to the address space descriptor. 1352 MinBus - The min bus. 1353 MaxBus - The max bus. 1354 BusRange - The bus range. 1355 1356 Returns: 1357 1358 Status Code. 1359 1360 --*/ 1361 { 1362 1363 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) { 1364 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) { 1365 if (MinBus != NULL) { 1366 *MinBus = (UINT16)(*Descriptors)->AddrRangeMin; 1367 } 1368 1369 if (MaxBus != NULL) { 1370 *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax; 1371 } 1372 1373 if (BusRange != NULL) { 1374 *BusRange = (UINT16)(*Descriptors)->AddrLen; 1375 } 1376 return EFI_SUCCESS; 1377 } 1378 1379 (*Descriptors)++; 1380 } 1381 1382 return EFI_NOT_FOUND; 1383 } 1384 1385