DMA コールバックを取り消すことはできません。DMA コールバックを取り消すには、ドライバの detach (9E) エントリポイントにコードを追加する必要があります。未処理のコールバックが存在する場合は、detach() ルーチンが DDI_SUCCESS を返すことはありません。Example 9–6を参照してください。DMA コールバックが発生すると、detach() ルーチンはコールバックが実行されるのを待つ必要があります。コールバックが完了したら、detach() はコールバックが再スケジュールを行わないようにする必要があります。次の例に示すように、状態構造体で追加のフィールドを指定することによって、コールバックが再スケジュールを行わないようにすることができます。
使用例 9-6 DMA コールバックの取り消しstatic int xxdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) { /* ... */ mutex_enter(&xsp->callback_mutex); xsp->cancel_callbacks = 1; while (xsp->callback_count > 0) { cv_wait(&xsp->callback_cv, &xsp->callback_mutex); } mutex_exit(&xsp->callback_mutex); /* ... */ } static int xxstrategy(struct buf *bp) { /* ... */ mutex_enter(&xsp->callback_mutex); xsp->bp = bp; error = ddi_dma_buf_bind_handle(xsp->handle, xsp->bp, flags, xxdmacallback, (caddr_t)xsp, &cookie, &ccount); if (error == DDI_DMA_NORESOURCES) xsp->callback_count++; mutex_exit(&xsp->callback_mutex); /* ... */ } static int xxdmacallback(caddr_t callbackarg) { struct xxstate *xsp = (struct xxstate *)callbackarg; /* ... */ mutex_enter(&xsp->callback_mutex); if (xsp->cancel_callbacks) { /* do not reschedule, in process of detaching */ xsp->callback_count--; if (xsp->callback_count == 0) cv_signal(&xsp->callback_cv); mutex_exit(&xsp->callback_mutex); return (DDI_DMA_CALLBACK_DONE); /* don't reschedule it */ } /* * Presumably at this point the device is still active * and will not be detached until the DMA has completed. * A return of 0 means try again later */ error = ddi_dma_buf_bind_handle(xsp->handle, xsp->bp, flags, DDI_DMA_DONTWAIT, NULL, &cookie, &ccount); if (error == DDI_DMA_MAPPED) { /* Program the DMA engine. */ xsp->callback_count--; mutex_exit(&xsp->callback_mutex); return (DDI_DMA_CALLBACK_DONE); } if (error != DDI_DMA_NORESOURCES) { xsp->callback_count--; mutex_exit(&xsp->callback_mutex); return (DDI_DMA_CALLBACK_DONE); } mutex_exit(&xsp->callback_mutex); return (DDI_DMA_CALLBACK_RUNOUT); }