2018年3月29日 星期四

[ACPI] EC AC ASL

最近有機會碰到 ASL code
做個紀錄

1. 範例程式碼
External(\_PR.POWS)

Scope(\_SB.PCI0.LPCB)
{
  Device(EC) {
    Name(_HID, EISAID("PNP0C09"))
    Name(_GPE, 0x00)
    Name(_CRS, ResourceTemplate() {
      IO(Decode16, 0x62, 0x62, 0x00, 0x01)
      IO(Decode16, 0x66, 0x66, 0x00, 0x01)
    })

    OperationRegion(ERAM,EmbeddedControl,0,0xFF)
    Field(ERAM,ByteAcc,Lock,Preserve) {
    // Field definitions
    }

    Method(_QXX) {
      ...
    }

    Device(AC) {
      Name(_HID, "ACPI0003")
      Name(_PCL, Package(1) {\_SB})

      Method(_PSR, 0, NotSerialized)
      {
        ...
      }
    }
  } 
}
2. External (Declare External Objects)
Syntax
  External (ObjectName, ObjectType, ReturnType, ParameterTypes)


用來引用不同 ACPI Table中的 ObjectName時使用
常見於 DSDT和 SSDT之間的互動
舉例
  先在 DSDT中宣告 External(\_PR.POWS)  // 位於CpuSsdt.asl中的變數
  就可直接使用 Store(1, \_PR.POWS) 改變數值

3. Scope (Open Named Scope)
Syntax
  Scope (Location) {ObjectList}

Example:
  Device(AC) 目前的位置是 \_SB.PCI0.LPCB.EC

  如果在外層加上
    Scope(\_SB) {
      Device(AC) {
        ...
      }
    }

  則新的 Device(AC)位置會變為 \_SB
  用來定義括號包含物件的層級位置,不會受到描寫時的位置影響

4. _HID (Hardware ID)

判斷 Device用的 ID,非必要,主要是提供給 OSPM判斷用的
Example ASL:
Name (_HID, EISAID ("PNP0C0C")) // Control-Method Power Button
Name (_HID, EISAID ("INT0800"))    // Firmware Hub
Name (_HID, "ACPI0003")                 // AC adapter device
Name (_HID, "MSFT0003")                // Vendor-defined device
Name (_HID, "80860003")                  // PCI-assigned device identifier

5. _GPE, _QXX

這兩個是一組的,_QXX是 Q event,也是一種 SCI,由 EC透過 GPIO發出
XX 的值可由對 IO 60h下指令 0x84,再到 IO 64h讀取

_GPE 的值是由 GPIO轉換後對應,OS會將此 GPE發送的訊息傳入 Device(EC)
爾後判斷對應的_QXX,執行不同的任務

6. OperationRegion()

OperationRegion (Declare Operation Region)
  Syntax
    OperationRegion (RegionName, RegionSpace, Offset, Length)


用來定義 ASL使用的空間,RegionSpace判斷不同 Type使用

範例 OperationRegion(ERAM,EmbeddedControl,0,0xFF)
指的是在 EC space中,開始位置為 0,範圍 0x100 Bytes,取名 ERAM




7. Field()

Field (Declare Field Objects)
  Syntax
    Field (RegionName, AccessType, LockRule, UpdateRule) {FieldUnitList}


將取過名的空間作細部配置,可以利用 Offset()做非連續的空間配置
另外同一空間中可以不同配置名稱重複定義

Field(ERAM,ByteAcc,Lock,Preserve) {
  AB11, 8,         // offset 0x00
  AB22, 8,         // offset 0x01
  AB33, 8,         // offset 0x02
  Offset(0x21),  //
  AB33, 8          // offset 0x21
}

Field(ERAM,ByteAcc,Lock,Preserve) {
  CD11, 16,       // offset 0x00
  CD22, 8,         // offset 0x02
}


8. AC Adapters and Power Source Objects

當 device的 _HID為"ACPI0003",會被認為是 AC power source
ACPI spec中定義的 Object有以下四種


 如果只有單一 AC輸入只需要 _PCL / _PSR就能正常運作

8-1. _PCL (Power Consumer List)
This object evaluates to a list of pointers, each pointing to a device or a bus powered by the power source device. Pointing to a bus indicates that all devices under the bus are powered by the power source device.

Return Value:
  A variable-length Package containing a list of References to devices or buses


8-2. _PSR (Power Source)
Returns whether the power source device is currently in use. This can be used to determine if system is running off this power supply or adapter. On mobile systes this will report that the system is not running on the AC adapter if any of the batteries in the system is being forced to discharge. In systems that contains multiple power sources, this object reports the power source’s online or offline status.

Return Value:
  An Integer containing the power source status
  0 – Off-line (not on AC power)
  1 – On-line


8-3. Notify()

改變 _PSR的狀態可以透過 Notify(AC, 0x80)實現
一般會放在 AC插拔的 Q event中去觸發

Method(_Q0A) {
  sleep(500)           // 等待hardware反應
  Notify(AC, 0x80)  // 改變 _PSR
}