JavaScript is required to for searching.
跳过导航链接
退出打印视图
编写设备驱动程序     Oracle Solaris 10 1/13 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

第 1 部分针对 Oracle Solaris 平台设计设备驱动程序

1.  Oracle Solaris 设备驱动程序概述

2.  Oracle Solaris 内核和设备树

3.  多线程

4.  属性

5.  管理事件和排队任务

6.  驱动程序自动配置

7.  设备访问:程控 I/O

8.  中断处理程序

9.  直接内存访问 (Direct Memory Access, DMA)

10.  映射设备和内核内存

11.  设备上下文管理

12.  电源管理

电源管理框架

设备电源管理

系统电源管理

设备电源管理模型

电源管理组件

多个电源管理组件

电源管理状态

电源级别

电源管理相关性

设备的自动电源管理

设备电源管理接口

繁忙-空闲状态转换

设备能耗状态转换

power() 入口点

系统电源管理模型

自动关闭阈值

繁忙状态

硬件状态

系统的自动电源管理

系统电源管理使用的入口点

detach() 入口点

attach() 入口点

电源管理设备访问示例

电源管理控制流程

电源管理接口的更改

13.  强化 Oracle Solaris 驱动程序

14.  分层驱动程序接口 (Layered Driver Interface, LDI)

第 2 部分设计特定种类的设备驱动程序

15.  字符设备驱动程序

16.  块设备驱动程序

17.  SCSI 目标驱动程序

18.  SCSI 主机总线适配器驱动程序

19.  网络设备驱动程序

20.  USB 驱动程序

21.  SR-IOV 驱动程序

第 3 部分生成设备驱动程序

22.  编译、装入、打包和测试驱动程序

23.  调试、测试和调优设备驱动程序

24.  推荐的编码方法

第 4 部分附录

A.  硬件概述

B.  Solaris DDI/DKI 服务汇总

C.  使设备驱动程序支持 64 位

D.  控制台帧缓存器驱动程序

E.  pci.conf 文件

索引

系统电源管理模型

本节详细介绍系统电源管理模型。该模型包括以下组件:

自动关闭阈值

经过一段可配置空闲时间后,系统可以自动关闭(即关闭电源)。该时间段称为自动关闭阈值。缺省情况下,将对在 1995 年 10 月 1 日到 1999 年 7 月 1 日间首次发布的 SPARC 桌面系统启用此行为。有关更多信息,请参见 power.conf(4) 手册页。可以使用 dtpower(1M) 或 power.conf(4) 覆盖自动关闭。

繁忙状态

可以采用几种方法度量系统的繁忙状态。当前支持的内置度量标准项包括键盘字符、鼠标活动、tty 字符、平均负荷值、磁盘读取和 NFS 请求。其中任何一项都可使系统处于繁忙状态。除内置度量标准外,还定义了一个接口,用于运行用户指定的可以表明系统处于繁忙状态的进程。

硬件状态

导出 reg 属性的设备被视为具有硬件状态,关闭系统之前,必须保存该硬件状态。没有 reg 属性的设备被视为无状态设备。但是,设备驱动程序可以另外一种方式处理这种情况。

如果驱动程序导出值为 needs-suspend-resumepm-hardware-state 属性,则必须调用具有硬件状态但没有 reg 属性的设备(如 SCSI 驱动程序),才能保存并恢复状态。否则,缺少 reg 属性即表示设备没有硬件状态。有关设备属性的信息,请参见第 4 章

具有 reg 属性但没有硬件状态的设备可以导出值为 no-suspend-resumepm-hardware-state 属性。将 no-suspend-resumepm-hardware-state 属性配合使用,可防止框架调用驱动程序来保存并恢复该状态。有关电源管理属性的更多信息,请参见 pm-components(9P) 手册页。

系统的自动电源管理

如果符合以下条件,系统将会关闭:

系统电源管理使用的入口点

系统电源管理将命令DDI_SUSPEND 传递给 detach(9E) 驱动程序入口点,以请求驱动程序保存设备硬件状态。系统电源管理将命令 DDI_RESUME 传递给 attach(9E) 驱动程序入口点,以请求驱动程序恢复设备硬件状态。

detach() 入口点

detach(9E) 的语法如下所示:

int detach(dev_info_t *dip, ddi_detach_cmd_t cmd);

具有 reg 属性或 pm-hardware-state 属性设置为 needs-suspend-resume 的设备必须能够保存设备的硬件状态。框架调用驱动程序的 detach(9E) 入口点使驱动程序保存状态,以便在系统电源重新打开后进行恢复。要处理 DDI_SUSPEND 命令,detach(9E) 必须执行以下任务:

如果驱动程序无法暂停设备并将其状态保存到内存,则驱动程序必须返回 DDI_FAILURE。然后,框架将中止系统电源管理操作。

在某些情况下,关闭设备电源存在一定风险。例如,如果关闭内含磁带的磁带机电源,则该磁带可能会损坏。在这种情况下,attach(9E) 应执行以下操作:

