1 /*++ 2 3 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 PciIo.c 15 16 Abstract: 17 18 PCI I/O Abstraction Driver 19 20 Revision History 21 22 --*/ 23 24 #include "PciBus.h" 25 26 // 27 // PCI I/O Support Function Prototypes 28 // 29 // 30 31 BOOLEAN 32 PciDevicesOnTheSamePath ( 33 IN PCI_IO_DEVICE *PciDevice1, 34 IN PCI_IO_DEVICE *PciDevice2 35 ); 36 37 38 EFI_STATUS 39 UpStreamBridgesAttributes ( 40 IN PCI_IO_DEVICE *PciIoDevice, 41 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, 42 IN UINT64 Attributes 43 ); 44 45 46 BOOLEAN 47 CheckBarType ( 48 IN PCI_IO_DEVICE *PciIoDevice, 49 UINT8 BarIndex, 50 PCI_BAR_TYPE BarType 51 ); 52 53 54 EFI_STATUS 55 SetBootVGA ( 56 IN PCI_IO_DEVICE *PciIoDevice 57 ); 58 59 EFI_STATUS 60 DisableBootVGA ( 61 IN PCI_IO_DEVICE *PciIoDevice 62 ); 63 64 65 EFI_STATUS 66 PciIoVerifyBarAccess ( 67 PCI_IO_DEVICE *PciIoDevice, 68 UINT8 BarIndex, 69 PCI_BAR_TYPE Type, 70 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 71 IN UINTN Count, 72 UINT64 *Offset 73 ); 74 75 EFI_STATUS 76 PciIoVerifyConfigAccess ( 77 PCI_IO_DEVICE *PciIoDevice, 78 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 79 IN UINTN Count, 80 IN UINT64 *Offset 81 ); 82 83 EFI_STATUS 84 EFIAPI 85 PciIoPollMem ( 86 IN EFI_PCI_IO_PROTOCOL *This, 87 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 88 IN UINT8 BarIndex, 89 IN UINT64 Offset, 90 IN UINT64 Mask, 91 IN UINT64 Value, 92 IN UINT64 Delay, 93 OUT UINT64 *Result 94 ); 95 96 EFI_STATUS 97 EFIAPI 98 PciIoPollIo ( 99 IN EFI_PCI_IO_PROTOCOL *This, 100 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 101 IN UINT8 BarIndex, 102 IN UINT64 Offset, 103 IN UINT64 Mask, 104 IN UINT64 Value, 105 IN UINT64 Delay, 106 OUT UINT64 *Result 107 ); 108 109 EFI_STATUS 110 EFIAPI 111 PciIoMemRead ( 112 IN EFI_PCI_IO_PROTOCOL *This, 113 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 114 IN UINT8 BarIndex, 115 IN UINT64 Offset, 116 IN UINTN Count, 117 IN OUT VOID *Buffer 118 ); 119 120 EFI_STATUS 121 EFIAPI 122 PciIoMemWrite ( 123 IN EFI_PCI_IO_PROTOCOL *This, 124 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 125 IN UINT8 BarIndex, 126 IN UINT64 Offset, 127 IN UINTN Count, 128 IN OUT VOID *Buffer 129 ); 130 131 EFI_STATUS 132 EFIAPI 133 PciIoIoRead ( 134 IN EFI_PCI_IO_PROTOCOL *This, 135 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 136 IN UINT8 BarIndex, 137 IN UINT64 Offset, 138 IN UINTN Count, 139 IN OUT VOID *Buffer 140 ); 141 142 EFI_STATUS 143 EFIAPI 144 PciIoIoWrite ( 145 IN EFI_PCI_IO_PROTOCOL *This, 146 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 147 IN UINT8 BarIndex, 148 IN UINT64 Offset, 149 IN UINTN Count, 150 IN OUT VOID *Buffer 151 ); 152 153 EFI_STATUS 154 EFIAPI 155 PciIoConfigRead ( 156 IN EFI_PCI_IO_PROTOCOL *This, 157 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 158 IN UINT32 Offset, 159 IN UINTN Count, 160 IN OUT VOID *Buffer 161 ); 162 163 EFI_STATUS 164 EFIAPI 165 PciIoConfigWrite ( 166 IN EFI_PCI_IO_PROTOCOL *This, 167 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 168 IN UINT32 Offset, 169 IN UINTN Count, 170 IN OUT VOID *Buffer 171 ); 172 173 EFI_STATUS 174 EFIAPI 175 PciIoCopyMem ( 176 IN EFI_PCI_IO_PROTOCOL *This, 177 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 178 IN UINT8 DestBarIndex, 179 IN UINT64 DestOffset, 180 IN UINT8 SrcBarIndex, 181 IN UINT64 SrcOffset, 182 IN UINTN Count 183 ); 184 185 EFI_STATUS 186 EFIAPI 187 PciIoMap ( 188 IN EFI_PCI_IO_PROTOCOL *This, 189 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, 190 IN VOID *HostAddress, 191 IN OUT UINTN *NumberOfBytes, 192 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 193 OUT VOID **Mapping 194 ); 195 196 EFI_STATUS 197 EFIAPI 198 PciIoUnmap ( 199 IN EFI_PCI_IO_PROTOCOL *This, 200 IN VOID *Mapping 201 ); 202 203 EFI_STATUS 204 EFIAPI 205 PciIoAllocateBuffer ( 206 IN EFI_PCI_IO_PROTOCOL *This, 207 IN EFI_ALLOCATE_TYPE Type, 208 IN EFI_MEMORY_TYPE MemoryType, 209 IN UINTN Pages, 210 OUT VOID **HostAddress, 211 IN UINT64 Attributes 212 ); 213 214 EFI_STATUS 215 EFIAPI 216 PciIoFreeBuffer ( 217 IN EFI_PCI_IO_PROTOCOL *This, 218 IN UINTN Pages, 219 IN VOID *HostAddress 220 ); 221 222 EFI_STATUS 223 EFIAPI 224 PciIoFlush ( 225 IN EFI_PCI_IO_PROTOCOL *This 226 ); 227 228 EFI_STATUS 229 EFIAPI 230 PciIoGetLocation ( 231 IN EFI_PCI_IO_PROTOCOL *This, 232 OUT UINTN *Segment, 233 OUT UINTN *Bus, 234 OUT UINTN *Device, 235 OUT UINTN *Function 236 ); 237 238 EFI_STATUS 239 EFIAPI 240 PciIoAttributes ( 241 IN EFI_PCI_IO_PROTOCOL *This, 242 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, 243 IN UINT64 Attributes, 244 OUT UINT64 *Result OPTIONAL 245 ); 246 247 EFI_STATUS 248 EFIAPI 249 PciIoGetBarAttributes( 250 IN EFI_PCI_IO_PROTOCOL *This, 251 IN UINT8 BarIndex, 252 OUT UINT64 *Supports, OPTIONAL 253 OUT VOID **Resources OPTIONAL 254 ); 255 256 EFI_STATUS 257 EFIAPI 258 PciIoSetBarAttributes( 259 IN EFI_PCI_IO_PROTOCOL *This, 260 IN UINT64 Attributes, 261 IN UINT8 BarIndex, 262 IN OUT UINT64 *Offset, 263 IN OUT UINT64 *Length 264 ); 265 266 267 // 268 // Pci Io Protocol Interface 269 // 270 EFI_PCI_IO_PROTOCOL PciIoInterface = { 271 PciIoPollMem, 272 PciIoPollIo, 273 { 274 PciIoMemRead, 275 PciIoMemWrite 276 }, 277 { 278 PciIoIoRead, 279 PciIoIoWrite 280 }, 281 { 282 PciIoConfigRead, 283 PciIoConfigWrite 284 }, 285 PciIoCopyMem, 286 PciIoMap, 287 PciIoUnmap, 288 PciIoAllocateBuffer, 289 PciIoFreeBuffer, 290 PciIoFlush, 291 PciIoGetLocation, 292 PciIoAttributes, 293 PciIoGetBarAttributes, 294 PciIoSetBarAttributes, 295 0, 296 NULL 297 }; 298 299 300 EFI_STATUS 301 InitializePciIoInstance ( 302 PCI_IO_DEVICE *PciIoDevice 303 ) 304 /*++ 305 306 Routine Description: 307 308 Initializes a PCI I/O Instance 309 310 Arguments: 311 312 Returns: 313 314 None 315 316 --*/ 317 318 { 319 CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL)); 320 return EFI_SUCCESS; 321 } 322 323 EFI_STATUS 324 PciIoVerifyBarAccess ( 325 PCI_IO_DEVICE *PciIoDevice, 326 UINT8 BarIndex, 327 PCI_BAR_TYPE Type, 328 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 329 IN UINTN Count, 330 UINT64 *Offset 331 ) 332 /*++ 333 334 Routine Description: 335 336 Verifies access to a PCI Base Address Register (BAR) 337 338 Arguments: 339 340 Returns: 341 342 None 343 344 --*/ 345 { 346 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 347 return EFI_INVALID_PARAMETER; 348 } 349 350 if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) { 351 return EFI_SUCCESS; 352 } 353 354 // 355 // BarIndex 0-5 is legal 356 // 357 if (BarIndex >= PCI_MAX_BAR) { 358 return EFI_INVALID_PARAMETER; 359 } 360 361 if (!CheckBarType (PciIoDevice, BarIndex, Type)) { 362 return EFI_INVALID_PARAMETER; 363 } 364 365 // 366 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX 367 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX 368 // 369 if (Width >= EfiPciIoWidthFifoUint8 && Width <= EfiPciIoWidthFifoUint64) { 370 Count = 1; 371 } 372 373 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03); 374 375 if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) { 376 return EFI_INVALID_PARAMETER; 377 } 378 379 *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress; 380 381 return EFI_SUCCESS; 382 } 383 384 EFI_STATUS 385 PciIoVerifyConfigAccess ( 386 PCI_IO_DEVICE *PciIoDevice, 387 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 388 IN UINTN Count, 389 IN UINT64 *Offset 390 ) 391 /*++ 392 393 Routine Description: 394 395 Verifies access to a PCI Config Header 396 397 Arguments: 398 399 Returns: 400 401 None 402 403 --*/ 404 { 405 UINT64 ExtendOffset; 406 407 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 408 return EFI_INVALID_PARAMETER; 409 } 410 411 // 412 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX 413 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX 414 // 415 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03); 416 417 if (PciIoDevice->IsPciExp) { 418 if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) { 419 return EFI_UNSUPPORTED; 420 } 421 422 ExtendOffset = LShiftU64 (*Offset, 32); 423 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0); 424 *Offset = (*Offset) | ExtendOffset; 425 426 } else { 427 if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) { 428 return EFI_UNSUPPORTED; 429 } 430 431 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset); 432 } 433 434 return EFI_SUCCESS; 435 } 436 437 EFI_STATUS 438 EFIAPI 439 PciIoPollMem ( 440 IN EFI_PCI_IO_PROTOCOL *This, 441 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 442 IN UINT8 BarIndex, 443 IN UINT64 Offset, 444 IN UINT64 Mask, 445 IN UINT64 Value, 446 IN UINT64 Delay, 447 OUT UINT64 *Result 448 ) 449 /*++ 450 451 Routine Description: 452 453 Poll PCI Memmory 454 455 Arguments: 456 457 Returns: 458 459 None 460 461 --*/ 462 { 463 EFI_STATUS Status; 464 PCI_IO_DEVICE *PciIoDevice; 465 466 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 467 468 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 469 return EFI_INVALID_PARAMETER; 470 } 471 472 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset); 473 if (EFI_ERROR (Status)) { 474 return EFI_UNSUPPORTED; 475 } 476 477 if (Width > EfiPciIoWidthUint64) { 478 return EFI_INVALID_PARAMETER; 479 } 480 481 Status = PciIoDevice->PciRootBridgeIo->PollMem ( 482 PciIoDevice->PciRootBridgeIo, 483 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 484 Offset, 485 Mask, 486 Value, 487 Delay, 488 Result 489 ); 490 return Status; 491 } 492 493 EFI_STATUS 494 EFIAPI 495 PciIoPollIo ( 496 IN EFI_PCI_IO_PROTOCOL *This, 497 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 498 IN UINT8 BarIndex, 499 IN UINT64 Offset, 500 IN UINT64 Mask, 501 IN UINT64 Value, 502 IN UINT64 Delay, 503 OUT UINT64 *Result 504 ) 505 /*++ 506 507 Routine Description: 508 509 Poll PCI IO 510 511 Arguments: 512 513 Returns: 514 515 None 516 517 --*/ 518 { 519 EFI_STATUS Status; 520 PCI_IO_DEVICE *PciIoDevice; 521 522 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 523 524 if ((UINT32)Width > EfiPciIoWidthUint64) { 525 return EFI_INVALID_PARAMETER; 526 } 527 528 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset); 529 if (EFI_ERROR (Status)) { 530 return EFI_UNSUPPORTED; 531 } 532 533 Status = PciIoDevice->PciRootBridgeIo->PollIo ( 534 PciIoDevice->PciRootBridgeIo, 535 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 536 Offset, 537 Mask, 538 Value, 539 Delay, 540 Result 541 ); 542 543 return Status; 544 } 545 546 EFI_STATUS 547 EFIAPI 548 PciIoMemRead ( 549 IN EFI_PCI_IO_PROTOCOL *This, 550 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 551 IN UINT8 BarIndex, 552 IN UINT64 Offset, 553 IN UINTN Count, 554 IN OUT VOID *Buffer 555 ) 556 /*++ 557 558 Routine Description: 559 560 Performs a PCI Memory Read Cycle 561 562 Arguments: 563 564 Returns: 565 566 None 567 568 --*/ 569 { 570 EFI_STATUS Status; 571 PCI_IO_DEVICE *PciIoDevice; 572 573 if (Buffer == NULL){ 574 return EFI_INVALID_PARAMETER; 575 } 576 577 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 578 579 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 580 return EFI_INVALID_PARAMETER; 581 } 582 583 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset); 584 if (EFI_ERROR (Status)) { 585 return EFI_UNSUPPORTED; 586 } 587 588 Status = PciIoDevice->PciRootBridgeIo->Mem.Read ( 589 PciIoDevice->PciRootBridgeIo, 590 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 591 Offset, 592 Count, 593 Buffer 594 ); 595 596 return Status; 597 } 598 599 EFI_STATUS 600 EFIAPI 601 PciIoMemWrite ( 602 IN EFI_PCI_IO_PROTOCOL *This, 603 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 604 IN UINT8 BarIndex, 605 IN UINT64 Offset, 606 IN UINTN Count, 607 IN OUT VOID *Buffer 608 ) 609 /*++ 610 611 Routine Description: 612 613 Performs a PCI Memory Write Cycle 614 615 Arguments: 616 617 Returns: 618 619 None 620 621 --*/ 622 { 623 EFI_STATUS Status; 624 PCI_IO_DEVICE *PciIoDevice; 625 626 if (Buffer == NULL){ 627 return EFI_INVALID_PARAMETER; 628 } 629 630 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 631 632 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 633 return EFI_INVALID_PARAMETER; 634 } 635 636 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset); 637 if (EFI_ERROR (Status)) { 638 return EFI_UNSUPPORTED; 639 } 640 641 Status = PciIoDevice->PciRootBridgeIo->Mem.Write ( 642 PciIoDevice->PciRootBridgeIo, 643 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 644 Offset, 645 Count, 646 Buffer 647 ); 648 649 return Status; 650 } 651 652 EFI_STATUS 653 EFIAPI 654 PciIoIoRead ( 655 IN EFI_PCI_IO_PROTOCOL *This, 656 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 657 IN UINT8 BarIndex, 658 IN UINT64 Offset, 659 IN UINTN Count, 660 IN OUT VOID *Buffer 661 ) 662 /*++ 663 664 Routine Description: 665 666 Performs a PCI I/O Read Cycle 667 668 Arguments: 669 670 Returns: 671 672 None 673 674 --*/ 675 { 676 EFI_STATUS Status; 677 PCI_IO_DEVICE *PciIoDevice; 678 679 if (Buffer == NULL){ 680 return EFI_INVALID_PARAMETER; 681 } 682 683 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 684 685 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 686 return EFI_INVALID_PARAMETER; 687 } 688 689 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset); 690 if (EFI_ERROR (Status)) { 691 return EFI_UNSUPPORTED; 692 } 693 694 Status = PciIoDevice->PciRootBridgeIo->Io.Read ( 695 PciIoDevice->PciRootBridgeIo, 696 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 697 Offset, 698 Count, 699 Buffer 700 ); 701 702 return Status; 703 } 704 705 EFI_STATUS 706 EFIAPI 707 PciIoIoWrite ( 708 IN EFI_PCI_IO_PROTOCOL *This, 709 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 710 IN UINT8 BarIndex, 711 IN UINT64 Offset, 712 IN UINTN Count, 713 IN OUT VOID *Buffer 714 ) 715 /*++ 716 717 Routine Description: 718 719 Performs a PCI I/O Write Cycle 720 721 Arguments: 722 723 Returns: 724 725 None 726 727 --*/ 728 { 729 EFI_STATUS Status; 730 PCI_IO_DEVICE *PciIoDevice; 731 732 if (Buffer == NULL){ 733 return EFI_INVALID_PARAMETER; 734 } 735 736 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 737 738 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 739 return EFI_INVALID_PARAMETER; 740 } 741 742 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset); 743 if (EFI_ERROR (Status)) { 744 return EFI_UNSUPPORTED; 745 } 746 747 Status = PciIoDevice->PciRootBridgeIo->Io.Write ( 748 PciIoDevice->PciRootBridgeIo, 749 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 750 Offset, 751 Count, 752 Buffer 753 ); 754 755 return Status; 756 } 757 758 EFI_STATUS 759 EFIAPI 760 PciIoConfigRead ( 761 IN EFI_PCI_IO_PROTOCOL *This, 762 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 763 IN UINT32 Offset, 764 IN UINTN Count, 765 IN OUT VOID *Buffer 766 ) 767 /*++ 768 769 Routine Description: 770 771 Performs a PCI Configuration Read Cycle 772 773 Arguments: 774 775 Returns: 776 777 None 778 779 --*/ 780 { 781 EFI_STATUS Status; 782 PCI_IO_DEVICE *PciIoDevice; 783 UINT64 Address; 784 785 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 786 787 Address = Offset; 788 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address); 789 if (EFI_ERROR (Status)) { 790 return Status; 791 } 792 793 Status = PciIoDevice->PciRootBridgeIo->Pci.Read ( 794 PciIoDevice->PciRootBridgeIo, 795 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 796 Address, 797 Count, 798 Buffer 799 ); 800 801 return Status; 802 } 803 804 EFI_STATUS 805 EFIAPI 806 PciIoConfigWrite ( 807 IN EFI_PCI_IO_PROTOCOL *This, 808 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 809 IN UINT32 Offset, 810 IN UINTN Count, 811 IN OUT VOID *Buffer 812 ) 813 /*++ 814 815 Routine Description: 816 817 Performs a PCI Configuration Write Cycle 818 819 Arguments: 820 821 Returns: 822 823 None 824 825 --*/ 826 { 827 EFI_STATUS Status; 828 PCI_IO_DEVICE *PciIoDevice; 829 UINT64 Address; 830 831 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 832 833 Address = Offset; 834 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address); 835 if (EFI_ERROR (Status)) { 836 return Status; 837 } 838 839 Status = PciIoDevice->PciRootBridgeIo->Pci.Write ( 840 PciIoDevice->PciRootBridgeIo, 841 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 842 Address, 843 Count, 844 Buffer 845 ); 846 847 return Status; 848 } 849 850 EFI_STATUS 851 EFIAPI 852 PciIoCopyMem ( 853 IN EFI_PCI_IO_PROTOCOL *This, 854 IN EFI_PCI_IO_PROTOCOL_WIDTH Width, 855 IN UINT8 DestBarIndex, 856 IN UINT64 DestOffset, 857 IN UINT8 SrcBarIndex, 858 IN UINT64 SrcOffset, 859 IN UINTN Count 860 ) 861 /*++ 862 863 Routine Description: 864 865 Copy PCI Memory 866 867 Arguments: 868 869 Returns: 870 871 None 872 873 --*/ 874 { 875 EFI_STATUS Status; 876 PCI_IO_DEVICE *PciIoDevice; 877 878 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 879 880 if ((UINT32)Width >= EfiPciIoWidthMaximum) { 881 return EFI_INVALID_PARAMETER; 882 } 883 884 if (Width == EfiPciIoWidthFifoUint8 || 885 Width == EfiPciIoWidthFifoUint16 || 886 Width == EfiPciIoWidthFifoUint32 || 887 Width == EfiPciIoWidthFifoUint64 || 888 Width == EfiPciIoWidthFillUint8 || 889 Width == EfiPciIoWidthFillUint16 || 890 Width == EfiPciIoWidthFillUint32 || 891 Width == EfiPciIoWidthFillUint64) { 892 return EFI_INVALID_PARAMETER; 893 } 894 895 Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset); 896 if (EFI_ERROR (Status)) { 897 return EFI_UNSUPPORTED; 898 } 899 900 Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset); 901 if (EFI_ERROR (Status)) { 902 return EFI_UNSUPPORTED; 903 } 904 905 Status = PciIoDevice->PciRootBridgeIo->CopyMem ( 906 PciIoDevice->PciRootBridgeIo, 907 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, 908 DestOffset, 909 SrcOffset, 910 Count 911 ); 912 913 return Status; 914 } 915 916 EFI_STATUS 917 EFIAPI 918 PciIoMap ( 919 IN EFI_PCI_IO_PROTOCOL *This, 920 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, 921 IN VOID *HostAddress, 922 IN OUT UINTN *NumberOfBytes, 923 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 924 OUT VOID **Mapping 925 ) 926 /*++ 927 928 Routine Description: 929 930 Maps a memory region for DMA 931 932 Arguments: 933 934 Returns: 935 936 None 937 938 --*/ 939 { 940 EFI_STATUS Status; 941 PCI_IO_DEVICE *PciIoDevice; 942 943 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 944 945 if ((UINT32)Operation >= EfiPciIoOperationMaximum) { 946 return EFI_INVALID_PARAMETER; 947 } 948 949 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) { 950 return EFI_INVALID_PARAMETER; 951 } 952 953 if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) { 954 Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64); 955 } 956 957 Status = PciIoDevice->PciRootBridgeIo->Map ( 958 PciIoDevice->PciRootBridgeIo, 959 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation, 960 HostAddress, 961 NumberOfBytes, 962 DeviceAddress, 963 Mapping 964 ); 965 966 return Status; 967 } 968 969 EFI_STATUS 970 EFIAPI 971 PciIoUnmap ( 972 IN EFI_PCI_IO_PROTOCOL *This, 973 IN VOID *Mapping 974 ) 975 /*++ 976 977 Routine Description: 978 979 Unmaps a memory region for DMA 980 981 Arguments: 982 983 Returns: 984 985 None 986 987 --*/ 988 { 989 EFI_STATUS Status; 990 PCI_IO_DEVICE *PciIoDevice; 991 992 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 993 994 Status = PciIoDevice->PciRootBridgeIo->Unmap ( 995 PciIoDevice->PciRootBridgeIo, 996 Mapping 997 ); 998 999 return Status; 1000 } 1001 1002 EFI_STATUS 1003 EFIAPI 1004 PciIoAllocateBuffer ( 1005 IN EFI_PCI_IO_PROTOCOL *This, 1006 IN EFI_ALLOCATE_TYPE Type, 1007 IN EFI_MEMORY_TYPE MemoryType, 1008 IN UINTN Pages, 1009 OUT VOID **HostAddress, 1010 IN UINT64 Attributes 1011 ) 1012 /*++ 1013 1014 Routine Description: 1015 1016 Allocates a common buffer for DMA 1017 1018 Arguments: 1019 1020 Returns: 1021 1022 None 1023 1024 --*/ 1025 { 1026 EFI_STATUS Status; 1027 PCI_IO_DEVICE *PciIoDevice; 1028 1029 if (Attributes & 1030 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) { 1031 return EFI_UNSUPPORTED; 1032 } 1033 1034 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 1035 1036 if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) { 1037 Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE; 1038 } 1039 1040 Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer ( 1041 PciIoDevice->PciRootBridgeIo, 1042 Type, 1043 MemoryType, 1044 Pages, 1045 HostAddress, 1046 Attributes 1047 ); 1048 1049 return Status; 1050 } 1051 1052 EFI_STATUS 1053 EFIAPI 1054 PciIoFreeBuffer ( 1055 IN EFI_PCI_IO_PROTOCOL *This, 1056 IN UINTN Pages, 1057 IN VOID *HostAddress 1058 ) 1059 /*++ 1060 1061 Routine Description: 1062 1063 Frees a common buffer 1064 1065 Arguments: 1066 1067 Returns: 1068 1069 None 1070 1071 --*/ 1072 { 1073 EFI_STATUS Status; 1074 PCI_IO_DEVICE *PciIoDevice; 1075 1076 if( HostAddress == NULL ){ 1077 return EFI_INVALID_PARAMETER; 1078 } 1079 1080 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 1081 1082 Status = PciIoDevice->PciRootBridgeIo->FreeBuffer ( 1083 PciIoDevice->PciRootBridgeIo, 1084 Pages, 1085 HostAddress 1086 ); 1087 1088 return Status; 1089 } 1090 1091 EFI_STATUS 1092 EFIAPI 1093 PciIoFlush ( 1094 IN EFI_PCI_IO_PROTOCOL *This 1095 ) 1096 /*++ 1097 1098 Routine Description: 1099 1100 Flushes a DMA buffer 1101 1102 Arguments: 1103 1104 Returns: 1105 1106 None 1107 1108 --*/ 1109 1110 { 1111 EFI_STATUS Status; 1112 UINT32 Register; 1113 PCI_IO_DEVICE *PciIoDevice; 1114 1115 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 1116 1117 // 1118 // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to 1119 // flush the posted write cycles through the PCI-PCI bridges 1120 // 1121 if (PciIoDevice->Parent != NULL) { 1122 Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register); 1123 } 1124 1125 // 1126 // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset 1127 // 1128 Status = PciIoDevice->PciRootBridgeIo->Flush ( 1129 PciIoDevice->PciRootBridgeIo 1130 ); 1131 1132 return Status; 1133 } 1134 1135 EFI_STATUS 1136 EFIAPI 1137 PciIoGetLocation ( 1138 IN EFI_PCI_IO_PROTOCOL *This, 1139 OUT UINTN *Segment, 1140 OUT UINTN *Bus, 1141 OUT UINTN *Device, 1142 OUT UINTN *Function 1143 ) 1144 /*++ 1145 1146 Routine Description: 1147 1148 Gets a PCI device's current bus number, device number, and function number. 1149 1150 Arguments: 1151 1152 Returns: 1153 1154 None 1155 1156 --*/ 1157 { 1158 PCI_IO_DEVICE *PciIoDevice; 1159 1160 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 1161 1162 if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) { 1163 return EFI_INVALID_PARAMETER; 1164 } 1165 1166 *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber; 1167 *Bus = PciIoDevice->BusNumber; 1168 *Device = PciIoDevice->DeviceNumber; 1169 *Function = PciIoDevice->FunctionNumber; 1170 1171 return EFI_SUCCESS; 1172 } 1173 1174 BOOLEAN 1175 CheckBarType ( 1176 IN PCI_IO_DEVICE *PciIoDevice, 1177 UINT8 BarIndex, 1178 PCI_BAR_TYPE BarType 1179 ) 1180 /*++ 1181 1182 Routine Description: 1183 1184 Sets a PCI controllers attributes on a resource range 1185 1186 Arguments: 1187 1188 Returns: 1189 1190 None 1191 1192 --*/ 1193 { 1194 switch (BarType) { 1195 1196 case PciBarTypeMem: 1197 1198 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 && 1199 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 && 1200 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 && 1201 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) { 1202 return FALSE; 1203 } 1204 1205 return TRUE; 1206 1207 case PciBarTypeIo: 1208 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 && 1209 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){ 1210 return FALSE; 1211 } 1212 1213 return TRUE; 1214 1215 default: 1216 break; 1217 } 1218 1219 return FALSE; 1220 } 1221 1222 EFI_STATUS 1223 EFIAPI 1224 PciIoAttributes ( 1225 IN EFI_PCI_IO_PROTOCOL * This, 1226 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, 1227 IN UINT64 Attributes, 1228 OUT UINT64 *Result OPTIONAL 1229 ) 1230 /*++ 1231 1232 Routine Description: 1233 1234 1235 Arguments: 1236 1237 Returns: 1238 1239 None 1240 1241 --*/ 1242 { 1243 EFI_STATUS Status; 1244 1245 PCI_IO_DEVICE *PciIoDevice; 1246 PCI_IO_DEVICE *Temp; 1247 UINT64 NewAttributes; 1248 UINT64 PciRootBridgeSupports; 1249 UINT64 PciRootBridgeAttributes; 1250 UINT64 NewPciRootBridgeAttributes; 1251 UINT64 NewUpStreamBridgeAttributes; 1252 UINT64 ModifiedPciRootBridgeAttributes; 1253 UINT16 EnableCommand; 1254 UINT16 DisableCommand; 1255 UINT16 EnableBridge; 1256 UINT16 DisableBridge; 1257 UINT16 Command; 1258 1259 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 1260 NewUpStreamBridgeAttributes = 0; 1261 1262 EnableCommand = 0; 1263 DisableCommand = 0; 1264 EnableBridge = 0; 1265 DisableBridge = 0; 1266 1267 switch (Operation) { 1268 case EfiPciIoAttributeOperationGet: 1269 if (Result == NULL) { 1270 return EFI_INVALID_PARAMETER; 1271 } 1272 1273 *Result = PciIoDevice->Attributes; 1274 return EFI_SUCCESS; 1275 1276 case EfiPciIoAttributeOperationSupported: 1277 if (Result == NULL) { 1278 return EFI_INVALID_PARAMETER; 1279 } 1280 1281 *Result = PciIoDevice->Supports; 1282 return EFI_SUCCESS; 1283 1284 case EfiPciIoAttributeOperationEnable: 1285 if(Attributes & ~(PciIoDevice->Supports)) { 1286 return EFI_UNSUPPORTED; 1287 } 1288 NewAttributes = PciIoDevice->Attributes | Attributes; 1289 break; 1290 case EfiPciIoAttributeOperationDisable: 1291 if(Attributes & ~(PciIoDevice->Supports)) { 1292 return EFI_UNSUPPORTED; 1293 } 1294 NewAttributes = PciIoDevice->Attributes & (~Attributes); 1295 break; 1296 case EfiPciIoAttributeOperationSet: 1297 if(Attributes & ~(PciIoDevice->Supports)) { 1298 return EFI_UNSUPPORTED; 1299 } 1300 NewAttributes = Attributes; 1301 break; 1302 default: 1303 return EFI_INVALID_PARAMETER; 1304 } 1305 1306 // 1307 // If VGA_IO is set, then set VGA_MEMORY too. This driver can not enable them seperately. 1308 // 1309 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) { 1310 NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; 1311 } 1312 1313 // 1314 // If VGA_MEMORY is set, then set VGA_IO too. This driver can not enable them seperately. 1315 // 1316 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) { 1317 NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO; 1318 } 1319 1320 // 1321 // If the attributes are already set correctly, then just return EFI_SUCCESS; 1322 // 1323 if ((NewAttributes ^ PciIoDevice->Attributes) == 0) { 1324 return EFI_SUCCESS; 1325 } 1326 1327 // 1328 // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and 1329 // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER. Strip these 3 bits off the new attribute mask so 1330 // a call to the PCI Root Bridge I/O Protocol can be made 1331 // 1332 1333 if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) { 1334 NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)); 1335 1336 // 1337 // Get the current attributes of this PCI device's PCI Root Bridge 1338 // 1339 Status = PciIoDevice->PciRootBridgeIo->GetAttributes ( 1340 PciIoDevice->PciRootBridgeIo, 1341 &PciRootBridgeSupports, 1342 &PciRootBridgeAttributes 1343 ); 1344 1345 // 1346 // Check to see if any of the PCI Root Bridge attributes are being modified 1347 // 1348 ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes; 1349 if (ModifiedPciRootBridgeAttributes) { 1350 1351 // 1352 // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing 1353 // 1354 if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) { 1355 // return EFI_UNSUPPORTED; 1356 } 1357 // 1358 // Call the PCI Root Bridge to attempt to modify the attributes 1359 // 1360 Status = PciIoDevice->PciRootBridgeIo->SetAttributes ( 1361 PciIoDevice->PciRootBridgeIo, 1362 NewPciRootBridgeAttributes, 1363 NULL, 1364 NULL 1365 ); 1366 if (EFI_ERROR (Status)) { 1367 // 1368 // The PCI Root Bridge could not modify the attributes, so return the error. 1369 // 1370 return Status; 1371 } 1372 } 1373 } 1374 1375 1376 if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) { 1377 1378 1379 // 1380 // Check to see if an VGA related attributes are being set. 1381 // 1382 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) { 1383 1384 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) { 1385 EnableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA; 1386 } else { 1387 DisableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA; 1388 } 1389 } 1390 1391 // 1392 // Check to see if an VGA related attributes are being set. 1393 // If ISA Enable on the PPB is set, the PPB will block the 1394 // 0x100-0x3FF for each 1KB block in the first 64K I/O block 1395 // 1396 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) { 1397 1398 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) { 1399 DisableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA; 1400 } else { 1401 EnableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA; 1402 } 1403 } 1404 1405 // 1406 // Check to see if an VGA related attributes are being set. 1407 // 1408 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) { 1409 1410 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) { 1411 EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1412 } else { 1413 DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1414 } 1415 } 1416 1417 } else { 1418 1419 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) { 1420 1421 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) { 1422 1423 // 1424 //Check if there have been an active VGA device on the same segment 1425 // 1426 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice); 1427 1428 if (Temp && Temp != PciIoDevice) { 1429 return EFI_UNSUPPORTED; 1430 } 1431 } 1432 } 1433 1434 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) { 1435 if (IS_PCI_GFX(&PciIoDevice->Pci)) { 1436 1437 // 1438 //Get the boot VGA on the same segement 1439 // 1440 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice); 1441 1442 if (!Temp) { 1443 1444 // 1445 // If there is no VGA device on the segement, set 1446 // this graphics card to decode the palette range 1447 // 1448 DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1449 } else { 1450 1451 // 1452 // Check these two agents are on the same path 1453 // 1454 if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) { 1455 1456 // 1457 // Check if they are on the same bus 1458 // 1459 if (Temp->Parent == PciIoDevice->Parent) { 1460 1461 PciReadCommandRegister (Temp, &Command); 1462 1463 // 1464 // If they are on the same bus, either one can 1465 // be set to snoop, the other set to decode 1466 // 1467 if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) { 1468 DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1469 } else { 1470 EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1471 } 1472 } else { 1473 1474 // 1475 // If they are on the same path but on the different bus 1476 // The first agent is set to snoop, the second one set to 1477 // decode 1478 // 1479 if (Temp->BusNumber > PciIoDevice->BusNumber) { 1480 PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); 1481 DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1482 } else { 1483 PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); 1484 EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1485 } 1486 } 1487 } else { 1488 1489 EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; 1490 } 1491 } 1492 } 1493 } 1494 } 1495 1496 // 1497 // Check to see of the I/O enable is being modified 1498 // 1499 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) { 1500 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) { 1501 EnableCommand |= EFI_PCI_COMMAND_IO_SPACE; 1502 } else { 1503 DisableCommand |= EFI_PCI_COMMAND_IO_SPACE; 1504 } 1505 } 1506 1507 // 1508 // Check to see of the Memory enable is being modified 1509 // 1510 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) { 1511 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) { 1512 EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE; 1513 } else { 1514 DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE; 1515 } 1516 } 1517 1518 // 1519 // Check to see of the Bus Master enable is being modified 1520 // 1521 if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) { 1522 if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) { 1523 EnableCommand |= EFI_PCI_COMMAND_BUS_MASTER; 1524 } else { 1525 DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER; 1526 } 1527 } 1528 1529 Status = EFI_SUCCESS; 1530 if (EnableCommand) { 1531 Status = PciEnableCommandRegister(PciIoDevice, EnableCommand); 1532 } 1533 1534 if (DisableCommand) { 1535 Status = PciDisableCommandRegister(PciIoDevice, DisableCommand); 1536 } 1537 1538 if (EFI_ERROR(Status)) { 1539 return EFI_UNSUPPORTED; 1540 } 1541 1542 if (EnableBridge) { 1543 Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge); 1544 } 1545 1546 if (DisableBridge) { 1547 Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge); 1548 } 1549 1550 if (EFI_ERROR(Status)) { 1551 return EFI_UNSUPPORTED; 1552 } 1553 1554 // 1555 // Set the upstream bridge attributes 1556 // 1557 if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) { 1558 1559 // 1560 // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 1561 // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 1562 // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge 1563 // 1564 NewUpStreamBridgeAttributes = Attributes & \ 1565 (~(EFI_PCI_IO_ATTRIBUTE_IO | \ 1566 EFI_PCI_IO_ATTRIBUTE_MEMORY | \ 1567 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \ 1568 EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \ 1569 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \ 1570 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)); 1571 1572 if (NewUpStreamBridgeAttributes){ 1573 UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes); 1574 } 1575 } 1576 1577 PciIoDevice->Attributes = NewAttributes; 1578 1579 return Status; 1580 } 1581 1582 EFI_STATUS 1583 EFIAPI 1584 PciIoGetBarAttributes ( 1585 IN EFI_PCI_IO_PROTOCOL * This, 1586 IN UINT8 BarIndex, 1587 OUT UINT64 *Supports, OPTIONAL 1588 OUT VOID **Resources OPTIONAL 1589 ) 1590 /*++ 1591 1592 Routine Description: 1593 1594 1595 Arguments: 1596 1597 Returns: 1598 1599 None 1600 1601 --*/ 1602 { 1603 UINT8 *Configuration; 1604 PCI_IO_DEVICE *PciIoDevice; 1605 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace; 1606 EFI_ACPI_END_TAG_DESCRIPTOR *End; 1607 1608 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 1609 1610 if (Supports == NULL && Resources == NULL) { 1611 return EFI_INVALID_PARAMETER; 1612 } 1613 1614 if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) { 1615 return EFI_UNSUPPORTED; 1616 } 1617 1618 // 1619 // This driver does not support modifications to the WRITE_COMBINE or 1620 // CACHED attributes for BAR ranges. 1621 // 1622 if (Supports != NULL) { 1623 *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; 1624 } 1625 1626 if (Resources != NULL) { 1627 Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); 1628 if (Configuration == NULL) { 1629 return EFI_OUT_OF_RESOURCES; 1630 } 1631 1632 AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; 1633 1634 AddressSpace->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; 1635 AddressSpace->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3); 1636 1637 AddressSpace->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress; 1638 AddressSpace->AddrLen = PciIoDevice->PciBar[BarIndex].Length; 1639 AddressSpace->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment; 1640 1641 switch (PciIoDevice->PciBar[BarIndex].BarType) { 1642 case PciBarTypeIo16: 1643 case PciBarTypeIo32: 1644 // 1645 // Io 1646 // 1647 AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; 1648 break; 1649 1650 case PciBarTypeMem32: 1651 // 1652 // Mem 1653 // 1654 AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 1655 // 1656 // 32 bit 1657 // 1658 AddressSpace->AddrSpaceGranularity = 32; 1659 break; 1660 1661 case PciBarTypePMem32: 1662 // 1663 // Mem 1664 // 1665 AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 1666 // 1667 // prefechable 1668 // 1669 AddressSpace->SpecificFlag = 0x6; 1670 // 1671 // 32 bit 1672 // 1673 AddressSpace->AddrSpaceGranularity = 32; 1674 break; 1675 1676 case PciBarTypeMem64: 1677 // 1678 // Mem 1679 // 1680 AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 1681 // 1682 // 64 bit 1683 // 1684 AddressSpace->AddrSpaceGranularity = 64; 1685 break; 1686 1687 case PciBarTypePMem64: 1688 // 1689 // Mem 1690 // 1691 AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 1692 // 1693 // prefechable 1694 // 1695 AddressSpace->SpecificFlag = 0x6; 1696 // 1697 // 64 bit 1698 // 1699 AddressSpace->AddrSpaceGranularity = 64; 1700 break; 1701 1702 default: 1703 break; 1704 } 1705 1706 // 1707 // put the checksum 1708 // 1709 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AddressSpace + 1); 1710 End->Desc = ACPI_END_TAG_DESCRIPTOR; 1711 End->Checksum = 0; 1712 1713 *Resources = Configuration; 1714 } 1715 1716 return EFI_SUCCESS; 1717 } 1718 1719 EFI_STATUS 1720 EFIAPI 1721 PciIoSetBarAttributes ( 1722 IN EFI_PCI_IO_PROTOCOL *This, 1723 IN UINT64 Attributes, 1724 IN UINT8 BarIndex, 1725 IN OUT UINT64 *Offset, 1726 IN OUT UINT64 *Length 1727 ) 1728 /*++ 1729 1730 Routine Description: 1731 1732 1733 Arguments: 1734 1735 Returns: 1736 1737 None 1738 1739 --*/ 1740 { 1741 EFI_STATUS Status; 1742 PCI_IO_DEVICE *PciIoDevice; 1743 UINT64 NonRelativeOffset; 1744 UINT64 Supports; 1745 1746 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); 1747 1748 // 1749 // Make sure Offset and Length are not NULL 1750 // 1751 if (Offset == NULL || Length == NULL) { 1752 return EFI_INVALID_PARAMETER; 1753 } 1754 1755 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) { 1756 return EFI_UNSUPPORTED; 1757 } 1758 // 1759 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes. 1760 // If Attributes is not 0, then return EFI_UNSUPPORTED. 1761 // 1762 Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; 1763 1764 if (Attributes != (Attributes & Supports)) { 1765 return EFI_UNSUPPORTED; 1766 } 1767 // 1768 // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and 1769 // Length are valid for this PCI device. 1770 // 1771 NonRelativeOffset = *Offset; 1772 Status = PciIoVerifyBarAccess ( 1773 PciIoDevice, 1774 BarIndex, 1775 PciBarTypeMem, 1776 EfiPciIoWidthUint8, 1777 (UINT32) *Length, 1778 &NonRelativeOffset 1779 ); 1780 if (EFI_ERROR (Status)) { 1781 return EFI_UNSUPPORTED; 1782 } 1783 1784 return EFI_SUCCESS; 1785 } 1786 1787 EFI_STATUS 1788 UpStreamBridgesAttributes ( 1789 IN PCI_IO_DEVICE *PciIoDevice, 1790 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, 1791 IN UINT64 Attributes 1792 ) 1793 /*++ 1794 1795 Routine Description: 1796 1797 Arguments: 1798 1799 Returns: 1800 1801 None 1802 1803 --*/ 1804 { 1805 PCI_IO_DEVICE *Parent; 1806 EFI_PCI_IO_PROTOCOL *PciIo; 1807 1808 Parent = PciIoDevice->Parent; 1809 1810 while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) { 1811 1812 // 1813 // Get the PciIo Protocol 1814 // 1815 PciIo = &Parent->PciIo; 1816 1817 PciIo->Attributes (PciIo, Operation, Attributes, NULL); 1818 1819 Parent = Parent->Parent; 1820 } 1821 1822 return EFI_SUCCESS; 1823 } 1824 1825 BOOLEAN 1826 PciDevicesOnTheSamePath ( 1827 IN PCI_IO_DEVICE *PciDevice1, 1828 IN PCI_IO_DEVICE *PciDevice2 1829 ) 1830 /*++ 1831 1832 Routine Description: 1833 1834 Arguments: 1835 1836 PciDevice1 - The pointer to the first PCI_IO_DEVICE. 1837 PciDevice2 - The pointer to the second PCI_IO_DEVICE. 1838 1839 Returns: 1840 1841 TRUE - The two Pci devices are on the same path. 1842 FALSE - The two Pci devices are not on the same path. 1843 1844 --*/ 1845 { 1846 1847 if (PciDevice1->Parent == PciDevice2->Parent) { 1848 return TRUE; 1849 } 1850 1851 return (BOOLEAN) ((PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1))); 1852 } 1853