ASL code基本操作

一、ASL基本准则

1.变量命名不超过四个字符,且不能以数字开头。

2、变量或者函数命名,不分大小写。

3.Scope形成作用域,概念类似于C++中的namespace,Java中的package。

4.Device定义也会形成自己的作用域,类似于C++中的Class的概念。

5.Method或者Function定义函数,函数可以定义在Device下或者Scope下,但是不能脱离Scope定义单独的函数,也就是说,函数必须依附于对象(Scope or Device).

6.以“_”字符开头的函数,都是系统保留的,不得给自己的函数起这样的名字。

7.ASL中没有运算符号(逻辑运算与数学运算都是如此),但是有与此等价的相应系统函数代替。

8.符号“\”引用根作用域,“^”引用父级或者上级作用域。

9.作用域,或者称路径,有相对与绝对之分。相对作用域从当前作用域开始,向上延伸。也就是说在当前作用域中使用函数和变量时,解析器会首先从当前作用域中寻找他的定义,如果找不到,则会从父级或从上级作用域中继续寻找,一直找到当前作用域的root为止。绝对路径,则从定义此变量或者函数的root作用域开始,一级级的写下去,一直写到此变量的作用域,作用域的引用使用符号“.”,例如:\SB.PCI0.ABCD。

10.函数最多可以传递8个参数,在函数里用Arg0~Arh7引用,不可以自己定义名字。

11.在函数里最多可以使用8个局部变量,用Local0~Local7表示,不用定义,但是在把局部变量的值赋值给其他变量之前,局部变量必须是有效的值,也就是说,至少有一次给局部变量赋值的操作。

12.声明变量时不需要显示声明其类型。

 

二、数据类型、赋值、基本运算 

1.数据类型ASL中支持的数据类型有:

     a)整型——Integer

     b)字符串——String

     c)事件——Event

     d)数组——Buffer

     e)对象集合——Package

2. 定义变量

     Name(MYTS,0)               //定义一个整数

     Name(TSTR,"Hello ASL")     //定义一个字符串

3.赋值

     最常用的赋值函数只有一个,即Store(),如:

     Store(0x1234,Local0)

     Store("Hello ASL",Local0)

4.算数运算

     算术运算的操作符如下图:

举例如下:

     

5.逻辑运算

     ASL中逻辑运算的函数如下图所示,运算的方法和数学中的逻辑运算相同,不过要使用逻辑运算函数代替符号

三、函数、流程控制

1.定义函数

     Method(TMED)

     {}

2.定义有两个输入参数的函数

     Method(TMED,2)

     {

          //Arg0

          //Arg1

     }

3.在函数中使用局部变量

     Method(TMED,2)

     {

          Store(Arg0,Local0)

          Store(Arg1,Local1)

          Add(Local0,Local1,Local0)

     }

4.在函数中使用返回值     

      Method(TMED,2)

     {

          Store(Arg0,Local0)

          Store(Arg1,Local1)

          Add(Local0,Local1,Local0)

          return(Local0)

     }

5.调用函数

     TMED(3,5)

6.保存函数的返回值

     Store(TMED(4,5),TMPD)

与常见的高级语言一样,ASL中也有与之对应的流程控制语句

分支控制If、ElseIf、Else 借用ACPI中的sample,展示如下

}

 

四、OperationRegion的使用,IO、Memory、PCI、EC读写

     OperationRegion是ACPI定义的一种操作Register方式,可以操作的Register包括IO Memory PCI等等,ACPI4.0支持的OperationRegion共有以下几种。此外,用户还可以自己写一个ACPI驱动,注册自己的OperationRegion。

就当前来说,并不是上面所有的OperationRegion都受到支持且可以使用,一些OperationRegion,受限于编译器,OS下AML的Interpreter支持等等因素,是不能确定能够在当前ASL中使用的,类似的OperationRegion有CMOS、PCIBARTarget、IPMI、SMBUS。另外,对于其他的一些OperationRegion,ACPI Spec有一些特殊的规定。

1.OS必须保证SystemIO OperationRegion 在任何情况下都可以使用

2.OS必须保证PCI Root Bus下的PCI_Config OperationRegion一定可用

3.OS必须保证,SystemMemory OperationRegion在访问通过Memory Map Report的Memory时,一定可用。事实上,这一条就是说明,只要是在有效地址空间中的Memory访问,OS必须保证Memory OperationRegion可用

 

此外其他OperationRegion,必须通过_Reg Method去判断,如果OperationRegion已经connect,则此时OperationRegion可用,如果没有connect,或者已经Disconnect,则不可通过此OperationRegion去访问设备的地址空间。

 

IO OperationRegion

接下来,将展示一个IO OperationRegion的使用,我们使用定义的OperationRegion,将debug code输出到80 Port

OperationRegion(DBGP,SystemIO,0x80,4)

Field (DBGP,ByteAcc,Lock,Preserve)

{

     P80L, 8

 

Store(0xA3,P80L)               //输出A3到80 Port

 

Memory OperationRegion

接下来,我们通过Memory OperationRegion展示一个相当好用的函数,我们知道,对于PCIe设备来说,有两种访问方式,一种是通过传统的PCI兼容方式,另一种是通过MMIO,不但可以访问PCI的256 Byte 的PCI Space,而且可以访问全部的4K PCI Space,那么接下来,我们将展示一组函数,他们能够让你在ASL里面自由的访问PCI Express的Configuration Space.

 

#define   PCIE_BASE   0xE0000000

Method(RDPB,1)

{

     Add(Arg0,PCIE_BASE,Local0)               //Add PCI Express MMIO base address

     OperationRegion(PECF,SystemMemory,Local0,0x1)

     Field (PECF,ByteAcc,Nolock,Preserve)

     {

          MCFG, 8

     }

     Return (MCFG)

}

 

上面展示的函数是直接通过MMIO访问PCIe 设备的configuration space,但是上面的函数只适合比较熟练的开发者使用,因为需要自己计算PCIe设备的地址,那么,我们把上面的函数稍微转换一下,变成下面的函数,这样就够直观了。

// Arg0 - bus NO

// Arg1 - dev NO

// Arg2 - func NO

// Arg3 - register offset

Merhod (RDPB , 4)

{

     ShiftLeft(Arg0,20,Local0)

     Or(ShiftLeft(Arg1,15),Local0,Local0)

     Or(ShiftLeft(Arg2,12),Local0,Local0)

     Or(Arg3,Local0,Local0)

     Add(Arg0,PCIE_BASE,Local0)

     OperationRegion(PECF,SystemMemory,Local0,0x1)

     Field(PECF,ByteAcc,Nolock,Preserve)

     {

          MCFG,8

     }

     Return (MCFG)

}

有了上面的函数,我们可以在ASL读某个PCIe设备的一个byte,例如,我们读PCI设备,bus 0,dev 31, func 3,register 0x40,可以使用如下 语句

Store(RDPB(0,31,3,0x40),Local0)

上面是读PCIe Register的函数,接下来,我们将上面的函数稍加修改,写一个写byte 到PCIe register的函数。

// Arg0 - bus NO

// Arg0 - dev NO

// Arg0 - func NO

// Arg0 - register offset

Merhod (WRPB , 4)

{

     ShiftLeft(Arg0,20,Local0)

     Or(ShiftLeft(Arg1,15),Local0,Local0)

     Or(ShiftLeft(Arg2,12),Local0,Local0)

     Or(Arg3,Local0,Local0)

     Add(Arg0,PCIE_BASE,Local0)

     OperationRegion(PECF,SystemMemory,Local0,0x1)

     Field(PECF,ByteAcc,Nolock,Preserve)

     {

          MCFG,8

     }

     Store (Arg4,MCFG)

}

然后可以通过以下语句,将一个Byte写入到 bus 0, dev 31, func 3 ,register 0x40

WRPD(0, 31, 3, 0x40, 5)

 

PCI_CONFIG Operation

可以通过定义PCI OperationRegion来访问PCI和PCIe设备的配置空间。不过,可以从PCI OperationRegion的定义看到,OperationRegion 本身只定义Register在Configuration space的位置和长度,但不能确定PCI设备bus number ,device number 和 function number,所以也就不能确定设备的地址。ACPI引入了其他一些Method来确定ACPI中PCI设备的地址。_SEG函数定义PCI设备的Segment,在x86架构中来说,一般不使用_SEG,所有的PCI设备默认都在Segment 0。_BBN函数定义PCI Root Bridge的bus number,一般来说在PCI Root Bridge下定义_BBN(0),

意指从bus 0开始。有了segment 和 bus,最后我们在PCI设备下定义一个_ADR属性,确定此PCI设备的Device number 和function number,_ADR的返回值中,高16位表示Device number,低16位表示function number,接下来将展示一段sample code,读写 bus 0, device 29, function 1  USB controller 的PCI Configuration Space。

Name(_ADR, 0x001d0001)

OperationRegion (USBR, PCI_Config, 0xC4, 1)

Field (USBR,ANYACC, NOLOCK, Preserve)

{

     URSE, 8

}

Method (TEMD)

{

     Store(3,URES)

}

 

EC OperationRegion

EC OperationRegion 是定义EC Space操作的,可以在ASL里面定义EC OperationRegion,直接读写EC OperationRegion, OS的ACPI或者EC Driver或将这些操作转换为对EC Space的读写。根据ACPI spec,对于一个读操作,driver会向EC发送0x80 command 读其中的value,对于写操作,driver 会向EC发送0x81 command将一个value写到EC space。接下来定义一个EC OPerationRegion,假设EC space offset 0x00是CPU的温度。

OperationRegion (ECF2,EmbeddedControl, 0x00,0xff)

Field(ECF2,ByteAcc,Lock,Preserve)

{

     CTMP,     8

}

Store(CTMP,Local0)               //Read CPU temperature from EC space

 

与上面其他OperationRegion不同的是,EC OperationRegion并不是任何时候都可以使用,所以我们要follow ACPI spec,在同一scope中定义一个_Reg属性,来判断EC OperationRegon是否可用

Name(ECON,0)                              //Variable to remember EC OperationRegion Status

Method(_REG,0x2)

{

     if(LEqual(Arg0,0x03))               // Is it EC OperationRegion ? Yes EC=3

     {

          if(Arg1)                              // Is OperationRegion Connect ? 

          {

               Store(0x01,ECON)          //Available

          }Else                                   //OperationRegion Disconnect

          {

               Store(0x00,ECON)          //unavailable

          }

     }

}

 

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值