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.  电源管理

13.  强化 Oracle Solaris 驱动程序

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

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

15.  字符设备驱动程序

16.  块设备驱动程序

块驱动程序结构概述

文件 I/O

块设备自动配置

控制设备访问

open() 入口点(块驱动程序)

close() 入口点(块驱动程序)

strategy() 入口点

buf 结构

bp_mapin 结构

同步数据传输(块驱动程序)

异步数据传输(块驱动程序)

检查是否有无效的 buf 请求

对请求进行排队

开始第一个传输

处理中断的设备

dump() 和 print() 入口点

dump() 入口点(块驱动程序)

print() 入口点(块驱动程序)

磁盘设备驱动程序

磁盘 ioctl

磁盘性能

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 文件

索引

块设备自动配置

attach(9E) 会为每个设备实例执行常见初始化任务:

块设备驱动程序创建类型为 S_IFBLK 的次要节点。因此,代表节点的块特殊文件会出现在 /devices 分层结构中。

块设备的逻辑设备名称位于 /dev/dsk 目录中,该名称由控制器编号、总线地址编号、磁盘编号和分片编号组成。如果节点类型设置为 DDI_NT_BLOCK 或 DDI_NT_BLOCK_CHAN,则这些名称由 devfsadm(1M) 程序创建。如果设备通过通道(即有附加寻址能力级别的总线)进行通信,则应该指定 DDI_NT_BLOCK_CHAN。SCSI 磁盘就是一个典型示例。DDI_NT_BLOCK_CHAN 可使总线地址字段 (tN) 出现在逻辑名称中。其他大多数设备则应该使用 DDI_NT_BLOCK。

次要设备指磁盘上的分区。对于每个次要设备,驱动程序必须创建 nblocks 或 Nblocks 属性。此整数属性给出了次要设备所支持的块数,以 DEV_BSIZE(即 512 字节)为单位。文件系统使用 nblocks 和 Nblocks 属性来确定设备限制。Nblocks 是 64 位版本的 nblocks。应该将 Nblocks 用于每个磁盘的存储容量超过 1 TB 的存储设备。有关更多信息,请参见设备属性。

示例 16-1 说明了一个典型的 attach(9E) 入口点,重点说明如何创建设备的次要节点和 Nblocks 属性。请注意,由于此示例使用 Nblocks 而非 nblocks,因此将调用 ddi_prop_update_int64(9F) 而非 ddi_prop_update_int(9F)。

作为附带说明,本示例还说明了如何使用 makedevice(9F) 为 ddi_prop_update_int64() 创建设备编号。makedevice 函数利用 ddi_driver_major(9F),后者基于指向 dev_info_t 结构的指针生成主设备号。使用 ddi_driver_major() 与使用 getmajor(9F) 类似,后者用于获取 dev_t 结构指针。

示例 16-1 块驱动程序 attach() 例程

static int
xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
     int instance = ddi_get_instance(dip);
     switch (cmd) {
       case DDI_ATTACH:
       /*
        * allocate a state structure and initialize it
        * map the devices registers
        * add the device driver's interrupt handler(s)
        * initialize any mutexes and condition variables
        * read label information if the device is a disk
        * create power manageable components
        *
        * Create the device minor node. Note that the node_type
        * argument is set to DDI_NT_BLOCK.
        */
       if (ddi_create_minor_node(dip, "minor_name", S_IFBLK,
          instance, DDI_NT_BLOCK, 0) == DDI_FAILURE) {
          /* free resources allocated so far */
          /* Remove any previously allocated minor nodes */
          ddi_remove_minor_node(dip, NULL);
          return (DDI_FAILURE);
        }
       /*
        * Create driver properties like "Nblocks". If the device
        * is a disk, the Nblocks property is usually calculated from
        * information in the disk label.  Use "Nblocks" instead of
        * "nblocks" to ensure the property works for large disks.
        */
       xsp->Nblocks = size;
       /* size is the size of the device in 512 byte blocks */
       maj_number = ddi_driver_major(dip);
       if (ddi_prop_update_int64(makedevice(maj_number, instance), dip, 
          "Nblocks", xsp->Nblocks) != DDI_PROP_SUCCESS) {
          cmn_err(CE_CONT, "%s: cannot create Nblocks property\n",
               ddi_get_name(dip));
         /* free resources allocated so far */
         return (DDI_FAILURE);
       }
       xsp->open = 0;
       xsp->nlayered = 0;
       /* ... */
       return (DDI_SUCCESS);

    case DDI_RESUME:
       /* For information, see Chapter 12, "Power Management," in this book. */
       default:
          return (DDI_FAILURE);
     }
}