5.5.2.4.7. 声明PCC运营区域
平台通信通道 (PCC) 在第 14 章中进行了描述。 平台通信通道表 中描述的 PCC 表包含有关给定平台中实现的 PCC 子空间的信息,其中每个子空间都是一个唯一的通道。
5.5.2.4.7.1. 概述
PCC操作区域与PCC表(平台通信通道表)结合使用。 PCC操作区域与PCC签名后面的共享内存区域相关联。 PCC 操作区域不得用于类型 4(从属子空间)的扩展子空间。指定用作PCC操作区域的PCC子空间不得用作标准ACPI功能(例如CPPC、RASF、PDTT和MPST)的PCC子空间。这些标准功能必须始终使用PCC 表。
5.5.2.4.7.2. 声明PCC操作区域
OperationRegion 术语的语法 (OperationRegion (声明操作区域)) 描述如下:
OperationRegion (
RegionName, // NameString
RegionSpace, // RegionSpaceKeyword
Offset, // TermArg=>Integer
Length // TermArg=>Integer
)
ACPI命名空间中的PCC操作区域术语定义如下:
OperationRegion ([subspace-name], PCC, [subspace-id], Length)
其中:
RegionName 设置为 [subspace-name] ,这是此 PCC 子空间的唯一名称。
RegionSpace必须设置为PCC,操作区域类型0x0A
偏移量必须设置为 [subspace-id],即该通道的子空间 ID,如 PCC 表 (PCCT) 中所定义。
长度是操作区域的总大小,等于共享内存中PCC签名之后的字段的总大小。
5.5.2.4.7.3. 在PCCOperationRegion 中声明消息字段
对于所有PCC子空间类型,PCC操作区域属于PCC子空间中PCC签名之后的区域。共享内存区域的布局特定于PCC子空间。因此,操作区域处理程序必须首先获取子空间类型,然后才能理解和访问子空间内的各个字段。
操作区域内的字段可使用 Field 关键字进行访问,并且对应于子空间共享内存中PCC签名之后的字段。 Field 术语的语法(来自 Field (Declare Field Objects) )如下:
Field (
RegionName,
AccessType,
LockRule,
UpdateRule
) {FieldUnitList}
对于PCC 运营区域:
RegionName 指定操作区域的名称,在字段术语上方声明。
AccessType 必须设置为 ByteAcc。
LockRule 指示访问该操作区域是否需要获取全局锁以进行同步。该字段必须设置为 NoLock。
UpdateRule 不适用于PCC操作区域,因为每个命令区域都是完整访问的。
FieldUnitList 指定子空间的共享内存区域内的各个字段,这取决于子空间的类型。字段的声明必须与子空间的布局匹配。因此,对于通用通信子空间(类型 0-2),FieldUnitList 可以声明如下:
Field(NAME, ByteAcc, NoLock, Preserve)
{
CMD, 16, // Command field
STAT, 16, // Status field, to be read on completion of the command
DATA, [Size] // Communication space of size [Size] bits
}
同样,对于扩展通信子空间(类型 3),FieldUnitList 可以声明如下:
Field(NAME, ByteAcc, NoLock, Preserve)
{
FLGS, 32, // Command Flags field
LEN, 32, // Length field
CMD, 32, // Command field
DATA, [Size] // Communication space of size [Size] bits
}
5.5.2.4.7.4. PCC操作区域声明示例
例如,如果平台功能使用 PCC 子空间以及子空间类型 3(扩展 PCC 通信通道)的 0x02 子空间 ID,则调用者可以声明操作区域如下:
OperationRegion(PFRM, PCC, 0x02, 0x10C)
Field(PFRM, ByteAcc, NoLock, Preserve)
{
Offset (4), // Flags start at offset 4 from beginning of shared memory
FLGS, 32, // Command Flags field
LGTH, 32, // Length field
COMD, 32, // Command field
COSP, 0x800 // Communication space of size 256 bytes
}
在此示例中,PFRM是专用于平台功能的子空间的名称,共享内存区域的大小为 0x10C 字节(256 字节通信空间和 16 字节字段,不包括PCC签名)。
5.5.2.4.7.5. 使用PCC操作区域
当PCC操作区域处理程序检测到对CMD字段的写入时,它开始在通道上传输消息。因此,调用者必须首先更新与操作区域相关的所有其他字段,然后在最后一步中编写命令本身。如在PCCOperationRegion 中声明消息字段中所述,要更新的字段特定于子空间类型。
对于通用通信子空间类型(类型 0、1 和 2),操作区域写入的顺序如下:
将命令负载写入DATA字段。 StepNumList-1 将命令负载写入DATA字段。
将命令写入CMD字段。
对于扩展通信子空间类型(类型3),操作区域写入的顺序如下:
以任意优先顺序将命令有效负载、长度和标志分别写入CMD、LEN和FLGS字段。 StepNumList-1 以任意优先顺序将命令有效负载、长度和标志分别写入CMD、LEN和FLGS字段。
将命令写入CMD字段。
在上述步骤中,字段如第 5.5.2.4.7.4 节所述。当平台完成命令处理后,它使用相同的子空间共享内存区域来返回响应数据。因此,调用者可以读取操作区域以检索响应数据。
如果在传输命令或其响应期间遇到通道错误,通道会在通道状态寄存器中报告错误状态。因此,调用者必须在处理返回数据之前首先检查通道状态寄存器。对于通用PCC通信子空间,通道状态寄存器位于共享内存区域本身,如通用通信通道状态字段中所述。为此,调用者必须检查操作区域中的STAT字段。对于扩展PCC通信子空间,通道状态寄存器位于系统存储器或IO中的任何位置,并由类型 3PCC子空间结构中的错误状态寄存器字段指向,如扩展PCC子空间(类型 3 和 4) 中所述。
####### 5.5.2.4.7.5.1。对PCC操作区域使用_REG方法
OS可能包含PCC操作区域处理程序,这些处理程序仅理解并支持本规范中定义的可能子空间的子集。 OS可以在 _REG 方法中提供补充信息,以指示支持哪些确切的子空间。要实现此目的,传递给 _REG 方法的 Arg0 参数必须包含地址空间ID (PCC) 和字节 1 中的合格地址空间子类型,如下所示:
Arg0,字节 0 = PCC = 0x0A Arg0,字节 1 = 第 14.1.2 节 中定义的子空间类型。
OS现在可以通过调用 Arg0=0x030A 和 Arg1 = 0x01 的 _REG 方法来指示支持处理PCC操作区域子空间类型 3。
####### 5.5.2.4.7.5.2。 PCCOperationRegion 的使用示例
以下示例ACPI功率计(功率计)实现描述了如何使用PCC操作区域来读取通过平台服务通道公开的平台功率传感器。在此示例系统中,平台服务通道被实现为扩展PCC通信通道(类型 3),并在PCCT中分配了 0x07 的PCC子空间ID。该示例平台实现了三个传感器:两个功率传感器(分别与CPU集群 0 和集群 1 关联)以及一个 SoC 级热传感器。功率传感器使用命令 0x15 (READ_POWER_SENSOR) 读取,而热传感器使用命令 0x16 (READ_THERMAL_SENSOR) 读取,两者都在平台服务通道上。 READ_POWER_SENSOR命令采用两个名为 SensorInstance 和MeasurementFormat 的输入参数,它们作为有效负载一起附加到命令中。 SensorInstance 指定正在引用哪个功率传感器。 MeasurementFormat 指定表示功耗的测量单位(瓦或毫瓦)。命令负载的格式如下:
typedef struct
{
BYTE SensorInstance; // Which instance of the sensor is being read
BYTE MeasurementFormat; // 0 = mW, 1 = W
} COMMAND_PAYLOAD;
通过将 SensorInstance 设置为 0x01 来读取CPU集群 0 的功率传感器,通过将 SensorInstance 设置为 0x02 来读取CPU集群 1 的功率传感器。
对来自平台的命令的响应的形式为:
typedef struct
{
DWORD Reading; // The sensor value read
DWORD Status; // Status of the operation - 0: success, non-zero: error
} SENSOR_RESPONSE;
这里,状态字段与所请求的服务的成功或失败有关。在请求传输期间,通道错误可能与服务无关地发生。通用占位符寄存器CHANNEL_STATUS_REG和关联的错误状态字段ERROR_STATUS_BIT用于说明如何读取通道状态寄存器以检测传输期间的通道错误。
现在可以为此示例平台实现ACPI功率计对象,如下所示:
Device (PMT0) // ACPI Power Meter object for CPU Cluster 0 Power Sensor
{
Name (_HID, "ACPI000D") // ACPI Power Meter device
// The Operation Region declaration, based on "An Example of PCC Operation
// Region Declaration" described earlier in this chapter.
OperationRegion (PFRM, PCC, 0x07, 0x8C)
Field(PFRM, ByteAcc, NoLock, Preserve)
{
FLGS, 32, // Command Flags field
LEN, 32, // Length field
CMD, 32, // Command field
DATA, 0x400 // Communication space of size 128 bytes
}
Method (_REG, 2) // Check if OS Op region handler is available
{
/*
* Check if Arg0.Byte0 = 0xA, PCC Operation Region Supported?
* Check if Arg0.Byte1 = 0x3, subchannel type 3 as defined in Table 14-357
* Disallow further processing until support for Type 3 becomes available
*/
}
// Read a Power sensor
Method (_PMM, 0, Serialized)
{
// Create the command buffer
Name(BUFF, Buffer(0x80){}) // Create PCC data buffer as BUFF
Name(PAYL, Buffer(2) {0x02, 0x01}) // Instance = CPU cluster 1
// Read power in units of Watts
DATA = PAYL // Only first two bytes written, the rest default to 0
// Update the length and status fields
LEN = 0x06 // 4B (command) + 2B (payload)
FLGS = 0x01 // Set Notify on Completion
/*
* All done. Now write to the command field to begin transmission of
* the message over the PCC subspace. On receipt, the platform will
* read power sensor of CPU cluster 0 and return the power consumption
* reading in the Operation Region itself
*/
CMD = 0x15 // READ_POWER_SENSOR command = 0x15
If(LEqual( LAnd (CHANNEL_STATUS_REG, ERROR_STATUS_BIT), 0x01)
{
Return (Ones). // Return invalid, so that the caller can take remedial steps
}
BUFF = DATA
CreateDWordField(BUFF, 0x00, PCL1) // Power consumed by CPU cluster 1
CreateDWordField(BUFF, 0x01, STAT) // Return status
If (STAT == 0x0)) // Successful?
{
Return (PCL1) // Return the power measurement for CPU cluster 1
}
Else
{
Return (Ones) // Return invalid
}
}
}