Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1315670
  • 博文数量: 554
  • 博客积分: 10425
  • 博客等级: 上将
  • 技术积分: 7555
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-09 09:49
文章分类

全部博文(554)

文章存档

2012年(1)

2011年(1)

2009年(8)

2008年(544)

分类:

2008-04-11 15:21:19


上下文管理操作
第11 章• 设备上下文管理195
devmap_dup 必须设置为驱动程序的devmap_dup(9E) 入口点的地址。
devmap_unmap 必须设置为驱动程序的devmap_unmap(9E) 入口点的地址。
用于设备上下文管理的入口点
以下入口点用于管理设备上下文:
 devmap(9E)
 devmap_access(9E)
 devmap_contextmgt(9E)
 devmap_dup(9E)
 devmap_unmap(9E)
devmap_map() 入口点
devmap(9E) 的语法如下所示:
int xxdevmap_map(devmap_cookie_t handle, dev_t dev, uint_t flags,
offset_t offset, size_t len, void **new-devprivate);
驱动程序从其devmap() 入口点返回并且系统已建立到设备内存的用户映射后,将会调用
devmap_map() 入口点。通过devmap() 入口点,驱动程序可以执行其他处理操作或分配特定
于映射的专用数据。例如,为了支持上下文切换,驱动程序必须分配上下文结构。然后,
驱动程序必须将上下文结构与映射关联。
系统期望驱动程序在*new-devprivate 中返回一个指向分配的专用数据的指针。驱动程序必
须存储用于定义专用数据中的映射范围的offset 和len。然后当系统调用devmap_unmap(9E)
时,驱动程序将使用此信息来确定要取消映射的映射量。
flags 指示驱动程序是否应为映射分配专用上下文。例如,如果flags 设置为MAP_PRIVATE,则
驱动程序可以分配用于存储设备上下文的内存区域。如果设置了MAP_SHARED,驱动程序将
返回指向共享区域的指针。
以下示例说明了devmap() 入口点。驱动程序分配了一个新的上下文结构。然后,驱动程序
便可保存通过入口点传入的相关参数。接下来,将通过分配或通过将映射附加至已经存在
的共享上下文来为映射指定新的上下文。映射访问设备的最短时间间隔设置为1 毫秒。
示例11–1 使用devmap() 例程
static int
int xxdevmap_map(devmap_cookie_t handle, dev_t dev, uint_t flags,
offset_t offset, size_t len, void **new_devprivate)
上下文管理操作
196 编写设备驱动程序• 2006 年11 月
示例11–1 使用devmap() 例程(续)
{
struct xxstate *xsp = ddi_get_soft_state(statep,
getminor(dev));
struct xxctx *newctx;
/* create a new context structure */
newctx = kmem_alloc(sizeof (struct xxctx), KM_SLEEP);
newctx->xsp = xsp;
newctx->handle = handle;
newctx->offset = offset;
newctx->flags = flags;
newctx->len = len;
mutex_enter(&xsp->ctx_lock);
if (flags & MAP_PRIVATE) {
/* allocate a private context and initialize it */
newctx->context = kmem_alloc(XXCTX_SIZE, KM_SLEEP);
xxctxinit(newctx);
} else {
/* set a pointer to the shared context */
newctx->context = xsp->ctx_shared;
}
mutex_exit(&xsp->ctx_lock);
上下文管理操作
第11 章• 设备上下文管理197
示例11–1 使用devmap() 例程(续)
/* give at least 1 ms access before context switching */
devmap_set_ctx_timeout(handle, drv_usectohz(1000));
/* return the context structure */
*new_devprivate = newctx;
return(0);
}
devmap_access() 入口点
对转换无效的映射进行访问时,将会调用devmap_access(9E) 入口点。映射转换在以下几种
情况下无效:作为对mmap(2) 的响应通过devmap_devmem_setup(9F) 创建映射;通过fork(2)
复制映射或通过调用devmap_unload(9F) 显式使映射无效。
devmap_access() 的语法如下所示:
int xxdevmap_access(devmap_cookie_t handle, void *devprivate,
offset_t offset, size_t len, uint_t type, uint_t rw);
其中:
handle 用户进程所访问的映射的映射句柄。
devprivate 指向与映射关联的驱动程序专用数据的指针。
offset 所访问映射内的偏移。
len 所访问内存的长度(以字节为单位)。
type 访问操作的类型。
rw 用于指定访问的方向。
系统期望devmap_access(9E) 调用devmap_do_ctxmgt(9F) 或devmap_default_access(9F) 以便
在devmap_access() 返回前装入内存地址转换。对于支持上下文切换的映射,设备驱动程序
应调用devmap_do_ctxmgt()。系统会通过devmap_access(9E) 向此例程传递所有参数以及指
向驱动程序入口点devmap_contextmgt(9E) 的指针,该指针用来处理上下文切换。对于不支
持上下文切换的映射,驱动程序应调用devmap_default_access(9F)。
devmap_default_access() 的用途是调用devmap_load(9F) 以装入用户转换。
以下示例说明了devmap_access(9E) 入口点。该映射分为两个区域。在偏移OFF_CTXMG 上开
始并且长度为CTXMGT_SIZE 字节的区域支持上下文管理。其余映射支持缺省访问。
上下文管理操作
198 编写设备驱动程序• 2006 年11 月
示例11–2 使用devmap_access() 例程
#define OFF_CTXMG 0
#define CTXMGT_SIZE 0x20000
static int
xxdevmap_access(devmap_cookie_t handle, void *devprivate,
offset_t off, size_t len, uint_t type, uint_t rw)
{
offset_t diff;
int error;
if ((diff = off - OFF_CTXMG) >= 0 && diff < CTXMGT_SIZE) {
error = devmap_do_ctxmgt(handle, devprivate, off,
len, type, rw, xxdevmap_contextmgt);
} else {
error = devmap_default_access(handle, devprivate,
off, len, type, rw);
}
return (error);
}
devmap_contextmgt() 入口点
devmap_contextmgt(9E) 的语法如下所示:
int xxdevmap_contextmgt(devmap_cookie_t handle, void *devprivate,
offset_t offset, size_t len, uint_t type, uint_t rw);
上下文管理操作
第11 章• 设备上下文管理199
devmap_contextmgt() 应使用当前对设备具有访问权限的映射的句柄调用
devmap_unload(9F)。此方法可使对于该映射的转换无效。通过此方法,可确保下次访问当
前映射时针对该映射调用devmap_access(9E)。对于引起访问事件发生的映射,需要验证其
映射转换。相应地,驱动程序必须为进程请求访问恢复设备上下文。并且,驱动程序必须
针对映射的handle 调用devmap_load(9F),该映射生成了对此入口点的调用。
访问已通过调用devmap_load() 对映射转换进行验证的部分映射时不会导致调用
devmap_access()。对devmap_unload() 的后续调用将使映射转换无效。通过此调用,可再次
调用devmap_access()。
如果devmap_load() 或devmap_unload() 返回错误,devmap_contextmgt() 会立即返回该错
误。如果设备驱动程序在恢复设备上下文时遇到硬件故障,则应返回-1。否则,成功处理
访问请求后,devmap_contextmgt() 应返回零。如果从devmap_contextmgt() 返回非零值,
则会向进程发送SIGBUS 或SIGSEGV。
以下示例说明如何管理单页设备上下文。
注– xxctxsave() 和xxctxrestore() 是与设备有关的上下文保存和恢复函数。xxctxsave() 用
于从寄存器中读取数据并将数据保存在软状态结构中。xxctxrestore() 用于提取软状态结
构中保存的数据并将数据写入设备寄存器。请注意,执行读取、写入和保存都需要使用
DDI/DKI 数据访问例程。
示例11–3 使用devmap_contextmgt() 例程
static int
xxdevmap_contextmgt(devmap_cookie_t handle, void *devprivate,
offset_t off, size_t len, uint_t type, uint_t rw)
{
int error;
struct xxctx *ctxp = devprivate;
struct xxstate *xsp = ctxp->xsp;
mutex_enter(&xsp->ctx_lock);
/* unload mapping for current context */
if (xsp->current_ctx != NULL) {
if ((error = devmap_unload(xsp->current_ctx->handle,
上下文管理操作
200 编写设备驱动程序• 2006 年11 月
示例11–3 使用devmap_contextmgt() 例程(续)
off, len)) != 0) {
xsp->current_ctx = NULL;
mutex_exit(&xsp->ctx_lock);
return (error);
}
}
/* Switch device context - device dependent */
if (xxctxsave(xsp->current_ctx, off, len) < 0) {
xsp->current_ctx = NULL;
mutex_exit(&xsp->ctx_lock);
return (-1);
}
if (xxctxrestore(ctxp, off, len) < 0){
xsp->current_ctx = NULL;
mutex_exit(&xsp->ctx_lock);
return (-1);
}
xsp->current_ctx = ctxp;
/* establish mapping for new context and return */
error = devmap_load(handle, off, len, type, rw);
if (error)
xsp->current_ctx = NULL;
mutex_exit(&xsp->ctx_lock);
上下文管理操作
第11 章• 设备上下文管理201
示例11–3 使用devmap_contextmgt() 例程(续)
return (error);
}
devmap_dup() 入口点
复制设备映射(例如,由调用fork(2) 的用户进程进行复制)时,将会调用devmap_dup(9E)
入口点。驱动程序预期会为新映射生成新的驱动程序专用数据。
devmap_dup() 的语法如下所示:
int xxdevmap_dup(devmap_cookie_t handle, void *devprivate,
devmap_cookie_t new-handle, void **new-devprivate);
其中:
handle 正在复制的映射的映射句柄。
new-handle 已复制的映射的映射句柄。
devprivate 指向与正在复制的映射关联的驱动程序专用数据的指针。
*new-devprivate 应设置为指向用于新映射的新驱动程序专用数据的指针。
缺省情况下使用devmap_dup() 所创建的映射会使其映射转换无效。第一次访问映射时,无
效的映射转换会强制调用devmap_access(9E) 入口点。
以下示例说明了一个典型的devmap_dup() 例程。
示例11–4 使用devmap_dup() 例程
static int
xxdevmap_dup(devmap_cookie_t handle, void *devprivate,
devmap_cookie_t new_handle, void **new_devprivate)
{
struct xxctx *ctxp = devprivate;
struct xxstate *xsp = ctxp->xsp;
struct xxctx *newctx;
上下文管理操作
202 编写设备驱动程序• 2006 年11 月
示例11–4 使用devmap_dup() 例程(续)
/* Create a new context for the duplicated mapping */
newctx = kmem_alloc(sizeof (struct xxctx), KM_SLEEP);
newctx->xsp = xsp;
newctx->handle = new_handle;
newctx->offset = ctxp->offset;
newctx->flags = ctxp->flags;
newctx->len = ctxp->len;
mutex_enter(&xsp->ctx_lock);
if (ctxp->flags & MAP_PRIVATE) {
newctx->context = kmem_alloc(XXCTX_SIZE, KM_SLEEP);
bcopy(ctxp->context, newctx->context, XXCTX_SIZE);
} else {
newctx->context = xsp->ctx_shared;
}
mutex_exit(&xsp->ctx_lock);
*new_devprivate = newctx;
return(0);
}
devmap_unmap() 入口点
对映射取消映射时,将会调用devmap_unmap(9E) 入口点。用户进程退出或调用munmap(2) 系
统调用会导致取消映射。
devmap_unmap() 的语法如下所示:
void xxdevmap_unmap(devmap_cookie_t handle, void *devprivate,
上下文管理操作
第11 章• 设备上下文管理203
offset_t off, size_t len, devmap_cookie_t new-handle1,
void **new-devprivate1, devmap_cookie_t new-handle2,
void **new-devprivate2);
其中:
handle 正在释放的映射的映射句柄。
devprivate 指向与映射关联的驱动程序专用数据的指针。
off 逻辑设备内存中取消映射开始处的偏移。
len 所取消映射的内存的长度(以字节为单位)。
new-handle1 系统用来描述在off - 1 位置结束的新区域的句柄。new-handle1 可以为
NULL。
new-devprivate1 要由驱动程序通过用于新区域的专用驱动程序映射数据进行填充的指
针,该新区域在off -1 位置结束。如果new-handle1 为NULL,则会忽略
new-devprivate1。
new-handle2 系统用来描述新区域的句柄,该新区域在off + len 位置开始。
new-handle2 可为NULL。
new-devprivate2 要由驱动程序通过用于新区域的驱动程序专用映射数据进行填充的指
针,该新区域在off + len 位置开始。如果new-handle2 为NULL,则会忽
略new-devprivate2。
devmap_unmap() 例程预期会释放通过devmap_map(9E) 或devmap_dup(9E) 创建此映射时分配的
任何驱动程序专用资源。如果只是取消映射部分映射,则驱动程序必须在释放旧的专用数
据之前为其余映射分配新的专用数据。不必针对已释放的映射的句柄调用
devmap_unload(9F),即使此句柄指向具有有效转换的映射时也是如此。不过,为了避免将
来出现devmap_access(9E) 问题,设备驱动程序应确保当前的映射表示形式设置为“无当前映
射”。
以下示例说明了一个典型的devmap_unmap() 例程。
示例11–5 使用devmap_unmap() 例程
static void
xxdevmap_unmap(devmap_cookie_t handle, void *devprivate,
offset_t off, size_t len, devmap_cookie_t new_handle1,
void **new_devprivate1, devmap_cookie_t new_handle2,
void **new_devprivate2)
上下文管理操作
204 编写设备驱动程序• 2006 年11 月
示例11–5 使用devmap_unmap() 例程(续)
{
struct xxctx *ctxp = devprivate;
struct xxstate *xsp = ctxp->xsp;
mutex_enter(&xsp->ctx_lock);
/*
* If new_handle1 is not NULL, we are unmapping
* at the end of the mapping.
*/
if (new_handle1 != NULL) {
/* Create a new context structure for the mapping */
newctx = kmem_alloc(sizeof (struct xxctx), KM_SLEEP);
newctx->xsp = xsp;
if (ctxp->flags & MAP_PRIVATE) {
/* allocate memory for the private context
/* and copy it */
newctx->context = kmem_alloc(XXCTX_SIZE, KM_SLEEP);
bcopy(ctxp->context, newctx->context, XXCTX_SIZE);
} else {
/* point to the shared context */
newctx->context = xsp->ctx_shared;
}
newctx->handle = new_handle1;
上下文管理操作
第11 章• 设备上下文管理205
示例11–5 使用devmap_unmap() 例程(续)
newctx->offset = ctxp->offset;
newctx->len = off - ctxp->offset;
*new_devprivate1 = newctx;
}
/*
* If new_handle2 is not NULL, we are unmapping
* at the beginning of the mapping.
*/
if (new_handle2 != NULL) {
/* Create a new context for the mapping */
newctx = kmem_alloc(sizeof (struct xxctx), KM_SLEEP);
newctx->xsp = xsp;
if (ctxp->flags & MAP_PRIVATE) {
newctx->context = kmem_alloc(XXCTX_SIZE, KM_SLEEP);
bcopy(ctxp->context, newctx->context, XXCTX_SIZE);
} else {
newctx->context = xsp->ctx_shared;
}
newctx->handle = new_handle2;
newctx->offset = off + len;
newctx->flags = ctxp->flags;
newctx->len = ctxp->len - (off + len - ctxp->off);
上下文管理操作
206 编写设备驱动程序• 2006 年11 月
示例11–5 使用devmap_unmap() 例程(续)
*new_devprivate2 = newctx;
}
if (xsp->current_ctx == ctxp)
xsp->current_ctx = NULL;
mutex_exit(&xsp->ctx_lock);
if (ctxp->flags & MAP_PRIVATE)
kmem_free(ctxp->context, XXCTX_SIZE);
kmem_free(ctxp, sizeof (struct xxctx));
}
将用户映射与驱动程序通知关联
用户进程通过mmap(2) 请求到设备的映射时,将会调用驱动程序的segmap(9E) 入口点。如果
驱动程序需要管理设备上下文,则在设置内存映射时,驱动程序必须使用
ddi_devmap_segmap(9F) 或devmap_setup(9F)。这两个函数都会调用驱动程序的devmap(9E) 入
口点,该入口点使用devmap_devmem_setup(9F) 将设备内存与用户映射关联。有关如何映射
设备内存的详细信息,请参见第10 章。
驱动程序必须向系统通知devmap_callback_ctl(9S) 入口点才能获取对用户映射的访问通
知。驱动程序通过向devmap_devmem_setup(9F) 提供一个指向devmap_callback_ctl(9S) 结构
的指针来通知系统。devmap_callback_ctl(9S) 结构描述了一组用于上下文管理的入口点。
系统通过调用这些入口点来通知设备驱动程序管理有关设备映射的事件。
系统会将每个映射与一个映射句柄关联。此句柄会传递给每个用于上下文管理的入口点。
该映射句柄可用来使映射转换无效和对映射转换进行验证。如果驱动程序使映射转换无
效,则会向该驱动程序通知将来对映射的任何访问。如果驱动程序对映射转换进行验证,
则不再向该驱动程序通知对映射的访问。映射总是在映射转换无效的情况下创建,以便第
一次访问映射时将会通知驱动程序。
以下示例说明如何使用设备上下文管理接口设置映射。
示例11–6 支持上下文管理的devmap(9E) 入口点
static struct devmap_callback_ctl xx_callback_ctl = {
DEVMAP_OPS_REV, xxdevmap_map, xxdevmap_access,
上下文管理操作
第11 章• 设备上下文管理207
示例11–6 支持上下文管理的devmap(9E) 入口点(续)
xxdevmap_dup, xxdevmap_unmap
};
static int
xxdevmap(dev_t dev, devmap_cookie_t handle, offset_t off,
size_t len, size_t *maplen, uint_t model)
{
struct xxstate *xsp;
uint_t rnumber;
int error;
/* Setup data access attribute structure */
struct ddi_device_acc_attr xx_acc_attr = {
DDI_DEVICE_ATTR_V0,
DDI_NEVERSWAP_ACC,
DDI_STRICTORDER_ACC
};
xsp = ddi_get_soft_state(statep, getminor(dev));
if (xsp == NULL)
return (ENXIO);
len = ptob(btopr(len));
rnumber = 0;
上下文管理操作
208 编写设备驱动程序• 2006 年11 月
示例11–6 支持上下文管理的devmap(9E) 入口点(续)
/* Set up the device mapping */
error = devmap_devmem_setup(handle, xsp->dip, &xx_callback_ctl,
rnumber, off, len, PROT_ALL, 0, &xx_acc_attr);
*maplen = len;
return (error);
}
管理映射访问
用户进程访问没有有效的映射转换的内存映射区域中的地址时,将会通知设备驱动程序。
访问事件发生时,必须使当前对设备具有访问权限的进程的映射转换无效。必须恢复请求
访问设备的进程的设备上下文。并且,必须对请求访问的进程的映射转换进行验证。
函数devmap_load(9F) 和devmap_unload(9F) 用于验证映射转换和使其无效。
devmap_load() 入口点
devmap_load(9F) 的语法如下所示:
int devmap_load(devmap_cookie_t handle, offset_t offset,
size_t len, uint_t type, uint_t rw);
devmap_load() 可以验证对于handle、offset 和len 指定的映射页的映射转换。通过验证对
这些页的映射转换,驱动程序将告知系统不要拦截对这些映射页的访问。并且,系统不得
在未通知设备驱动程序的情况下允许继续进行访问。
必须通过映射的偏移和句柄调用devmap_load(),该映射可生成访问事件以便完成访问。如
果不针对此句柄调用devmap_load(9F),则不会验证映射转换,并且进程将收到SIGBUS。
devmap_unload() 入口点
devmap_unload(9F) 的语法如下所示:
int devmap_unload(devmap_cookie_t handle, offset_t offset,
size_t len);
上下文管理操作
第11 章• 设备上下文管理209
devmap_unload() 可使对handle、offset 和len 指定的映射页的映射转换无效。通过使对这些
页的映射转换无效,设备驱动程序将告知系统拦截对这些映射页的访问。并且,下次通过
调用devmap_access(9E) 入口点访问这些映射页时,系统必须通知设备驱动程序。
对于这两个函数而言,请求会影响包含offset 的整页,直到包含由offset + len 所表示的最后一
个字节的整页(包含该页)。设备驱动程序必须确保对于所映射的每页设备内存而言,在
任意时刻仅有一个进程具有有效转换。
如果成功,两个函数都将返回零。但是,如果在对映射转换进行验证或使其无效时出现错
误,则该错误将返回给设备驱动程序。设备驱动程序必须将此错误返回给系统。
上下文管理操作
210 编写设备驱动程序• 2006 年11 月
电源管理
电源管理提供控制和管理计算机系统或设备的电源使用情况的功能。使用电源管理,可使
系统在空闲时消耗较少的电量,在未使用时完全关闭电源,从而节省能源。例如,桌面计
算机系统耗电量很大,但经常处于空闲状态,尤其是在夜间。电源管理软件可以检测到系
统未被使用的情况。因此,电源管理可以关闭系统或其中某些组件的电源。
本章提供了有关以下主题的信息:
 第211 页中的“电源管理框架”
 第212 页中的“设备电源管理模型”
 第222 页中的“系统电源管理模型”
 第230 页中的“电源管理设备访问示例”
 第232 页中的“电源管理控制流程”
