JavaScript is required to for searching.
跳过导航链接
退出打印视图
编写设备驱动程序     Oracle Solaris 11.1 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)

DMA 模型

设备 DMA 的类型

总线主控器 DMA

第三方 DMA

第一方 DMA

主机平台 DMA 的类型

DMA 软件组件:句柄、窗口和 Cookie

DMA 操作

执行总线主控器 DMA 传送

执行第一方 DMA 传送

执行第三方 DMA 传送

DMA 特性

ddi_dma_attr 结构

S 总线示例

ISA 总线示例

管理 DMA 资源

对象锁定

分配 DMA 句柄

分配 DMA 资源

设备寄存器结构

DMA 回调示例

确定最大突发流量大小

分配专用 DMA 缓冲区

处理资源分配故障

对 DMA 引擎进行编程

释放 DMA 资源

释放 DMA 句柄

取消 DMA 回调

同步内存对象

高速缓存

ddi_dma_sync() 函数

DMA 窗口

10.  映射设备和内核内存

11.  设备上下文管理

12.  电源管理

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.  Oracle Solaris DDI/DKI 服务汇总

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

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

E.  pci.conf 文件

索引

请告诉我们如何提高我们的文档:
过于简略
不易阅读或难以理解
重要信息缺失
错误的内容
需要翻译的版本
其他
Your rating has been updated
感谢您的反馈!

您的反馈将非常有助于我们提供更好的文档。 您是否愿意参与我们的内容改进并提供进一步的意见?

DMA 操作

不同类型的 DMA 之间,DMA 传送的步骤都相似。以下各节提供了执行 DMA 传送的方法。


注 - 在来自文件系统的缓冲区的块驱动程序中,不必确保 DMA 对象是否已在内存中锁定。该文件系统已在内存中锁定了数据。


执行总线主控器 DMA 传送

对于总线主控器 DMA,驱动程序应执行以下步骤:

  1. 描述 DMA 特性。通过此步骤,例程可确保设备能够访问缓冲区。

  2. 分配 DMA 句柄。

  3. 确保 DMA 对象已在内存中锁定。请参见 physio(9F)ddi_umem_lock(9F) 手册页。

  4. 为该对象分配 DMA 资源。

  5. 对设备的 DMA 引擎进行编程。

  6. 启动引擎。

  7. 传送完成后,继续执行总线主控器操作。

  8. 执行所需的对象同步。

  9. 释放 DMA 资源。

  10. 释放 DMA 句柄。

执行第一方 DMA 传送

对于第一方 DMA,驱动程序应执行以下步骤:

  1. 分配 DMA 通道。

  2. 使用 ddi_dmae_1stparty(9F) 配置通道。

  3. 确保 DMA 对象已在内存中锁定。请参见 physio(9F)ddi_umem_lock(9F) 手册页。

  4. 为该对象分配 DMA 资源。

  5. 对设备的 DMA 引擎进行编程。

  6. 启动引擎。

  7. 传送完成后,继续执行总线主控器操作。

  8. 执行所需的对象同步。

  9. 释放 DMA 资源。

  10. 取消分配 DMA 通道。

执行第三方 DMA 传送

对于第三方 DMA,驱动程序应执行以下步骤:

  1. 分配 DMA 通道。

  2. 使用 ddi_dmae_getattr(9F) 检索系统的 DMA 引擎特性。

  3. 在内存中锁定 DMA 对象。请参见 physio(9F)ddi_umem_lock(9F) 手册页。

  4. 为该对象分配 DMA 资源。

  5. 使用 ddi_dmae_prog(9F) 对系统 DMA 引擎进行编程,以执行传送。

  6. 执行所需的对象同步。

  7. 使用 ddi_dmae_stop(9F) 停止 DMA 引擎。

  8. 释放 DMA 资源。

  9. 取消分配 DMA 通道。

某些硬件平台会以特定于总线的方式限制 DMA 功能。驱动程序应使用 ddi_slaveonly(9F) 来确定设备是否位于可以执行 DMA 的插槽中。

DMA 特性

DMA 特性描述 DMA 引擎的特性和限制,其中包括:

设备驱动程序必须通过 ddi_dma_attr(9S) 结构向系统通知任何 DMA 引擎限制。此操作可以确保设备的 DMA 引擎可以访问系统分配的 DMA 资源。系统可能对设备特性实施附加限制,但绝不会取消驱动程序实施的任何限制。

ddi_dma_attr 结构

DMA 特性结构包含以下成员:

typedef struct ddi_dma_attr {
    uint_t      dma_attr_version;       /* version number */
    uint64_t    dma_attr_addr_lo;       /* low DMA address range */
    uint64_t    dma_attr_addr_hi;       /* high DMA address range */
    uint64_t    dma_attr_count_max;     /* DMA counter register */
    uint64_t    dma_attr_align;         /* DMA address alignment */
    uint_t      dma_attr_burstsizes;    /* DMA burstsizes */
    uint32_t    dma_attr_minxfer;       /* min effective DMA size */
    uint64_t    dma_attr_maxxfer;       /* max DMA xfer size */
    uint64_t    dma_attr_seg;           /* segment boundary */
    int         dma_attr_sgllen;        /* s/g length */
    uint32_t    dma_attr_granular;      /* granularity of device */
    uint_t      dma_attr_flags;         /* Bus specific DMA flags */
} ddi_dma_attr_t;

