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