[ACPI 6.2A 规范中文版]第5章:ACPI软件编程模型

 

5 ACPI 软件编程模型—111 5.6.4 通用事件处理—293
5.1 系统描述表架构的概述—111 5.6.5 GPIO-signaled ACPI 事件—297
5.1.1 地址空间的转移—114 5.6.6 设备对象通知—300
5.2 ACPI系统描述表—114 5.6.7 设备类专用对象—306
……. 5.2.1~5.2.29 (115~253) 5.6.8 预定义对象、方法和资源的ACPI名称-309
5.3 ACPI命名空间—259 5.6.9 Interrupt-signaled ACPI 事件—321
5.3.1 预定义根命名空间—262 5.6.10 使用_PRW设备对象管理唤醒事件—324
5.3.2 对象—262 5.7 预定于对象—324
5.4 定义区块编码—262 5.7.1 \_GL (全局锁互斥)—325
5.4.1 AML编码—263 5.7.2 _OSI (操作系统接口)—325
5.4.2 定义区块加载—263 5.7.3 \_OS (操作系统的名字对象)—328
5.5 控制方法和ACPI源语言(ASL)–265 5.7.4 \_REV (数据对象版本)—328
5.5.1 ASL 语句—266 5.7.5 _DLM (设备锁互斥)—329
5.5.2 控制方法执行—266 5.8 系统配置对象—331
5.6 ACPI事件编程模型—291 5.8.1 _PIC 方法—331
5.6.1 ACPI事件编程模型组件—291
5.6.2 ACPI事件类型—292
5.6.3 固定事件处理—292

5 ACPI软件编程模型

ACPI定义了一个硬件注册接口,该接口是与ACPI兼容的OS用于控制机器的核心电源管理特性,如第4部分所述,“ACPI硬件规范”。ACPI还提供了一个抽象接口,用于控制ACPI系统的电源管理和配置。最后,ACPI定义了ACPI兼容操作系统和平台运行时固件之间的接口。

为了让硬件供应商在选择实现时具有灵活性,ACPI使用表来描述系统信息、特性和控制这些特性的方法。这些表列出了系统板或设备上的设备,这些设备不能被检测或使用其他硬件标准来管理,以及它们的功能,如第3节所述。他们还列出了一些系统功能,如睡眠电源状态、系统中可用的动力飞机和时钟源的描述、电池、系统指示灯等等。这使OSPM能够控制系统设备,而不需要知道如何实现系统控制。

本节讨论的主题包括:

•定义了ACPI系统描述表体系结构,并讨论了oem提供的定义块在该体系结构中的作用。

•讨论了ACPI名称空间的概念。

5.1系统描述表体系结构概述

根系统描述指针(RSDP)结构位于系统的内存地址空间中,由平台固件设置。这个结构包含扩展系统描述表(XSDT)的地址,它引用了向OSPM提供数据的其他描述表,提供了基本系统的实现和配置的知识(参见图5-26)。

所有系统描述表从相同的头开始。系统描述表的主要目的是为OSPM定义各种行业标准的实现细节。这些定义使这些实现的各个部分在硬件需求和设计上灵活,但仍然提供了直接控制硬件所需的知识。

扩展系统描述表(XSDT)指向内存中的其他表。始终是第一个表,它指向固定的ACPI描述表(FADT)。这个表中的数据包括各种固定长度的条目,它们描述了硬件的固定ACPI特性。FADT表总是引用不同的系统描述表(DSDT),它包含了各种系统特性的信息和描述。这些表之间的关系如图5-27所示。

OSPM找到了第5.2.5.1节中描述的RSDP结构(“在IA-PC系统上找到RSDP”)或第5.2.5.2节(“在UEFI启用系统中找到RSDP”)。

当OSPM定位结构时,它会查看根系统描述表或扩展系统描述表的物理地址。根系统描述表以签名“RSDT”开始,而扩展的系统描述表以签名“XSDT”开始。这些表包含一个或多个物理指针,用于提供关于系统的各种信息的其他系统描述表。如图5-27所示,固定ACPI描述表(FADT)的根系统描述表中总有一个物理地址。

当OSPM跟踪一个物理指针到另一个表时,它会检查每个表的已知签名。根据签名,OSPM可以在描述表中解释实现特定的数据。

FADT的目的是定义与配置和电源管理相关的各种静态系统信息。固定的ACPI描述表以“FACP”签名开始。FADT描述了在平台上的ACPI硬件寄存器的实现和配置细节。

对于ACPI硬件寄存器模块(PM1a_EVT_BLK、PM1b_EVT_BLK、PM1a_CNT_BLK、PM1b_CNT_BLK、PM2_CNT_BLK、PM_TMR_BLK、GP0_BLK、GP1_BLK和一个或多个P_BLKs)的规范,请参见第4.8节“ACPI注册模型”。“PM1a_EVT_BLK、PM1b_EVT_BLK、PM1a_CNT_BLK、PM1b_CNT_BLK、PM2_CNT_BLK和PM_TMR_BLK块是用于控制低级ACPI系统功能的。