其中:

dma_attr_version

特性结构的版本号。dma_attr_version 应设置为 DMA_ATTR_V0。

dma_attr_addr_lo

DMA 引擎可以访问的最低总线地址。

dma_attr_addr_hi

DMA 引擎可以访问的最高总线地址。

dma_attr_count_max

指定 DMA 引擎可在一个 cookie 中处理的最大传送计数。该限制表示为最大计数减 1。此计数用作位掩码,因此计数也必须比 2 的幂小 1。

dma_attr_align

指定通过 ddi_dma_mem_alloc(9F) 分配内存时的对齐要求。例如,以页边界对齐。dma_attr_align 字段仅在分配内存时使用。在绑定操作过程中,将省略此字段。对于绑定操作,驱动程序必须确保缓冲区已正确对齐。

dma_attr_burstsizes

指定设备支持的突发流量大小。突发流量大小是指设备在放弃总线之前可以传输的数据量。此成员是突发流量大小的二进制编码,这些大小是 2 的幂次方。例如,如果设备能够执行 1 字节、2 字节、4 字节和 16 字节突发传输,则应将此字段设置为 0x17。系统还会使用此字段来确定对齐限制。

dma_attr_minxfer

设备可以执行的最小有效传送大小。此大小还会影响对齐和填充的限制。

dma_attr_maxxfer

描述 DMA 引擎在一个 I/O 命令中可以容纳的最大字节数。此限制仅在 dma_attr_maxxfer 小于 (dma_attr_count_max + 1) * dma_attr_sgllen 时才有意义。

dma_attr_seg

DMA 引擎的地址寄存器的上限。当地址寄存器的高 8 位为包含段号的锁存器时,通常会使用 dma_attr_seg 。低 24 位用于寻址段。在此情况下,dma_attr_seg 会设置为 0xFFFFFF,这可以防止系统在为对象分配资源时跨越 24 位段边界。

dma_attr_sgllen

指定分散/集中列表中的最大项数。dma_attr_sgllen 是 DMA 引擎在对设备的一个 I/O 请求中可以使用的 cookie 数。如果 DMA 引擎不包含任何分散/集中列表,则此字段应设置为 1。

dma_attr_granular

此字段用于提供设备 DMA 传送能力的粒度(以字节为单位)。指定海量存储设备的扇区大小即是关于如何使用该值的一个例子。如果绑定操作需要部分映射,则可使用此字段确保 DMA 窗口中的 cookie 大小之和为粒度的整数倍。但是,如果设备没有分散/集中功能,则 DDI 无法确保粒度。对于此情况,dma_attr_granular 字段的值应为 1。

dma_attr_flags

此字段可以设置为 DDI_DMA_FORCE_PHYSICAL,这表示如果系统同时支持物理 I/O 地址和虚拟 I/O 地址,则系统应返回物理 I/O 地址而非虚拟 I/O 地址。如果系统不支持物理 DMA,则 ddi_dma_alloc_handle(9F) 的返回值为 DDI_DMA_BADATTR。在此情况下,驱动程序必须清除 DDI_DMA_FORCE_PHYSICAL 并重试该操作。

S 总线示例

在 SPARC 计算机中,S 总线上的 DMA 引擎具有以下特性:

在 SPARC 计算机中,S 总线上的 DMA 引擎具有以下特性结构:

static ddi_dma_attr_t attributes = {
    DMA_ATTR_V0,   /* Version number */
    0xFF000000,    /* low address */
    0xFFFFFFFF,    /* high address */
    0xFFFFFFFF,    /* counter register max */
    1,             /* byte alignment */
    0x7,           /* burst sizes: 0x1 | 0x2 | 0x4 */
    0x1,           /* minimum transfer size */
    0xFFFFFFFF,    /* max transfer size */
    0xFFFFFFFF,    /* address register max */
    1,             /* no scatter-gather */
    512,           /* device operates on sectors */
    0,             /* attr flag: set to 0 */
};

ISA 总线示例

在 x86 计算机中,ISA 总线上的 DMA 引擎具有以下特性:

在 x86 计算机中,ISA 总线上的 DMA 引擎具有以下特性结构:

static ddi_dma_attr_t attributes = {
    DMA_ATTR_V0,   /* Version number */
    0x00000000,    /* low address */
    0x00FFFFFF,    /* high address */
    0xFFFF,        /* counter register max */
    1,             /* byte alignment */
    0x7,           /* burst sizes */
    0x1,           /* minimum transfer size */
    0xFFFFFFFF,    /* max transfer size */
    0x000FFFFF,    /* address register max */
    17,            /* scatter-gather */
    512,           /* device operates on sectors */
    0,             /* attr flag: set to 0 */
};