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