编写设备驱动程序

DMA 传输(同步)

字符驱动程序通常在 read(9E)write(9E) 中使用 physio(9F) 来设置 DMA 传输,如示例 15–5 中所示。

int physio(int (*strat)(struct buf *), struct buf *bp,
     dev_t dev, int rw, void (*mincnt)(struct buf *),
     struct uio *uio);

physio(9F) 要求驱动程序提供 strategy(9E) 例程的地址。physio(9F) 可确保内存空间处于锁定状态,即在数据传输期间内存不能页出。由于 DMA 传输不能处理缺页,因此这种锁定对 DMA 传输来说是十分必要的。physio(9F) 还提供了一种将较大的传输分解为一系列更小的、更易于管理的传输的自动方法。有关更多信息,请参见minphys() 入口点


示例 15–5 使用 physio(9F) 的 read(9E) 和 write(9E) 例程

static int
xxread(dev_t dev, struct uio *uiop, cred_t *credp)
{
     struct xxstate *xsp;
     int ret;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
        return (ENXIO);
     ret = physio(xxstrategy, NULL, dev, B_READ, xxminphys, uiop);
     return (ret);
}    

static int
xxwrite(dev_t dev, struct uio *uiop, cred_t *credp)
{     
     struct xxstate *xsp;
     int ret;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
        return (ENXIO);
     ret = physio(xxstrategy, NULL, dev, B_WRITE, xxminphys, uiop);
     return (ret);
}

在对 physio(9F) 的调用中,xxstrategy 是指向驱动程序 strategy() 例程的指针。如果将 NULL 作为 buf(9S) 结构指针传递,则指示 physio(9F) 分配 buf(9S) 结构。如果驱动程序必须向 physio(9F) 提供 buf(9S) 结构,应使用 getrbuf(9F) 来分配该结构。如果传输成功完成,physio(9F) 返回零;如果传输失败,则返回错误号。调用 strategy(9E) 后,physio(9F) 会调用 biowait(9F) 以进入阻塞状态,直到传输完成或失败。physio(9F) 的返回值由 buf(9S) 结构中 bioerror(9F) 设置的错误字段确定。