Writing Device Drivers

Freeing the DMA Resources

After a DMA transfer is completed (usually in the interrupt routine), the driver can release DMA resources by calling ddi_dma_unbind_handle(9F).

As described in Synchronizing Memory Objects, ddi_dma_unbind_handle(9F) calls ddi_dma_sync(9F), eliminating the need for any explicit synchronization. After calling ddi_dma_unbind_handle(9F), the DMA resources become invalid, and further references to them have undefined results. Example 8–5 shows how to use ddi_dma_unbind_handle(9F).


Example 8–5 Freeing DMA Resources

static uint_t
xxintr(caddr_t arg)
{
     struct xxstate *xsp = (struct xxstate *)arg;
     uint8_t    status;
        volatile   uint8_t   temp;
     mutex_enter(&xsp->mu);
     /* read status */
     status = ddi_get8(xsp->access_hdl, &xsp->regp->csr);
     if (!(status & INTERRUPTING)) {
            mutex_exit(&xsp->mu);
            return (DDI_INTR_UNCLAIMED);
     }
     ddi_put8(xsp->access_hdl, &xsp->regp->csr, CLEAR_INTERRUPT);
      /* for store buffers */
     temp = ddi_get8(xsp->access_hdl, &xsp->regp->csr);
     ddi_dma_unbind_handle(xsp->handle);
     ...
         /* check for errors */
     ...
     xsp->busy = 0;
     mutex_exit(&xsp->mu);
     if (pending transfers) {
            (void) xxstart((caddr_t)xsp);
     }
     return (DDI_INTR_CLAIMED);
}

The DMA resources should be released and reallocated if a different object will be used in the next transfer. However, if the same object is always used, the resources can be allocated once and continually reused as long as there are intervening calls to ddi_dma_sync(9F).