Oracle® Solaris 11.2 デバイスドライバの記述

印刷ビューの終了

更新: 2014 年 9 月
 
 

DMA コールバックの取り消し

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);
}