电源管理框架
Solaris Power ManagementTM 框架依靠设备驱动程序来实现特定于设备的电源管理功能。该
框架分两部分实现:
 设备电源管理-自动关闭未使用的设备,以减少能耗
 系统电源管理-当整个系统处于空闲状态时,自动关闭计算机
设备电源管理
该框架使设备可在经过指定的空闲时间间隔后降低能耗。在电源管理过程中,系统软件会
检查空闲设备。电源管理框架会导出接口,通过这些接口,可以在系统软件与设备驱动程
序之间进行通信。
Solaris 电源管理框架提供了下列设备电源管理功能:
 适用于电源可管理设备且与设备无关的模型。
 dtpower(1M),一种用于配置工作站电源管理的工具。电源管理也可以通过
power.conf(4) 和/etc/default/power 文件来实现。
12 第1 2 章
211
 一组DDI 接口,用于通知框架电源管理兼容性和空闲状态。
系统电源管理
系统电源管理可在关闭系统电源之前保存系统状态。因此,系统可以在重新打开时立即返
回到相同状态。
要关闭整个系统并返回到关闭前的状态,请执行以下步骤:
 停止内核线程和用户进程。以后再重新启动这些线程和进程。
 将系统中所有设备的硬件状态保存到磁盘。以后再恢复该状态。
