SCI全称是System Control Interrupt(系统控制中断)当硬件产生了一些ACPI事件的时候,它可以使用系统控制中断SCI来通知OS。SCI是一个低电平有效共享的中断信号。ACPI Spec说有2种类型的event会产生SCI,一种叫做Fixed-FeatureEvents,另外一种是General-PurposeEvents。Fixed-Feature Events 产生的SCI通常是由OS inbox driver去处理的。所以我们只需要关注GPE 。
SCI中断的相关信息被记录在FADT table中,OS通过FADT获得SCI使用的中断号码,从而能够在SCI产生时处理该中断。
通常情况下SCI_INT会被设置成IRQ9,但是它也不是固定的,我们也可以按照板子的设计修改SCI_INT。
芯片组的spec会有寄存器用来配置SCI IRQ number。下图是PCH上的一个寄存器描述。
芯片组的spec会有专门的寄存器用来控制GPE。下图是PCH上的一个寄存器描述。
为了客制化一些功能或者实现一些特殊的Feature,通常要配置一些GPIO让它能够在特定的条件下产生SCI,这时我们要把特定的GPIO配置成INPUT, SCI,把GPE0_EN对应的bit设置起来。然后需要在ACPI table中提供_Lxx的形式的method,至于xx则是和GPE_STS这个register相对应的,所以要特别注意的是通常情况下Intel PCH GPIO 都是从GPE_STS的bit16开始的,所以如果是GPIO0那么这个method应该是_L10。当系统中相关的GPIO status有变化就会触发SCI, _LXX(),就会被调用了。
EC的SCI虽然跟通常的GPE稍有差别, 但本质上它仍然是GPE。参考代码如下图所示:
Device (EC0)
{
Name (_HID, EISAID ("PNP0C09"))
Name (_UID, 1)
Name (_GPE, Add(EC_SCI_GPI, 16)) // GPE for Runtime SCI
…
}
它跟普通的GPE的区别是,EC有一个叫做Q_EVENT的东西。所谓Q_EVENT指的是OS收到EC的SCI后,OS通过发84h command 给EC读取EC Ram中的值,这个值被称为Q_EVENT ID。这也是Q_EVENT得名的原因(Q是Query的缩写,而84h就是Query Embedded Controller)。然后OS中的asl code会根据该id去调用_QXX()如下面的code所示,这里的XX指的就是EVENT ID。每当电源插入,电池充电,屏幕开合的时候,通常EC就会产生Q_EVENT。
// AC Power Connected
Method (_Q26, 0, NotSerialized)
{
Store (One, \PWRS)
Notify (AC, 0x80)
Notify (BATX, 0x80)
\PNOT ()
}
参考:
- [1. ACPI Spec](https://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf)
- [2. EC.asl](https://github.com/roboard/coreboot/blob/master/src/ec/quanta/it8518/acpi/ec.asl)