In the SunOS 4.1 system, to do a DMA transfer the driver mapped a buffer into the DMA space, retrieved the DMA address and programed the device, did the transfer, and freed the mapping. This was accomplished in this sequence:
mb_mapalloc()( ) - Map buffer into DMA space
MBI_ADDR()( ) - Retrieve address from returned cookie
Program the device and start the DMA
mb_mapfree()( ) - Free mapping when DMA is complete
The first three usually occurred in a start()( ) routine, and the last in the interrupt routine.
The SunOS 5.7 DMA model is similar, but it has been extended. The goal of the new DMA model is to abstract the platform-dependent details of DMA away from the driver. A sliding DMA window has been added for drivers that need to do DMA to large objects, and the DMA routines can be informed of device limitations (such as 24-bit addressing).
The sequence for DMA is as follows: The driver allocates a DMA handle using ddi_dma_alloc_handle(9F). The DMA handle can be reused for subsequent DMA transfers. Then the driver commits DMA resources using either ddi_dma_buf_bind_handle(9F) or ddi_dma_addr_bind_handle(9F), retrieves the DMA address from the DMA cookie to do the DMA, and frees the mapping with ddi_dma_unbind_handle(9F). The new sequence is something like this:
ddi_dma_alloc_handle(9F) - Allocate a DMA handle
ddi_dma_buf_bind_handle(9F) - Allocate DMA resources and retrieve address from the returned cookie
Program the device and start the DMA
Perform the transfer.
If the transfer involves several windows, you can call ddi_dma_getwin(9F) to move to subsequent windows.
ddi_dma_unbind_handle(9F) - Free mapping when DMA is complete
ddi_dma_free_handle(9F) - Free DMA handle when no longer needed
Additional routines have been added to synchronize any underlying caches and buffers, and handle IOPB memory. See Chapter 7, DMA, for details.
In addition, in the SunOS 4.1 system, the driver had to inform the system that it might do DMA, either through the mb_driver structure or with a call to adddma()( ). This was needed because the kernel might need to block interrupts to prevent DMA, but needed to know the highest interrupt level to block. Because the new implementation uses mutexes, this is no longer needed.