5.5.2.4.6.2. 声明和使用 GenericSerialBus 数据缓冲区
使用 GenericSerialBus 事务的数据缓冲区允许AML接收状态和数据长度值,并且可以实现“进程调用”协议。 BufferAcc 访问类型用于向字段处理程序指示将使用特定于区域的数据缓冲区。
对于 GenericSerialBus 操作区域,此数据缓冲区被定义为任意长度的缓冲区,如果使用“C”样式声明表示,则将建模如下:
typedef struct
{
BYTE Status; // Byte 0 of the data buffer
BYTE Length; // Byte 1 of the data buffer
BYTE[x-1] Data; // Bytes 2-x of the arbitrary length data buffer,
} // where x is the last index of the overall buffer
其中:
状态(字节 0)指示给定 GenericSerialBus 事务的状态代码。
长度(字节 1)指定数据缓冲区中存在的有效数据的字节数(字节 2-x)。该字段的使用仅为读/写块协议定义。对于其他协议(数据长度由协议隐含),该字段被保留。由于该字段是一个字节,因此数据缓冲区的最大长度为255。
Data(字节2-x)表示任意长度的缓冲区,是实际数据存储的位置。
例如,以下ASL显示了使用 GenericSerialBus 数据缓冲区对智能电池设备执行事务。
/* Create the GenericSerialBus data buffer */
Name (BUFF, Buffer (34){}) // 创建 GenericSerialBus 数据缓冲区作为 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) CreateField (BUFF, 0x10, 256, DBUF) // DBUF = Data (Block - Bytes 2-33)
/* Read the battery temperature */
BUFF = BTMP // Invoke Read Word transaction
If (STAT == 0x00) // Successful?
{
// DATW = Battery temperature in 1/10th degrees Kelvin
}
/* Read the battery manufacturer name */
BUFF = MFGN // Invoke Read Blocktransaction
If (STAT == 0x00) // Successful?
{
// LEN = Length of the manufacturer name
// DBUF = Manufacturer name (as a counted string)
}
请注意使用 CreateField 原语来访问数据缓冲区的子元素(状态、长度和数据),其中数据(字节 2-33)被“类型转换”为字 (DATW) 和块 (DBUF) 数据。
上面的示例演示了如何使用 Store() 运算符调用读取块事务来获取电池制造商的名称。对源操作数 (MFGN) 的计算会产生一个 34 字节缓冲区,该缓冲区由 Store() 复制到目标缓冲区 (BUFF)。
捕获写操作的结果,例如检查状态代码,需要额外的 Store() 运算符,如下所示:
BUFF = (MFGN = BUFF)
If (STAT == 0x00) // Transaction successful?
{
...
}
请注意,外部 Store() 将写入块事务的结果复制回BUFF。这就是 BufferAcc 双向性的本质。应该注意的是,存储(或解析)GenericSerialBus Write 事务的结果不是必需的,尽管对于确定事务的结果很有用。
由于只有目标操作数是双向传递的,GenericSerialBus Process Call 协议需要类似的语义。这些事务需要使用 double-Store() 语义来正确捕获返回结果。