ACPI协议中EC RAM的读写

简述

EC中提供了一个256字节大小的可读写区域,一般称为EC RAM,用于与BIOS间进行数据的交互,如常见的电池电量信息,便是EC写在EC RAM中的,BIOS会去读取此处的信息,记录在ACPI Table中,OS解析这部分ACPI Table的内容后再展现出来。该怎么去读写这个区域呢?ACPI中第12章有详细的定义,下面来看一看。

ACPI中的定义

ACPI中提供了两个命令用于EC RAM的读写,如下:

读操作: 

 1.往EC的Command Port写入0x80命令 

 2.往EC的Data Port写入需要读取的数据的Offset 

 3.读取EC的Data Port,读到的数据便是结果

  

 写操作: 

 1.往EC的Command Port写入0x81命令

 2.往EC的Data Port写入所写数据的Offset 

 3.往EC的Data Port写入所写数据的值

参考代码

VOID
OemECWrite(
  IN UINT8  Index,
  IN UINT8  Value
  )
{
  //
  // Write Command
  //
  OemSendCmdToEcOrKbc (EC_C_PORT, EC_C_WRITE_MEM, FALSE);

  //
  // send ECRAM offset to DATA port
  //
  OemSendDataToEcOrKbc (EC_C_PORT, Index);

  //
  // Write DATA to EC ram
  //
  OemSendDataToEcOrKbc (EC_C_PORT, Value);
}

UINT8
OemECRead(
  IN UINT8 Index
  )
{
  OemSendCmdToEcOrKbc (EC_C_PORT, EC_C_READ_MEM, FALSE);

  //
  // send ECRAM offset to DATA port
  //
  OemSendDataToEcOrKbc (EC_C_PORT, Index);

  //
  // get DATA from EC
  //
  return OemGetDataFromEcOrKbc (EC_C_PORT, FALSE);
}

VOID
OemSendCmdToEcOrKbc (
  IN  UINT8    Port,
  IN  UINT8    Cmd,
  IN  BOOLEAN  KBMouseCtrl
  )
{

  WaitKbcIbe (Port);        // Wait Input Buffer Empty
  IoWrite8 (Port, Cmd);
  WaitKbcIbe (Port);    // Wait Input Buffer Empty

}

VOID
OemSendDataToEcOrKbc (
  IN  UINT8  Port,
  IN  UINT8  Data
  )
{
  WaitKbcIbe (Port);        // Wait Input Buffer Empty
  IoWrite8 (Port - 4, Data);
  WaitKbcIbe (Port);        // Wait Input Buffer Empty
}


UINT8
OemGetDataFromEcOrKbc (
  IN  UINT8   Port,
  IN  BOOLEAN  KBMouseCtrl
  )
{
  UINT8         Data;

  WaitKbcIbe (Port);        // Wait Input Buffer Empty
  WaitKbcObf (Port);        // Wait Output Buffer Full
  Data = IoRead8 (Port - 4);

  return Data;
}

EFI_STATUS
WaitKbcIbe (
  IN UINT16  CommandState
  )
/*++
Routine Description:

  Wait for input buffer empty
  
Arguments:

  CommandState - the Io to read.
  
Returns:

  EFI_SUCCESS - input buffer full.
--*/
{
  UINT8  KbdCmdState = 0;
  UINTN  Index;

  for (Index = 0; Index < EC_TIME_OUT; Index++) 
  {
    KbdCmdState = (UINT8)IoRead8 (CommandState);
    
    if (!(KbdCmdState & EC_S_IBF)) 
    {
      return EFI_SUCCESS;
    } 
    else
    {
      MicroSecondDelay(15);
    }
  }
  return EFI_DEVICE_ERROR;
}

EFI_STATUS
WaitKbcObf (
  IN UINT16  CommandState
)
/*++

Routine Description:

  Wait for output buffer full

Arguments:

  CommandState - the Io to read.

Returns:

  EFI_SUCCESS - input buffer full.

--*/
{
  UINT8  KbdCmdState = 0;
  UINTN  Index;

  for (Index = 0; Index < EC_TIME_OUT; Index++) 
  {
    KbdCmdState = (UINT8)IoRead8 (CommandState);
    
    if (KbdCmdState & EC_S_OBF) 
    {
      return EFI_SUCCESS;
    } 
    else
    {
      MicroSecondDelay(15);
    }
  }
  return EFI_DEVICE_ERROR;
}

版权声明:
作者:bin
链接:https://ay123.net/mystudy/bios/736/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>