如果上述两种操作的结果都是肯定的,则应拒绝 DDI_SUSPEND 请求。示例 12-6 给出了使用 ddi_removing_power(9F) 检查 DDI_SUSPEND 命令是否会产生问题的 attach(9E) 例程。

必须接受转储请求。框架使用 dump(9E) 入口点写出包含内存内容的状态文件。有关使用该入口点时对设备驱动程序强加的限制,请参见 dump(9E) 手册页。

使用 DDI_SUSPEND 命令调用电源可管理组件的 detach(9E) 入口点时,应保存关闭设备电源时的状态。驱动程序应取消待处理的超时。驱动程序还应禁止对 pm_raise_power(9F) 的任何调用,但 dump(9E) 请求除外。通过使用 DDI_RESUME 命令调用 attach(9E) 来恢复设备时,可以恢复超时以及对 pm_raise_power () 的调用。驱动程序必须掌握其足够的状态信息,才能够正确处理这种可能发生的情况。以下示例显示了实现 DDI_SUSPEND 命令的 detach(9E) 例程。

示例 12-6 实现 DDI_SUSPENDdetach(9E) 例程

int
xxdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
    struct xxstate *xsp;
    int instance;

    instance = ddi_get_instance(dip);
    xsp = ddi_get_soft_state(statep, instance);

    switch (cmd) {
    case DDI_DETACH:
       /* ... */
    case DDI_SUSPEND:
       /*
        * We do not allow DDI_SUSPEND if power will be removed and
        * we have a device that damages tape when power is removed
        * We do support DDI_SUSPEND for Device Reconfiguration.
        */
        if (ddi_removing_power(dip) && xxdamages_tape(dip))
            return (DDI_FAILURE);
        mutex_enter(&xsp->mu);
        xsp->xx_suspended = 1;  /* stop new operations */
       /*
        * Sleep waiting for all the commands to be completed
        *
        * If a callback is outstanding which cannot be cancelled
        * then either wait for the callback to complete or fail the
        * suspend request
        *
        * This section is only needed if the driver maintains a
        * running timeout
        */
        if (xsp->xx_timeout_id) {
            timeout_id_t temp_timeout_id = xsp->xx_timeout_id;

            xsp->xx_timeout_id = 0;
            mutex_exit(&xsp->mu);
            untimeout(temp_timeout_id);
            mutex_enter(&xsp->mu);
        }
        if (!xsp->xx_state_saved) {
           /*
            * Save device register contents into
            * xsp->xx_device_state
            */
        }
        mutex_exit(&xsp->mu);
        return (DDI_SUCCESS);
    default:
        return (DDI_FAILURE);
}

attach() 入口点

attach(9E) 的语法如下所示:

int attach(dev_info_t *dip, ddi_attach_cmd_t cmd);

恢复系统电源后,每个具有 reg 属性或具有值为 needs-suspend-resumepm-hardware-state 属性的设备都会使用 DDI_RESUME 命令值调用其 attach(9E) 入口点。如果系统关闭被中止,则即使尚未关闭电源,也会调用每个暂停的驱动程序以进行恢复。因此,attach(9E) 中的恢复代码不能对系统是否已实际断电作出任何假设。

电源管理框架认为组件的电源级别在执行 DDI_RESUME 时未知。根据设备性质,驱动程序编写者有两种选择:

以下示例显示了使用 DDI_RESUME 命令的 attach(9E) 例程。

示例 12-7 实现 DDI_RESUMEattach(9E) 例程

int
xxattach(devinfo_t *dip, ddi_attach_cmd_t cmd)
{
    struct xxstate *xsp;
    int    instance;

    instance = ddi_get_instance(dip);
    xsp = ddi_get_soft_state(statep, instance);

    switch (cmd) {
    case DDI_ATTACH:
    /* ... */
    case DDI_RESUME:
        mutex_enter(&xsp->mu);
        if (xsp->xx_pm_state_saved) {
            /*
             * Restore device register contents from
             * xsp->xx_device_state
             */
        }
       /*
        * This section is optional and only needed if the
        * driver maintains a running timeout
        */
        xsp->xx_timeout_id = timeout( /* ... */ );

        xsp->xx_suspended = 0;        /* allow new operations */
        cv_broadcast(&xsp->xx_suspend_cv);
       /* If it is possible to determine in a device-specific 
        * way what the power levels of components are without 
        * powering the components up,
        * then the following code is recommended
        */
        for (i = 0; i < num_components; i++) {
            xsp->xx_power_level[i] = xx_get_power_level(dip, i);
            if (xsp->xx_power_level[i] != XX_LEVEL_UNKNOWN)
                (void) pm_power_has_changed(dip, i, 
                    xsp->xx_power_level[i]);
        }
        mutex_exit(&xsp->mu);
        return(DDI_SUCCESS);
    default:
        return(DDI_FAILURE);
    }
}

注 - detach(9E)attach(9E) 接口也可用于恢复被停止的系统。