X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdePkg%2FLibrary%2FBaseSmbusLib%2FSmbusLib.c;h=16ae2fa279c13d19c81a3fe628a7ae1e97308068;hp=5aad978836af3c5e3129e4a25cc5990672ebde03;hb=5b1b9d8bf4565b194ac16294c58993c62bcae315;hpb=878ddf1fc3540a715f63594ed22b6929e881afb4 diff --git a/MdePkg/Library/BaseSmbusLib/SmbusLib.c b/MdePkg/Library/BaseSmbusLib/SmbusLib.c index 5aad978836..16ae2fa279 100644 --- a/MdePkg/Library/BaseSmbusLib/SmbusLib.c +++ b/MdePkg/Library/BaseSmbusLib/SmbusLib.c @@ -10,548 +10,824 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - Module Name: SmbusLib.h + Module Name: SmbusLib.c **/ -RETURN_STATUS -EFIAPI -BaseSmBusLibConstructor ( - IN VOID *Param1, - IN VOID *Param2 - ) -{ - return RETURN_SUCCESS; -} +#include "SmbusLibRegisters.h" -// -// BUGBUG: use PCD to retrieve BUS, DEV, FUNC & OFFSET for SMBUS host BAR -// -#define SMBUS_HOST_BUS 0 -#define SMBUS_HOST_DEV 31 -#define SMBUS_HOST_FUNC 3 -#define SMBUS_HOST_SMB_BASE 0x20 - -// -// Offsets of registers for SMBUS controller -// -#define R_HST_STS 0 -#define R_HST_CNT 2 -#define R_HST_CMD 3 -#define R_XMIT_SLVA 4 -#define R_HST_D0 5 -#define R_HST_D1 6 -#define R_HOST_BLOCK_DB 7 -#define R_PEC 8 -#define R_RCV_SLVA 9 -#define R_SLV_DATA 0x0a -#define R_AUX_STS 0x0c -#define R_AUX_CTL 0x0d -#define R_SMLINK_PIN_CTL 0x0e -#define R_SMBUS_PIN_CTL 0x0f -#define R_SLV_STS 0x10 -#define R_SLV_CMD 0x11 -#define R_NOTIFY_DADDR 0x14 -#define R_NOTIFY_DLOW 0x16 -#define R_NOTIFY_DHIGH 0x17 +#define SMBUS_LIB_SLAVE_ADDRESS(SmBusAddress) (((SmBusAddress) >> 1) & 0x7f) +#define SMBUS_LIB_COMMAND(SmBusAddress) (((SmBusAddress) >> 8) & 0xff) +#define SMBUS_LIB_LENGTH(SmBusAddress) (((SmBusAddress) >> 16) & 0x3f) +#define SMBUS_LIB_PEC(SmBusAddress) ((BOOLEAN) (((SmBusAddress) & SMBUS_LIB_PEC_BIT) != 0)) +#define SMBUS_LIB_RESEARVED(SmBusAddress) ((SmBusAddress) & ~(((1 << 22) - 2) | SMBUS_LIB_PEC_BIT)) // -// Bits in HST_STS +// Replaced by PCD // -#define B_HST_STS_DS 0x80 -#define B_HST_STS_INUSE 0x40 -#define B_HST_STS_SMBALERT 0x20 -#define B_HST_STS_FAILED 0x10 -#define B_HST_STS_BUS_ERR 0x08 -#define B_HST_STS_DEV_ERR 0x04 -#define B_HST_STS_INTR 0x02 -#define B_HST_STS_BUSY 0x01 -#define B_HST_STS_ERR ( B_HST_STS_BUS_ERR | \ - B_HST_STS_DEV_ERR | \ - B_HST_STS_FAILED ) -#define B_HST_STS_ALL ( B_HST_STS_DS | \ - B_HST_STS_INUSE | \ - B_HST_STS_SMBALERT | \ - B_HST_STS_ERR | \ - B_HST_STS_INTR ) +#define ICH_SMBUS_IO_BASE_ADDRESS 0xEFA0 -// -// Bits in HST_CNT -// -#define B_HST_CNT_PEC 0x80 -#define B_HST_CNT_START 0x40 -#define B_HST_CNT_LAST_BYTE 0x20 -#define B_HST_CNT_SMB_CMD 0x1c -#define B_HST_CNT_KILL 0x02 -#define B_HST_CNT_INTREN 0x01 +/** + Reads an 8-bit register on ICH SMBUS controller. -// -// SMBUS Protocols -// -#define B_SMB_CMD_QUICK 0 -#define B_SMB_CMD_BYTE 1 -#define B_SMB_CMD_BYTE_DATA 2 -#define B_SMB_CMD_WORD_DATA 3 -#define B_SMB_CMD_PROCESS_CALL 4 -#define B_SMB_CMD_BLOCK 5 -#define B_SMB_CMD_I2C 6 -#define B_SMB_CMD_BLOCK_PROCESS 7 + This internal function reads an SMBUS register specified by Offset. -// -// Bits in AUX_CTL -// -#define B_AUX_CTL_E32B 0x02 -#define B_AUX_CTL_AAC 0x01 + @param Offset The offset of SMBUS register. -// -// SMBUS Rd/Wr control -// -#define B_SMBUS_READ 1 -#define B_SMBUS_WRITE 0 + @return The value read. -static -UINT16 -EFIAPI -GetSmBusIOBaseAddress ( - VOID +**/ +UINT8 +InternalSmBusIoRead8 ( + IN UINTN Offset ) { - UINT32 SmbusBar; - - SmbusBar = PciRead32 ( - PCI_LIB_ADDRESS ( - SMBUS_HOST_BUS, - SMBUS_HOST_DEV, - SMBUS_HOST_FUNC, - SMBUS_HOST_SMB_BASE - ) - ); - ASSERT ((SmbusBar & 0xffff001f) == 1); - return (UINT16)(SmbusBar & ~1); + return IoRead8 (ICH_SMBUS_IO_BASE_ADDRESS + Offset); } -static -BOOLEAN -EFIAPI -SmBusAcquire ( - IN UINT16 SmBusBase - ) -{ - UINT8 HstSts; +/** + Writes an 8-bit register on ICH SMBUS controller. - HstSts = IoRead8 (SmBusBase + R_HST_STS); - if (HstSts & B_HST_STS_INUSE) { - return FALSE; - } + This internal function writes an SMBUS register specified by Offset. - // - // BUGBUG: Dead loop may occur here - // - while (HstSts & B_HST_STS_BUSY) { - ASSERT (HstSts & B_HST_STS_INUSE); - HstSts = IoRead8 (SmBusBase + R_HST_STS); - } - return TRUE; -} + @param Offset The offset of SMBUS register. + @param Value The value to write to SMBUS register. -static -VOID -EFIAPI -SmBusStart ( - IN UINT16 SmBusBase, - IN UINT8 SmBusProtocol, - IN UINT8 SlaveAddress + @return The value written the SMBUS register. + +**/ +UINT8 +InternalSmBusIoWrite8 ( + IN UINTN Offset, + IN UINT8 Value ) { - IoWrite8 (SmBusBase + R_XMIT_SLVA, SlaveAddress); - IoWrite8 ( - SmBusBase + R_HST_CNT, - IoBitFieldWrite8 (SmBusBase + R_HST_CNT, 2, 4, SmBusProtocol) | - B_HST_CNT_START - ); + return IoWrite8 (ICH_SMBUS_IO_BASE_ADDRESS + Offset, Value); } -static -UINT8 -EFIAPI -SmBusWait ( - IN UINT16 SmBusBase +/** + Acquires the ownership of SMBUS. + + This internal function reads the host state register. + If the SMBUS is not available, RETURN_TIMEOUT is returned; + Otherwise, it performs some basic initializations and returns + RETURN_SUCCESS. + + @retval RETURN_SUCCESS The SMBUS command was executed successfully. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + +**/ +RETURN_STATUS +InternalSmBusAcquire ( + VOID ) { - UINT8 HstSts; + UINT8 HostStatus; - while (((HstSts = IoRead8 (SmBusBase + R_HST_STS)) & B_HST_STS_INTR) == 0); - return HstSts; + HostStatus = InternalSmBusIoRead8 (SMBUS_R_HST_STS); + if ((HostStatus & SMBUS_B_INUSE_STS) != 0) { + return RETURN_TIMEOUT; + } else if ((HostStatus & SMBUS_B_HOST_BUSY) != 0) { + // + // Clear host status register and exit. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_STS, SMBUS_B_HSTS_ALL); + return RETURN_TIMEOUT; + } + // + // Clear out any odd status information (Will Not Clear In Use). + // + InternalSmBusIoWrite8 (SMBUS_R_HST_STS, HostStatus); + + return RETURN_SUCCESS; } -static -VOID -EFIAPI -SmBusCleanup ( - IN UINT16 SmBusBase +/** + Starts the SMBUS transaction and waits until the end. + + This internal function start the SMBUS transaction and waits until the transaction + of SMBUS is over by polling the INTR bit of Host status register. + If the SMBUS is not available, RETURN_TIMEOUT is returned; + Otherwise, it performs some basic initializations and returns + RETURN_SUCCESS. + + @param HostControl The Host control command to start SMBUS transaction. + + @retval RETURN_SUCCESS The SMBUS command was executed successfully. + @retval RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect). + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. Device errors are + a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalSmBusStart ( + IN UINT8 HostControl ) { - IoWrite8 (SmBusBase + R_HST_STS, B_HST_STS_ALL); + UINT8 HostStatus; + UINT8 AuxiliaryStatus; + + // + // Set Host Control Register (Initiate Operation, Interrupt disabled). + // + InternalSmBusIoWrite8 (SMBUS_R_HST_CTL, HostControl + SMBUS_B_START); + + do { + // + // Poll INTR bit of Host Status Register. + // + HostStatus = InternalSmBusIoRead8 (SMBUS_R_HST_STS); + } while ((HostStatus & (SMBUS_B_INTR | SMBUS_B_ERROR | SMBUS_B_BYTE_DONE_STS)) == 0); + + if ((HostStatus & SMBUS_B_ERROR) == 0) { + return RETURN_SUCCESS; + } + // + // Clear error bits of Host Status Register. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_STS, SMBUS_B_ERROR); + // + // Read Auxiliary Status Register to judge CRC error. + // + AuxiliaryStatus = InternalSmBusIoRead8 (SMBUS_R_AUX_STS); + if ((AuxiliaryStatus & SMBUS_B_CRCE) != 0) { + return RETURN_CRC_ERROR; + } + + return RETURN_DEVICE_ERROR; } -static -RETURN_STATUS -EFIAPI -SmBusQuick ( - IN UINT8 SmBusAddress +/** + Executes an SMBUS quick, byte or word command. + + This internal function executes an SMBUS quick, byte or word commond. + If Status is not NULL, then the status of the executed command is returned in Status. + + @param HostControl The value of Host Control Register to set. + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The byte/word write to the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte/word read from the SMBUS. + +**/ +UINT16 +InternalSmBusNonBlock ( + IN UINT8 HostControl, + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status ) { - RETURN_STATUS Status; - UINT16 SmBusBase; + RETURN_STATUS ReturnStatus; + UINT8 AuxiliaryControl; - SmBusBase = GetSmBusIOBaseAddress (); - if (!SmBusAcquire (SmBusBase)) { - return RETURN_TIMEOUT; + // + // Try to acquire the ownership of ICH SMBUS. + // + ReturnStatus = InternalSmBusAcquire (); + if (RETURN_ERROR (ReturnStatus)) { + goto Done; } + // + // Set the appropriate Host Control Register and auxiliary Control Register. + // + AuxiliaryControl = 0; + if (SMBUS_LIB_PEC (SmBusAddress)) { + AuxiliaryControl |= SMBUS_B_AAC; + HostControl |= SMBUS_B_PEC_EN; + } + // + // Set Host Commond Register. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_CMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress)); + // + // Write value to Host Data 0 and Host Data 1 Registers. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_D0, (UINT8) Value); + InternalSmBusIoWrite8 (SMBUS_R_HST_D1, (UINT8) (Value >> 8)); + // + // Set Auxiliary Control Regiester. + // + InternalSmBusIoWrite8 (SMBUS_R_AUX_CTL, AuxiliaryControl); + // + // Set SMBUS slave address for the device to send/receive from. + // + InternalSmBusIoWrite8 (SMBUS_R_XMIT_SLVA, (UINT8) SmBusAddress); + // + // Start the SMBUS transaction and wait for the end. + // + ReturnStatus = InternalSmBusStart (HostControl); + // + // Read value from Host Data 0 and Host Data 1 Registers. + // + Value = InternalSmBusIoRead8 (SMBUS_R_HST_D1) << 8; + Value |= InternalSmBusIoRead8 (SMBUS_R_HST_D0); + // + // Clear Host Status Register and Auxiliary Status Register. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_STS, SMBUS_B_HSTS_ALL); + InternalSmBusIoWrite8 (SMBUS_R_AUX_STS, SMBUS_B_CRCE); - SmBusStart (SmBusAddress, B_SMB_CMD_QUICK, SmBusAddress); - if (SmBusWait (SmBusAddress) & B_HST_STS_ERR) { - Status = RETURN_DEVICE_ERROR; - } else { - Status = RETURN_SUCCESS; +Done: + if (Status != NULL) { + *Status = ReturnStatus; } - SmBusCleanup (SmBusAddress); - return Status; + return Value; } +/** + Executes an SMBUS quick read command. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ VOID EFIAPI SmBusQuickRead ( - IN UINTN SmBusAddress, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL ) { - RETURN_STATUS RetStatus; - - ASSERT ((SmBusAddress & ~0xfe) == 0); - RetStatus = SmBusQuick ((UINT8)SmBusAddress | B_SMBUS_READ); - if (Status) { - *Status = RetStatus; - } + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_QUICK, + SmBusAddress | SMBUS_B_READ, + 0, + Status + ); } -BOOLEAN -EFIAPI -SmBusQuickWrite ( - IN UINTN SmBusAddress, - OUT RETURN_STATUS *Status - ) -{ - RETURN_STATUS RetStatus; +/** + Executes an SMBUS quick write command. - ASSERT ((SmBusAddress & ~0xfe) == 0); - RetStatus = SmBusQuick ((UINT8)SmBusAddress | B_SMBUS_WRITE); - if (Status) { - *Status = RetStatus; - } - return (BOOLEAN)!RETURN_ERROR (RetStatus); -} + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). -static -UINT16 + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +VOID EFIAPI -SmBusByteWord ( - IN UINTN SmBusAddress, - IN UINT16 Value, - IN UINT8 SmBusProtocol, - OUT RETURN_STATUS *Status +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL ) { - RETURN_STATUS RetStatus; - UINT16 SmBusBase; - - if (Status == NULL) { - Status = &RetStatus; - } - - SmBusBase = GetSmBusIOBaseAddress (); - if (!SmBusAcquire (SmBusBase)) { - *Status = RETURN_TIMEOUT; - return Value; - } + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_QUICK, + SmBusAddress | SMBUS_B_WRITE, + 0, + Status + ); +} - IoWrite8 (SmBusBase + R_HST_CMD, (UINT8)(SmBusAddress >> 8)); - IoWrite8 (SmBusBase + R_HST_D0, (UINT8)Value); - IoWrite8 (SmBusBase + R_HST_D1, (UINT8)(Value >> 8)); - if ((INTN)SmBusAddress < 0) { - IoOr8 (SmBusBase + R_HST_CNT, B_HST_CNT_PEC); - IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_AAC); - } else { - IoAnd8 (SmBusBase + R_HST_CNT, (UINT8)~B_HST_CNT_PEC); - IoAnd8 (SmBusBase + R_AUX_CTL, (UINT8)~B_AUX_CTL_AAC); - } +/** + Executes an SMBUS receive byte command. - SmBusStart (SmBusBase, SmBusProtocol, (UINT8)SmBusAddress); + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). - if (SmBusWait (SmBusBase) & B_HST_STS_ERR) { - *Status = RETURN_DEVICE_ERROR; - } else { - *Status = RETURN_SUCCESS; - Value = IoRead8 (SmBusBase + R_HST_D0); - Value |= (UINT16)IoRead8 (SmBusBase + R_HST_D1) << 8; - } + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. - SmBusCleanup (SmBusBase); - return Value; -} + @return The byte received from the SMBUS. +**/ UINT8 EFIAPI SmBusReceiveByte ( - IN UINTN SmBusAddress, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfe | MAX_BIT)) == 0); - return (UINT8)SmBusByteWord ( - SmBusAddress | B_SMBUS_READ, - 0, - B_SMB_CMD_BYTE, - Status - ); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return (UINT8) InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_BYTE, + SmBusAddress | SMBUS_B_READ, + 0, + Status + ); } +/** + Executes an SMBUS send byte command. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ UINT8 EFIAPI SmBusSendByte ( - IN UINTN SmBusAddress, - IN UINT8 Value, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfe | MAX_BIT)) == 0); - return (UINT8)SmBusByteWord ( - SmBusAddress | B_SMBUS_WRITE, - Value, - B_SMB_CMD_BYTE, - Status - ); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return (UINT8) InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_BYTE, + SmBusAddress | SMBUS_B_WRITE, + Value, + Status + ); } +/** + Executes an SMBUS read data byte command. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ UINT8 EFIAPI SmBusReadDataByte ( - IN UINTN SmBusAddress, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); - return (UINT8)SmBusByteWord ( - SmBusAddress | B_SMBUS_READ, - 0, - B_SMB_CMD_BYTE_DATA, - Status - ); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return (UINT8) InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_BYTE_DATA, + SmBusAddress | SMBUS_B_READ, + 0, + Status + ); } +/** + Executes an SMBUS write data byte command. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ UINT8 EFIAPI SmBusWriteDataByte ( - IN UINTN SmBusAddress, - IN UINT8 Value, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT (((UINT32)SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); - return (UINT8)SmBusByteWord ( - SmBusAddress | B_SMBUS_WRITE, - Value, - B_SMB_CMD_BYTE_DATA, - Status - ); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return (UINT8) InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_BYTE_DATA, + SmBusAddress | SMBUS_B_WRITE, + Value, + Status + ); } +/** + Executes an SMBUS read data word command. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ UINT16 EFIAPI SmBusReadDataWord ( - IN UINTN SmBusAddress, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); - return SmBusByteWord ( - SmBusAddress | B_SMBUS_READ, + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_WORD_DATA, + SmBusAddress | SMBUS_B_READ, 0, - B_SMB_CMD_WORD_DATA, Status ); } +/** + Executes an SMBUS write data word command. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ UINT16 EFIAPI SmBusWriteDataWord ( - IN UINTN SmBusAddress, - IN UINT16 Value, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); - return SmBusByteWord ( - SmBusAddress | B_SMBUS_WRITE, + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_WORD_DATA, + SmBusAddress | SMBUS_B_WRITE, Value, - B_SMB_CMD_WORD_DATA, Status ); } +/** + Executes an SMBUS process call command. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The 16-bit value returned by the process call command. + +**/ UINT16 EFIAPI SmBusProcessCall ( - IN UINTN SmBusAddress, - IN UINT16 Value, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); - return SmBusByteWord ( - SmBusAddress | B_SMBUS_WRITE, + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusNonBlock ( + SMBUS_V_SMB_CMD_PROCESS_CALL, + SmBusAddress | SMBUS_B_WRITE, Value, - B_SMB_CMD_PROCESS_CALL, Status ); } -static +/** + Executes an SMBUS block command. + + Executes an SMBUS block read, block write and block write-block read command + on the SMBUS device specified by SmBusAddress. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + + @param HostControl The value of Host Control Register to set. + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS. + @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes read from the SMBUS. + +**/ UINTN -EFIAPI -SmBusBlock ( - IN UINTN SmBusAddress, - IN UINT8 SmBusProtocol, - IN VOID *InBuffer, - OUT VOID *OutBuffer, - OUT RETURN_STATUS *Status +InternalSmBusBlock ( + IN UINT8 HostControl, + IN UINTN SmBusAddress, + IN UINT8 *WriteBuffer, + OUT UINT8 *ReadBuffer, + OUT RETURN_STATUS *Status ) { - RETURN_STATUS RetStatus; - UINT16 SmBusBase; - UINTN Index; - UINTN BytesCount; - - BytesCount = (UINT8)(SmBusAddress >> 16); - ASSERT (BytesCount <= 32); - - if (Status == NULL) { - Status = &RetStatus; + RETURN_STATUS ReturnStatus; + UINTN Index; + UINTN BytesCount; + UINT8 AuxiliaryControl; + + BytesCount = SMBUS_LIB_LENGTH (SmBusAddress); + // + // Try to acquire the ownership of ICH SMBUS. + // + ReturnStatus = InternalSmBusAcquire (); + if (RETURN_ERROR (ReturnStatus)) { + goto Done; } - - SmBusBase = GetSmBusIOBaseAddress (); - if (!SmBusAcquire (SmBusBase)) { - *Status = RETURN_TIMEOUT; - return 0; + // + // Set the appropriate Host Control Register and auxiliary Control Register. + // + AuxiliaryControl = SMBUS_B_E32B; + if (SMBUS_LIB_PEC (SmBusAddress)) { + AuxiliaryControl |= SMBUS_B_AAC; + HostControl |= SMBUS_B_PEC_EN; } - - IoWrite8 (SmBusBase + R_HST_CMD, (UINT8)(SmBusAddress >> 8)); - IoWrite8 (SmBusBase + R_HST_D0, (UINT8)BytesCount); - if ((INTN)SmBusAddress < 0) { - IoOr8 (SmBusBase + R_HST_CNT, B_HST_CNT_PEC); - IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_AAC); - } else { - IoAnd8 (SmBusBase + R_HST_CNT, (UINT8)~B_HST_CNT_PEC); - IoAnd8 (SmBusBase + R_AUX_CTL, (UINT8)~B_AUX_CTL_AAC); + // + // Set Host Command Register. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_CMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress)); + // + // Set Auxiliary Control Regiester. + // + InternalSmBusIoWrite8 (SMBUS_R_AUX_CTL, AuxiliaryControl); + // + // Clear byte pointer of 32-byte buffer. + // + InternalSmBusIoRead8 (SMBUS_R_HST_CTL); + + if (WriteBuffer != NULL) { + // + // Write the number of block to Host Block Data Byte Register. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_D0, (UINT8) BytesCount); + // + // Write data block to Host Block Data Register. + // + for (Index = 0; Index < BytesCount; Index++) { + InternalSmBusIoWrite8 (SMBUS_R_HOST_BLOCK_DB, WriteBuffer[Index]); + } } - // - // BUGBUG: E32B bit does not exist in ICH3 or earlier + // Set SMBUS slave address for the device to send/receive from. // - IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_E32B); - ASSERT (IoRead8 (SmBusBase + R_AUX_CTL) & B_AUX_CTL_E32B); - for (Index = 0; InBuffer != NULL && Index < BytesCount; Index++) { - IoWrite8 (SmBusBase + R_HOST_BLOCK_DB, ((UINT8*)InBuffer)[Index]); + InternalSmBusIoWrite8 (SMBUS_R_XMIT_SLVA, (UINT8) SmBusAddress); + // + // Start the SMBUS transaction and wait for the end. + // + ReturnStatus = InternalSmBusStart (HostControl); + if (RETURN_ERROR (ReturnStatus)) { + goto Done; } - SmBusStart (SmBusBase, SmBusProtocol, (UINT8)SmBusAddress); - - if (SmBusWait (SmBusBase) & B_HST_STS_ERR) { - *Status = RETURN_DEVICE_ERROR; - } else { - *Status = RETURN_SUCCESS; - BytesCount = IoRead8 (SmBusBase + R_HST_D0); - for (Index = 0; OutBuffer != NULL && Index < BytesCount; Index++) { - ((UINT8*)OutBuffer)[Index] = IoRead8 (SmBusBase + R_HOST_BLOCK_DB); + if (ReadBuffer != NULL) { + // + // Read the number of block from host block data byte register. + // + BytesCount = InternalSmBusIoRead8 (SMBUS_R_HST_D0); + // + // Write data block from Host Block Data Register. + // + for (Index = 0; Index < BytesCount; Index++) { + ReadBuffer[Index] = InternalSmBusIoRead8 (SMBUS_R_HOST_BLOCK_DB); } } + // + // Clear Host Status Register and Auxiliary Status Register. + // + InternalSmBusIoWrite8 (SMBUS_R_HST_STS, SMBUS_B_HSTS_ALL); + InternalSmBusIoWrite8 (SMBUS_R_AUX_STS, SMBUS_B_CRCE); + +Done: + if (Status != NULL) { + *Status = ReturnStatus; + } - SmBusCleanup (SmBusBase); return BytesCount; } +/** + Executes an SMBUS read block command. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes read. + +**/ UINTN EFIAPI SmBusReadBlock ( - IN UINTN SmBusAddress, - OUT VOID *Buffer, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0); - return SmBusBlock ( - SmBusAddress | B_SMBUS_READ, - B_SMB_CMD_BLOCK, + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusBlock ( + SMBUS_V_SMB_CMD_BLOCK, + SmBusAddress | SMBUS_B_READ, NULL, Buffer, Status ); } +/** + Executes an SMBUS write block command. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ UINTN EFIAPI SmBusWriteBlock ( - IN UINTN SmBusAddress, - OUT VOID *Buffer, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0); - return SmBusBlock ( - SmBusAddress | B_SMBUS_WRITE, - B_SMB_CMD_BLOCK, + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusBlock ( + SMBUS_V_SMB_CMD_BLOCK, + SmBusAddress | SMBUS_B_WRITE, Buffer, NULL, Status ); } +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If WriteBuffer is NULL, then ASSERT(). + If ReadBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS. + @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ UINTN EFIAPI SmBusBlockProcessCall ( - IN UINTN SmBusAddress, - IN VOID *OutBuffer, - OUT VOID *InBuffer, - OUT RETURN_STATUS *Status + IN UINTN SmBusAddress, + IN VOID *WriteBuffer, + OUT VOID *ReadBuffer, + OUT RETURN_STATUS *Status OPTIONAL ) { - ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0); - return SmBusBlock ( - SmBusAddress | B_SMBUS_WRITE, - B_SMB_CMD_BLOCK_PROCESS, - OutBuffer, - InBuffer, + ASSERT (WriteBuffer != NULL); + ASSERT (ReadBuffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusBlock ( + SMBUS_V_SMB_CMD_BLOCK_PROCESS, + SmBusAddress | SMBUS_B_WRITE, + WriteBuffer, + ReadBuffer, Status ); } - -RETURN_STATUS -EFIAPI -SmBusArpAll ( - IN UINTN SmBusAddress - ); - -RETURN_STATUS -EFIAPI -SmBusArpDevice ( - IN UINTN SmBusAddress, - IN CONST GUID *Uuid - ); - -RETURN_STATUS -EFIAPI -SmBusGetUuid ( - IN UINTN SmBusAddress, - OUT GUID *Uuid - );