strategy(9E) 例程源于块驱动程序。策略函数因实现用于对块设备的 I/O 请求的有效排队的策略而得名。面向字符设备的驱动程序也可以使用 strategy(9E) 例程。在这里提供的字符 I/O 模型中,strategy(9E) 并不维护请求队列,只是一次为一个请求提供服务。
在以下示例中,用于面向字符的 DMA 设备的 strategy(9E) 例程为同步数据传输分配 DMA 资源。strategy() 通过对设备寄存器进行编程来启动此命令。有关详细说明,请参见第 9 章。
strategy(9E) 不会以参数形式接收设备编号 (dev_t)。设备编号是从传递给 strategy(9E) 的 buf(9S) 结构中的 b_edev 字段检索到的。
static int xxstrategy(struct buf *bp) { minor_t instance; struct xxstate *xsp; ddi_dma_cookie_t cookie; instance = getminor(bp->b_edev); xsp = ddi_get_soft_state(statep, instance); /* ... */ * If the device has power manageable components, * mark the device busy with pm_busy_components(9F), * and then ensure that the device is * powered up by calling pm_raise_power(9F). */ /* Set up DMA resources with ddi_dma_alloc_handle(9F) and * ddi_dma_buf_bind_handle(9F). */ xsp->bp = bp; /* remember bp */ /* Program DMA engine and start command */ return (0); }
虽然声明了 strategy() 返回 int,但 strategy() 必须总是返回零。
在完成 DMA 传输时,设备会产生中断,从而导致对中断例程的调用。在以下示例中,xxintr() 接收指向可能产生中断的设备的状态结构的指针。
static u_int xxintr(caddr_t arg) { struct xxstate *xsp = (struct xxstate *)arg; if ( /* device did not interrupt */ ) { return (DDI_INTR_UNCLAIMED); } if ( /* error */ ) { /* error handling */ } /* Release any resources used in the transfer, such as DMA resources. * ddi_dma_unbind_handle(9F) and ddi_dma_free_handle(9F) * Notify threads that the transfer is complete. */ biodone(xsp->bp); return (DDI_INTR_CLAIMED); }
驱动程序通过调用 bioerror(9F) 来指示错误。当传输完成或者使用 biodone(9F) 指示错误后,驱动程序必须调用 bioerror(9F)。