13.3. 使用 SMBus 协议
本节提供有关如何使用各类 SMBus 协议从 AML 访问 SMBus 设备的信息和示例。
13.3.1. 读取/写入 Quick(SMBQuick)
SMBus 读取/写入 Quick 协议(SMBQuick)通常用于通过设备特定的二进制命令(例如 ON 和 OFF)控制简单设备。该协议不使用命令值,因此在字段定义中只能指定单个元素(位于偏移量 0)。该协议不传输数据。
下面的 ASL 代码说明了应如何访问支持读取/写入 Quick 协议的设备:
OperationRegion(SMBD, SMBus, 0x4200, 0x100) // SMBus device at slave address 0x42
Field(SMBD, BufferAcc, NoLock, Preserve)
{
AccessAs(BufferAcc, SMBQuick) // Use the SMBus Read/Write Quick protocol
FLD0, 8 // Virtual register at command value 0.
}
/* Create the SMBus data buffer */
Name(BUFF, Buffer(34){}) // Create SMBus data buffer as BUFF
CreateByteField(BUFF, 0x00, OB1) // OB1 = Status (Byte)
/* Signal device (e.g. OFF) */
Store(FLD0, BUFF) // Invoke Read Quick transaction
If(LEqual(OB1, 0x00)) {...} // Successful?
/* Signal device (e.g. ON) */
Store(BUFF, FLD0) // Invoke Write Quick transaction
在本示例中,定义了位于偏移量 0 的单个字段元素(FLD0)来表示该协议的读/写位。对 FLD0 的访问将导致对该设备发生一次 SMBus 事务。读取该字段会产生一次 Read Quick,而写入该字段会产生一次 Write Quick。无论哪种情况,都不会传输数据——对该寄存器的访问仅用作调用该事务的一种机制。
13.3.2. 发送/接收字节(SMBSendReceive)
SMBus 发送/接收字节协议(SMBSendReceive)传输单个字节的数据。与读/写快速命令一样,此协议不使用命令值,因此在字段定义中只能指定单个元素(位于偏移量 0 处)。
以下 ASL 代码说明了应如何访问支持发送/接收字节协议的设备:
OperationRegion(SMBD, SMBus, 0x4200, 0x100) // SMBus device at slave address 0x42
Field(SMBD, BufferAcc, NoLock, Preserve)
{
AccessAs(BufferAcc, SMBSendReceive) // Use the SMBus Send/Receive Byte protocol
FLD0, 8 // Virtual register at command value 0.
}
// Create the SMBus data buffer
Name(BUFF, Buffer(34){}) // Create SMBus data buffer as BUFF
CreateByteField(BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateByteField(BUFF, 0x02, DATA) // DATA = Data (Byte)
// Receive a byte of data from the device
Store(FLD0, BUFF) // Invoke a Receive Byte transaction
If(LEqual(STAT, 0x00)) // Successful?
{
// DATA = Received byte...
}
// Send the byte '0x16' to the device
Store(0x16, DATA) // Save 0x16 into the data buffer
Store(BUFF, FLD0) // Invoke a Send Byte transaction
在此示例中,定义了位于偏移量 0 处的单个字段元素(FLD0)来表示该协议的数据字节。对 FLD0 的访问将导致对该设备发生一次 SMBus 事务。读取该字段会产生一次接收字节事务,而向该字段写入则会产生一次发送字节事务。
13.3.3. 读/写字节(SMBByte)
SMBus 读/写字节协议(SMBByte)同样传输单个字节的数据。但与发送/接收字节不同,此协议使用命令值来引用最多 256 个字节大小的虚拟寄存器。
以下 ASL 代码说明了应如何访问支持读/写字节协议的设备:
OperationRegion(SMBD, SMBus, 0x4200, 0x100) // SMBus device at slave address 0x42
Field(SMBD, BufferAcc, NoLock, Preserve)
{
AccessAs(BufferAcc, SMBByte) // Use the SMBus Read/Write Byte protocol
FLD0, 8, // Virtual register at command value 0.
FLD1, 8, // Virtual register at command value 1.
FLD2, 8 // Virtual register at command value 2.
}
// Create the SMBus data buffer
Name(BUFF, Buffer(34){}) // Create SMBus data buffer as BUFF
CreateByteField(BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateByteField(BUFF, 0x02, DATA) // DATA = Data (Byte)
// Read a byte of data from the device using command value 1
Store(FLD1, BUFF) // Invoke a Read Byte transaction
If(LEqual(STAT, 0x00)) // Successful?
{
// DATA = Byte read from FLD1...
}
// Write the byte '0x16' to the device using command value 2
Store(0x16, DATA) // Save 0x16 into the data buffer
Store(BUFF, FLD2) // Invoke a Write Byte transaction
在此示例中,定义了三个字段元素(FLD0、FLD1 和 FLD2)来表示命令值 0、1 和 2 的虚拟寄存器。对任一字段元素的访问都将导致对该设备发生一次 SMBus 事务。读取 FLD1 会产生一次命令值为 1 的读字节事务,而向 FLD2 写入会产生一次命令值为 2 的写字节事务。
13.3.4. 读/写字(SMBWord)
SMBus 读/写字协议(SMBWord)传输 2 字节的数据。此协议同样使用命令值来引用最多 256 个字大小的虚拟设备寄存器。
以下 ASL 代码说明了应如何访问支持读/写字协议的设备:
OperationRegion(SMBD, SMBus, 0x4200, 0x100) // SMBus device at slave address 0x42
Field(SMBD, BufferAcc, NoLock, Preserve)
{
AccessAs(BufferAcc, SMBWord) // Use the SMBus Read/Write Word protocol
FLD0, 8, // Virtual register at command value 0.
FLD1, 8, // Virtual register at command value 1.
FLD2, 8 // Virtual register at command value 2.
}
// Create the SMBus data buffer
Name(BUFF, Buffer(34){}) // Create SMBus data buffer as BUFF
CreateByteField(BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateWordField(BUFF, 0x02, DATA) // DATA = Data (Word)
// Read two bytes of data from the device using command value 1
Store(FLD1, BUFF) // Invoke a Read Word transaction
If(LEqual(STAT, 0x00)) // Successful?
{
// DATA = Word read from FLD1...
}
// Write the word '0x5416' to the device using command value 2
Store(0x5416, DATA) // Save 0x5416 into the data buffer
Store(BUFF, FLD2) // Invoke a Write Word transaction
在此示例中,定义了三个字段元素(FLD0、FLD1 和 FLD2)来表示命令值 0、1 和 2 的虚拟寄存器。对任一字段元素的访问都将导致对该设备发生一次 SMBus 事务。读取 FLD1 会产生一次命令值为 1 的读字事务,而向 FLD2 写入会产生一次命令值为 2 的写字事务。
请注意,尽管访问每个字段元素时传输的是一个字(16 位)数据,这些字段仍被列为每个 8 位。实际数据大小由协议决定。每个字段元素都声明为 8 位长度,以便使命令值与字节偏移量等效。
13.3.5. 读/写块(SMBBlock)
SMBus 读/写块协议(SMBBlock)传输可变大小(0-32 字节)的数据。此协议使用命令值来引用最多 256 个块大小的虚拟寄存器。
以下 ASL 代码说明了应如何访问支持读/写块协议的设备:
OperationRegion(SMBD, SMBus, 0x4200, 0x100) // SMBus device at slave address 0x42
Field(SMBD, BufferAcc, NoLock, Preserve)
{
AccessAs(BufferAcc, SMBBlock) // Use the SMBus Read/Write Block protocol
FLD0, 8, // Virtual register at command value 0.
FLD1, 8, // Virtual register at command value 1.
FLD2, 8 // Virtual register at command value 2.
}
// Create the SMBus data buffer
Name(BUFF, Buffer(34){}) // Create SMBus data buffer as BUFF
CreateByteField(BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateByteField(BUFF, 0x01, SIZE) // SIZE = Length (Byte)
CreateField(BUFF, 0x10, 256, DATA) // DATA = Data (Block)
// Read block data from the device using command value 1
Store(FLD1, BUFF) // Invoke a Read Block transaction
If(LEqual(STAT, 0x00)) // Successful?
{
// SIZE = Size (number of bytes)
// of the block data read from FLD1...
// DATA = Block data read from FLD1...
}
// Write the block 'TEST' to the device using command value 2
Store("TEST", DATA) // Save "TEST" into the data buffer
Store(4, SIZE) // Length of valid data in the data buffer
Store(BUFF, FLD2) // Invoke a Write Word transaction
在此示例中,定义了三个字段元素(FLD0、FLD1 和 FLD2)来表示命令值 0、1 和 2 的虚拟寄存器。对任一字段元素的访问都将导致对该设备发生一次 SMBus 事务。读取 FLD1 会产生一次命令值为 1 的读块事务,而向 FLD2 写入会产生一次命令值为 2 的写块事务。
13.3.6. 字处理调用(SMBProcessCall)
SMBus 处理调用协议(SMBProcessCall)双向传输 2 字节的数据(执行一次写字后再执行一次读字,作为一个原子事务)。此协议使用命令值来引用最多 256 个字大小的虚拟寄存器。
以下 ASL 代码说明了应如何访问支持处理调用协议的设备:
OperationRegion(SMBD, SMBus, 0x4200, 0x100) // SMBus device at slave address 0x42
Field(SMBD, BufferAcc, NoLock, Preserve)
{
AccessAs(BufferAcc, SMBProcessCall) // Use the SMBus Process Call protocol
FLD0, 8, // Virtual register at command value 0.
FLD1, 8, // Virtual register at command value 1.
FLD2, 8 // Virtual register at command value 2.
}
// Create the SMBus data buffer
Name(BUFF, Buffer(34){}) // Create SMBus data buffer as BUFF
CreateByteField(BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateWordField(BUFF, 0x02, DATA) // DATA = Data (Word)
// Process Call with input value '0x5416' to the device using command value 1
Store(0x5416, DATA) // Save 0x5416 into the data buffer
Store(Store(BUFF, FLD1), BUFF) // Invoke a Process Call transaction
If(LEqual(STAT, 0x00)) // Successful?
{
// DATA = Word returned from FLD1...
}
在此示例中,定义了三个字段元素(FLD0、FLD1 和 FLD2)来表示命令值 0、1 和 2 的虚拟寄存器。对任一字段元素的访问都将导致对该设备发生一次 SMBus 事务。读取或写入 FLD1 都会产生一次命令值为 1 的处理调用事务。请注意,与其他协议不同,处理调用在单个原子事务中同时涉及一次写操作和一次读操作。这意味着,SMBus 数据缓冲区的 Data 元素会在事务调用之前被设置为输入值,并在事务成功完成后保存输出值。
13.3.7. 块处理调用(SMBBlockProcessCall)
SMBus 块写入-读取块处理调用协议(SMBBlockProcessCall)双向传输一个数据块(执行一次写块后再执行一次读块,作为一个原子事务)。可传输的数据总量上限为 32 字节。此协议使用命令值来引用最多 256 个块大小的虚拟寄存器。
以下 ASL 代码说明了应如何访问支持处理调用协议的设备:
OperationRegion(SMBD, SMBus, 0x4200, 0x100) // SMbus device at slave address 0x42
Field(SMBD, BufferAcc, NoLock, Preserve)
{
AccessAs(BufferAcc, SMBBlockProcessCall) // Use the Block Process Call protocol
FLD0, 8, // Virtual register representing a command value of 0
FLD1, 8 // Virtual register representing a command value of 1
}
// Create the SMBus data buffer as BUFF
Name(BUFF, Buffer(34)()) // Create SMBus data buffer as BUFF
CreateByteField(BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateByteField(BUFF, 0x01, SIZE) // SIZE = Length (Byte)
CreateField(BUFF, 0x10, 256, DATA) // Data (Block)
// Process Call with input value "ACPI" to the device using command value 1
Store("ACPI", DATA) // Fill in outgoing data
Store(8, SIZE) // Length of the valid data
Store(Store(BUFF, FLD1), BUFF) // Execute the PC
if (LEqual(STAT, 0x00)) // Test the status
{
// BUFF now contains information returned
// from PC
// SIZE now equals size of data returned
}