6.5. 其他对象和控制方法
表 6.65 其他对象和方法
| 对象 | 描述 |
|---|---|
| _BBN | 由平台启动固件设置的 PCI 总线编号。 |
| _BDN | 在 ACPI 与传统接口之间关联扩展坞。 |
| _DCK | 指示该设备是一个扩展坞。 |
| _DEP | 指示设备对象;由于将来会访问操作区域,OSPM 应在启动顺序中为其分配更高优先级。 |
| _FIT | 求值后得到 NFIT 结构缓冲区的对象。 |
| _GLK | 指示在访问设备时必须获取全局锁。 |
| _INI | 在 ACPI 已启用后不久运行的设备初始化方法。 |
| _LSI | 标签存储信息 - 返回与 NVDIMM 对象关联的标签存储区域的信息,包括其大小。 |
| _LSR | 标签存储读取 - 从 NVDIMM 对象的标签存储区域返回标签数据。 |
| _LSW | 标签存储写入 - 将标签数据写入 NVDIMM 对象的标签存储区域。 |
| _REG | 将操作区域可用性变化通知给 AML 代码。 |
| _SEG | 指示总线段位置。 |
6.5.1. _INI(初始化)
_INI 是一个设备初始化对象,用于执行设备特定的初始化。该控制方法位于设备对象之下,并且仅在 OSPM 加载描述表时运行。此方法的调用时机以及为此方法编写代码都受到一些限制。_INI 方法只能访问那些已按 _REG 方法定义被指示为可用的操作区域。_REG 方法在 _REG(区域)中描述。该控制方法在 _ADR、_CID、_HID、_SUN 和 _UID 运行之前执行。
参数:
无
返回值:
无
在对 _INI 对象求值之前,OSPM 会先对设备的 _STA 对象求值。如果设备不存在 _STA 对象,则假定该设备既存在又可正常工作。如果 _STA 对象表明设备存在,OSPM 将对该设备的 _INI 求值(如果 _INI 方法存在),并检查该设备的每个子对象是否具有 _INI 方法。如果 _STA 方法表明设备不存在且不可正常工作,则 OSPM 不会运行 _INI,也不会检查该设备的子对象是否具有 _INI 方法。如果 _STA 对象求值表明设备不存在但可正常工作,则 OSPM 不会对 _INI 对象求值,但会检查该设备的每个子对象是否具有 _INI 对象(有关此特殊情况的说明,请参见 _STA 的描述)。如果设备在表已经加载之后才变为存在,OSPM 不会对 _INI 方法求值,也不会检查子对象的 _INI 方法。
OSPM 基于 _STA 的存在位和功能位所执行的 _INI 对象操作总结如下表所示。
表 6.66 OSPM _INI 对象操作
| _STA 存在位 | _STA 功能位 | 操作 |
|---|---|---|
| 0 | 0 | 不运行 _INI,不检查设备子对象 |
| 0 | 1 | 不运行 _INI,检查设备子对象 |
| 1 | 0 | 运行 _INI,检查设备子对象 |
| 1 | 1 | 运行 _INI,检查设备子对象 |
_INI 控制方法通常用于将设备切换出传统操作模式。例如,平台启动固件通常将 CardBus 控制器配置为传统模式,以支持传统操作系统。在使用 ACPI OSPM 枚举该设备之前,必须将 CardBus 控制器初始化为 CardBus 模式。对于此类系统,供应商可以在 CardBus 控制器下包含一个 _INI 控制方法,以将设备切换到 CardBus 模式。
除了设备初始化之外,如果 \_SB 命名空间下存在 _INI 对象,OSPM 还会在命名空间初始化开始时无条件地对其求值。
6.5.2. _DCK(扩展坞)
该控制方法位于表示扩展坞的设备对象中(即,具有扩展坞所有 _EJx 控制方法的设备对象)。_DCK 的存在向 OSPM 表明该设备确实是一个扩展坞。
_DCK 还控制扩展坞连接器上的隔离逻辑。这使得 OSPM 能够在总线激活且设备出现在总线上之前,为扩展坞插接做好准备。
参数:(1)
Arg0 - 一个包含扩展坞动作代码的 整数
0 - 取消扩展坞连接(与连接器隔离)
1 - 连接扩展坞(移除与连接器的隔离)
返回值:
一个包含扩展坞状态代码的整数
1 - 成功
0 - 失败
注意
当以 0 调用 _DCK 时,OSPM 将忽略返回值。跟在 _EJx 控制方法之后的 _STA 对象将通知便携式设备是否已被弹出。
6.5.3. _BDN(BIOS 扩展坞名称)
_BDN 用于关联通过 ACPI 报告的扩展坞与通过传统接口报告的同一个扩展坞。它主要用于从非 ACPI 环境升级时的兼容。
参数:
无
返回值:
一个包含 EISA Dock ID 的 Integer
_BDN 必须出现在表示扩展坞的设备对象之下,也就是具有 _Ejx 方法的设备对象之下。此对象必须返回一个 DWORD,该值是即插即用 BIOS 功能 5(获取扩展坞标识符)为扩展坞返回的 EISA 打包 DockID。
注意
如果机器不支持 PNPBIOS,则不要求提供此对象。
6.5.4. _REG(区域)
OS 会运行 _REG 控制方法,以将操作区域可用性变化通知给 AML 代码。当操作区域处理程序不可用时,AML 无法访问该区域中的数据字段。(对操作区域的写入将被忽略,而读取将返回不确定的数据。)
参数:(2)
Arg0 – 一个 Integer,包含操作区域地址空间 ID 和可选的补充限定符(参见第 5.5.2.4 节和表 5.149。)
Arg1 - 一个 Integer,包含处理程序连接代码:
0 – 断开处理程序 1 – 连接处理程序
返回值:
无
除下文所示情况外,控制方法必须假定所有操作区域都不可访问,直到执行 _REG(RegionSpace, 1) 方法,其中 RegionSpace 是地址空间 ID,或者根据操作区域不同,可能是带附加限定符的地址空间 ID。有关哪些操作区域具有地址空间限定符的更多信息,请参见对操作区域的访问。一旦针对特定操作区域执行了 _REG,表明操作区域处理程序已就绪,控制方法就可以访问该操作区域中的字段。反之,当 _REG 方法的执行尚未表明操作区域处理程序已就绪时,控制方法不得访问操作区域中的字段。
例如,在 Embedded Controller 驱动程序就绪之前,控制方法不能访问 Embedded Controller。一旦 OSPM 运行 _REG(EmbeddedControl, 1),控制方法随后就可以访问 Embedded Controller 地址空间中的操作区域。此外,如果 OSPM 执行 _REG(EmbeddedControl, 0),控制方法必须停止访问 Embedded Controller 地址空间中的操作区域。
上述规则的例外情况是:
OSPM 必须保证以下操作区域始终可访问:StepNumList-1 OSPM 必须保证以下操作区域始终可访问:
在包含 _BBN 对象的 PCI 根总线上的 PCI_Config 操作区域。
SystemIO 操作区域。
在访问由系统地址映射接口返回的内存时的 SystemMemory 操作区域。
注意
由于上述区域类型是永久可用的,因此不需要 _REG 方法,OSPM 也不会对出现在这些类型操作区域声明所在同一作用域中的任何 _REG 方法求值。
- OSPM 必须在执行任何控制方法之前,使通过 ECDT 中描述的 Embedded Controllers 访问的 Embedded Controller 操作区域可用。在 OSPM 运行 _REG(EmbeddedControl, 0) 之后,这些操作区域可能会变为不可访问。
将 _REG 放在与操作区域声明相同的作用域中。当在该作用域中声明的操作区域可供使用时,OS 将运行该作用域中的 _REG。
示例:
Scope(\_SB.PCI0) {
OperationRegion(OPR1, PCI_Config, ...)
Method(_REG, 2) {...} // OSPM executes this when PCIO operation region handler
// status changes
Device(PCI1) {
Method(2) {...}
Device(ETH0) {
OperationRegion(OPR2, PCI_Config, ...)
Method(_REG,2) {...}
}
}
Device(EC0) {
Name(_HID, EISAID("PNP0C09"))
OperationRegion(OPR4, EmbeddedControl, ...)
Method(_REG, 2) {...} // OSPM executes this when EC operation region
// handler status changes
}
}
}
当 PCI0 操作区域处理程序就绪时,OSPM 将运行在 PCI0 作用域中声明的 _REG 方法,以指示在 PCI0 作用域内可以访问 PCI 配置空间操作区域(换句话说,允许访问 OPR1)。最后,当 Embedded Controller 操作区域处理程序就绪时,OSPM 将运行 EC0 作用域中的 _REG 方法,以指示在 EC0 作用域内可以访问 EC 空间操作区域(换句话说,允许访问 OPR4)。应注意,一旦主控制器或桥控制器已被编程设置了总线号,PCI 配置空间操作区域就已准备就绪。直到 PCI-PCI 桥已被正确配置,才会运行 PCI1 的 _REG 方法。同时,OS 也将运行 ETH0 的 _REG 方法,因为其 PCI 配置空间此时也可用。当 ETH0 设备启动时,OS 将再次运行 ETH0 的 _REG 方法。此外,当主控制器或桥控制器被关闭或禁用时,子设备的 PCI 配置空间操作区域将不再可用。因此,在其被关闭时会运行 ETH0 的 _REG 方法,并且在 PCI1 被关闭时还会再次运行。
注意
OS 只运行那些与操作区域声明位于相同作用域中的 _REG 方法,并且这些操作区域使用的是刚刚变为可用的操作区域类型。例如,当 PCI 总线驱动程序加载时,不会运行 EC 设备中的 _REG,因为在 EC 下声明的操作区域并未使用 PCI 驱动程序所提供的任何操作区域类型(即配置空间、I/O 和内存)。
6.5.5. _BBN(基总线号)
对于多根 PCI 平台,_BBN 对象求值为平台启动固件所分配的 PCI 总线号。这对于访问特定总线的 PCI_Config 操作区域是必需的。_BBN 对象位于 PCI 主机桥之下,并且由于它是 PCI 总线号,因此在一个段内对每个主机桥都必须唯一。
参数:
无
返回值:
一个包含 PCI 总线号的 Integer。_BBN 返回整数的低 8 位是 PCI 基总线号。其他位保留。
6.5.6. _SEG(段)
可选的 _SEG 对象位于 PCI 主机桥之下,并求值为一个整数,用于描述 PCI 段组(参见 PCI Firmware Specification v3.0)。如果 _SEG 不存在,OSPM 假定所有 PCI 总线段都位于 PCI Segment Group 0 中。
参数:
无
返回值:
PCI 段组纯粹是一个由系统固件管理并由 OSPM 使用的软件概念。它是 PCI 总线(或总线段)的逻辑集合。它与任何物理实体都没有关联。它是一种对 PCI 总线段和 PCI Express 层级结构进行逻辑分组的方式。_SEG 比 _BBN 高一个层级。
PCI 段组通过允许复用 PCI 总线编号来支持系统中超过 256 条总线。在每个 PCI 段组内,PCI 总线的总线编号必须唯一。不同 PCI 段组中的 PCI 总线允许具有相同的总线编号。
一个 PCI 段组包含一个或多个 PCI 主机桥。
_SEG 返回整数的低 16 位是 PCI 段组编号。其他位保留。
示例:
Device(ND0) { // this is a node 0
Name(_HID, "ACPI0004")
// Returns the "Current Resources"
Name(_CRS,
ResourceTemplate() {
...
}
)
Device(PCI0) {
Name(_HID, EISAID("PNP0A03"))
Name(_ADR, 0x00000000)
Name(_SEG, 0) // The buses below the host bridge belong to PCI segment 0
...
Name(_BBN, 0)
...
}
Device(PCI1) {
...
Name(_SEG, 0) // The buses below the host bridge belong to PCI segment 0
...
Name(_BBN, 16)
...
}
...
}
Device(ND1) { // this is a node 1
Name(_HID, "ACPI0004")
// Returns the "Current Resources"
Name(_CRS,
ResourceTemplate() {
...
}
)
Device(PCI0) {
Name(_HID, EISAID("PNP0A03"))
Name(_ADR, 0x00000000)
Name(_SEG, 1) // The buses below the host bridge belong to PCI segment 1
...
Name(_BBN, 0)
...
}
Device(PCI1) {
...
Name(_SEG, 1) // The buses below the host bridge belong to PCI segment 1
...
Name(_BBN, 16)
...
}
}
6.5.7. _GLK(全局锁)
这个可选命名对象位于某个设备对象的作用域内。该对象返回一个值,用于向任何访问此设备的实体表明(换句话说,OSPM 或任何设备驱动程序)在访问该设备时是否必须获取全局锁。当非 OS 代码(例如基于 Intel 架构系统中的基于 SMM 的代码)可能对设备资源执行有争议的访问时,基于 OS 的设备访问必须在获取全局锁的情况下执行。
注意
默认行为:如果在给定设备的作用域内不存在 _GLK,则该设备不需要全局锁。
参数:
无
返回值:
一个包含全局锁需求代码的 Integer:
0 - 此设备不需要全局锁 1 - 此设备需要全局锁
设备资源争用的一个示例是:某个基于 SMBus 的设备的设备驱动程序与基于 SMM 的代码争用对 Embedded Controller、SMB-HC 和 SMBus 目标设备的访问。在这种情况下,设备驱动程序在访问设备时必须获取并释放全局锁,以避免与访问上述任一资源的基于 SMM 的代码发生资源争用。
6.5.8. _DEP(操作区域依赖项)
_DEP 求值为一个 package,并指定设备对象;由于将来的操作区域访问,OSPM 应在启动顺序中为这些设备对象分配更高的优先级。
为了提高在需要时 SPB 操作区域处理程序可用的可能性,OSPM 需要预先知道哪些方法会访问它——_DEP 向 OSPM 提供此信息。虽然 _DEP 关键字可用于确定启动顺序,但只有 _REG 方法(_REG (Region))回调可被依赖来判断某个区域在给定时间点是否可访问。
参数:
无。
返回值:
一个包含对象引用的可变长度 Package。
示例:
Device(\_SB.TC3) {
...
OperationRegion(OPRG,
GenericSerialBus,
0x00,
0x100)
...
}
Device(\_SB.TP1) {
...
Name (_DEP, Package() {\_SB.TC3})
...
}
6.5.9. _FIT(固件接口表)
此方法求值为一个 buffer,返回的数据格式为一系列 NFIT 结构(参见 NVDIMM 固件接口表(NFIT))。此方法可以出现在 NVDIMM 根设备之下(参见 NVDIMM 根设备)。当 _FIT 方法存在时,OSPM 始终会对其求值。
_FIT 返回 NFIT 中的所有条目。
针对 NVDIMM 根设备的 NFIT 更新通知值(参见 NVDIMM 根设备通知值)会通知 OSPM 它需要重新求值 _FIT 方法。
注意
NFIT 是在 OS 启动时枚举的 ACPI 表。对于 NVDIMM 热插拔的情况,相应的 NFIT 结构将不会出现在 NFIT 中。_FIT 方法也用于在热插拔期间动态提供这些结构。
参数:
无
返回值:
一个包含 NFIT 结构列表的 Buffer
_FIT 用法的 ASL 示例:
Scope (\_SB) {
Device (NVDR) {
Name(_HID, "ACPI0012")
OperationRegion (OPRN, SystemMemory,
Offset in system memory of NFIT Structures, Length in bytes)
Field (OPRN, ByteAcc, NoLock, Preserve) {
FITD, Length in bits
}
Method (_FIT, 0) {
Return (FITD)
}
...
} // end NVDR
...
} // end scope \\_SB
6.5.10. NVDIMM 标签方法
下表概述了附加到 NVDIMM 对象的 NVDIMM 标签方法。
表 6.67 NVDIMM 标签方法
| 对象 | 描述 |
|---|---|
| _LSI | 标签存储信息 - 返回与 NVDIMM 对象关联的标签存储区域的信息,包括其大小。 |
| _LSR | 标签存储读取 - 从 NVDIMM 对象的标签存储区域返回标签数据。 |
| _LSW | 标签存储写入 - 将标签数据写入 NVDIMM 对象的标签存储区域。 |
6.5.10.1. _LSI(标签存储信息)
这个可选对象返回所请求设备的标签存储区域信息。
参数:
无。
返回值:
一个 Package,包含如下所述的标签存储区域信息
返回值信息:
_LSI 以如下格式返回一个 package:
Package {
Status // Integer (DWORD)
SizeOfLabelStorageArea // Integer (DWORD)
MaxTransferLength // Integer (DWORD)
}
表 6.68 _LSI 返回 package 值
| 字段 | 格式 | 描述 |
|---|---|---|
| Status | Integer (DWORD) | 指示 _LSI 请求的状态。0x00000000 - 成功 - 返回的 package 有效 0x00000001 - 失败 - 返回 package 的其余部分无效 |
| SizeOfLabelStorageArea | Integer (DWORD) | 标签存储区域的大小(以字节为单位) |
| MaxTransferLength | Integer (DWORD) | 单次调用 _LSR 和 _LSW 方法所支持的最大数据字节数。这是平台支持的传输大小与 NVDIMM 支持的传输大小中的较小值。0x00000000 - NVDIMM 不支持标签存储。非零值 - NVDIMM 支持标签存储。 |
6.5.10.2. _LSR(标签存储读取)
这个可选对象从指定偏移量开始返回标签存储区域中的标签数据。
参数:
Arg0 - 偏移量(Integer(DWORD),标签存储区域中开始读取的字节偏移量)Arg1 - 传输长度(Integer(DWORD),从标签存储区域传输的字节数。传输长度为 0 时不读取数据。
返回值:
一个 Package,包含如下所述的来自标签存储区域的标签数据
返回值信息:
_LSR 以如下格式返回一个 package:
Package {
Status // Integer (DWORD)
LabelData // Buffer
}
表 6.69 _LSR 返回 package 值
| 字段 | 格式 | 描述 |
|---|---|---|
| Status | Integer (DWORD) | 指示 _LSR 请求的状态:0x00000000 - 成功 0x00000001 - 失败 0x00000002 - 输入参数无效 - Offset > 通过 _LSI 报告的 SizeOfLabelStorageArea - Offset + TransferLength > 通过 _LSI 报告的 SizeOfLabelStorageArea - TransferLength > 通过 _LSI 报告的 MaxTransferLength 0x00000003 - 标签存储区域已锁定且无法访问 0x00000004 - 硬件故障导致无法读取数据 注意:任何其他非零值都表示失败。 |
| LabelData | Buffer | 包含返回的标签存储数据。如果 Status 为 Success,则输出大小等于 TransferLength;否则,输出缓冲区的内容应为 0。标签存储区域数据的格式在 UEFI 中定义。 |
6.5.10.3. _LSW(标签存储写入)
这个可选对象从指定偏移量开始将标签数据写入标签存储区域。
参数 :
Arg0 - 偏移量(Integer(DWORD),标签存储区域中的字节偏移量,标签数据将写入目标 NVDIMM 的该位置)
Arg1 - 传输长度(Integer(DWORD),传输到标签存储区域的字节数。传输长度为 0 时不写入数据。
Arg2 - 标签数据(Buffer),要写入标签存储区域的标签数据。LabelData 的大小如上面的 TransferLength 字段所示。标签存储区域数据的格式在 UEFI 中定义。
返回值 :
一个 Integer (DWORD),包含 _LSW 的状态,如下所示:
0x00000000 - 成功
0x00000001 - 失败
0x00000002 - 输入参数无效:
Offset > 通过 _LSI 报告的 SizeOfLabelStorageArea
Offset + TransferLength > 通过 _LSI 报告的 SizeOfLabelStorageArea
TransferLength > 通过 _LSI 报告的 MaxTransferLength
0x00000003 - 标签存储区域已锁定且无法访问
0x00000004 - 硬件故障导致无法写入数据
注意:任何其他非零值都表示失败。
6.5.11. _CBR(CXL 主机桥寄存器信息)
该对象是一个可选控制方法,由 OSPM 调用以确定 CXL 主机桥寄存器的内存位置以及表示寄存器布局的版本。_CBR 对象位于某个 CXL 主机桥设备之下,并且对于系统中的每个 CXL 主机桥实例都必须返回唯一值。
对于启动时即存在的 CXL 主机桥,CEDT 应提供主机桥寄存器基地址。Host Bus Device 中需要 _UID 对象,以便 OSPM 将 CEDT 中的条目与 ACPI 命名空间中存在的设备进行匹配。
有关 CEDT 的更多信息,请参见 http://uefi.org/acpi 中标题为 “CXL 早期发现表” 的部分。
参数:
无
返回值:
一个 package,包含如下所述的 CXL 主机桥寄存器信息:
Package {
Version, //Integer (DWORD)
Base, //Integer (DWORDQWORD)
Length //Integer (DWORD)
}
表 6.70 _CBR 返回 package 值
| 字段 | 格式 | 描述 |
|---|---|---|
| Version | Integer (DWORD) | 表示主桥寄存器块布局的版本号:0x00000000:遵循 CXL 1.1 规范 0x00000001:遵循 CXL 2.0 规范 |
| Base | Integer (QWORD) | 主桥寄存器块的 64 位内存地址:如果 Version = 0,这表示 CXL 1.1 下游端口 RCRB 的基地址 如果 Version = 1,这表示 CXL 2.0 主桥组件寄存器 (CHBCR) 的基地址 |
| Length | Integer (DWORD) | 主桥寄存器块的长度(以字节为单位):如果 Version = 0,此字段必须设置为 8 KB (0x2000) 如果 Version = 1,此字段必须设置为 64 KB (0x10000) |
注:可在http://uefi.org/acpi找到指向 CXL 1.1 和 CXL 2.0 规范的链接,位于每个规范对应的标题下。
示例:
Device(CXL0 ) {
Name(_HID, EISAID ("ACPI0016")) // New HID to indicate CXL hierarchy
Name(_CID, EISAID ("PNP0A08")) // To support 遗留 OSs that understands PCIe
// but not the new HID
Name(_UID, 0)
Method (_CBR, 0) {
Return( 0x00, DP_RCRB_BASE, 0x2000)
}
// Standard PCIe methods like _ BBN, _CRS.
// PCIe _CRS describes .IO resources. PCIe _BBN describes bus number of CXL RCiEP
// PCIe _OSC is used to negotiate control of CXL.IO capabilities
...
}