在示例 9–1 中,xxstart() 用作回调函数。特定设备状态结构用作 xxstart() 的参数。xxstart() 函数将尝试启动命令。如果由于资源不可用而无法启动该命令,则会安排以后在资源可用时调用 xxstart()。
由于 xxstart() 用作 DMA 回调,因此 xxstart() 必须遵守以下规则,DMA 回调中将强制执行这些规则:
不能假定资源可用。回调必须尝试再次分配资源。
回调必须向系统指明分配是否成功。如果回调未能分配资源,则应返回 DDI_DMA_CALLBACK_RUNOUT,在此情况下需要以后再次调用 xxstart()。DDI_DMA_CALLBACK_DONE 表示回调成功,因此不需要再进行回调。
static int xxstart(caddr_t arg) { struct xxstate *xsp = (struct xxstate *)arg; struct device_reg *regp; int flags; mutex_enter(&xsp->mu); if (xsp->busy) { /* transfer in progress */ mutex_exit(&xsp->mu); return (DDI_DMA_CALLBACK_RUNOUT); } xsp->busy = 1; regp = xsp->regp; if ( /* transfer is a read */ ) { flags = DDI_DMA_READ; } else { flags = DDI_DMA_WRITE; } mutex_exit(&xsp->mu); if (ddi_dma_buf_bind_handle(xsp->handle,xsp->bp,flags, xxstart, (caddr_t)xsp, &cookie, &ccount) != DDI_DMA_MAPPED) { /* really should check all return values in a switch */ mutex_enter(&xsp->mu); xsp->busy=0; mutex_exit(&xsp->mu); return (DDI_DMA_CALLBACK_RUNOUT); } /* Program the DMA engine. */ return (DDI_DMA_CALLBACK_DONE); }