1 /** @file 2 PCI Library using SMM PCI Root Bridge I/O Protocol. 3 4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials are 6 licensed and made available under the terms and conditions of 7 the BSD License which accompanies this distribution. The full 8 text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 #include <PiSmm.h> 16 #include <Protocol/SmmPciRootBridgeIo.h> 17 #include <Library/PciLib.h> 18 #include <Library/DebugLib.h> 19 #include <Library/BaseLib.h> 20 #include <Library/SmmServicesTableLib.h> 21 22 23 /** 24 Assert the validity of a PCI address. A valid PCI address should contain 1's 25 only in the low 28 bits. 26 27 @param A The address to validate. 28 @param M Additional bits to assert to be zero. 29 30 **/ 31 #define ASSERT_INVALID_PCI_ADDRESS(A,M) \ 32 ASSERT (((A) & (~0xfffffff | (M))) == 0) 33 34 /** 35 Translate PCI Lib address into format of PCI Root Bridge I/O Protocol. 36 37 @param A The address that encodes the PCI Bus, Device, Function and 38 Register. 39 40 **/ 41 #define PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS(A) \ 42 ((((A) << 4) & 0xff000000) | (((A) >> 4) & 0x00000700) | (((A) << 1) & 0x001f0000) | (LShiftU64((A) & 0xfff, 32))) 43 44 // 45 // Global varible to cache pointer to PCI Root Bridge I/O protocol. 46 // 47 EFI_SMM_PCI_ROOT_BRIDGE_IO_PROTOCOL *mSmmPciRootBridgeIo = NULL; 48 49 /** 50 The constructor function caches the pointer to PCI Root Bridge I/O protocol. 51 52 The constructor function locates PCI Root Bridge I/O protocol from protocol database. 53 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. 54 55 @param ImageHandle The firmware allocated handle for the EFI image. 56 @param SystemTable A pointer to the EFI System Table. 57 58 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. 59 60 **/ 61 EFI_STATUS 62 EFIAPI 63 PciLibConstructor ( 64 IN EFI_HANDLE ImageHandle, 65 IN EFI_SYSTEM_TABLE *SystemTable 66 ) 67 { 68 EFI_STATUS Status; 69 70 Status = gSmst->SmmLocateProtocol (&gEfiSmmPciRootBridgeIoProtocolGuid, NULL, (VOID**) &mSmmPciRootBridgeIo); 71 ASSERT_EFI_ERROR (Status); 72 ASSERT (mSmmPciRootBridgeIo != NULL); 73 74 return EFI_SUCCESS; 75 } 76 77 /** 78 Internal worker function to read a PCI configuration register. 79 80 This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Read() service. 81 It reads and returns the PCI configuration register specified by Address, 82 the width of data is specified by Width. 83 84 @param Address The address that encodes the PCI Bus, Device, Function and 85 Register. 86 @param Width The width of data to read 87 88 @return The value read from the PCI configuration register. 89 90 **/ 91 UINT32 92 SmmPciLibPciRootBridgeIoReadWorker ( 93 IN UINTN Address, 94 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width 95 ) 96 { 97 UINT32 Data; 98 99 mSmmPciRootBridgeIo->Pci.Read ( 100 mSmmPciRootBridgeIo, 101 Width, 102 PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), 103 1, 104 &Data 105 ); 106 107 return Data; 108 } 109 110 /** 111 Internal worker function to writes a PCI configuration register. 112 113 This function wraps EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Pci.Write() service. 114 It writes the PCI configuration register specified by Address with the 115 value specified by Data. The width of data is specifed by Width. 116 Data is returned. 117 118 @param Address The address that encodes the PCI Bus, Device, Function and 119 Register. 120 @param Width The width of data to write 121 @param Data The value to write. 122 123 @return The value written to the PCI configuration register. 124 125 **/ 126 UINT32 127 SmmPciLibPciRootBridgeIoWriteWorker ( 128 IN UINTN Address, 129 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 130 IN UINT32 Data 131 ) 132 { 133 mSmmPciRootBridgeIo->Pci.Write ( 134 mSmmPciRootBridgeIo, 135 Width, 136 PCI_TO_PCI_ROOT_BRIDGE_IO_ADDRESS (Address), 137 1, 138 &Data 139 ); 140 return Data; 141 } 142 143 /** 144 Registers a PCI device so PCI configuration registers may be accessed after 145 SetVirtualAddressMap(). 146 147 Registers the PCI device specified by Address so all the PCI configuration registers 148 associated with that PCI device may be accessed after SetVirtualAddressMap() is called. 149 150 If Address > 0x0FFFFFFF, then ASSERT(). 151 152 @param Address The address that encodes the PCI Bus, Device, Function and 153 Register. 154 155 @retval RETURN_SUCCESS The PCI device was registered for runtime access. 156 @retval RETURN_UNSUPPORTED An attempt was made to call this function 157 after ExitBootServices(). 158 @retval RETURN_UNSUPPORTED The resources required to access the PCI device 159 at runtime could not be mapped. 160 @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to 161 complete the registration. 162 163 **/ 164 RETURN_STATUS 165 EFIAPI 166 PciRegisterForRuntimeAccess ( 167 IN UINTN Address 168 ) 169 { 170 ASSERT_INVALID_PCI_ADDRESS (Address, 0); 171 return RETURN_UNSUPPORTED; 172 } 173 174 /** 175 Reads an 8-bit PCI configuration register. 176 177 Reads and returns the 8-bit PCI configuration register specified by Address. 178 This function must guarantee that all PCI read and write operations are 179 serialized. 180 181 If Address > 0x0FFFFFFF, then ASSERT(). 182 183 @param Address The address that encodes the PCI Bus, Device, Function and 184 Register. 185 186 @return The read value from the PCI configuration register. 187 188 **/ 189 UINT8 190 EFIAPI 191 PciRead8 ( 192 IN UINTN Address 193 ) 194 { 195 ASSERT_INVALID_PCI_ADDRESS (Address, 0); 196 197 return (UINT8) SmmPciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint8); 198 } 199 200 /** 201 Writes an 8-bit PCI configuration register. 202 203 Writes the 8-bit PCI configuration register specified by Address with the 204 value specified by Value. Value is returned. This function must guarantee 205 that all PCI read and write operations are serialized. 206 207 If Address > 0x0FFFFFFF, then ASSERT(). 208 209 @param Address The address that encodes the PCI Bus, Device, Function and 210 Register. 211 @param Value The value to write. 212 213 @return The value written to the PCI configuration register. 214 215 **/ 216 UINT8 217 EFIAPI 218 PciWrite8 ( 219 IN UINTN Address, 220 IN UINT8 Value 221 ) 222 { 223 ASSERT_INVALID_PCI_ADDRESS (Address, 0); 224 225 return (UINT8) SmmPciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint8, Value); 226 } 227 228 /** 229 Performs a bitwise OR of an 8-bit PCI configuration register with 230 an 8-bit value. 231 232 Reads the 8-bit PCI configuration register specified by Address, performs a 233 bitwise OR between the read result and the value specified by 234 OrData, and writes the result to the 8-bit PCI configuration register 235 specified by Address. The value written to the PCI configuration register is 236 returned. This function must guarantee that all PCI read and write operations 237 are serialized. 238 239 If Address > 0x0FFFFFFF, then ASSERT(). 240 241 @param Address The address that encodes the PCI Bus, Device, Function and 242 Register. 243 @param OrData The value to OR with the PCI configuration register. 244 245 @return The value written back to the PCI configuration register. 246 247 **/ 248 UINT8 249 EFIAPI 250 PciOr8 ( 251 IN UINTN Address, 252 IN UINT8 OrData 253 ) 254 { 255 return PciWrite8 (Address, (UINT8) (PciRead8 (Address) | OrData)); 256 } 257 258 /** 259 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit 260 value. 261 262 Reads the 8-bit PCI configuration register specified by Address, performs a 263 bitwise AND between the read result and the value specified by AndData, and 264 writes the result to the 8-bit PCI configuration register specified by 265 Address. The value written to the PCI configuration register is returned. 266 This function must guarantee that all PCI read and write operations are 267 serialized. 268 269 If Address > 0x0FFFFFFF, then ASSERT(). 270 271 @param Address The address that encodes the PCI Bus, Device, Function and 272 Register. 273 @param AndData The value to AND with the PCI configuration register. 274 275 @return The value written back to the PCI configuration register. 276 277 **/ 278 UINT8 279 EFIAPI 280 PciAnd8 ( 281 IN UINTN Address, 282 IN UINT8 AndData 283 ) 284 { 285 return PciWrite8 (Address, (UINT8) (PciRead8 (Address) & AndData)); 286 } 287 288 /** 289 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit 290 value, followed a bitwise OR with another 8-bit value. 291 292 Reads the 8-bit PCI configuration register specified by Address, performs a 293 bitwise AND between the read result and the value specified by AndData, 294 performs a bitwise OR between the result of the AND operation and 295 the value specified by OrData, and writes the result to the 8-bit PCI 296 configuration register specified by Address. The value written to the PCI 297 configuration register is returned. This function must guarantee that all PCI 298 read and write operations are serialized. 299 300 If Address > 0x0FFFFFFF, then ASSERT(). 301 302 @param Address The address that encodes the PCI Bus, Device, Function and 303 Register. 304 @param AndData The value to AND with the PCI configuration register. 305 @param OrData The value to OR with the result of the AND operation. 306 307 @return The value written back to the PCI configuration register. 308 309 **/ 310 UINT8 311 EFIAPI 312 PciAndThenOr8 ( 313 IN UINTN Address, 314 IN UINT8 AndData, 315 IN UINT8 OrData 316 ) 317 { 318 return PciWrite8 (Address, (UINT8) ((PciRead8 (Address) & AndData) | OrData)); 319 } 320 321 /** 322 Reads a bit field of a PCI configuration register. 323 324 Reads the bit field in an 8-bit PCI configuration register. The bit field is 325 specified by the StartBit and the EndBit. The value of the bit field is 326 returned. 327 328 If Address > 0x0FFFFFFF, then ASSERT(). 329 If StartBit is greater than 7, then ASSERT(). 330 If EndBit is greater than 7, then ASSERT(). 331 If EndBit is less than StartBit, then ASSERT(). 332 333 @param Address The PCI configuration register to read. 334 @param StartBit The ordinal of the least significant bit in the bit field. 335 Range 0..7. 336 @param EndBit The ordinal of the most significant bit in the bit field. 337 Range 0..7. 338 339 @return The value of the bit field read from the PCI configuration register. 340 341 **/ 342 UINT8 343 EFIAPI 344 PciBitFieldRead8 ( 345 IN UINTN Address, 346 IN UINTN StartBit, 347 IN UINTN EndBit 348 ) 349 { 350 return BitFieldRead8 (PciRead8 (Address), StartBit, EndBit); 351 } 352 353 /** 354 Writes a bit field to a PCI configuration register. 355 356 Writes Value to the bit field of the PCI configuration register. The bit 357 field is specified by the StartBit and the EndBit. All other bits in the 358 destination PCI configuration register are preserved. The new value of the 359 8-bit register is returned. 360 361 If Address > 0x0FFFFFFF, then ASSERT(). 362 If StartBit is greater than 7, then ASSERT(). 363 If EndBit is greater than 7, then ASSERT(). 364 If EndBit is less than StartBit, then ASSERT(). 365 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 366 367 @param Address The PCI configuration register to write. 368 @param StartBit The ordinal of the least significant bit in the bit field. 369 Range 0..7. 370 @param EndBit The ordinal of the most significant bit in the bit field. 371 Range 0..7. 372 @param Value The new value of the bit field. 373 374 @return The value written back to the PCI configuration register. 375 376 **/ 377 UINT8 378 EFIAPI 379 PciBitFieldWrite8 ( 380 IN UINTN Address, 381 IN UINTN StartBit, 382 IN UINTN EndBit, 383 IN UINT8 Value 384 ) 385 { 386 return PciWrite8 ( 387 Address, 388 BitFieldWrite8 (PciRead8 (Address), StartBit, EndBit, Value) 389 ); 390 } 391 392 /** 393 Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and 394 writes the result back to the bit field in the 8-bit port. 395 396 Reads the 8-bit PCI configuration register specified by Address, performs a 397 bitwise OR between the read result and the value specified by 398 OrData, and writes the result to the 8-bit PCI configuration register 399 specified by Address. The value written to the PCI configuration register is 400 returned. This function must guarantee that all PCI read and write operations 401 are serialized. Extra left bits in OrData are stripped. 402 403 If Address > 0x0FFFFFFF, then ASSERT(). 404 If StartBit is greater than 7, then ASSERT(). 405 If EndBit is greater than 7, then ASSERT(). 406 If EndBit is less than StartBit, then ASSERT(). 407 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 408 409 @param Address The PCI configuration register to write. 410 @param StartBit The ordinal of the least significant bit in the bit field. 411 Range 0..7. 412 @param EndBit The ordinal of the most significant bit in the bit field. 413 Range 0..7. 414 @param OrData The value to OR with the PCI configuration register. 415 416 @return The value written back to the PCI configuration register. 417 418 **/ 419 UINT8 420 EFIAPI 421 PciBitFieldOr8 ( 422 IN UINTN Address, 423 IN UINTN StartBit, 424 IN UINTN EndBit, 425 IN UINT8 OrData 426 ) 427 { 428 return PciWrite8 ( 429 Address, 430 BitFieldOr8 (PciRead8 (Address), StartBit, EndBit, OrData) 431 ); 432 } 433 434 /** 435 Reads a bit field in an 8-bit PCI configuration register, performs a bitwise 436 AND, and writes the result back to the bit field in the 8-bit register. 437 438 Reads the 8-bit PCI configuration register specified by Address, performs a 439 bitwise AND between the read result and the value specified by AndData, and 440 writes the result to the 8-bit PCI configuration register specified by 441 Address. The value written to the PCI configuration register is returned. 442 This function must guarantee that all PCI read and write operations are 443 serialized. Extra left bits in AndData are stripped. 444 445 If Address > 0x0FFFFFFF, then ASSERT(). 446 If StartBit is greater than 7, then ASSERT(). 447 If EndBit is greater than 7, then ASSERT(). 448 If EndBit is less than StartBit, then ASSERT(). 449 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 450 451 @param Address The PCI configuration register to write. 452 @param StartBit The ordinal of the least significant bit in the bit field. 453 Range 0..7. 454 @param EndBit The ordinal of the most significant bit in the bit field. 455 Range 0..7. 456 @param AndData The value to AND with the PCI configuration register. 457 458 @return The value written back to the PCI configuration register. 459 460 **/ 461 UINT8 462 EFIAPI 463 PciBitFieldAnd8 ( 464 IN UINTN Address, 465 IN UINTN StartBit, 466 IN UINTN EndBit, 467 IN UINT8 AndData 468 ) 469 { 470 return PciWrite8 ( 471 Address, 472 BitFieldAnd8 (PciRead8 (Address), StartBit, EndBit, AndData) 473 ); 474 } 475 476 /** 477 Reads a bit field in an 8-bit port, performs a bitwise AND followed by a 478 bitwise OR, and writes the result back to the bit field in the 479 8-bit port. 480 481 Reads the 8-bit PCI configuration register specified by Address, performs a 482 bitwise AND followed by a bitwise OR between the read result and 483 the value specified by AndData, and writes the result to the 8-bit PCI 484 configuration register specified by Address. The value written to the PCI 485 configuration register is returned. This function must guarantee that all PCI 486 read and write operations are serialized. Extra left bits in both AndData and 487 OrData are stripped. 488 489 If Address > 0x0FFFFFFF, then ASSERT(). 490 If StartBit is greater than 7, then ASSERT(). 491 If EndBit is greater than 7, then ASSERT(). 492 If EndBit is less than StartBit, then ASSERT(). 493 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 494 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 495 496 @param Address The PCI configuration register to write. 497 @param StartBit The ordinal of the least significant bit in the bit field. 498 Range 0..7. 499 @param EndBit The ordinal of the most significant bit in the bit field. 500 Range 0..7. 501 @param AndData The value to AND with the PCI configuration register. 502 @param OrData The value to OR with the result of the AND operation. 503 504 @return The value written back to the PCI configuration register. 505 506 **/ 507 UINT8 508 EFIAPI 509 PciBitFieldAndThenOr8 ( 510 IN UINTN Address, 511 IN UINTN StartBit, 512 IN UINTN EndBit, 513 IN UINT8 AndData, 514 IN UINT8 OrData 515 ) 516 { 517 return PciWrite8 ( 518 Address, 519 BitFieldAndThenOr8 (PciRead8 (Address), StartBit, EndBit, AndData, OrData) 520 ); 521 } 522 523 /** 524 Reads a 16-bit PCI configuration register. 525 526 Reads and returns the 16-bit PCI configuration register specified by Address. 527 This function must guarantee that all PCI read and write operations are 528 serialized. 529 530 If Address > 0x0FFFFFFF, then ASSERT(). 531 If Address is not aligned on a 16-bit boundary, then ASSERT(). 532 533 @param Address The address that encodes the PCI Bus, Device, Function and 534 Register. 535 536 @return The read value from the PCI configuration register. 537 538 **/ 539 UINT16 540 EFIAPI 541 PciRead16 ( 542 IN UINTN Address 543 ) 544 { 545 ASSERT_INVALID_PCI_ADDRESS (Address, 1); 546 547 return (UINT16) SmmPciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint16); 548 } 549 550 /** 551 Writes a 16-bit PCI configuration register. 552 553 Writes the 16-bit PCI configuration register specified by Address with the 554 value specified by Value. Value is returned. This function must guarantee 555 that all PCI read and write operations are serialized. 556 557 If Address > 0x0FFFFFFF, then ASSERT(). 558 If Address is not aligned on a 16-bit boundary, then ASSERT(). 559 560 @param Address The address that encodes the PCI Bus, Device, Function and 561 Register. 562 @param Value The value to write. 563 564 @return The value written to the PCI configuration register. 565 566 **/ 567 UINT16 568 EFIAPI 569 PciWrite16 ( 570 IN UINTN Address, 571 IN UINT16 Value 572 ) 573 { 574 ASSERT_INVALID_PCI_ADDRESS (Address, 1); 575 576 return (UINT16) SmmPciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint16, Value); 577 } 578 579 /** 580 Performs a bitwise OR of a 16-bit PCI configuration register with 581 a 16-bit value. 582 583 Reads the 16-bit PCI configuration register specified by Address, performs a 584 bitwise OR between the read result and the value specified by 585 OrData, and writes the result to the 16-bit PCI configuration register 586 specified by Address. The value written to the PCI configuration register is 587 returned. This function must guarantee that all PCI read and write operations 588 are serialized. 589 590 If Address > 0x0FFFFFFF, then ASSERT(). 591 If Address is not aligned on a 16-bit boundary, then ASSERT(). 592 593 @param Address The address that encodes the PCI Bus, Device, Function and 594 Register. 595 @param OrData The value to OR with the PCI configuration register. 596 597 @return The value written back to the PCI configuration register. 598 599 **/ 600 UINT16 601 EFIAPI 602 PciOr16 ( 603 IN UINTN Address, 604 IN UINT16 OrData 605 ) 606 { 607 return PciWrite16 (Address, (UINT16) (PciRead16 (Address) | OrData)); 608 } 609 610 /** 611 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit 612 value. 613 614 Reads the 16-bit PCI configuration register specified by Address, performs a 615 bitwise AND between the read result and the value specified by AndData, and 616 writes the result to the 16-bit PCI configuration register specified by 617 Address. The value written to the PCI configuration register is returned. 618 This function must guarantee that all PCI read and write operations are 619 serialized. 620 621 If Address > 0x0FFFFFFF, then ASSERT(). 622 If Address is not aligned on a 16-bit boundary, then ASSERT(). 623 624 @param Address The address that encodes the PCI Bus, Device, Function and 625 Register. 626 @param AndData The value to AND with the PCI configuration register. 627 628 @return The value written back to the PCI configuration register. 629 630 **/ 631 UINT16 632 EFIAPI 633 PciAnd16 ( 634 IN UINTN Address, 635 IN UINT16 AndData 636 ) 637 { 638 return PciWrite16 (Address, (UINT16) (PciRead16 (Address) & AndData)); 639 } 640 641 /** 642 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit 643 value, followed a bitwise OR with another 16-bit value. 644 645 Reads the 16-bit PCI configuration register specified by Address, performs a 646 bitwise AND between the read result and the value specified by AndData, 647 performs a bitwise OR between the result of the AND operation and 648 the value specified by OrData, and writes the result to the 16-bit PCI 649 configuration register specified by Address. The value written to the PCI 650 configuration register is returned. This function must guarantee that all PCI 651 read and write operations are serialized. 652 653 If Address > 0x0FFFFFFF, then ASSERT(). 654 If Address is not aligned on a 16-bit boundary, then ASSERT(). 655 656 @param Address The address that encodes the PCI Bus, Device, Function and 657 Register. 658 @param AndData The value to AND with the PCI configuration register. 659 @param OrData The value to OR with the result of the AND operation. 660 661 @return The value written back to the PCI configuration register. 662 663 **/ 664 UINT16 665 EFIAPI 666 PciAndThenOr16 ( 667 IN UINTN Address, 668 IN UINT16 AndData, 669 IN UINT16 OrData 670 ) 671 { 672 return PciWrite16 (Address, (UINT16) ((PciRead16 (Address) & AndData) | OrData)); 673 } 674 675 /** 676 Reads a bit field of a PCI configuration register. 677 678 Reads the bit field in a 16-bit PCI configuration register. The bit field is 679 specified by the StartBit and the EndBit. The value of the bit field is 680 returned. 681 682 If Address > 0x0FFFFFFF, then ASSERT(). 683 If Address is not aligned on a 16-bit boundary, then ASSERT(). 684 If StartBit is greater than 15, then ASSERT(). 685 If EndBit is greater than 15, then ASSERT(). 686 If EndBit is less than StartBit, then ASSERT(). 687 688 @param Address The PCI configuration register to read. 689 @param StartBit The ordinal of the least significant bit in the bit field. 690 Range 0..15. 691 @param EndBit The ordinal of the most significant bit in the bit field. 692 Range 0..15. 693 694 @return The value of the bit field read from the PCI configuration register. 695 696 **/ 697 UINT16 698 EFIAPI 699 PciBitFieldRead16 ( 700 IN UINTN Address, 701 IN UINTN StartBit, 702 IN UINTN EndBit 703 ) 704 { 705 return BitFieldRead16 (PciRead16 (Address), StartBit, EndBit); 706 } 707 708 /** 709 Writes a bit field to a PCI configuration register. 710 711 Writes Value to the bit field of the PCI configuration register. The bit 712 field is specified by the StartBit and the EndBit. All other bits in the 713 destination PCI configuration register are preserved. The new value of the 714 16-bit register is returned. 715 716 If Address > 0x0FFFFFFF, then ASSERT(). 717 If Address is not aligned on a 16-bit boundary, then ASSERT(). 718 If StartBit is greater than 15, then ASSERT(). 719 If EndBit is greater than 15, then ASSERT(). 720 If EndBit is less than StartBit, then ASSERT(). 721 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 722 723 @param Address The PCI configuration register to write. 724 @param StartBit The ordinal of the least significant bit in the bit field. 725 Range 0..15. 726 @param EndBit The ordinal of the most significant bit in the bit field. 727 Range 0..15. 728 @param Value The new value of the bit field. 729 730 @return The value written back to the PCI configuration register. 731 732 **/ 733 UINT16 734 EFIAPI 735 PciBitFieldWrite16 ( 736 IN UINTN Address, 737 IN UINTN StartBit, 738 IN UINTN EndBit, 739 IN UINT16 Value 740 ) 741 { 742 return PciWrite16 ( 743 Address, 744 BitFieldWrite16 (PciRead16 (Address), StartBit, EndBit, Value) 745 ); 746 } 747 748 /** 749 Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and 750 writes the result back to the bit field in the 16-bit port. 751 752 Reads the 16-bit PCI configuration register specified by Address, performs a 753 bitwise OR between the read result and the value specified by 754 OrData, and writes the result to the 16-bit PCI configuration register 755 specified by Address. The value written to the PCI configuration register is 756 returned. This function must guarantee that all PCI read and write operations 757 are serialized. Extra left bits in OrData are stripped. 758 759 If Address > 0x0FFFFFFF, then ASSERT(). 760 If Address is not aligned on a 16-bit boundary, then ASSERT(). 761 If StartBit is greater than 15, then ASSERT(). 762 If EndBit is greater than 15, then ASSERT(). 763 If EndBit is less than StartBit, then ASSERT(). 764 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 765 766 @param Address The PCI configuration register to write. 767 @param StartBit The ordinal of the least significant bit in the bit field. 768 Range 0..15. 769 @param EndBit The ordinal of the most significant bit in the bit field. 770 Range 0..15. 771 @param OrData The value to OR with the PCI configuration register. 772 773 @return The value written back to the PCI configuration register. 774 775 **/ 776 UINT16 777 EFIAPI 778 PciBitFieldOr16 ( 779 IN UINTN Address, 780 IN UINTN StartBit, 781 IN UINTN EndBit, 782 IN UINT16 OrData 783 ) 784 { 785 return PciWrite16 ( 786 Address, 787 BitFieldOr16 (PciRead16 (Address), StartBit, EndBit, OrData) 788 ); 789 } 790 791 /** 792 Reads a bit field in a 16-bit PCI configuration register, performs a bitwise 793 AND, and writes the result back to the bit field in the 16-bit register. 794 795 Reads the 16-bit PCI configuration register specified by Address, performs a 796 bitwise AND between the read result and the value specified by AndData, and 797 writes the result to the 16-bit PCI configuration register specified by 798 Address. The value written to the PCI configuration register is returned. 799 This function must guarantee that all PCI read and write operations are 800 serialized. Extra left bits in AndData are stripped. 801 802 If Address > 0x0FFFFFFF, then ASSERT(). 803 If Address is not aligned on a 16-bit boundary, then ASSERT(). 804 If StartBit is greater than 15, then ASSERT(). 805 If EndBit is greater than 15, then ASSERT(). 806 If EndBit is less than StartBit, then ASSERT(). 807 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 808 809 @param Address The PCI configuration register to write. 810 @param StartBit The ordinal of the least significant bit in the bit field. 811 Range 0..15. 812 @param EndBit The ordinal of the most significant bit in the bit field. 813 Range 0..15. 814 @param AndData The value to AND with the PCI configuration register. 815 816 @return The value written back to the PCI configuration register. 817 818 **/ 819 UINT16 820 EFIAPI 821 PciBitFieldAnd16 ( 822 IN UINTN Address, 823 IN UINTN StartBit, 824 IN UINTN EndBit, 825 IN UINT16 AndData 826 ) 827 { 828 return PciWrite16 ( 829 Address, 830 BitFieldAnd16 (PciRead16 (Address), StartBit, EndBit, AndData) 831 ); 832 } 833 834 /** 835 Reads a bit field in a 16-bit port, performs a bitwise AND followed by a 836 bitwise OR, and writes the result back to the bit field in the 837 16-bit port. 838 839 Reads the 16-bit PCI configuration register specified by Address, performs a 840 bitwise AND followed by a bitwise OR between the read result and 841 the value specified by AndData, and writes the result to the 16-bit PCI 842 configuration register specified by Address. The value written to the PCI 843 configuration register is returned. This function must guarantee that all PCI 844 read and write operations are serialized. Extra left bits in both AndData and 845 OrData are stripped. 846 847 If Address > 0x0FFFFFFF, then ASSERT(). 848 If Address is not aligned on a 16-bit boundary, then ASSERT(). 849 If StartBit is greater than 15, then ASSERT(). 850 If EndBit is greater than 15, then ASSERT(). 851 If EndBit is less than StartBit, then ASSERT(). 852 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 853 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 854 855 @param Address The PCI configuration register to write. 856 @param StartBit The ordinal of the least significant bit in the bit field. 857 Range 0..15. 858 @param EndBit The ordinal of the most significant bit in the bit field. 859 Range 0..15. 860 @param AndData The value to AND with the PCI configuration register. 861 @param OrData The value to OR with the result of the AND operation. 862 863 @return The value written back to the PCI configuration register. 864 865 **/ 866 UINT16 867 EFIAPI 868 PciBitFieldAndThenOr16 ( 869 IN UINTN Address, 870 IN UINTN StartBit, 871 IN UINTN EndBit, 872 IN UINT16 AndData, 873 IN UINT16 OrData 874 ) 875 { 876 return PciWrite16 ( 877 Address, 878 BitFieldAndThenOr16 (PciRead16 (Address), StartBit, EndBit, AndData, OrData) 879 ); 880 } 881 882 /** 883 Reads a 32-bit PCI configuration register. 884 885 Reads and returns the 32-bit PCI configuration register specified by Address. 886 This function must guarantee that all PCI read and write operations are 887 serialized. 888 889 If Address > 0x0FFFFFFF, then ASSERT(). 890 If Address is not aligned on a 32-bit boundary, then ASSERT(). 891 892 @param Address The address that encodes the PCI Bus, Device, Function and 893 Register. 894 895 @return The read value from the PCI configuration register. 896 897 **/ 898 UINT32 899 EFIAPI 900 PciRead32 ( 901 IN UINTN Address 902 ) 903 { 904 ASSERT_INVALID_PCI_ADDRESS (Address, 3); 905 906 return SmmPciLibPciRootBridgeIoReadWorker (Address, EfiPciWidthUint32); 907 } 908 909 /** 910 Writes a 32-bit PCI configuration register. 911 912 Writes the 32-bit PCI configuration register specified by Address with the 913 value specified by Value. Value is returned. This function must guarantee 914 that all PCI read and write operations are serialized. 915 916 If Address > 0x0FFFFFFF, then ASSERT(). 917 If Address is not aligned on a 32-bit boundary, then ASSERT(). 918 919 @param Address The address that encodes the PCI Bus, Device, Function and 920 Register. 921 @param Value The value to write. 922 923 @return The value written to the PCI configuration register. 924 925 **/ 926 UINT32 927 EFIAPI 928 PciWrite32 ( 929 IN UINTN Address, 930 IN UINT32 Value 931 ) 932 { 933 ASSERT_INVALID_PCI_ADDRESS (Address, 3); 934 935 return SmmPciLibPciRootBridgeIoWriteWorker (Address, EfiPciWidthUint32, Value); 936 } 937 938 /** 939 Performs a bitwise OR of a 32-bit PCI configuration register with 940 a 32-bit value. 941 942 Reads the 32-bit PCI configuration register specified by Address, performs a 943 bitwise OR between the read result and the value specified by 944 OrData, and writes the result to the 32-bit PCI configuration register 945 specified by Address. The value written to the PCI configuration register is 946 returned. This function must guarantee that all PCI read and write operations 947 are serialized. 948 949 If Address > 0x0FFFFFFF, then ASSERT(). 950 If Address is not aligned on a 32-bit boundary, then ASSERT(). 951 952 @param Address The address that encodes the PCI Bus, Device, Function and 953 Register. 954 @param OrData The value to OR with the PCI configuration register. 955 956 @return The value written back to the PCI configuration register. 957 958 **/ 959 UINT32 960 EFIAPI 961 PciOr32 ( 962 IN UINTN Address, 963 IN UINT32 OrData 964 ) 965 { 966 return PciWrite32 (Address, PciRead32 (Address) | OrData); 967 } 968 969 /** 970 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit 971 value. 972 973 Reads the 32-bit PCI configuration register specified by Address, performs a 974 bitwise AND between the read result and the value specified by AndData, and 975 writes the result to the 32-bit PCI configuration register specified by 976 Address. The value written to the PCI configuration register is returned. 977 This function must guarantee that all PCI read and write operations are 978 serialized. 979 980 If Address > 0x0FFFFFFF, then ASSERT(). 981 If Address is not aligned on a 32-bit boundary, then ASSERT(). 982 983 @param Address The address that encodes the PCI Bus, Device, Function and 984 Register. 985 @param AndData The value to AND with the PCI configuration register. 986 987 @return The value written back to the PCI configuration register. 988 989 **/ 990 UINT32 991 EFIAPI 992 PciAnd32 ( 993 IN UINTN Address, 994 IN UINT32 AndData 995 ) 996 { 997 return PciWrite32 (Address, PciRead32 (Address) & AndData); 998 } 999 1000 /** 1001 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit 1002 value, followed a bitwise OR with another 32-bit value. 1003 1004 Reads the 32-bit PCI configuration register specified by Address, performs a 1005 bitwise AND between the read result and the value specified by AndData, 1006 performs a bitwise OR between the result of the AND operation and 1007 the value specified by OrData, and writes the result to the 32-bit PCI 1008 configuration register specified by Address. The value written to the PCI 1009 configuration register is returned. This function must guarantee that all PCI 1010 read and write operations are serialized. 1011 1012 If Address > 0x0FFFFFFF, then ASSERT(). 1013 If Address is not aligned on a 32-bit boundary, then ASSERT(). 1014 1015 @param Address The address that encodes the PCI Bus, Device, Function and 1016 Register. 1017 @param AndData The value to AND with the PCI configuration register. 1018 @param OrData The value to OR with the result of the AND operation. 1019 1020 @return The value written back to the PCI configuration register. 1021 1022 **/ 1023 UINT32 1024 EFIAPI 1025 PciAndThenOr32 ( 1026 IN UINTN Address, 1027 IN UINT32 AndData, 1028 IN UINT32 OrData 1029 ) 1030 { 1031 return PciWrite32 (Address, (PciRead32 (Address) & AndData) | OrData); 1032 } 1033 1034 /** 1035 Reads a bit field of a PCI configuration register. 1036 1037 Reads the bit field in a 32-bit PCI configuration register. The bit field is 1038 specified by the StartBit and the EndBit. The value of the bit field is 1039 returned. 1040 1041 If Address > 0x0FFFFFFF, then ASSERT(). 1042 If Address is not aligned on a 32-bit boundary, then ASSERT(). 1043 If StartBit is greater than 31, then ASSERT(). 1044 If EndBit is greater than 31, then ASSERT(). 1045 If EndBit is less than StartBit, then ASSERT(). 1046 1047 @param Address The PCI configuration register to read. 1048 @param StartBit The ordinal of the least significant bit in the bit field. 1049 Range 0..31. 1050 @param EndBit The ordinal of the most significant bit in the bit field. 1051 Range 0..31. 1052 1053 @return The value of the bit field read from the PCI configuration register. 1054 1055 **/ 1056 UINT32 1057 EFIAPI 1058 PciBitFieldRead32 ( 1059 IN UINTN Address, 1060 IN UINTN StartBit, 1061 IN UINTN EndBit 1062 ) 1063 { 1064 return BitFieldRead32 (PciRead32 (Address), StartBit, EndBit); 1065 } 1066 1067 /** 1068 Writes a bit field to a PCI configuration register. 1069 1070 Writes Value to the bit field of the PCI configuration register. The bit 1071 field is specified by the StartBit and the EndBit. All other bits in the 1072 destination PCI configuration register are preserved. The new value of the 1073 32-bit register is returned. 1074 1075 If Address > 0x0FFFFFFF, then ASSERT(). 1076 If Address is not aligned on a 32-bit boundary, then ASSERT(). 1077 If StartBit is greater than 31, then ASSERT(). 1078 If EndBit is greater than 31, then ASSERT(). 1079 If EndBit is less than StartBit, then ASSERT(). 1080 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 1081 1082 @param Address The PCI configuration register to write. 1083 @param StartBit The ordinal of the least significant bit in the bit field. 1084 Range 0..31. 1085 @param EndBit The ordinal of the most significant bit in the bit field. 1086 Range 0..31. 1087 @param Value The new value of the bit field. 1088 1089 @return The value written back to the PCI configuration register. 1090 1091 **/ 1092 UINT32 1093 EFIAPI 1094 PciBitFieldWrite32 ( 1095 IN UINTN Address, 1096 IN UINTN StartBit, 1097 IN UINTN EndBit, 1098 IN UINT32 Value 1099 ) 1100 { 1101 return PciWrite32 ( 1102 Address, 1103 BitFieldWrite32 (PciRead32 (Address), StartBit, EndBit, Value) 1104 ); 1105 } 1106 1107 /** 1108 Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and 1109 writes the result back to the bit field in the 32-bit port. 1110 1111 Reads the 32-bit PCI configuration register specified by Address, performs a 1112 bitwise OR between the read result and the value specified by 1113 OrData, and writes the result to the 32-bit PCI configuration register 1114 specified by Address. The value written to the PCI configuration register is 1115 returned. This function must guarantee that all PCI read and write operations 1116 are serialized. Extra left bits in OrData are stripped. 1117 1118 If Address > 0x0FFFFFFF, then ASSERT(). 1119 If Address is not aligned on a 32-bit boundary, then ASSERT(). 1120 If StartBit is greater than 31, then ASSERT(). 1121 If EndBit is greater than 31, then ASSERT(). 1122 If EndBit is less than StartBit, then ASSERT(). 1123 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 1124 1125 @param Address The PCI configuration register to write. 1126 @param StartBit The ordinal of the least significant bit in the bit field. 1127 Range 0..31. 1128 @param EndBit The ordinal of the most significant bit in the bit field. 1129 Range 0..31. 1130 @param OrData The value to OR with the PCI configuration register. 1131 1132 @return The value written back to the PCI configuration register. 1133 1134 **/ 1135 UINT32 1136 EFIAPI 1137 PciBitFieldOr32 ( 1138 IN UINTN Address, 1139 IN UINTN StartBit, 1140 IN UINTN EndBit, 1141 IN UINT32 OrData 1142 ) 1143 { 1144 return PciWrite32 ( 1145 Address, 1146 BitFieldOr32 (PciRead32 (Address), StartBit, EndBit, OrData) 1147 ); 1148 } 1149 1150 /** 1151 Reads a bit field in a 32-bit PCI configuration register, performs a bitwise 1152 AND, and writes the result back to the bit field in the 32-bit register. 1153 1154 Reads the 32-bit PCI configuration register specified by Address, performs a 1155 bitwise AND between the read result and the value specified by AndData, and 1156 writes the result to the 32-bit PCI configuration register specified by 1157 Address. The value written to the PCI configuration register is returned. 1158 This function must guarantee that all PCI read and write operations are 1159 serialized. Extra left bits in AndData are stripped. 1160 1161 If Address > 0x0FFFFFFF, then ASSERT(). 1162 If Address is not aligned on a 32-bit boundary, then ASSERT(). 1163 If StartBit is greater than 31, then ASSERT(). 1164 If EndBit is greater than 31, then ASSERT(). 1165 If EndBit is less than StartBit, then ASSERT(). 1166 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 1167 1168 @param Address The PCI configuration register to write. 1169 @param StartBit The ordinal of the least significant bit in the bit field. 1170 Range 0..31. 1171 @param EndBit The ordinal of the most significant bit in the bit field. 1172 Range 0..31. 1173 @param AndData The value to AND with the PCI configuration register. 1174 1175 @return The value written back to the PCI configuration register. 1176 1177 **/ 1178 UINT32 1179 EFIAPI 1180 PciBitFieldAnd32 ( 1181 IN UINTN Address, 1182 IN UINTN StartBit, 1183 IN UINTN EndBit, 1184 IN UINT32 AndData 1185 ) 1186 { 1187 return PciWrite32 ( 1188 Address, 1189 BitFieldAnd32 (PciRead32 (Address), StartBit, EndBit, AndData) 1190 ); 1191 } 1192 1193 /** 1194 Reads a bit field in a 32-bit port, performs a bitwise AND followed by a 1195 bitwise OR, and writes the result back to the bit field in the 1196 32-bit port. 1197 1198 Reads the 32-bit PCI configuration register specified by Address, performs a 1199 bitwise AND followed by a bitwise OR between the read result and 1200 the value specified by AndData, and writes the result to the 32-bit PCI 1201 configuration register specified by Address. The value written to the PCI 1202 configuration register is returned. This function must guarantee that all PCI 1203 read and write operations are serialized. Extra left bits in both AndData and 1204 OrData are stripped. 1205 1206 If Address > 0x0FFFFFFF, then ASSERT(). 1207 If Address is not aligned on a 32-bit boundary, then ASSERT(). 1208 If StartBit is greater than 31, then ASSERT(). 1209 If EndBit is greater than 31, then ASSERT(). 1210 If EndBit is less than StartBit, then ASSERT(). 1211 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 1212 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). 1213 1214 @param Address The PCI configuration register to write. 1215 @param StartBit The ordinal of the least significant bit in the bit field. 1216 Range 0..31. 1217 @param EndBit The ordinal of the most significant bit in the bit field. 1218 Range 0..31. 1219 @param AndData The value to AND with the PCI configuration register. 1220 @param OrData The value to OR with the result of the AND operation. 1221 1222 @return The value written back to the PCI configuration register. 1223 1224 **/ 1225 UINT32 1226 EFIAPI 1227 PciBitFieldAndThenOr32 ( 1228 IN UINTN Address, 1229 IN UINTN StartBit, 1230 IN UINTN EndBit, 1231 IN UINT32 AndData, 1232 IN UINT32 OrData 1233 ) 1234 { 1235 return PciWrite32 ( 1236 Address, 1237 BitFieldAndThenOr32 (PciRead32 (Address), StartBit, EndBit, AndData, OrData) 1238 ); 1239 } 1240 1241 /** 1242 Reads a range of PCI configuration registers into a caller supplied buffer. 1243 1244 Reads the range of PCI configuration registers specified by StartAddress and 1245 Size into the buffer specified by Buffer. This function only allows the PCI 1246 configuration registers from a single PCI function to be read. Size is 1247 returned. When possible 32-bit PCI configuration read cycles are used to read 1248 from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit 1249 and 16-bit PCI configuration read cycles may be used at the beginning and the 1250 end of the range. 1251 1252 If StartAddress > 0x0FFFFFFF, then ASSERT(). 1253 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). 1254 If Size > 0 and Buffer is NULL, then ASSERT(). 1255 1256 @param StartAddress The starting address that encodes the PCI Bus, Device, 1257 Function and Register. 1258 @param Size The size in bytes of the transfer. 1259 @param Buffer The pointer to a buffer receiving the data read. 1260 1261 @return Size 1262 1263 **/ 1264 UINTN 1265 EFIAPI 1266 PciReadBuffer ( 1267 IN UINTN StartAddress, 1268 IN UINTN Size, 1269 OUT VOID *Buffer 1270 ) 1271 { 1272 UINTN ReturnValue; 1273 1274 ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); 1275 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); 1276 1277 if (Size == 0) { 1278 return Size; 1279 } 1280 1281 ASSERT (Buffer != NULL); 1282 1283 // 1284 // Save Size for return 1285 // 1286 ReturnValue = Size; 1287 1288 if ((StartAddress & BIT0) != 0) { 1289 // 1290 // Read a byte if StartAddress is byte aligned 1291 // 1292 *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); 1293 StartAddress += sizeof (UINT8); 1294 Size -= sizeof (UINT8); 1295 Buffer = (UINT8*)Buffer + 1; 1296 } 1297 1298 if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { 1299 // 1300 // Read a word if StartAddress is word aligned 1301 // 1302 WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); 1303 StartAddress += sizeof (UINT16); 1304 Size -= sizeof (UINT16); 1305 Buffer = (UINT16*)Buffer + 1; 1306 } 1307 1308 while (Size >= sizeof (UINT32)) { 1309 // 1310 // Read as many double words as possible 1311 // 1312 WriteUnaligned32 (Buffer, PciRead32 (StartAddress)); 1313 StartAddress += sizeof (UINT32); 1314 Size -= sizeof (UINT32); 1315 Buffer = (UINT32*)Buffer + 1; 1316 } 1317 1318 if (Size >= sizeof (UINT16)) { 1319 // 1320 // Read the last remaining word if exist 1321 // 1322 WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); 1323 StartAddress += sizeof (UINT16); 1324 Size -= sizeof (UINT16); 1325 Buffer = (UINT16*)Buffer + 1; 1326 } 1327 1328 if (Size >= sizeof (UINT8)) { 1329 // 1330 // Read the last remaining byte if exist 1331 // 1332 *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); 1333 } 1334 1335 return ReturnValue; 1336 } 1337 1338 /** 1339 Copies the data in a caller supplied buffer to a specified range of PCI 1340 configuration space. 1341 1342 Writes the range of PCI configuration registers specified by StartAddress and 1343 Size from the buffer specified by Buffer. This function only allows the PCI 1344 configuration registers from a single PCI function to be written. Size is 1345 returned. When possible 32-bit PCI configuration write cycles are used to 1346 write from StartAdress to StartAddress + Size. Due to alignment restrictions, 1347 8-bit and 16-bit PCI configuration write cycles may be used at the beginning 1348 and the end of the range. 1349 1350 If StartAddress > 0x0FFFFFFF, then ASSERT(). 1351 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). 1352 If Size > 0 and Buffer is NULL, then ASSERT(). 1353 1354 @param StartAddress The starting address that encodes the PCI Bus, Device, 1355 Function and Register. 1356 @param Size The size in bytes of the transfer. 1357 @param Buffer The pointer to a buffer containing the data to write. 1358 1359 @return Size written to StartAddress. 1360 1361 **/ 1362 UINTN 1363 EFIAPI 1364 PciWriteBuffer ( 1365 IN UINTN StartAddress, 1366 IN UINTN Size, 1367 IN VOID *Buffer 1368 ) 1369 { 1370 UINTN ReturnValue; 1371 1372 ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); 1373 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); 1374 1375 if (Size == 0) { 1376 return 0; 1377 } 1378 1379 ASSERT (Buffer != NULL); 1380 1381 // 1382 // Save Size for return 1383 // 1384 ReturnValue = Size; 1385 1386 if ((StartAddress & BIT0) != 0) { 1387 // 1388 // Write a byte if StartAddress is byte aligned 1389 // 1390 PciWrite8 (StartAddress, *(UINT8*)Buffer); 1391 StartAddress += sizeof (UINT8); 1392 Size -= sizeof (UINT8); 1393 Buffer = (UINT8*)Buffer + 1; 1394 } 1395 1396 if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { 1397 // 1398 // Write a word if StartAddress is word aligned 1399 // 1400 PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); 1401 StartAddress += sizeof (UINT16); 1402 Size -= sizeof (UINT16); 1403 Buffer = (UINT16*)Buffer + 1; 1404 } 1405 1406 while (Size >= sizeof (UINT32)) { 1407 // 1408 // Write as many double words as possible 1409 // 1410 PciWrite32 (StartAddress, ReadUnaligned32 (Buffer)); 1411 StartAddress += sizeof (UINT32); 1412 Size -= sizeof (UINT32); 1413 Buffer = (UINT32*)Buffer + 1; 1414 } 1415 1416 if (Size >= sizeof (UINT16)) { 1417 // 1418 // Write the last remaining word if exist 1419 // 1420 PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); 1421 StartAddress += sizeof (UINT16); 1422 Size -= sizeof (UINT16); 1423 Buffer = (UINT16*)Buffer + 1; 1424 } 1425 1426 if (Size >= sizeof (UINT8)) { 1427 // 1428 // Write the last remaining byte if exist 1429 // 1430 PciWrite8 (StartAddress, *(UINT8*)Buffer); 1431 } 1432 1433 return ReturnValue; 1434 } 1435