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