追踨法蘭克

2012年5月7日 星期一

Embedded Controller & KBC


EC和KBC是位於LPC下的一個控制器,KBC用來控制鍵盤的運作而EC通常包含了KBC的功能,且還有許多和硬體溝通功能,如Keyboard, PS2 device, Hot Key control, LED control, LCD brightness, power management, 音量控制, 電池偵測, Thermal Control等。我們要透過EC與硬體的溝
通方式在ACPI spec裡有定義,它會透過OS Driver來達到控制、監控硬體的功能,於是我們必需撰寫ASL code來支援這些功能,也就是BIOS的工作。它也提拱了三組的Host Interface,來讓我們下Command來控制它。

Host Interface 1 (no Logical KBC Interface): Standard keyboard functions. (Data port: 0x60, Command/Status port: 0x64)
Status Port 0x64:

Host Interface 2 (Logical KBC Interface 0): Operating System access of ACPI command. (Data port: 0x62, Command/Status port: 0x66)
Status Port:0x66:



Command:
0x80 – Read EC space with SCI
0x81 – Write EC space with SCI
0x82 – Burst enable no SCI needed
0x83 – Burst disable no SCI needed
0x84 – Query SCI event

當發Q Event 時,也就是EC控制的部分硬體發出事件(比如說Hot Key事件: Fn+F3調整LCD亮度),此時OS會到EC讀取一組Q Event number(0x0~0xFF), 然後再透過ACPI Driver去執行ASL _QXX下的Method,此ASL code就是我們BIOS所需要implement的部分,我們必須把硬體事件該做的事定義出來。

pesudo code:

Device(EC0) {
// PnP ID  Name(_HID, EISAID(“PNP0C09”))
// Returns the “Current Resources” of EC  Name(_CRS,
    ResourceTemplate(){
    IO(Decode16, 0x62, 0x62, 0, 1)
    IO(Decode16, 0x66, 0x66, 0, 1)
  })
// Indicate that the EC SCI is bit 0 of the GP_STS register
  Name(_GPE, 0) // embedded controller is wired to bit 0 of GPE
  OperationRegion(\EC0, EmbeddedControl, 0, 0xFF)
  Field(EC0, ByteAcc, Lock, Preserve) {
// Field definitions
  ...   }
// Query methods
  Method(_Q00){..}
  Method(_QFF){..}
}


Host Interface 3 (Logical KBC Interface 1): SMI access of special command (Data port: 0x68, Command/Status port: 0x6C)





範例1: 做 KBC Reset. (KBC Rest command 為Host Interface 1 的0xFE)

∴我們必需先判斷0x64 Status Port 的IBF Bit 1和OBF Bit 0是否為0.
    當為0 時再對0x64 port下0xFE command.

pesudo code:

#define KBC_STD_CMD_RESET 0xFE                         ;Reset command 0xFE
#define KbcTimeOutPeriod xxxxxxx
KBC_DEV mKbcDev;

 void main ( ) {
        ...
        mKbcDev.CmdPort = 0x64;
        mKbcDev.DataPort = 0x60;

       TimeOut = EfiReadTsc() + KbcTimeOutPeriod;        

        do {
          KbcReadStatus (&ControlStatus);
          ControlStatus &= 0x02;
          if ((EfiReadTsc() >= TimOut) {                                  ;KBC timeout
            return ERROR;
          }
        } while (ControlStatus != 0x0);
        KbcSetCmd (KBC_STD_CMD_RESET);
        ...
}

EFI_STATUS
KbcSetCmd (
  IN  UINT8    Cmd
  )
{
       mKbcDev.Write(Cmd);
       ....
 }

EFI_STATUS
 KbcReadStatus (
  Out  UINT8  *Status 
)
{
       mKbcDev.Read(Status);
       ....
}


範例2: 在OS下透過Hot Key: Fn+F3,Fn+F4來EC 控制LCD亮度控制,請撰寫相關ASL code. (Hot Key Event: 0x50:增加亮度, 0x4C:減少亮度)

(等補完ACPI介紹再提供範例2解答,先放流程圖)

這篇文章提到一些ASL code、硬體事件的發生和ACPI Driver等關鍵字,這是ACPI spec所定義的,將在其它篇文章介紹ACPI在做什麼。

2 則留言: