6.3. 设备插入、移除和状态对象
本节定义的对象提供了用于处理设备动态插入和移除以及确定设备和通知处理状态的机制。
设备插入和移除对象还用于将移动平台对接和脱离到外围扩展坞。这些对象提供有关设备是否存在、哪些设备物理上位于同一设备中(独立于这些设备所在的总线),以及用于控制弹出或联锁机制的方法的信息。
当可移除设备具有软件控制的、类似 VCR 的弹出机制,而不是“突发式”弹出机制时,系统会更加稳定。在这种系统中,设备的弹出按钮不会立即移除设备,而只是向操作系统发出信号。然后 OSPM 关闭设备、关闭打开的文件、卸载驱动程序,并向硬件发送命令以弹出设备。
如果设备在系统处于工作状态时被物理插入(换句话说,热插入),硬件会生成一个通用事件。
用于处理该事件的控制方法使用 Notify(device,0) 命令将新设备所在的总线或新设备的设备对象通知给 OSPM。如果 Notify 命令指向新设备的设备对象,则控制方法必须已经更改了 _STA 返回的设备状态,以表明该设备现在已存在。通过使 Notify 的对象在命名空间层次结构中尽可能接近新设备所在位置,可以优化此过程的性能。Notify 命令也可以从 _WAK 控制方法中使用(参见第 7.4.5 节),以指示系统处于睡眠状态期间可能发生的设备更改。有关 Notify 命令的更多信息,请参见第 5.6.6 节。
OSPM 使用标识和配置对象来识别、配置并为新设备以及在层次结构中该设备之下找到的任何设备加载设备驱动程序。
如果设备具有 _LCK 控制方法,OSPM 之后可以运行此控制方法来锁定该设备。
步骤 2 中提到的新设备不一定是单个设备,也可以是整棵设备树。例如,它可以指向 PCI-PCI 桥接停靠连接器。随后 OSPM 将加载并配置它在该桥下找到的所有设备。如果这些新设备并非都位于同一总线之下,控制方法也可以指向层级中的几个不同设备。(换句话说,有多条总线穿过该连接器)。
对于移除设备,ACPI 同时支持热移除(系统处于 S0 状态)和温移除(系统处于睡眠状态:S1-S4)。这是通过 _EJx 控制方法完成的。可弹出的设备会针对该设备所支持的每个睡眠状态包含一个 _EJx 控制方法(最多可列出 2 个 _EJx 对象)。例如,热移除设备会提供 _EJ0;温移除设备会使用 _EJ1-EJ4 之一。这些控制方法用于在弹出即将发生时向硬件发出信号。
动态移除设备的事件顺序如下:
按下弹出按钮并生成一个通用事件。(如果系统处于睡眠状态,则应唤醒系统)。
该事件的控制方法使用 Notify(device, 3) 命令通知 OSPM 用户请求弹出的是哪个具体设备。并不需要对每个可能被弹出的设备都调用 Notify,而只需对顶层设备调用。层级中的任何子设备,或者该设备上的任何依赖于弹出的设备(如下文 _EJD 所述),都会被自动移除。
操作系统关闭并卸载将被移除的设备。
如果设备具有 _LCK 控制方法,OSPM 运行此控制方法以解锁该设备。
操作系统检查该设备存在哪些 _EJx 控制方法。如果移除事件将导致系统切换到电池供电(换句话说,执行脱离停靠)且电池电量低、已耗尽或不存在,则 OSPM 使用所列出的受支持最低睡眠状态的 _EJx;否则使用状态最高的 _EJx。在作出该决定后,OSPM 运行相应的 _EJx 控制方法,为弹出准备硬件。
温移除要求系统进入睡眠状态。如果该移除将是温移除,则 OSPM 将系统置于适当的 Sx 状态。如果该移除将是热移除,则 OSPM 跳到下面的步骤 8。
对于温移除,系统被置于睡眠状态。然后硬件使用电机等机构来弹出设备。弹出后立即,硬件将系统转换到 S0。如果在收到弹出通知时系统处于睡眠状态,则操作系统会根据用户的唤醒设置将系统恢复到相应的睡眠状态。
OSPM 调用 _STA 来确定弹出是否成功发生。(在这种情况下,控制方法不需要使用 Notify(device,3) 命令来将 _STA 的变化通知 OSPM。)如果存在任何机械故障,_STA 返回 3:设备存在但不工作,OSPM 将把该问题通知用户。
注意
此机制对于移除单个设备和移除多个设备(例如脱离停靠)是相同的。
ACPI 并不禁止设备的突发式移除;但是,不推荐这种类型的移除,因为当发生突发式移除时,无法保证系统和数据完整性。由于 操作系统 未被告知,其设备驱动程序无法保存数据缓冲区,也无法在设备被移除之前停止对设备的访问。为了处理突发式移除,必须引发一个通用事件。其关联的控制方法必须使用 Notify 命令来指示设备是从哪条总线上被移除的。
设备插入和移除对象列于下表中。
表 6.20 设备插入、移除和状态对象
| 对象 | 描述 |
|---|---|
| _EDL | 求值结果为命名空间引用包的对象,该包包含依赖于包含 _EDL 的设备的设备对象。 |
| _EJD | 求值结果为设备对象名称的对象,该设备是某个设备所依赖的对象。每当被命名的设备被弹出时,依赖设备都必须接收到弹出通知。 |
| _EJx | 用于弹出设备的控制方法。 |
| _LCK | 锁定或解锁设备的控制方法。 |
| _OST | 由 OSPM 调用以向平台传达处理状态的控制方法。 |
| _RMV | 指示给定设备可移除的对象。 |
| _STA | 返回设备状态的控制方法。 |
6.3.1. _EDL(弹出设备列表)
该对象求值为一个命名空间引用包,其中包含声明 _EDL 对象的设备之下、依赖于该设备的设备对象名称。这主要用于支持扩展坞。在声明 _EDL 对象的设备可被弹出之前,OSPM 会为 _EDL 对象中列出的设备做好物理移除准备。
参数:
无
返回值:
一个变长的 Package,包含命名空间引用列表
在 OSPM 通过设备的 _EJx 方法弹出某个设备之前,_EDL 返回的包中列出的所有依赖设备都会被准备为可移除。请注意,不会执行依赖设备下的 _EJx 方法。
在描述包含扩展坞的平台时,会在扩展坞设备下声明 _EDL 对象。例如,如果某移动系统可以连接到两种不同类型的扩展坞,则会在两个扩展坞设备下都声明 _EDL,并且其求值结果为这样一个打包列表:当系统从扩展坞中弹出时,必须一并弹出的设备列表。
符合 ACPI 的操作系统会在弹出该设备之前立即对 _EDL 方法求值。
6.3.2. _EJD(弹出依赖设备)
该对象用于指定一个设备的名称,声明此对象的设备依赖于该设备。该对象主要用于支持扩展坞。在 _EJD 所指示的设备被弹出之前,OSPM 将为依赖设备(换句话说,声明此对象的设备)做好移除准备。
参数:
无
返回值:
一个包含设备名称的 String
_EJD 在 ACPI 表加载时求值一次。_EJD 所指示设备的 EJx 方法将用于弹出所有依赖设备。当设备本身被弹出时,其依赖设备也将被弹出。
注意
当 _EJD 所指示的设备被弹出时,OSPM 不会执行依赖设备的 _EJx 方法。
在描述包含扩展坞的平台时,通常需要不止一个 _EJD 对象。例如,如果一个扩展坞将一个 PCI 设备和一个 ACPI 配置设备同时连接到移动系统,那么 PCI 设备描述包和 ACPI 配置设备描述包都必须包含一个 _EJD 对象,其求值结果为扩展坞的名称(即扩展坞描述包中的 _ADR 或 _HID 对象中指定的名称)。因此,当停靠连接器发出弹出请求信号时,OSPM 首先尝试禁用并卸载 PCI 和 ACPI 配置设备这两者的驱动程序。
注意
ACPI 1.0 操作系统仅在表加载过程中对 _EJD 方法求值一次。这极大限制了表设计者描述动态依赖关系的自由度,例如在具有多个扩展坞的场景中创建的那些依赖关系。下方示例说明了这一限制;通过 ACPI 1.0 兼容命名空间提供的 _EJD 信息省略了 DOCK2 的弹出依赖列表中的 IDE2 设备。从 ACPI 2.0 开始,OSPM 通过使用 _EDL 方法,可以获得系统中弹出依赖关系的更深入视图。
示例
_EJD 和 _EDL 的一个使用示例如下:
Scope(\_SB.PCI0) {
Device(DOCK1) { // Pass through dock - DOCK1
Name(_ADR, ...)
Method(_EJ0, 0) {...}
Method(_DCK, 1) {...}
Name(_BDN, ...)
Method(_STA, 0) {0xF}
Name(_EDL, Package( ) { // DOCK1 has two dependent devices - IDE2 and CB2
\\_SB.PCI0.IDE2,
\\_SB.PCI0.CB2})
}
Device(DOCK2) { // Pass through dock - DOCK2
Name(_ADR, ...)
Method(_EJ0, 0) {...}
Method(_DCK, 1) {...}
Name(_BDN, ...)
Method(_STA, 0) {0x0}
Name(_EDL, Package( ) { // DOCK2 has one dependent device - IDE2
\\_SB.PCI0.IDE2})
}
Device(IDE1) { // IDE Drive1 not dependent on the dock
Name(_ADR, ...)
}
Device(IDE2) { // IDE Drive2
Name(_ADR, ...)
Name(_EJD,"\\_SB.PCI0.DOCK1") // Dependent on DOCK1
}
Device(CB2) { // CardBus Controller
Name(_ADR, ...)
Name(_EJD,"\\_SB.PCI0.DOCK1") // Dependent on DOCK1
}
} // end \\_SB.PCIO
6.3.3. _EJx(弹出)
这些控制方法是可选的,提供给支持软件控制的类似 VCR 式弹出机制的设备,或者在设备可从系统中移除之前需要执行某种操作(例如隔离电源/数据线)的设备。为了支持温移除(系统处于睡眠状态)和热移除(系统处于 S0),会针对设备支持移除的每个睡眠状态列出一个 _EJx 控制方法,其中 x 是所支持的睡眠状态。例如,_EJ0 表示设备支持热移除;_EJ1-EJ4 表示设备支持温移除。
参数: (1)
Arg0 - 一个包含设备弹出控制的 Integer
0 - 取消弹出请求标记(绝不会以此值调用 EJ0)
1 - 热弹出或标记为待弹出
返回值:
无
对于热移除,当 OSPM 调用 _EJ0 控制方法时,设备必须立即被弹出。_EJ0 控制方法在弹出完成之前不得返回。调用 _EJ0 后,OSPM 通过验证设备是否不再存在来确定弹出是否成功。对于 _HID 设备,OSPM 对 _STA 方法求值。对于 _ADR 设备,OSPM 通过该设备的总线驱动程序进行检查。
对于温移除,_EJ1-_EJ4 控制方法不会导致设备立即弹出。相反,它们会设置专有寄存器,以便在系统进入给定睡眠状态时让硬件做好弹出准备。只有在 OSPM 通过写入 SLP_EN 寄存器使系统进入睡眠状态之后,硬件才会弹出设备。系统恢复后,OSPM 调用 _STA 来确定弹出是否成功。
一个设备对象可以具有多个 _EJx 控制方法。首先,它会列出用于以首选睡眠状态弹出设备的 EJx 控制方法。可选地,当弹出后系统没有电源(例如,没有电池)时,设备可以列出一个 EJ4 控制方法供使用。例如,一台支持热停靠的笔记本电脑可能会列出 _EJ0 和 _EJ4。
6.3.4. _LCK(锁定)
该控制方法是可选的,仅对于支持软件控制锁定机制的设备才是必需的。当操作系统调用此控制方法时,相关设备将根据传入参数的值被锁定或解锁。对于锁定请求,控制方法在设备完全锁定之前不得完成。
参数:
Arg0 - 一个包含设备锁定控制的 Integer
0 - 解锁设备
1 - 锁定设备
返回值:
无
在描述平台时,设备对某个设备使用 _LCK 控制方法或 _EJx 控制方法二者之一。
6.3.5. _OST(OSPM 状态指示)
此对象是一个可选控制方法,由 OSPM 调用以向平台指示处理状态。在设备弹出、设备热添加、错误断开恢复或其他事件处理期间,OSPM 可能需要与平台执行特定的握手。OSPM 也可能需要向平台表明其无法完成所请求的操作;例如,当用户按下某个当前正在使用或由于其他原因当前无法被弹出的设备的弹出按钮时。在这种情况下,OSPM 对 ACPI 弹出请求 通知的处理失败。OSPM 可以通过调用 _OST 控制方法向平台指示该失败。作为指示弹出失败的状态通知的结果,平台可以采取某些操作,包括重新发出该通知,或者点亮适当的指示灯以向用户示意失败。
参数: (3)
Arg0 - 包含源事件的 整数
Arg1 - 包含状态码的 整数
Arg2 - 包含状态信息的 缓冲区
返回值:
无
参数信息:
Arg0 - 源事件:DWordConst
如果 source_event 的值 <= 0xFF,则此参数是其处理产生了该状态指示的 ACPI 通知值。这就是传递给 Notify 运算符的值。
如果 source_event 的值为 0x100 或更大,则 OSPM 状态指示是 OSPM 操作的结果,如 OST 源事件代码中所示。例如,在由用户界面触发的设备弹出失败时,此参数将以 0x103 的值传递给 _OST。
如果 OSPM 无法识别发起通知的值,则 OSPM 调用 _OST 时,此参数使用一个所有位都置位(全为 1)的值。
Arg1 – 状态码:DWordConst。OSPM 指示特定于通知值的状态。状态码说明参见表 6.22、表 6.23 和表 6.25。
Arg2 - 一个缓冲区,包含关于该状态指示的详细 OSPM 特定信息。此参数可以为 null。
表 6.21 OST 源事件代码
| 源事件代码 | 说明 |
|---|---|
| 0-0xFF | 保留给通知值 |
| 0x100 | 操作系统关机处理 |
| 0x101-0x102 | 保留 |
| 0x103 | 弹出处理 |
| 0x104-0x1FF | 保留 |
| 0x200 | 插入处理 |
| 0x201-0xFFFFFFFF | 保留 |
表 6.22 一般处理状态码
| 状态码 | 说明 |
|---|---|
| 0 | 成功 |
| 1 | 非特定失败 |
| 2 | 无法识别的 Notify 代码 |
| 3-0x7F | 保留 |
| 0x80-0xFFFFFFFF | 特定于通知值的状态码 |
表 6.23 操作系统关机处理(源事件:0x100)状态码
| 状态码 | 说明 |
|---|---|
| 0x80 | OS 关机请求被拒绝 |
| 0x81 | OS 正在关机 |
| 0x82 | OS 关机完成 |
| 0x83 | 不支持 OS 优雅关机 |
| 0x84-0xFFFFFFFF | 保留 |
6.3.5.1. 优雅关机请求的处理序列:
在收到优雅关机请求(见 表 5.155,值 0x81)之后,OS 将负责以下列状态码之一进行响应:
0x80(OS 关机请求被拒绝) - 如果 OS 无法执行优雅关机,则将发送此值。
0x81(OS 正在关机) - OS 已启动优雅关机过程。
0x83(不支持 OS 优雅关机) - OS 不支持优雅关机请求。
如果 OS 确实启动了优雅关机,则它应继续每 10 秒生成一次“OS 正在关机”消息(_OST 源事件 0x100 状态码 0x81)。这起到心跳作用,以便请求优雅关机的服务知道该请求当前正在处理中。如果平台在 60 秒内未收到“OS 正在关机”消息,则应假定 OS 关机没有继续进行。
当优雅关机过程完成时,OSPM 将发送“OS 关机完成”消息,然后将平台转换到 G2“软关机”电源状态。
表 6.24 弹出请求 / 弹出处理(源事件:0x03 和 0x103)状态码
| 状态码 | 说明 |
|---|---|
| 0x80 | OSPM 不支持设备弹出 |
| 0x81 | 设备正被应用程序使用 |
| 0x82 | 设备忙 |
| 0x83 | 弹出依赖项正忙,或 OSPM 不支持其弹出 |
| 0x84 | 弹出正在进行中(挂起) |
| 0x85-0xFFFFFFFF | 保留 |
表 6.25 插入处理(源事件:0x200)状态码
| 状态码 | 说明 |
|---|---|
| 0x80 | 设备插入正在进行中(挂起) |
| 0x81 | 设备驱动程序加载失败 |
| 0x82 | OSPM 不支持设备插入 |
| 0x83-0x8F | 保留 |
| 0x90-0x9F | 插入失败 - 资源不可用,具体如下位编码所述:位 [3] 总线或段号 位 [2] 中断 位 [1] I/O 位 [0] 内存 |
| 0xA0-0xFFFFFFFF | 保留 |
平台可能会向 OSPM 发出多个通知,而 OSPM 也可能异步处理这些通知。因此,OSPM 对通知调用 _OST 时,可能独立于平台或软件传递给 OSPM 的通知顺序。
下图提供了一个在使用 _OST 对象的平台上进行设备弹出的事件流示例。