GPE0_BLK和GPE1_BLK块为控制方法的中断处理模型提供了基础。P_BLK块用于控制处理器特性。

除了ACPI硬件寄存器实现信息之外,FADT还包含一个物理指针,它指向被称为区分系统描述表(DSDT)的数据结构,该数据结构以定义块格式编码(参见第5.2.11节“定义块”)。

一个定义块包含了关于平台硬件实现细节的信息,这些信息以数据对象的形式排列在一个层次(树状结构)实体中,称为“ACPI名称空间”,它代表了平台的硬件配置。由OSPM加载的所有定义块组合成一个表示平台的名称空间。数据对象的编码格式为ACPI机器语言,简称AML。在AML中编码的数据对象被称为AML解释器的OSPM实体“评估”。它们的值可能是静态的或动态的。AML解释器的动态数据对象评估功能包括对编程评估的支持,包括访问地址空间(例如,I/O或内存访问)、计算和逻辑评估,以确定结果。动态名称空间对象称为“控制方法”。OSPM“加载”或“卸载”整个定义块作为一个逻辑单元——从名称空间中添加或删除相关的对象。DSDT总是在启动时由OSPM加载,不能卸载。它包含一个定义块,命名为区分定义块,其中包含实现和配置信息OSPM可以用于执行电源管理、热管理、或插件和播放功能,这些功能超出了ACPI硬件寄存器所描述的信息。

定义块可以定义新的系统属性,或者在某些情况下,建立在先前的定义之上。可以从系统内存地址空间加载一个定义块。定义块的一个用途是描述和分发平台版本的更改。

定义块允许将硬件平台实现的广泛变化描述为与acpi兼容的操作系统,同时将变化限制在合理的边界上。定义块允许使用一些定义良好的对象名称来表示简单的平台实现。理论上,可以在定义块中定义一个PCI配置类空间的访问方法,通过从I/O空间构建它,但这不是定义块规范的目标。这样的空间通常定义为“内置”操作符。

一些运算符执行简单的函数,而另一些运算符包含复杂的函数。定义块的力量来自于它允许这些操作以多种方式粘合在一起的能力,从而为OSPM提供功能。这些操作人员的目的是让许多有用的硬件设计成为acpi表达,而不是允许所有硬件设计被表达。

5.1.1地址空间翻译

有些平台可能包含执行翻译的桥,当I/O和/或内存周期通过桥时。这种翻译可以采取加减乘除的形式。或者它可以采用从I/O循环转换到内存周期的形式,然后再返回。当翻译发生时,在读或写周期中由处理器在处理器总线上放置的地址与I/O总线桥上的I/O总线上的地址不相同。在处理器总线上的处理器位置的地址将被称为处理器相对地址。在I/O总线上的桥位置的地址将被称为总线相对地址。除非另有说明,本节中使用的所有地址都是处理器相对地址。

例如,考虑一个具有两个root PCI总线的平台。平台设计者有几个选择。一种解决方案是将16位I/O空间分成两部分,将一部分分配给第一个根PCI总线,并将一部分分配给第二个根总线。另一种解决方案是让根PCI总线解码整个16位I/O空间,将第二个根PCI总线的I/O空间映射到内存空间。在第二个场景中,当处理器需要从第二个root PCI总线下的一个设备的I/O寄存器读取数据时,需要在根PCI总线桥用于映射I/O空间的范围内执行内存读取。

注:由于历史兼容性问题,行业标准pc不提供地址空间翻译。

5.2 ACPI系统描述表

注:本小节内容较多,独立一章描述。

[ACPI 6.2A 规范中文版]第5.2章:ACPI系统描述表

5.3 ACPI名称空间

对于所有定义块,系统维护一个单独的分层命名空间,用于引用对象。所有定义都将加载到相同的名称空间中。尽管这允许一个定义块从另一个定义块引用对象和数据(从而支持交互),但这也意味着OEMs必须注意避免任何命名冲突(注意:2.在大多数情况下,由于名称空间是分层的,通常动态定义文件的大部分将加载到层次结构的不同部分。名称空间的根和正在设计交互的某些位置是必须额外注意的区域。)。只有定义块的卸载操作才能从名称空间中删除名称,因此试图装入定义块的名称冲突被认为是致命的。名称空间的内容只在加载或卸载操作时发生更改。

名称空间在本质上是层次化的,每个名称允许“下面”的名称集合。以下命名约定适用于所有名称:

•所有名字都是固定的32位。

•名称的第一个字节包含:‘A’–‘Z’, ‘_’, (0x41–0x5A, 0x5F).

•一个名称的其余三个字节包含:‘A’–‘Z’, ‘0’–‘9’, ‘_’, (0x41–0x5A, 0x30–0x39, 0x5F)

•按照惯例,当ASL编译器的名称小于4个字符时,它是用尾随下划线(‘ _ ‘)完成的。参见ACPI源语言(ASL)参考章节中AML NameSeg的语言定义。

•以“_”开头的名称由本规范保留。定义块只能使用由该规范定义的“_”开头的名称。

