Home | History | Annotate | Download | only in SmbusLib
      1 /** @file
      2 Intel QNC SMBUS library implementation built upon I/O library.
      3 
      4 Copyright (c) 2013-2015 Intel Corporation.
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full 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 //
     17 // Include common header file for this module.
     18 //
     19 #include "CommonHeader.h"
     20 
     21 /**
     22   Gets Io port base address of Smbus Host Controller.
     23 
     24   This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress
     25   to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base
     26   address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always
     27   read Pci configuration space to get that value in each Smbus bus transaction.
     28 
     29   @return The Io port base address of Smbus host controller.
     30 
     31 **/
     32 UINTN
     33 InternalGetSmbusIoPortBaseAddress (
     34   VOID
     35   )
     36 {
     37   UINTN     IoPortBaseAddress;
     38 
     39   if (FeaturePcdGet (PcdSmbaIoBaseAddressFixed)) {
     40     IoPortBaseAddress = (UINTN) PcdGet16 (PcdSmbaIoBaseAddress);
     41   } else {
     42     IoPortBaseAddress = (UINTN) LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) & B_QNC_LPC_SMBUS_BASE_MASK;
     43   }
     44 
     45   //
     46   // Make sure that the IO port base address has been properly set.
     47   //
     48   ASSERT (IoPortBaseAddress != 0);
     49 
     50   return IoPortBaseAddress;
     51 }
     52 
     53 
     54 /**
     55   Acquires the ownership of SMBUS.
     56 
     57   This internal function reads the host state register.
     58   If the SMBUS is not available, RETURN_TIMEOUT is returned;
     59   Otherwise, it performs some basic initializations and returns
     60   RETURN_SUCCESS.
     61 
     62   @param  IoPortBaseAddress The Io port base address of Smbus Host controller.
     63 
     64   @retval RETURN_SUCCESS    The SMBUS command was executed successfully.
     65   @retval RETURN_TIMEOUT    A timeout occurred while executing the SMBUS command.
     66 
     67 **/
     68 RETURN_STATUS
     69 InternalSmBusAcquire (
     70   UINTN                     IoPortBaseAddress
     71   )
     72 {
     73 
     74   //
     75   // Clear host status register and exit.
     76   //
     77   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, 0);
     78   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, 0);
     79   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, 0);
     80   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
     81 
     82   return RETURN_SUCCESS;
     83 }
     84 
     85 /**
     86   Starts the SMBUS transaction and waits until the end.
     87 
     88   This internal function start the SMBUS transaction and waits until the transaction
     89   of SMBUS is over by polling the INTR bit of Host status register.
     90   If the SMBUS is not available, RETURN_TIMEOUT is returned;
     91   Otherwise, it performs some basic initializations and returns
     92   RETURN_SUCCESS.
     93 
     94   @param  IoPortBaseAddress   The Io port base address of Smbus Host controller.
     95   @param  HostControl         The Host control command to start SMBUS transaction.
     96 
     97   @retval RETURN_SUCCESS      The SMBUS command was executed successfully.
     98   @retval RETURN_CRC_ERROR    The checksum is not correct (PEC is incorrect).
     99   @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected
    100                               in the Host Status Register bit.  Device errors are
    101                               a result of a transaction collision, illegal command field,
    102                               unclaimed cycle (host initiated), or bus errors (collisions).
    103 
    104 **/
    105 RETURN_STATUS
    106 InternalSmBusStart (
    107   IN  UINTN                   IoPortBaseAddress,
    108   IN  UINT8                   HostControl
    109   )
    110 {
    111   UINT8   HostStatus;
    112 
    113   //
    114   // Set Host Control Register (Initiate Operation, Interrupt disabled).
    115   //
    116   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, HostControl + B_QNC_SMBUS_START);
    117 
    118   do {
    119     //
    120     // Poll INTR bit of Host Status Register.
    121     //
    122     HostStatus = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS);
    123   } while ((HostStatus & (B_QNC_SMBUS_BYTE_DONE_STS | B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0);
    124 
    125   if ((HostStatus & (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0) {
    126     return RETURN_SUCCESS;
    127   }
    128   //
    129   // Clear error bits of Host Status Register.
    130   //
    131   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR));
    132 
    133   return RETURN_DEVICE_ERROR;
    134 }
    135 
    136 /**
    137   Executes an SMBUS quick, byte or word command.
    138 
    139   This internal function executes an SMBUS quick, byte or word commond.
    140   If Status is not NULL, then the status of the executed command is returned in Status.
    141 
    142   @param  HostControl     The value of Host Control Register to set.
    143   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    144                           SMBUS Command, SMBUS Data Length, and PEC.
    145   @param  Value           The byte/word write to the SMBUS.
    146   @param  Status          Return status for the executed command.
    147                           This is an optional parameter and may be NULL.
    148 
    149   @return The byte/word read from the SMBUS.
    150 
    151 **/
    152 UINT16
    153 InternalSmBusNonBlock (
    154   IN  UINT8                     HostControl,
    155   IN  UINTN                     SmBusAddress,
    156   IN  UINT16                    Value,
    157   OUT RETURN_STATUS             *Status
    158   )
    159 {
    160   RETURN_STATUS                 ReturnStatus;
    161   UINTN                         IoPortBaseAddress;
    162 
    163   IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
    164 
    165   //
    166   // Try to acquire the ownership of QNC SMBUS.
    167   //
    168   ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
    169   if (RETURN_ERROR (ReturnStatus)) {
    170     goto Done;
    171   }
    172 
    173   //
    174   // Set Host Commond Register.
    175   //
    176   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
    177   //
    178   // Write value to Host Data 0 and Host Data 1 Registers.
    179   //
    180   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) Value);
    181   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, (UINT8) (Value >> 8));
    182 
    183 
    184   //
    185   // Set SMBUS slave address for the device to send/receive from.
    186   //
    187   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);
    188   //
    189   // Start the SMBUS transaction and wait for the end.
    190   //
    191   ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
    192   //
    193   // Read value from Host Data 0 and Host Data 1 Registers.
    194   //
    195   Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD1) << 8);
    196   Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0));
    197 
    198   //
    199   // Clear Host Status Register and Auxiliary Status Register.
    200   //
    201   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
    202 
    203 Done:
    204   if (Status != NULL) {
    205     *Status = ReturnStatus;
    206   }
    207 
    208   return Value;
    209 }
    210 
    211 /**
    212   Executes an SMBUS quick read command.
    213 
    214   Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.
    215   Only the SMBUS slave address field of SmBusAddress is required.
    216   If Status is not NULL, then the status of the executed command is returned in Status.
    217   If PEC is set in SmBusAddress, then ASSERT().
    218   If Command in SmBusAddress is not zero, then ASSERT().
    219   If Length in SmBusAddress is not zero, then ASSERT().
    220   If any reserved bits of SmBusAddress are set, then ASSERT().
    221 
    222   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    223                           SMBUS Command, SMBUS Data Length, and PEC.
    224   @param  Status          Return status for the executed command.
    225                           This is an optional parameter and may be NULL.
    226 
    227 **/
    228 VOID
    229 EFIAPI
    230 SmBusQuickRead (
    231   IN  UINTN                     SmBusAddress,
    232   OUT RETURN_STATUS             *Status       OPTIONAL
    233   )
    234 {
    235   ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
    236   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
    237   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
    238   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    239 
    240   InternalSmBusNonBlock (
    241     V_QNC_SMBUS_HCTL_CMD_QUICK,
    242     SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
    243     0,
    244     Status
    245     );
    246 
    247 }
    248 
    249 /**
    250   Executes an SMBUS quick write command.
    251 
    252   Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.
    253   Only the SMBUS slave address field of SmBusAddress is required.
    254   If Status is not NULL, then the status of the executed command is returned in Status.
    255   If PEC is set in SmBusAddress, then ASSERT().
    256   If Command in SmBusAddress is not zero, then ASSERT().
    257   If Length in SmBusAddress is not zero, then ASSERT().
    258   If any reserved bits of SmBusAddress are set, then ASSERT().
    259 
    260   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    261                           SMBUS Command, SMBUS Data Length, and PEC.
    262   @param  Status          Return status for the executed command.
    263                           This is an optional parameter and may be NULL.
    264 
    265 **/
    266 VOID
    267 EFIAPI
    268 SmBusQuickWrite (
    269   IN  UINTN                     SmBusAddress,
    270   OUT RETURN_STATUS             *Status       OPTIONAL
    271   )
    272 {
    273   ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
    274   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
    275   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
    276   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    277 
    278   InternalSmBusNonBlock (
    279     V_QNC_SMBUS_HCTL_CMD_QUICK,
    280     SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
    281     0,
    282     Status
    283     );
    284 
    285 }
    286 
    287 /**
    288   Executes an SMBUS receive byte command.
    289 
    290   Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.
    291   Only the SMBUS slave address field of SmBusAddress is required.
    292   The byte received from the SMBUS is returned.
    293   If Status is not NULL, then the status of the executed command is returned in Status.
    294   If Command in SmBusAddress is not zero, then ASSERT().
    295   If Length in SmBusAddress is not zero, then ASSERT().
    296   If any reserved bits of SmBusAddress are set, then ASSERT().
    297 
    298   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    299                           SMBUS Command, SMBUS Data Length, and PEC.
    300   @param  Status          Return status for the executed command.
    301                           This is an optional parameter and may be NULL.
    302 
    303   @return The byte received from the SMBUS.
    304 
    305 **/
    306 UINT8
    307 EFIAPI
    308 SmBusReceiveByte (
    309   IN  UINTN          SmBusAddress,
    310   OUT RETURN_STATUS  *Status        OPTIONAL
    311   )
    312 {
    313   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
    314   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
    315   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    316 
    317   return (UINT8) InternalSmBusNonBlock (
    318                    V_QNC_SMBUS_HCTL_CMD_BYTE,
    319                    SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
    320                    0,
    321                    Status
    322                    );
    323 
    324 }
    325 
    326 /**
    327   Executes an SMBUS send byte command.
    328 
    329   Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.
    330   The byte specified by Value is sent.
    331   Only the SMBUS slave address field of SmBusAddress is required.  Value is returned.
    332   If Status is not NULL, then the status of the executed command is returned in Status.
    333   If Command in SmBusAddress is not zero, then ASSERT().
    334   If Length in SmBusAddress is not zero, then ASSERT().
    335   If any reserved bits of SmBusAddress are set, then ASSERT().
    336 
    337   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    338                           SMBUS Command, SMBUS Data Length, and PEC.
    339   @param  Value           The 8-bit value to send.
    340   @param  Status          Return status for the executed command.
    341                           This is an optional parameter and may be NULL.
    342 
    343   @return The parameter of Value.
    344 
    345 **/
    346 UINT8
    347 EFIAPI
    348 SmBusSendByte (
    349   IN  UINTN          SmBusAddress,
    350   IN  UINT8          Value,
    351   OUT RETURN_STATUS  *Status        OPTIONAL
    352   )
    353 {
    354   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
    355   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
    356   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    357 
    358   return (UINT8) InternalSmBusNonBlock (
    359                    V_QNC_SMBUS_HCTL_CMD_BYTE,
    360                    SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
    361                    Value,
    362                    Status
    363                    );
    364 
    365 }
    366 
    367 /**
    368   Executes an SMBUS read data byte command.
    369 
    370   Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.
    371   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
    372   The 8-bit value read from the SMBUS is returned.
    373   If Status is not NULL, then the status of the executed command is returned in Status.
    374   If Length in SmBusAddress is not zero, then ASSERT().
    375   If any reserved bits of SmBusAddress are set, then ASSERT().
    376 
    377   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    378                           SMBUS Command, SMBUS Data Length, and PEC.
    379   @param  Status          Return status for the executed command.
    380                           This is an optional parameter and may be NULL.
    381 
    382   @return The byte read from the SMBUS.
    383 
    384 **/
    385 UINT8
    386 EFIAPI
    387 SmBusReadDataByte (
    388   IN  UINTN          SmBusAddress,
    389   OUT RETURN_STATUS  *Status        OPTIONAL
    390   )
    391 {
    392   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
    393   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    394 
    395   return (UINT8) InternalSmBusNonBlock (
    396                    V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,
    397                    SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
    398                    0,
    399                    Status
    400                    );
    401 }
    402 
    403 /**
    404   Executes an SMBUS write data byte command.
    405 
    406   Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.
    407   The 8-bit value specified by Value is written.
    408   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
    409   Value is returned.
    410   If Status is not NULL, then the status of the executed command is returned in Status.
    411   If Length in SmBusAddress is not zero, then ASSERT().
    412   If any reserved bits of SmBusAddress are set, then ASSERT().
    413 
    414   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    415                           SMBUS Command, SMBUS Data Length, and PEC.
    416   @param  Value           The 8-bit value to write.
    417   @param  Status          Return status for the executed command.
    418                           This is an optional parameter and may be NULL.
    419 
    420   @return The parameter of Value.
    421 
    422 **/
    423 UINT8
    424 EFIAPI
    425 SmBusWriteDataByte (
    426   IN  UINTN          SmBusAddress,
    427   IN  UINT8          Value,
    428   OUT RETURN_STATUS  *Status        OPTIONAL
    429   )
    430 {
    431   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
    432   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    433 
    434   return (UINT8) InternalSmBusNonBlock (
    435                    V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,
    436                    SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
    437                    Value,
    438                    Status
    439                    );
    440 }
    441 
    442 /**
    443   Executes an SMBUS read data word command.
    444 
    445   Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.
    446   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
    447   The 16-bit value read from the SMBUS is returned.
    448   If Status is not NULL, then the status of the executed command is returned in Status.
    449   If Length in SmBusAddress is not zero, then ASSERT().
    450   If any reserved bits of SmBusAddress are set, then ASSERT().
    451 
    452   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    453                           SMBUS Command, SMBUS Data Length, and PEC.
    454   @param  Status          Return status for the executed command.
    455                           This is an optional parameter and may be NULL.
    456 
    457   @return The byte read from the SMBUS.
    458 
    459 **/
    460 UINT16
    461 EFIAPI
    462 SmBusReadDataWord (
    463   IN  UINTN          SmBusAddress,
    464   OUT RETURN_STATUS  *Status        OPTIONAL
    465   )
    466 {
    467   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 2);
    468   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    469 
    470   return InternalSmBusNonBlock (
    471            V_QNC_SMBUS_HCTL_CMD_WORD_DATA,
    472            SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
    473            0,
    474            Status
    475            );
    476 
    477 }
    478 
    479 /**
    480   Executes an SMBUS write data word command.
    481 
    482   Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.
    483   The 16-bit value specified by Value is written.
    484   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
    485   Value is returned.
    486   If Status is not NULL, then the status of the executed command is returned in Status.
    487   If Length in SmBusAddress is not zero, then ASSERT().
    488   If any reserved bits of SmBusAddress are set, then ASSERT().
    489 
    490   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    491                           SMBUS Command, SMBUS Data Length, and PEC.
    492   @param  Value           The 16-bit value to write.
    493   @param  Status          Return status for the executed command.
    494                           This is an optional parameter and may be NULL.
    495 
    496   @return The parameter of Value.
    497 
    498 **/
    499 UINT16
    500 EFIAPI
    501 SmBusWriteDataWord (
    502   IN  UINTN          SmBusAddress,
    503   IN  UINT16         Value,
    504   OUT RETURN_STATUS  *Status        OPTIONAL
    505   )
    506 {
    507   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 2);
    508   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    509 
    510   return InternalSmBusNonBlock (
    511          V_QNC_SMBUS_HCTL_CMD_WORD_DATA,
    512          SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
    513          Value,
    514          Status
    515          );
    516 }
    517 
    518 /**
    519   Executes an SMBUS process call command.
    520 
    521   Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.
    522   The 16-bit value specified by Value is written.
    523   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
    524   The 16-bit value returned by the process call command is returned.
    525   If Status is not NULL, then the status of the executed command is returned in Status.
    526   If Length in SmBusAddress is not zero, then ASSERT().
    527   If any reserved bits of SmBusAddress are set, then ASSERT().
    528 
    529   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    530                           SMBUS Command, SMBUS Data Length, and PEC.
    531   @param  Value           The 16-bit value to write.
    532   @param  Status          Return status for the executed command.
    533                           This is an optional parameter and may be NULL.
    534 
    535   @return The 16-bit value returned by the process call command.
    536 
    537 **/
    538 UINT16
    539 EFIAPI
    540 SmBusProcessCall (
    541   IN  UINTN          SmBusAddress,
    542   IN  UINT16         Value,
    543   OUT RETURN_STATUS  *Status        OPTIONAL
    544   )
    545 {
    546   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
    547   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    548 
    549   return InternalSmBusNonBlock (
    550            V_QNC_SMBUS_HCTL_CMD_PROCESS_CALL,
    551            SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
    552            Value,
    553            Status
    554            );
    555 
    556 }
    557 
    558 /**
    559   Executes an SMBUS block command.
    560 
    561   Executes an SMBUS block read, block write and block write-block read command
    562   on the SMBUS device specified by SmBusAddress.
    563   Bytes are read from the SMBUS and stored in Buffer.
    564   The number of bytes read is returned, and will never return a value larger than 32-bytes.
    565   If Status is not NULL, then the status of the executed command is returned in Status.
    566   It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
    567   SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
    568 
    569   @param  HostControl     The value of Host Control Register to set.
    570   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    571                           SMBUS Command, SMBUS Data Length, and PEC.
    572   @param  WriteBuffer     Pointer to the buffer of bytes to write to the SMBUS.
    573   @param  ReadBuffer      Pointer to the buffer of bytes to read from the SMBUS.
    574   @param  Status          Return status for the executed command.
    575                           This is an optional parameter and may be NULL.
    576 
    577   @return The number of bytes read from the SMBUS.
    578 
    579 **/
    580 UINTN
    581 InternalSmBusBlock (
    582   IN  UINT8                     HostControl,
    583   IN  UINTN                     SmBusAddress,
    584   IN  UINT8                     *WriteBuffer,
    585   OUT UINT8                     *ReadBuffer,
    586   OUT RETURN_STATUS             *Status
    587   )
    588 {
    589   RETURN_STATUS                 ReturnStatus;
    590   UINTN                         Index;
    591   UINTN                         BytesCount;
    592   UINTN                         IoPortBaseAddress;
    593 
    594   IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
    595 
    596   BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);
    597 
    598   //
    599   // Try to acquire the ownership of ICH SMBUS.
    600   //
    601   ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
    602   if (RETURN_ERROR (ReturnStatus)) {
    603     goto Done;
    604   }
    605 
    606   //
    607   // Set Host Command Register.
    608   //
    609   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
    610 
    611   //
    612   // Clear byte pointer of 32-byte buffer.
    613   //
    614   IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL);
    615 
    616   if (WriteBuffer != NULL) {
    617     //
    618     // Write the number of block to Host Block Data Byte Register.
    619     //
    620     IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) BytesCount);
    621     //
    622     // Write data block to Host Block Data Register.
    623     //
    624     for (Index = 0; Index < BytesCount; Index++) {
    625       IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index, WriteBuffer[Index]);
    626     }
    627   }
    628   //
    629   // Set SMBUS slave address for the device to send/receive from.
    630   //
    631   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);
    632   //
    633   // Start the SMBUS transaction and wait for the end.
    634   //
    635   ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
    636   if (RETURN_ERROR (ReturnStatus)) {
    637     goto Done;
    638   }
    639 
    640   if (ReadBuffer != NULL) {
    641     //
    642     // Read the number of block from host block data byte register.
    643     //
    644     BytesCount = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0);
    645     //
    646     // Write data block from Host Block Data Register.
    647     //
    648     for (Index = 0; Index < BytesCount; Index++) {
    649       ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index);
    650     }
    651   }
    652 
    653 Done:
    654   //
    655   // Clear Host Status Register and Auxiliary Status Register.
    656   //
    657   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
    658 
    659   if (Status != NULL) {
    660     *Status = ReturnStatus;
    661   }
    662 
    663   return BytesCount;
    664 }
    665 
    666 /**
    667   Executes an SMBUS read block command.
    668 
    669   Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.
    670   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
    671   Bytes are read from the SMBUS and stored in Buffer.
    672   The number of bytes read is returned, and will never return a value larger than 32-bytes.
    673   If Status is not NULL, then the status of the executed command is returned in Status.
    674   It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
    675   SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
    676   If Length in SmBusAddress is not zero, then ASSERT().
    677   If Buffer is NULL, then ASSERT().
    678   If any reserved bits of SmBusAddress are set, then ASSERT().
    679 
    680   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    681                           SMBUS Command, SMBUS Data Length, and PEC.
    682   @param  Buffer          Pointer to the buffer to store the bytes read from the SMBUS.
    683   @param  Status          Return status for the executed command.
    684                           This is an optional parameter and may be NULL.
    685 
    686   @return The number of bytes read.
    687 
    688 **/
    689 UINTN
    690 EFIAPI
    691 SmBusReadBlock (
    692   IN  UINTN          SmBusAddress,
    693   OUT VOID           *Buffer,
    694   OUT RETURN_STATUS  *Status        OPTIONAL
    695   )
    696 {
    697   ASSERT (Buffer != NULL);
    698   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
    699   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
    700   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    701 
    702   return InternalSmBusBlock (
    703            V_QNC_SMBUS_HCTL_CMD_BLOCK,
    704            SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
    705            NULL,
    706            Buffer,
    707            Status
    708            );
    709 }
    710 
    711 /**
    712   Executes an SMBUS write block command.
    713 
    714   Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.
    715   The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
    716   Bytes are written to the SMBUS from Buffer.
    717   The number of bytes written is returned, and will never return a value larger than 32-bytes.
    718   If Status is not NULL, then the status of the executed command is returned in Status.
    719   If Length in SmBusAddress is zero or greater than 32, then ASSERT().
    720   If Buffer is NULL, then ASSERT().
    721   If any reserved bits of SmBusAddress are set, then ASSERT().
    722 
    723   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
    724                           SMBUS Command, SMBUS Data Length, and PEC.
    725   @param  Buffer          Pointer to the buffer to store the bytes read from the SMBUS.
    726   @param  Status          Return status for the executed command.
    727                           This is an optional parameter and may be NULL.
    728 
    729   @return The number of bytes written.
    730 
    731 **/
    732 UINTN
    733 EFIAPI
    734 SmBusWriteBlock (
    735   IN  UINTN          SmBusAddress,
    736   OUT VOID           *Buffer,
    737   OUT RETURN_STATUS  *Status        OPTIONAL
    738   )
    739 {
    740   ASSERT (Buffer != NULL);
    741   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
    742   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
    743   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    744 
    745   return InternalSmBusBlock (
    746            V_QNC_SMBUS_HCTL_CMD_BLOCK,
    747            SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
    748            Buffer,
    749            NULL,
    750            Status
    751            );
    752 }
    753 
    754 /**
    755   Executes an SMBUS block process call command.
    756 
    757   Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress.
    758   The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
    759   Bytes are written to the SMBUS from WriteBuffer.  Bytes are then read from the SMBUS into ReadBuffer.
    760   If Status is not NULL, then the status of the executed command is returned in Status.
    761   It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read.
    762   SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
    763   If Length in SmBusAddress is zero or greater than 32, then ASSERT().
    764   If WriteBuffer is NULL, then ASSERT().
    765   If ReadBuffer is NULL, then ASSERT().
    766   If any reserved bits of SmBusAddress are set, then ASSERT().
    767 
    768   @param  SmBusAddress  Address that encodes the SMBUS Slave Address,
    769                         SMBUS Command, SMBUS Data Length, and PEC.
    770   @param  WriteBuffer   Pointer to the buffer of bytes to write to the SMBUS.
    771   @param  ReadBuffer    Pointer to the buffer of bytes to read from the SMBUS.
    772   @param  Status        Return status for the executed command.
    773                         This is an optional parameter and may be NULL.
    774                         RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.
    775                         RETURN_DEVICE_ERROR  The request was not completed because a failure
    776                         reflected in the Host Status Register bit.  Device errors are a result
    777                         of a transaction collision, illegal command field, unclaimed cycle
    778                         (host initiated), or bus errors (collisions).
    779                         RETURN_CRC_ERROR  The checksum is not correct (PEC is incorrect)
    780                         RETURN_UNSUPPORTED  The SMBus operation is not supported.
    781 
    782   @return The number of bytes written.
    783 
    784 **/
    785 UINTN
    786 EFIAPI
    787 SmBusBlockProcessCall (
    788   IN  UINTN          SmBusAddress,
    789   IN  VOID           *WriteBuffer,
    790   OUT VOID           *ReadBuffer,
    791   OUT RETURN_STATUS  *Status        OPTIONAL
    792   )
    793 {
    794   ASSERT (WriteBuffer != NULL);
    795   ASSERT (ReadBuffer  != NULL);
    796   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
    797   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
    798   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
    799   if (Status != NULL) {
    800     *Status = RETURN_UNSUPPORTED;
    801   }
    802   return 0;
    803 }
    804