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