•使用“\”进行名称,使名称指向名称空间的根(“\”不是32位固定长度名称的一部分)。

•一个名字进行“^”导致的名称引用父当前名称空间(“^”不是32位定长名字的一部分)。

除了前面带有“\”的名称外,当前名称空间确定在名称空间层次结构中创建名称的位置,并找到引用的名称。通过在当前名称空间中查找匹配的名称,然后在父名称空间中找到名称。如果父名称空间不包含名称,则搜索将继续向上递归地向上,直到找到名称或名称空间没有父名称(名称空间的根)。这表示未找到该名称(注意:除非执行的操作在名称解析中明确地准备了失败,否则这将被认为是一个错误,并可能导致系统停止工作。)

试图访问根的父节点的名称将导致未找到名称。

有两种类型的名称空间路径:绝对名称空间路径(即以“\”前缀开头的)和相对命名空间路径(即相对于当前名称空间的名称)。上面讨论的名称空间搜索规则只适用于单个NameSeg路径,这是一个相对命名空间路径。对于那些相对路径名称包含多个NameSegs或父前缀,“^”,搜索规则不适用。如果搜索规则不应用于相对名称空间路径,则相对于当前名称空间查找名称空间对象。例如:

ABCD / /搜索规则适用

^ ABCD / /搜索规则不适用

XYZ。ABCD//搜索规则不适用。

\ XYZ。ABCD//搜索规则不适用。

所有名称引用都使用32位固定长度的名称,或者使用名称扩展前缀将多个32位固定长度的名称组件连接在一起。这对于引用对象的名称(例如控件方法)非常有用,因为它不在当前名称空间的范围内。

下图显示了在加载了一个有差异的定义块之后的ACPI名称空间的一个示例。

由于名称空间搜索规则,使用相对的单个段名称访问名称空间对象时必须小心。试图访问一个相对对象递归到根,直到找到对象或遇到根。这会导致无意的结果。例如,使用图5.5中描述的名称空间,试图从\_SB_.PCI0中访问一个名为object的_CRS。如果使用绝对或相对路径名,IDE0将会有不同的结果。如果指定了绝对路径名(\_SB_.PCI0.IDE0._CRS),则会导致该对象不存在。访问使用单个段名称(_CRS)将实际访问\_SB_.PCI0。_CRS对象。注意,访问将成功地发生,没有错误。

5.3.1预定义的根名称空间

以下名称空间是在名称空间根下定义的。

5.3.2对象

除本地外,所有对象都有全局范围。本地数据对象具有每个调用的范围和生命周期,并用于从开始到结束处理当前的调用。

对象的内容差别很大。然而,大多数对象引用任何受支持数据类型的数据变量、控制方法或系统软件提供的函数。

对象可能包含一个修订字段。连续的ACPI规范定义了对象修改,这样它们就可以向后兼容支持以前的规范/对象修改的OSPM实现。在以前的对象定义的末尾添加了新的对象字段。OSPM根据它支持的修订号(包括所有之前的修订)来解释对象。因此,OSPM期望一个对象的长度可以大于或等于已知对象修改的长度。当使用比OSPM已知的版本号更大的修订号来评估对象时,OSPM会忽略内部对象字段值,这些值超出了已知修改的定义对象字段范围。

5.4定义块编码

此部分指定定义块中用于定义名称(只加载时间)、对象和包的编码。

5.4.1 AML编码

定义块被编码为一个从头到尾的流。流中的lead字节来自于第19节所示的AML编码表,“ACPI源语言(ASL)引用”,并表示如何解释以下字节数,其中每个字节可以依次表示如何解释以下字节数。对于AML编码的完整规范,请参见第19节“ACPI源语言(ASL)引用”。

在流中定义了两个级别的数据。一个是打包和对象声明(加载时间),另一个是对象引用(包内容/运行时)。

所有编码都是这样的,编码的前导字节表示正在生成的声明或引用的类型。该类型在流中具有隐式或显式长度。所有显式长度声明都采用下面所示的形式,其中PkgLength是操作数据的长度的长度。

隐式长度对象的编码要么有固定长度的编码,要么允许嵌套的编码,在某个点上,要么是显式的或隐式的固定长度。

PkgLength被编码为在流中由1到4个字节组成的序列,其中最重要的两个字节为0,表示PkgLength编码中有多少字节。接下来的两个字节只用于一个字节的编码,这允许一个字节的编码长度到0x3F。较长的编码(不使用这两个位)的最大长度如下:两个字节的0x0FFF编码,3字节的0x0FFFFF编码,以及4字节长度编码的0x0FFFFFFFF。

包长度不能落在逻辑边界上是致命的。例如,如果一个包包含在另一个包中,那么根据定义,它的长度必须包含在外部包中,类似于隐式长度的数据。

5.4.2定义块加载

在某个时候,系统软件决定“加载”一个定义块。当系统对数据进行传递并填充ACPI名称空间并相应地初始化对象时,就完成了加载。出现人口的名称空间要么来自当前名称空间位置,要么由所有嵌套的包定义,要么来自根,如果名称前面有“\”。