图 6.6 使用 _OST 的设备弹出流程示例
注
为了保持与 ACPI 规范先前版本的 OSPM 实现的兼容性,平台不得依赖 OSPM 对 _OST 对象的求值来保证平台的正常运行。
_OST 用法的 ASL 示例:
External (\_SB.PCI4, DeviceObj)
Scope(\_SB.PCI4) {
OperationRegion(LED1, SystemIO, 0x10C0, 0x20)
Field(LED1, AnyAcc, NoLock, Preserve)
{ // LED controls
S0LE, 1, // Slot 0 Ejection Progress LED
S0LF, 1, // Slot 0 Ejection Failure LED
S1LE, 1, // Slot 1 Ejection Progress LED
S1LF, 1, // Slot 1 Ejection Failure LED
S2LE, 1, // Slot 2 Ejection Progress LED
S2LF, 1, // Slot 2 Ejection Failure LED
S3LE, 1, // Slot 3 Ejection Progress LED
S3LF, 1 // Slot 3 Ejection Failure LED
}
Device(SLT3) { // hot plug device
Name(_ADR, 0x000C0003)
Method(_OST, 3, Serialized) { // OS calls \_OST with notify code 3 or 0x103
// and status codes 0x80-0x83
// to indicate a hot remove request failure.
// to indicate a hot remove request failure.
// Status code 0x84 indicates an ejection
// request pending.
If(LEqual(Arg0,Ones)) // Unspecified event
{
// Perform generic event processing here
}
Switch(And(Arg0,0xFF)) // Mask to retain low byte
{
Case(0x03) // Ejection request
{
Switch(Arg1)
{
Case(Package(){0x80, 0x81, 0x82, 0x83})
{ // Ejection Failure for some reason
Store(Zero, ^^S3LE) // Turn off Ejection Progress LED
Store(One, ^^S3LF) // Turn on Ejection Failure LED
}
Case(0x84) // Eject request pending
{
Store(One, ^^S3LE) // Turn on Ejection Request LED
Store(Zero, ^^S3LF) // Turn off Ejection Failure LED
}
}
}
}
} // end \_OST
Method(_EJ0, 1) // Successful ejection sequence
{
Store(Zero, ^^S3LE) // Turn off Ejection Progress LED
}
} // end SLT3
} // end scope \\_SB.PCI4
Scope (\_GPE)
{
Method(_E13)
{
Store(One, \\_SB.PCI4.S3LE) // Turn on ejection request LED
Notify(\_SB.PCI4.SLT3, 3) // Ejection request driven from GPE13
}
}
6.3.5.2. 错误断开恢复的处理序列
如果 OS 在收到错误断开恢复请求之后尝试恢复操作(见 IPMI 状态码 ,值 0x0F),则 OS 将负责调用 _OST,并在 Arg1 的低字中使用以下状态码之一:
0x80(成功) - 如果 OS 成功恢复了所有受错误断开恢复影响的子设备,重新配置它们并使其恢复到功能状态,则将发送此值。在对 _OST 求值时,所有子设备都可访问。
0x81(未恢复) - OS 未能成功恢复一个或多个受错误断开恢复影响的子设备。对受错误断开恢复影响的子设备的访问可能不可靠。
Arg1 的高字可用于传递特定于总线的状态信息。
6.3.6. _RMV(移除)
可选的 _RMV 对象向 OSPM 指示设备是否可以在系统处于工作状态时被移除,并且无需执行任何 ACPI 系统固件操作即可将该设备安全地从系统中移除(换句话说,仅支持突发式移除的任何设备)。任何此类可移除设备如果没有 _LCK 或 _EJx 控制方法,则必须具有 _RMV 对象。这使 OSPM 能够向用户指示该设备可以被移除,并提供一种在移除设备之前关闭该设备的方法。OSPM 会先将设备转换到 D3,然后再告知用户可以安全移除该设备。
在设备检查通知之后,将重新求值此方法。
参数:
无
返回值:
一个 Integer,包含设备移除状态:
0 - 设备不可移除 1 - 设备可移除
注
实现 ACPI 1.0 的操作系统将此对象的存在解释为该设备是可移除的。
6.3.7. _STA(设备状态)
此对象返回设备的当前状态,可以是以下之一:已启用、已禁用或已移除。
OSPM 在对设备 _INI 方法求值之前,会先对 _STA 对象求值。Present 位和 Functioning 位的返回值决定是否应对 _INI 求值,以及是否应枚举并初始化该设备的子级。参见 _INI(初始化)。
如果某个设备对象描述的是一个不在可枚举总线上的设备,并且该设备对象没有 _STA 对象,则 OSPM 假定该设备存在、已启用、在 UI 中显示并且功能正常。
此方法不得引用任何尚未由 _REG 方法声明为可用的操作区域。
参数:
无
返回值:
一个包含设备状态位图的 Integer:
位 [0] - 如果设备存在,则置位。
位 [1] - 如果设备已启用并对其资源进行解码,则置位。
位 [2] - 如果设备应在 UI 中显示,则置位。
位 [3] - 如果设备工作正常,则置位(如果设备未通过其诊断,则清零)。
位 [4] - 如果电池存在,则置位。
位 [31:5] - 保留(必须清零)。
返回值信息
如果位 [0] 被清零,则位 1 也必须被清零(换句话说,不存在的设备不能被启用)。
只有当位 0 和位 1 都置位时,设备才能对其硬件资源进行解码。如果设备不存在(位 [0] 清零)或未启用(位 [1] 清零),则设备不得对其资源进行解码。
如果某个设备存在于机器中,但不应显示在 OSPM 用户界面中,则位 2 清零。例如,笔记本电脑可能具有游戏杆硬件(因此它存在并对其资源进行解码),但用于插入游戏杆的连接器需要端口复制器。如果端口复制器未插入,则游戏杆不应出现在 UI 中,因此位 [2] 清零。
_STA 可以返回位 0 清零(不存在)且位 [3] 置位(设备功能正常)。这种情况用于指示一个有效设备,但不应为其加载设备驱动程序(例如,桥设备)。此设备的子设备可能存在且有效。对于 _STA 返回此位组合的设备,OSPM 应继续向下枚举。
_STA 的位 [4] 仅适用于控制方法电池设备(PNP0C0A)。对于所有其他设备,OSPM 必须忽略此位。
如果某个设备对象(包括处理器对象)没有 _STA 对象,则 OSPM 假定上述所有位均已置位(即,设备存在、已启用、在 UI 中显示且功能正常)。