Writing Device Drivers

ddi_dma_sync() Function

A memory object might have multiple mappings, such as for the CPU and for a device, by means of a DMA handle. A driver with multiple mappings needs to call ddi_dma_sync(9F) if any mappings are used to modify the memory object. Calling ddi_dma_sync() ensures that the modification of the memory object is complete before the object is accessed through a different mapping. The ddi_dma_sync() function can also inform other mappings of the object if any cached references to the object are now stale. Additionally, ddi_dma_sync() flushes or invalidates stale cache references as necessary.

Generally, the driver must call ddi_dma_sync() when a DMA transfer completes. The exception to this rule is if deallocating the DMA resources with ddi_dma_unbind_handle(9F) does an implicit ddi_dma_sync() on behalf of the driver. The syntax for ddi_dma_sync() is as follows:

int ddi_dma_sync(ddi_dma_handle_t handle, off_t off,
size_t length, uint_t type);

If the object is going to be read by the DMA engine of the device, the device's view of the object must be synchronized by setting type to DDI_DMA_SYNC_FORDEV. If the DMA engine of the device has written to the memory object and the object is going to be read by the CPU, the CPU's view of the object must be synchronized by setting type to DDI_DMA_SYNC_FORCPU.

The following example demonstrates synchronizing a DMA object for the CPU:

if (ddi_dma_sync(xsp->handle, 0, length, DDI_DMA_SYNC_FORCPU)
    == DDI_SUCCESS) {
    /* the CPU can now access the transferred data */
    /* ... */
} else {
    /* error handling */
}

Use the flag DDI_DMA_SYNC_FORKERNEL if the only mapping is for the kernel, as in the case of memory that is allocated by ddi_dma_mem_alloc(9F). The system tries to synchronize the kernel's view more quickly than the CPU's view. If the system cannot synchronize the kernel view faster, the system acts as if the DDI_DMA_SYNC_FORCPU flag were set.