定义块中的第一个对象必须是命名控制方法。这是定义块的初始化控制。

包是包含对一个或多个对象的有序引用的对象。包也可以看作是数组的顶点,包中包含的任何对象都可以是另一个包。这允许固定的或动态的深度和顶点的多维数组。

未命名对象用于填充命名对象的内容。无法在“根”中创建未命名的对象。未命名的对象可以用作控制方法的参数。

在创建对象时,控制方法的执行可能会产生错误。如果创建命名对象块的方法在被阻塞时重新输入,就会发生这种情况。这将会发生,因为所有命名的对象都有一个绝对路径。即使指定的对象名称是相对的,这也是正确的。例如,下面的ASL代码段在功能上是相同的。

请注意,在上面的示例中,死方法的执行总是会失败,因为对象\_SB_.FOO。BAR是在加载时创建的。

“定义块级别”的术语用于指不包含在任何控制方法中的AML字节流。这样的AML字节流可以出现在“根”范围内,也可以出现在“设备、PowerResource、处理器、范围和ThermalZone”操作符创建/打开的范围内。请参阅“第19.6条,ASL操作员参考”以获得详细说明。

不仅是命名对象,而且所有术语对象(数学、逻辑、条件表达式等)都可以在定义块级别上使用。在定义块级别允许这种可执行的AML操作码允许BIOS作者根据系统设置定义动态对象列表。例如:

5.5 控制方法和ACPI源语言(ASL)

OEMs和平台固件供应商使用ACPI源语言编写定义块,并使用转换器来生成第5.4节中描述的字节流编码,“定义块编码”。例如,在前面的小节中所示的ASL语句生成的示例字节流显示在下面的ASL示例中。对于ASL语句的完整规范,请参见第19节“ACPI源语言(ASL)引用”。

5.5.1 ASL语句

ASL主要是一种声明性语言。美国手语语句声明对象。每个对象有三个部分,其中两个可以为空:             

                                 Object := ObjectType FixedList VariableList

FixedList引用一个已知长度的列表,该列表提供了给定ObjectType的所有实例必须具有的数据。它被写成(a, b, c,),其中参数的数量取决于特定的ObjectType,一些元素可以是嵌套的对象,也就是(a, b, (q, r, s, t), d)。一些ObjectTypes可以有一个空FixedList。

VariableList是指帮助定义父类的子对象的列表,而不是预定长度。它被写为{x, y, z, aa, bb, cc},任何参数都可以是嵌套对象。ObjectType确定变量列表的合法元素是什么。一些ObjectTypes可以有一个空变量列表。

有关ASL语言的详细说明,请参见第19节“ACPI源语言(ASL)引用”。关于ACPI控制方法机器语言(AML)的详细说明,ASL转换器的输出基于该语言,参见第20节“ACPI机器语言(AML)规范”。

5.5.2控制方法执行

OSPM根据需要评估控制方法对象,以查询或调整系统级硬件状态。这称为调用。

控制方法可以使用其他内部或定义良好的控制方法来完成手头的任务,其中包括操作软件提供的定义控制方法。控件方法可以引用名称空间中的任何对象。对控制方法的解释不是先发制人的,而是可以阻止的。当控制方法阻塞时,OSPM可以启动或继续执行不同的控制方法。控制方法只能假设对全局对象的访问在任何期间都是独占的,控制方法不会阻塞。

全局对象是在表加载时创建的名称空间对象。

5.5.2.1参数

多达七个参数可以传递给控制方法。每个参数都是一个对象,该对象可以是引用其他对象的“package”样式对象。对参数对象的访问是通过ASL ArgTerm (ArgX)语言元素提供的。传递给任何控制方法的参数数量是固定的,并且在创建控件方法包时定义。

方法参数可以采用下列形式之一:

•引用一个命名对象的ACPI名称或namepath。这包括LocalX和ArgX名称。在这种情况下,与名称关联的对象作为参数传递。

•引用另一种控制方法的ACPI名称或namepath。在这种情况下,方法被调用,方法的返回值作为参数传递。如果方法中没有返回任何对象,则会发生致命错误。如果该对象在方法调用之后不被使用,它将被自动删除。

版本6.2勘误表一页267。

•一个有效的美国手语表达。在这种情况下,表达式被求值,并且这个评价结果的对象作为参数传递。如果该对象在方法调用之后不被使用,它将被自动删除。

5.5.2.2 方法调用协定

控制方法的调用约定可以最好地描述为引用-引用-常量。在这个约定中,作为参数传递的对象通过“reference”传递,这意味着它们不会被复制到新的对象,因为它们被传递给被称为控制方法(在调用过程中复制对象或对象包装器的调用约定称为按值或调用副本)。

这个基于调用的常量约定允许在每个方法调用之间共享内部对象,从而减少必须执行的对象副本的数量,以及必须复制的缓冲区的数量。这个调用约定适合于主机操作系统内核中的ACPI子系统的底层特性,在这个系统中,非分页动态内存通常是溢价的。ASL程序员必须了解调用约定和相关的副作用。

