编写设备驱动程序

DMA 传输(异步)

支持 aread(9E)awrite(9E) 的字符驱动程序使用 aphysio(9F),而非 physio(9F)

int aphysio(int (*strat)(struct buf *), int (*cancel)(struct buf *),
     dev_t dev, int rw, void (*mincnt)(struct buf *),
     struct aio_req *aio_reqp);

注 –

anocancel(9F) 的地址是唯一一个当前可作为第二个参数传递到 aphysio(9F) 的值。


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

示例 15–5示例 15–6 说明了 aread(9E)awrite(9E) 入口点与 read(9E)write(9E) 入口点之间的轻微差异。这种差异主要在于,前两者使用 aphysio(9F),而非 physio(9F)


示例 15–6 使用 aphysio(9F) 的 aread(9E) 和 awrite(9E) 例程

static int
xxaread(dev_t dev, struct aio_req *aiop, cred_t *cred_p)
{
     struct xxstate *xsp;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
         return (ENXIO);
     return (aphysio(xxstrategy, anocancel, dev, B_READ,
     xxminphys, aiop));
}

static int
xxawrite(dev_t dev, struct aio_req *aiop, cred_t *cred_p)
{
     struct xxstate *xsp;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
        return (ENXIO);
     return (aphysio(xxstrategy, anocancel, dev, B_WRITE,
     xxminphys,aiop));  
}

在对 aphysio(9F) 的调用中,xxstrategy() 是指向驱动程序策略例程的指针。aiop 是指向 aio_req(9S) 结构的指针。aiop 将被传递到 aread(9E)awrite(9E)aio_req(9S) 描述了数据在用户空间中的存储位置。如果成功调度了 I/O 请求,aphysio(9F) 返回零;如果调度失败,则返回错误号。调用 strategy(9E) 后,aphysio(9F) 会返回而不等待 I/O 完成或失败。