编写适用于 Oracle® Solaris 11.2 的设备驱动程序

退出打印视图

更新时间: 2014 年 9 月
 
 

对 DMA 引擎进行编程

如果资源已成功分配,则必须对设备进行编程。尽管对 DMA 引擎进行编程是特定于设备的,但所有 DMA 引擎都需要一个起始地址和一个传送计数。设备驱动程序将从 ddi_dma_addr_bind_handle(9F)ddi_dma_buf_bind_handle(9F)ddi_dma_getwin(9F) 的成功调用所返回的 DMA cookie 中检索这两个值。这些函数都会返回第一个 DMA cookie 以及指示 DMA 对象是否包含多个 cookie 的 cookie 计数。如果 cookie 计数 N 大于 1,则必须对 ddi_dma_nextcookie(9F) 调用 N-1 次,以检索其余所有 cookie。

DMA cookie 的类型为 ddi_dma_cookie(9S)。这一类型的 cookie 包含以下字段:

uint64_t    _dmac_ll;       /* 64-bit DMA address */
uint32_t    _dmac_la[2];    /* 2 x 32-bit address */
size_t      dmac_size;      /* DMA cookie size */
uint_t      dmac_type;      /* bus specific type bits */

dmac_laddress 指定适用于对设备的 DMA 引擎进行编程的 64 位 I/O 地址。如果设备具有 64 位 DMA 地址寄存器,则驱动程序应使用此字段对 DMA 引擎进行编程。dmac_address 字段指定应该用于具有 32 位 DMA 地址寄存器的设备的 32 位 I/O 地址。dmac_size 字段包含传送计数。根据总线体系结构,驱动程序可能需要 cookie 中的 dmac_type 字段。驱动程序不应对 cookie 执行任何处理,如逻辑或算术处理。

示例 9-4  ddi_dma_cookie(9S) 示例
ddi_dma_cookie_t            cookie;

     if (ddi_dma_buf_bind_handle(xsp->handle,xsp->bp, flags, xxstart,
     (caddr_t)xsp, &cookie, &xsp->ccount) != DDI_DMA_MAPPED) {
         /* error handling */
      }
     sglp = regp->sglist;
     for (cnt = 1; cnt <= SGLLEN; cnt++, sglp++) {
     /* store the cookie parms into the S/G list */
     ddi_put32(xsp->access_hdl, &sglp->dma_size,
         (uint32_t)cookie.dmac_size);
     ddi_put32(xsp->access_hdl, &sglp->dma_addr,
         cookie.dmac_address);
     /* Check for end of cookie list */
     if (cnt == xsp->ccount)
         break;
     /* Get next DMA cookie */
     (void) ddi_dma_nextcookie(xsp->handle, &cookie);
     }
     /* start DMA transfer */
     ddi_put8(xsp->access_hdl, &regp->csr,
     ENABLE_INTERRUPTS | START_TRANSFER);