然而,与纯粹的调用引用约定不同,被调用的控制方法修改参数的能力非常有限。这减少了混淆的问题,例如,当调用方法意外地修改一个对象或变量时,调用者会将其作为参数传递。实际上,传递给控制方法的参数作为常量传递,除非在特定的受控环境下,否则无法修改。

一般来说,通过ArgX术语传递给控制方法的对象不能被调用方法直接写入或修改。换句话说,当一个ArgX术语用作目标操作符时,在ASL语句中,现有的ArgX对象没有被修改。相反,新对象将替换现有的对象,而ArgX项实际上变成了LocalX项。

只读参数规则的唯一例外是,如果ArgX术语包含通过RefOf ASL操作符创建的对象引用。在这种情况下,使用ArgX术语作为目标操作数,将会导致存储在ACPI名称中的任何现有对象被重写操作所引用。

在某些有限的情况下,可以创建一个新的可写对象,该对象将允许控制方法来更改ArgX对象的值。这些情况仅限于缓冲区和包对象,其中对象的“值”是间接表示的。对于缓冲区,可以创建可写索引或字段,该索引或字段引用原始缓冲区数据,并允许调用方法读取或修改数据。对于包,可以创建可写索引,以允许调用的方法修改包中各个元素的内容。

可以使用范围操作符或使用完整路径名在名称空间中创建当前范围之外的动态对象。这些对象在方法退出时仍然会被销毁。在方法的范围之外创建的对象是静态的。例如:

对象\ XYZ。当包含上述ASL的表加载时,BAR是创建的静态对象。对象\ XYZ.FOO。BAR是一个动态对象,它是在FOO方法中的名称(BAR, 7)语句被执行时创建的。对象\ XYZ。FOOB是由\XYZ创建的动态对象。当名称(\XYZ)时,FOO方法。FOOB, 3)语句被执行。注意,\ XYZ。FOOB对象在\XYZ之后被销毁。FOO方法退出。

5.5.2.4操作区域的接入

5.5.2.4.1操作区域

控制方法读写数据位置的地址空间(例如,系统内存和系统I / O)进行现场操作(参见19.6.46字段(申报领域对象)”)在一个实体声明一个数据元素被称为一个“操作区域”,然后执行访问使用数据元素名称。一个操作区域是在地址空间内的一个特定的操作区域,它使用一个起始地址(偏移量)和一个长度来声明为整个地址空间的子集(参见19.6.99“操作区域(声明操作区域)”)。控制方法必须对通过在操作区域中声明的字段访问的任何地址进行独占访问。控制方法不能直接访问任何其他硬件寄存器,包括acl定义的寄存器块。一些ACPI寄存器在定义的ACPI寄存器块中,代表控制方法执行维护。例如,GPEx_BLK不是由控件方法直接访问的,而是用来为控制方法调用提供可扩展的中断处理模型。

注意:访问OpRegion可能会阻塞,即使OpRegion不受互斥锁的保护。例如,由于嵌入式控制器的慢特性,嵌入式控制器OpRegion字段访问可能会阻塞。

表5-157定义了操作区域空间。

5.5.2.4.2 CMOS协议

本节描述如何从ASL访问CMOS电池支持的非易失性存储器。大多数计算机包含一个RTC/CMOS设备,可以表示为非易失性存储器的线性数组。有一种标准机制,用于访问与原IBM PC/AT中使用的摩托罗拉RTC/CMOS设备兼容的设备中的第一个64字节的非易失性RAM。现有的RTC/CMOS设备通常包含64字节的非易失性RAM,并且不存在用于访问这个额外存储区域的标准机制。为提供从AML中这些设备中所有非易失性存储器的访问,每个扩展类型都存在PnP id。这些是PNP0B00, PNP0B01和PNP0B02。这些PnP IDs支持的特定设备在9.15节中描述,“PC/AT RTC/CMOS设备”,以及字段定义ASL示例代码。对应于这些设备的驱动程序,对其各自的设备类型访问SystemCMOS操作区域。

所有与当前时间、日期、日期、月份、年份和世纪相关的CMOS字节都是只读的。

5.5.2.4.3 PCI设备的目标协议

本节描述如何从ASL访问PCI设备的控制寄存器。每个PCI设备都有一个与它们相关联的地址空间,称为配置空间。在偏移0x10的偏移0x27中,有6个基本地址寄存器(bar)。这些条包含PCI设备的一系列控制寄存器的基本地址(在I/O或内存空间中)。由于一个插入和播放操作系统可以随时改变这些条的值,ASL不能从这些确定的使用I/O或内存操作区域来读取和写入。此外,一个插入和播放操作系统将自动地分配与这些棒相关的I/O和内存区域的所有权到与PCI设备相关的设备驱动程序。ACPI操作系统(也必须是一个插件和操作系统)将不允许ASL读取和写入本地设备驱动程序所拥有的区域。

