5.5.2.4.6.3. 使用通用串行总线协议
本节提供有关如何使用每个 GenericSerialBus 协议访问AML中的 GenericSerialBus 设备的信息和示例。
快速读/写 (AttribQuick)
GenericSerialBus 读/写快速协议 (AttribQuick) 通常用于使用设备特定的二进制命令(例如ON和OFF)来控制简单设备。该协议不使用命令值,因此只能在字段定义中指定单个元素(位于偏移 0 处)。该协议不传输任何数据。
以下ASL代码说明了如何访问支持读/写快速协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
// GenericSerialBus device at command value offset 0
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer (){1,6})),
AccessAs (BufferAcc, AttribQuick),
// Use the GenericSerialBus Read/Write Quick protocol
FLD0, 8 // Virtual register at command value 0.
}
/* Create the GenericSerialBus data buffer */
Name (BUFF, Buffer (2){}) // Create GenericSerialBus data buffer as BUFF
CreateByteField (BUFF, 0x00, STAT) // STAT = Status (Byte)
/* 信号设备(例如OFF)*/
BUFF = FLD0 // Invoke Read Quick transaction
If (STAT == 0x00) // Was the transactions successful?
{
...
}
/* Signal device (e.g. ON) */
FLD0 = FLD0 // Invoke Write Quick transaction
在此示例中,偏移量 0 处的单个字段元素 (FLD0) 被定义为表示协议的读/写位。访问FLD0将导致设备发生 GenericSerialBus 事务。读取字段会导致“快速读取”,写入字段会导致“快速写入”。在这两种情况下,数据都不会被传输——对寄存器的访问只是用作调用事务的机制。
发送/接收字节 (AttribSendReceive)
GenericSerialBus 发送/接收字节协议 (AttribSendReceive) 传输单个字节的数据。与快速读/写一样,该协议不使用命令值,因此只能在字段定义中指定单个元素(偏移量为 0)。
以下ASL代码说明了如何访问支持发送/接收字节协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
// GenericSerialBus device at command value offset 0
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer (){1,6})),
AccessAs(BufferAcc, AttribSendReceive),
// Use the GenericSerialBus Send/Receive Byte protocol
FLD0, 8 // Virtual register at command value 0.
}
// Create the GenericSerialBus data buffer
Name (BUFF, Buffer (3){}) // Create GenericSerialBus 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
BUFF = FLD0 // Invoke a Receive Byte transaction
If (STAT == 0x00) // Successful?
{
// DATA = Received byte...
}
// Send the byte '0x16' to the device
DATA = 0x16 // Save 0x16 into the data buffer
FLD0 = BUFF //Invoke a Send Byte transaction
在此示例中,偏移量 0 处的单个字段元素 (FLD0) 被定义为表示协议的数据字节。访问FLD0将导致设备发生 GenericSerialBus 事务。读取该字段会产生一个接收字节,写入该字段会产生一个发送字节。
读/写字节 (AttribByte)
GenericSerialBus 读/写字节协议 (AttribByte) 也传输单个字节的数据。但与发送/接收字节不同,该协议使用命令值来引用最多 256 字节大小的虚拟寄存器。
以下ASL代码说明了如何访问支持读/写字节协议的设备:
操作区域(TOP1、GenericSerialBus、0x00、0x100) // GenericSerialBus device at command value offset Field (TOP1, BufferAcc, NoLock, Preserve) { Connection (I2CSerialBusV2 (0x5a,,100000,,"\_SB.I2C",,,,,RawDataBuffer (){1,6})), AccessAs(BufferAcc, AttribByte), // Use the GenericSerialBus 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 GenericSerialBus data buffer
Name (BUFF, Buffer (3){})
// Create GenericSerialBus 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
BUFF = FLD1 // Invoke a Read Byte transaction
If (STAT == 0x00) // Successful?
{
// DATA = Byte read from FLD1...
}
// Write the byte '0x16' to the device using command value 2
DATA = 0x16 // Save 0x16 into the data buffer
FLD2 = BUFF // Invoke a Write Byte transaction
在此示例中,定义了三个字段元素(FLD0、FLD1和FLD2)来表示命令值 0、1 和 2 的虚拟寄存器。访问任何字段元素都会导致设备发生 GenericSerialBus 事务。读取FLD1会产生命令值为 1 的读字节,写入FLD2会产生命令值为 2 的写字节。
读/写字(AttribWord)
GenericSerialBus 读/写字协议 (AttribWord) 传输 2 个字节的数据。该协议还使用命令值来引用最多 256 个字大小的虚拟设备寄存器。
以下ASL代码说明了如何访问支持读/写字协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
// GenericSerialBus device at command value offset 0
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer (){1,6})),
AccessAs (BufferAcc, AttribWord),
// Use the GenericSerialBus 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 GenericSerialBus data buffer
Name(BUFF, Buffer(6){}) // Create GenericSerialBus 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 */
BUFF = FLD1 // Invoke a Read Word transaction
If (STAT == 0x00) // Was the transaction successful?
{
// DATA = Word read from FLD1...
}
/* Write the word '0x5416' to the device using command value 2 */
DATA = 0x5416 // Save 0x5416 into the data buffer
FLD2 = BUFF // Invoke a Write Word transaction
在此示例中,定义了三个字段元素(FLD0、FLD1和FLD2)来表示命令值 0、1 和 2 的虚拟寄存器。访问任何字段元素都会导致设备发生 GenericSerialBus 事务。读取FLD1会产生命令值为 1 的读字,写入FLD2会产生命令值为 2 的写字。
请注意,虽然访问每个字段元素会传输一个字(16 位)数据,但每个字段都列为 8 位。实际数据大小由协议决定。每个字段元素都声明为 8 位长度,以便命令值和字节偏移量相等。
读/写块(AttribBlock)
GenericSerialBus 读/写块协议 (AttribBlock) 传输可变大小的数据。该协议使用命令值来引用最多 256 个块大小的虚拟寄存器。
以下ASL代码说明了如何访问支持读/写块协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer(){1,6})),
Offset(0x0),
AccessAs(BufferAcc, AttribBlock),
TFK1, 8,
TFK2, 8
}
// Create the GenericSerialBus data buffer
Name (BUFF, Buffer (34){}) // Create SerialBus buf as BUFF
CreateByteField (BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateBytefield (BUFF, 0x01, LEN) // LEN = Length (Byte)
CreateWordField (BUFF, 0x03, DATW) // DATW = Data (Word - Bytes 2 & 3, or 16 bits)
CreateField (BUFF, 16, 256, DBUF) // DBUF = Data (Bytes 2-33)
CreateField (BUFF, 16, 32, DATD) // DATD = Data (DWord)
/* Read block of data from the device using command value 0 */
BUFF = TFK1
If (STAT != 0x00)
{
Return (0)
}
/* Read block of data from the device using command value 1 */
BUFF = TFK2
If (STAT != 0x00)
{
Return (0)
}
在此示例中,定义了两个字段元素(TFK1和TFK2)来表示命令值 0 和 1 的虚拟寄存器。访问任何字段元素都将导致设备发生 GenericSerialBus 事务。
写入数据块需要类似的语义,例如以下示例:
Store (16, LEN) // In bits, so 4 bytes
LEN = 16
BUFF = (TFK1 = BUFF)
If (STAT == 0x00) // Was the transaction successful?
{
...
}
此访问器对于某些 SPB 不可行,因为总线可能不支持适当的功能。如果需要可变长度缓冲区但总线不支持块访问器,请参阅 SerialBytes 协议。
字进程调用(AttribProcessCall)
GenericSerialBus 进程调用协议 (AttribProcessCall) 双向传输 2 个字节的数据(执行写入字,然后执行读取字作为原子事务)。该协议使用命令值来引用最多 256 个字大小的虚拟寄存器。
以下ASL代码说明了如何访问支持进程调用协议的设备:
操作区域(TOP1、GenericSerialBus、0x00、0x100) // GenericSerialBus device at slave address 0x42 Field (TOP1, BufferAcc, NoLock, Preserve) { Connection (I2CSerialBusV2 (0x5a,,100000,,"\_SB.I2C",,,,,RawDataBuffer(){1,6})), AccessAs (BufferAcc, AttribProcessCall), // Use the GenericSerialBus 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 GenericSerialBus data buffer
Name (BUFF, Buffer (6){}) // Create GenericSerialBus 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 */
DATA = 0x5416 // Save 0x5416 into the data buffer
BUFF = (FLD1 = BUFF) // Invoke a Process Call transaction
If (STAT == 0x00) // Was the transaction successful?
{
// DATA = Word returned from FLD1...
}
在此示例中,定义了三个字段元素(FLD0、FLD1和FLD2)来表示命令值 0、1 和 2 的虚拟寄存器。访问任何字段元素都会导致设备发生 GenericSerialBus 事务。读取或写入FLD1会导致命令值为 1 的“进程调用”。请注意,与其他协议不同,“进程调用”涉及单个原子事务中的写入和读取操作。这意味着 GenericSerialBus 数据缓冲区的数据元素在调用事务之前设置有输入值,并在事务成功完成后保存输出值。
块进程调用(AttribBlockProcessCall)
GenericSerialBus 块写入-读取块进程调用协议 (AttribBlockProcessCall) 双向传输数据块(执行写入块,然后执行读取块作为原子事务)。该协议使用命令值来引用最多 256 个块大小的虚拟寄存器。
以下ASL代码说明了如何访问支持进程调用协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
// GenericSerialBus device at slave address 0x42
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer(){1,6})),
AccessAs (BufferAcc, AttribBlockProcessCall),
// 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 GenericSerialBus data buffer as BUFF
Name (BUFF, Buffer (35){}) // Create GenericSerialBus data buffer as BUFF
CreateByteField (BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateByteField (BUFF, 0x01, LEN) // LEN = Length (Byte)
CreateField (BUFF, 0x10, 256, DATA) // Data (Block)
/* Process Call with input value "ACPI" to the device using command value 1 */
DATA = "ACPI" // 填写传出数据 LEN = 4 // Length of the valid data not including status (STAT) // and length (LEN) bytes. BUFF = (FLD1 = BUFF)
If (STAT == 0x00) // Test the status
{
// BUFF now contains information returned from PC
// LEN now equals size of data returned
}
读/写 N 字节 (AttribBytes)
GenericSerialBus 读/写 N 字节协议 (AttribBytes) 传输可变大小的数据。指定为 AccessAs 属性一部分的双向调用的读取传输字节长度。
以下ASL代码说明了如何访问支持读/写 N 字节协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer(){1,6})),
AccessAs (BufferAcc, AttribBytes (4)),
TFK1, 8, //TFK1 at command value 0
TFK2, 8, //TFK2 at command value 1
Connection (I2CSerialBus (0x5b,,100000,,"\\_SB.I2C",,,,RawDataBuffer (){2,9})),
// same connection attribute, but different vendor data passed to driver
AccessAs (BufferAcc, AttribByte),
TM1, 8 //TM1 at command value 2
}
// Create the GenericSerialBus data buffer
Name (BUFF, Buffer(34) {}) // Create SerialBus buf as BUFF
CreateByteField (BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateBytefield (BUFF, 0x01, LEN) // LEN = Length (Byte)
CreateWordField (BUFF, 0x02, DATW) // DATW = Data (Word - Bytes 2 & 3, or 16 bits)
CreateField (BUFF, 16, 256, DBUF) // DBUF = Data (Bytes 2-34)
CreateField (BUFF, 16, 32, DATD) // DATD = Data (DWord)
// Read block of data from the device using command value 0
BUFF = TFK1
If (STAT != 0x00)
{
Return (0)
}
// Write block of data to the device using command value 1
BUFF = (TFK2 = BUFF)
If (STAT != 0x00)
{
Return (0)
}
在此示例中,定义了两个字段元素(TFK1和TFK2)来表示命令值 0 和 1 的虚拟寄存器。访问任何字段元素都将导致在 AccessAttributes 中指定长度的设备上发生 GenericSerialBus 事务。
原始读/写 N 字节 (AttribRawBytes)
GenericSerialBus 原始读/写 N 字节协议 (AttribRawBytes) 传输可变大小的数据。指定为 AccessAs 属性一部分的双向事务的读取传输字节长度。原始访问将忽略操作区域定义中指定的初始命令值。
以下ASL代码说明了如何访问支持读/写 N 字节协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer(){1,6})),
AccessAs(BufferAcc, AttribRawBytes (4)),
TFK1, 8
}
/* Create the GenericSerialBus data buffer */
Name(BUFF, Buffer (34){}) // 创建 SerialBus buf 为 BUFF CreateByteField (BUFF, 0x00, STAT) // STAT = Status (Byte) CreateByteField (BUFF, 0x01, LEN) // LEN = Length (Byte) CreateWordField (BUFF, 0x02, DATW) // DATW = Data (Word - Bytes 2 & 3, or 16 bits) CreateField (BUFF, 16, 256, DBUF) // DBUF = Data (Bytes 2-34) CreateField (BUFF, 16, 32, DATD) // DATD = Data (DWord)
DATW = 0x0B // Store appropriate reference data for driver to interpret
/* Read from TFK1 */
BUFF = TFK1
If (STAT != 0x00)
{
Return (0)
}
/* Write to TFK1 */
BUFF = (TFK1 = BUFF)
If (STAT != 0x00)
{
Return(0)
}
对任何字段元素的访问都会导致在 AccessAttributes 中指定长度的设备上发生 GenericSerialBus 事务。
原始访问假设编写者了解访问所通过的总线以及正在访问的设备。该协议可能仅确保缓冲区被传输到适当的驱动程序,但驱动程序必须能够解释缓冲区以与寄存器进行通信。
原始块进程调用 (AttribRawProcessBytes)
GenericSerialBus 原始写入-读取块进程调用协议 (AttribRawProcessBytes) 双向传输数据块(执行写入块,然后执行读取块作为原子事务)。指定为 AccessAs 属性一部分的双向事务的读取传输字节长度。原始访问将忽略操作区域定义中指定的初始命令值。
以下ASL代码说明了如何访问支持进程调用协议的设备:
OperationRegion (TOP1, GenericSerialBus, 0x00, 0x100)
// GenericSerialBus device at slave address 0x42
Field (TOP1, BufferAcc, NoLock, Preserve)
{
Connection (I2CSerialBusV2 (0x5a,,100000,,"\\_SB.I2C",,,,,RawDataBuffer (){1,6})),
AccessAs (BufferAcc, AttribRawProcessBytes (2)),
// Use the Raw Bytes Process Call protocol
FLD0, 8
}
// Create the GenericSerialBus data buffer as BUFF
Name (BUFF, Buffer (34){}) // Create GenericSerialBus data buffer as BUFF
CreateByteField (BUFF, 0x00, STAT) // STAT = Status (Byte)
CreateByteField (BUFF, 0x01, LEN) // LEN = Length (Byte)
CreateWordField (BUFF,0x02, DATW) // Data (Bytes 2 and 3)
CreateField (BUFF, 0x10, 256, DATA) // Data (Block)
DATW = 0x0B //Store appropriate reference data for driver to interpret
/* Process Call with input value "ACPI" to the device */
DATA = "ACPI" // Fill in outgoing data
LEN = 4 // Length of the valid data
BUFF = (FLD0 = BUFF) // Execute the PC
If (STAT == 0x00) // Test the status
{
// BUFF now contains information returned from PC
// LEN now equals size of data returned
}
原始访问假设编写者了解访问所通过的总线以及正在访问的设备。该协议可能仅确保缓冲区被传输到适当的驱动程序,但驱动程序必须能够解释缓冲区以与寄存器进行通信。