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