如果一个平台使用PCI BAR目标操作区域,ACPI操作系统将不会为相关的PCI函数加载本机设备驱动程序。例如,如果PCI函数中的任何一个条都与PCI BAR目标操作区域相关联,那么操作系统将假定PCI函数完全处于ACPI系统固件的控制之下。将不会加载任何驱动程序。因此,一个PCI函数可以作为一个平台控制器用于某些任务(热插拔PCI,等等),ACPI系统固件执行。

5.5.2.4.3.1 声明PCI BAR目标操作区域

PCI条包含一个PCI设备的控制寄存器位于内部的I/O或内存区域的基本地址。每个BAR实现一个协议来确定这些控制寄存器是否在I/O或内存空间内,以及PCI设备解码的地址空间有多大。(详情请参阅PCI规范。)

通过在PCI设备的PCI配置空间中提供BAR的偏移量来声明PCI BAR目标操作区域。该BAR决定是否通过I/O或内存循环来实际访问设备,而不是通过操作区域的声明。该区域的长度也类似地暗示着。

在术语OperationRegion(PBAR、PciBarTarget、0x10、0x4)中,偏移量是在设备的配置空间内的BAR的偏移量。这将是使用设备中的第一个BAR的操作区域的一个示例。

5.5.2.4.3.2 PCI头类型和PCI BAR目标操作区域

PCI BAR目标操作区域只能在具有PCI头类型0的PCI设备范围内声明。与其他头类型的PCI设备是桥梁。PCI桥的控制超出了ASL的范围。

5.5.2.4.4 声明IPMI操作区域

本部分描述了智能平台管理接口(IPMI)地址空间和使用该地址空间与AML的基板管理控制器(BMC)硬件进行通信。

与SMBus类似,IPMI操作区域是基于命令的,在IPMI地址空间中的每个偏移量表示一个IPMI命令和响应对。鉴于这种唯一性,IPMI操作区域包括对其字段定义的限制,并要求对所有事务使用特定于IPMI的数据缓冲区。本节介绍的IPMI接口是用于与IPMI规范兼容的任何硬件实现,而不考虑系统接口类型。

支持ACPI-compatible IPMI通用地址空间的操作系统是可选的,并且是取决于ACPI IPMI设备的存在,即“IPI0001”即插即用的设备ID。如果存在,OSPM应该加载必要的驱动程序软件基于指定的系统接口类型作为_IFT(IPMI接口类型)控制方法下的设备,并注册处理程序访问到IPMI操作区域空间。

有关更多信息,请参见IPMI规范。

每个IPMI操作区域定义标识一个单独的IPMI网络函数。操作区域仅定义为需要从AML访问的IPMI网络函数。与其他区域一样,IPMI操作区域只能通过字段项访问(参见5.5.2.4.4.1,“声明IPMI字段”)。

该接口将每个IPMI网络函数建模为具有256个字节的线性地址范围。该范围内的每个字节偏移对应于单个命令值(例如,字节偏移0xC1等于命令值0xC1),最多为256个命令值。通过这样做,IPMI地址空间看起来是线性的,并且可以以类似于其他地址空间类型的方式进行处理。

操作区域术语的语法(从19.6.99节开始,“OperationRegion(声明操作区域)”)如下所述。

OperationRegion (
                                     RegionName, // NameString
                                     RegionSpace, // RegionSpaceKeyword
                                     Offset, // TermArg=>Integer
                                     Length // TermArg=>Integer
)

地点:

•区域名称为这个IPMI网络函数指定一个名称(例如,“POWR”)。

•区域空间必须设置为IPMI(操作区域类型值0x07)。

•偏移量是一个字大小的值,指定目标设备的网络函数和初始命令值偏移量。网络函数地址存储在高字节中,命令值偏移存储在低字节中。例如,值0x3000将用于一个具有0x06的网络函数的设备,以及初始值为0(0)的值。

•长度设置为0x100(256),表示可能的命令值的最大数量,对于初始值为0(0)的区域,这两个值的差值用于非零偏移的区域。例如,一个具有0x3010偏移值的区域将具有相应的0xF0长度(0x100 – 0x10)。

例如,一个基板管理控制器将支持网络函数0x30中的电能计量功能,以及IPMI命令在网络函数0x06上查询BMC设备信息。

下面的ASL代码显示了使用OperationRegion术语来描述这些IPMI函数:

Device (IPMI)
{
 Name(_HID, “IPI0001”) // IPMI device
 Name(_IFT, 0x1) // KCS system interface type                                                           OperationRegion(DEVC, IPMI, 0x0600, 0x100) // Device info network function
 OperationRegion(POWR, IPMI, 0x3000, 0x100) // Power network function
:
}

请注意,本例中的这些操作区域是在“拥有”IPMI设备的当前上下文内定义的。这将确保根据_IFT对象返回的值来使用正确的操作区域处理程序。每个定义对应一个单独的网络函数,并使用初始的命令值偏移量为0(0)。

5.5.2.4.4.1 声明IPMI字段

