编写设备驱动程序

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 */
};