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