与其他区域一样,IPMI操作区域只能通过字段项访问。每个字段元素被分配一个唯一的命令值,并表示目标网络函数的虚拟命令。

字段项的语法(从第19.6.40节开始,“事件(声明事件同步对象)”)在下面描述。

Field(
RegionName, // NameString=>OperationRegion
AccessType, // AccessTypeKeyword – BufferAcc
LockRule, // LockRuleKeyword
UpdateRule // UpdateRuleKeyword – ignored
) {FieldUnitList}

地点:

•区域名称指定之前为网络函数定义的操作区域名称。

•AccessType必须设置为BufferAcc。这表明对字段元素的访问将使用特定于区域的数据缓冲区进行。对于这种访问类型,字段处理程序不知道数据缓冲区的内容,这些内容可能是任何大小的。当在一个操作中使用该类型的字段作为源参数时,它只是计算一个缓冲区。然而,当用作目标时,缓冲区会双向传递,以允许从写操作返回数据。修改后的缓冲区将成为该命令的响应消息。这与执行结果与写入目的地的值相同的正常情况略有不同。请注意,源代码从未更改,因为它只代表一个特定的IPMI命令的虚拟寄存器。

•LockRule指出,如果访问该操作区域,则需要获取全局锁以进行同步。该字段应该被设置为锁定系统,固件可以通过IPMI访问BMC,否则就停止。

•UpdateRule不适用于IPMI操作区域,因为每个虚拟寄存器都是完整访问的。对于所有的IPMI字段定义,这个字段都被忽略。

IPMI操作区域要求在命令值粒度上声明所有字段元素。这意味着每个虚拟寄存器不能被分解为字段定义中的单个位。

只能在字段定义之外访问虚拟寄存器的子部分。这种限制是为了简化IPMI接口,并与IPMI规范定义的物理模型保持一致。

由于IPMI通信的系统接口是由IPMI设备下的_IFT对象决定的,所以在字段定义中不需要使用AccessAs术语。实际上,它的使用将被操作处理程序忽略。

例如,power meter网络函数的命令值0xC1的寄存器可能表示设置BMC强制功率限制的命令,而相同网络函数的命令值0xC2的寄存器可能表示当前配置的功率限制。同时,在命令值0xC8上的寄存器可能代表最新的功率表测量。

5.5.2.4.4.2 声明和使用IPMI请求和响应缓冲区

由于IPMI操作区域中的每个虚拟寄存器都表示一个独立的IPMI命令,并且操作依赖于双向缓冲区的使用,因此需要一个公共的缓冲结构来表示请求和响应消息。对IPMI事务的数据缓冲区的使用允许AML接收状态和数据长度值。

IPMI数据缓冲区被定义为一个固定长度的66字节缓冲区,如果使用“C”样式的声明表示,将建模如下:

typedef struct
{
BYTEStatus; // Byte 0 of the data buffer
BYTELength; // Byte 1 of the data buffer
BYTE[64]Data; // Bytes 2 through 65 of the data buffer
}

地点:

•Status(字节0)表示给定IPMI命令的状态码。参见第5.5.2.4.4.3节“IPMI状态代码”,了解更多信息。

•Length(字节1)指定数据缓冲区中存在的有效数据字节数。有效长度值为0到64。在执行操作之前,该值表示请求数据缓冲区的长度。然后,这个值表示结果响应数据缓冲区的长度。

•数据(字节65-2)表示一个64字节的缓冲区,是存储实际数据的位置。在执行操作之前,这表示实际的请求消息有效负载。然后,这表示IPMI命令返回的响应消息有效负载。

例如,下面的ASL显示了使用IPMI数据缓冲区来执行一个power函数的命令。此代码基于5.5.2.4.4.1节中的示例ASL,“声明IPMI字段”,其中列出了有关IPMI功率测量命令的操作区域和字段定义。

/* Create the IPMI data buffer */
Name(BUFF, Buffer(66){})                       // Create IPMI data buffer as BUFF
CreateByteField(BUFF, 0x00, STAT)      // STAT = Status (Byte)
CreateByteField(BUFF, 0x01, LENG)    // LENG = Length (Byte)
CreateByteField(BUFF, 0x02, MODE)   // MODE = Mode (Byte)
CreateByteField(BUFF, 0x03, RESV)   // RESV = Reserved (Byte)
Store(0x2, LENG)                                  // Request message is 2 bytes long
Store(0x1, MODE)                                 // Set Mode to 1
Store(Store(BUFF, GPMM), BUFF)     // Write the request into the GPMM command,
                                                               // then read the results
CreateByteField(BUFF, 0x02, CMPC)   // CMPC = Completion code (Byte)
CreateWordField(BUFF, 0x03, APOW)  // APOW = Average power measurement (Word)
If(LAnd(LEqual(STAT, 0x0), LEqual(CMPC, 0x0))) // Successful?
{
Return(APOW)                                  // Return the average power measurement
}
Else
{
Return(Ones)                                     // Return invalid
}

注意,使用CreateField原语访问数据缓冲区的子元素(状态、长度和数据),其中数据(字节65-2)是“类型转换”到不同的字段(包括结果完成代码)。

