Home | History | Annotate | Download | only in PeiPciLibPciCfg2
      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