仅适用于SPARC – 当前,仅Solaris 操作系统支持的某些SPARC系统实现了系统电源管理。有
关更多信息,请参见power.conf(4) 手册页。
Solaris 操作系统中的系统电源管理框架提供了下列系统电源管理功能:
 与平台无关的系统空闲模型。
 pmconfig(1M),一种用于配置工作站电源管理的工具。电源管理也可以通过
power.conf(4) 和/etc/default/power 文件来实现。
 一组接口,使设备驱动程序可以覆盖用于确定哪些驱动程序具有硬件状态的方法。
 一组允许框架对驱动程序进行调用以便保存和恢复设备状态的接口。
 用于通知进程已执行恢复操作的机制。
设备电源管理模型
以下各节详细介绍设备电源管理模型。该模型包括以下元素:
 组件
 空闲
 电源级别
 相关性
 策略
 设备电源管理接口
 电源管理入口点
电源管理组件
如果在设备处于空闲状态时可以减少设备能耗,则该设备是电源可管理设备。从概念上
讲,电源可管理设备由许多电源可管理硬件单元组成,这些硬件单元称为组件。
设备驱动程序通知系统有关设备组件及其相关电源级别的信息。因此,在驱动程序初始化
期间,驱动程序会在其attach(9E) 入口点中创建pm-components(9P) 属性。
设备电源管理模型
212 编写设备驱动程序• 2006 年11 月
大多数电源可管理设备仅实现单个组件。例如,磁盘就是一个电源可管理的单组件设备,
当磁盘处于空闲状态时,可以停止磁盘轴的转动以节省电能。
如果一个设备具有多个可单独控制的电源可管理单元,则该设备应实现多个组件。
例如,配有监视器的图形卡缓存卡就是一个电源可管理的双组件设备。图形卡缓存电子设
备是第一个组件[组件0]。未使用图形卡缓存电子设备时,其能耗将会降低。监视器是第二
个组件[组件1]。未使用监视器时,监视器也可以进入低能耗模式。系统将图形卡缓存电子
设备和监视器视为一个由两个组件组成的设备。
多个电源管理组件
对于电源管理框架而言,所有组件均“一视同仁”,并且组件之间完全无关。如果组件状
态不完全兼容,则设备驱动程序必须确保不会出现不需要的状态组合。例如,图形卡缓
存/监视器卡具有以下几种可能状态:D0、D1、D2 和D3。与卡连接的监视器具有以下几种可
能状态:On、Standby、Suspend 和Off。这些状态并不一定相互兼容。例如,如果监视器处
于On 状态,则图形卡缓存必须处于D0 状态(即完全打开)。如果在图形卡缓存处于D3 状
态时,其驱动程序收到一个请求,要求打开监视器电源使监视器处于On 状态,则在将监视
器设置为On 之前,驱动程序必须调用pm_raise_power(9F) 才能启动图形卡缓存。如果系统
在监视器处于On 状态时请求降低图形卡缓存的电能供给,则驱动程序必须拒绝该请求。
电源管理状态
每个设备组件都可处于以下两种状态之一:繁忙或空闲。设备驱动程序通过调用
pm_busy_component(9F) 和pm_idle_component(9F) 通知框架设备状态的更改。最初创建组件
时,组件被视为空闲状态。
电源级别
通过设备导出的pm-components 属性,设备电源管理框架可了解设备支持的电源级别。电源
级别值必须是正整数。对电源级别的解释由设备驱动程序编写者确定。在pm-components
属性中必须按单一递增顺序列出电源级别。该框架将0 电源级别解释为关闭。如果框架由
于相关性必须打开设备电源,则它会将每个组件都设置为其最高电源级别。
以下示例给出了某驱动程序的.conf 文件中的pm-components 项,该驱动程序实现了一个电
源管理组件(即磁盘主轴马达)。磁盘轴马达是组件0。该轴马达支持两个电源级别。这两
个级别表示“停止”和“全速旋转”。
示例12–1 pm-component 项样例
pm-components="NAME=Spindle Motor", "0=Stopped", "1=Full Speed";
以下示例说明如何在驱动程序的attach() 例程中实现示例12–1。
 
 

以上文章转自于 : http://developers.sun.com.cn/
阅读(463) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~