上面的示例演示了如何使用Store()操作符和双向数据缓冲区来调用由虚拟寄存器表示的实际IPMI命令。内部存储()将请求消息数据缓冲区写入IPMI操作区域处理程序,并调用该命令。外部存储()获取该命令的结果并将其写入数据缓冲区,这一次表示响应消息。

5.5.2.4.4.3  IPMI状态代码

每个IPMI命令都会返回一个状态码,作为响应消息的第一个字节,包含在双向数据缓冲区中。此状态代码可以指示成功、各种错误,并可能从IPMI操作处理程序超时。这是必要的,因为有可能对某些IPMI命令需要5秒执行,由于AML商店()操作是同步的,自然,它是必要的,以确保及时IPMI操作返回,以免阻塞OSPM AML解释器。

注意:此状态代码与IPMI完成代码不同,IPMI完成代码作为数据缓冲区有效负载中响应消息的第一个字节返回。完成代码在完整的IPMI规范中描述。

5.5.2.4.5声明GeneralPurposeIO(GPIO)操作区域。

对于一般的目标操作区域,下面描述了OperationRegion术语的语法(从19.6.99小节开始,“OperationRegion(声明操作区域)”)。

OperationRegion (
                                     RegionName, // NameString
                                     RegionSpace, // RegionSpaceKeyword
                                     Offset, // TermArg=>Integer
                                     Length // TermArg=>Integer
)

地点:

•区域名称为这个通用目的区域指定一个名称(例如,“GPI1”)。

•区域空间必须设置为通用目的(操作区域类型值0x08)。

•为特定目的区域空间忽略偏移。

•长度是在操作区域中被包含的GPIO IO大头针的最大数量,集中到下一个字节。

必须在被访问的GPIO控制器设备的范围内声明GeneralPurposeIO OpRegions。

5.5.2.4.5.1声明GeneralPurposeIO字段

与其他区域一样,泛型目标操作区域只能通过字段项访问。每个字段元素表示在OpRegion声明中声明的长度字节的一个子集。通过一个给定字段名称访问的OpRegion内的pin由连接描述符定义。连接描述符后面的定义字段位的总数必须等于描述符中列出的引脚的数目。字段项的语法(来自第19.6.46节)描述如下。

Field(
          RegionName,        // NameString=>OperationRegion
          AccessType,         // AccessTypeKeyword
          LockRule,             // LockRuleKeyword
          UpdateRule          // UpdateRuleKeyword – ignored
) {FieldUnitList}

地点:

•区域名称指定前面声明的操作区域名称。

•AccessType必须设置为ByteAcc。

•LockRule指出,如果访问该操作区域,则需要获取全局锁以进行同步。注意,在hw减少的ACPI平台上,该字段必须设置为NoLock。

•UpdateRule不适用于一般用途的操作区域,因为保存总是必需的。该字段对于所有泛型目标字段定义都是忽略的。

下面的ASL代码显示了应用程序区域、字段和偏移量的术语,因为它们适用于GeneralPurposeIO 空间。

5.5.2.4.6声明GenericSerialBus操作区域

对于GenericSerialBus操作区域,下面将描述OperationRegion项的语法(从19.6.99节开始,“OperationRegion(声明操作区域)”)。

OperationRegion (
                               RegionName, // NameString
                               RegionSpace, // RegionSpaceKeyword
                               Offset, // TermArg=>Integer
                               Length // TermArg=>Integer
)

地点:

•区域名称为该区域指定一个名称(例如,TOP1)。

•区域空间必须设置为GenericSerialBus(操作区域类型值0x09)。

•Offset指定目标设备的初始命令值偏移量。例如,值0x00表示为0(0)的命令值偏移量。原始协议忽略此值。

•长度设置为0x100(256),表示可能的命令值的最大数量。

注意:操作区域必须在串行总线控制器设备的范围内声明。

下面的ASL代码显示了应用于SPB空间的OperationRegion、Field和Offset项的用法。

本例中的操作区域定义在目标控制器设备I2C的范围内。

GenericSerialBus区域只能通过字段项访问(参见第19.6.46节“字段(声明字段对象))GenericSerialBus协议使用AccessAs项分配给字段元素(参见第19.3.4“ASL宏”)。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ACPI导航

[ACPI 6.2A 规范中文版]译者绪论

[ACPI 6.2A 规范中文版]第1章:介绍

[ACPI 6.2A 规范中文版]第2章:术语的定义

[ACPI 6.2A 规范中文版]第3章:ACPI概述

[ACPI 6.2A 规范中文版]第4章:ACPI硬件规范

[ACPI 6.2A 规范中文版]第4.8章:ACPI寄存器模型

[ACPI 6.2A 规范中文版]第5章:ACPI软件编程模型

[ACPI 6.2A 规范中文版]第6章:设备配置

[ACPI 6.2A 规范中文版]第7章:电源和性能管理

[ACPI 6.2A 规范中文版]第8章:处理器配置和控制