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