DDI_DMAE(9F) | Kernel Functions for Drivers | DDI_DMAE(9F) |
ddi_dmae, ddi_dmae_alloc, ddi_dmae_release, ddi_dmae_prog, ddi_dmae_disable, ddi_dmae_enable, ddi_dmae_stop, ddi_dmae_getcnt, ddi_dmae_1stparty, ddi_dmae_getattr - system DMA engine functions
int ddi_dmae_alloc(dev_info_t *dip, int chnl, int (*callback) (caddr_t),
caddr_t arg);
int ddi_dmae_release(dev_info_t *dip, int chnl);
int ddi_dmae_prog(dev_info_t *dip, struct ddi_dmae_req *dmaereqp,
ddi_dma_cookie_t *cookiep, int chnl);
int ddi_dmae_disable(dev_info_t *dip, int chnl);
int ddi_dmae_enable(dev_info_t *dip, int chnl);
int ddi_dmae_stop(dev_info_t *dip, int chnl);
int ddi_dmae_getcnt(dev_info_t *dip, int chnl, int *countp);
int ddi_dmae_1stparty(dev_info_t *dip, int chnl);
int ddi_dmae_getattr(dev_info_t *dip, ddi_dma_attr_t *attrp);
illumos DDI specific (illumos DDI).
dip
chnl
callback
DDI_DMA_SLEEP
DDI_DMA_DONTWAIT
arg
dmaereqp
cookiep
countp
attrp
There are three possible ways that a device can perform DMA engine functions:
Bus master DMA
Third-party DMA
First-party DMA
The ddi_dmae_alloc() function is used to acquire a DMA channel of the system DMA engine. ddi_dmae_alloc() allows only one device at a time to have a particular DMA channel allocated. It must be called prior to any other system DMA engine function on a channel. If the device allows the channel to be shared with other devices, it must be freed using ddi_dmae_release() after completion of the DMA operation. In any case, the channel must be released before the driver successfully detaches. See detach(9E). No other driver may acquire the DMA channel until it is released.
If the requested channel is not immediately available, the value of callback determines what action will be taken. If the value of callback is DDI_DMA_DONTWAIT, ddi_dmae_alloc() will return immediately. The value DDI_DMA_SLEEP will cause the thread to sleep and not return until the channel has been acquired. Any other value is assumed to be a callback function address. In that case, ddi_dmae_alloc() returns immediately, and when resources might have become available, the callback function is called (with the argument arg) from interrupt context. When the callback function is called, it should attempt to allocate the DMA channel again. If it succeeds or no longer needs the channel, it must return the value DDI_DMA_CALLBACK_DONE. If it tries to allocate the channel but fails to do so, it must return the value DDI_DMA_CALLBACK_RUNOUT. In this case, the callback function is put back on a list to be called again later.
The ddi_dmae_prog() function programs the DMA channel for a DMA transfer. The ddi_dmae_req structure contains all the information necessary to set up the channel, except for the memory address and count. Once the channel has been programmed, subsequent calls to ddi_dmae_prog() may specify a value of NULL for dmaereqp if no changes to the programming are required other than the address and count values. It disables the channel prior to setup, and enables the channel before returning. The DMA address and count are specified by passing ddi_dmae_prog() a DMA cookie. Other DMA engine parameters are specified by the DMA engine request structure passed in through dmaereqp. The fields of that structure are documented in ddi_dmae_req(9S).
Before using ddi_dmae_prog(), you must allocate system DMA resources using DMA setup functions such as ddi_dma_mem_alloc(9F). ddi_dma_addr_bind_handle(9F) can then be used to retrieve a cookie which contains the address and count. Then this cookie is passed to ddi_dmae_prog().
The ddi_dmae_disable() function disables the DMA channel so that it no longer responds to a device's DMA service requests.
The ddi_dmae_enable() function enables the DMA channel for operation. This may be used to re-enable the channel after a call to ddi_dmae_disable(). The channel is automatically enabled after successful programming by ddi_dmae_prog().
The ddi_dmae_stop() function disables the channel and terminates any active operation.
The ddi_dmae_getcnt() function examines the count register of the DMA channel and sets *countp to the number of bytes remaining to be transferred. The channel is assumed to be stopped.
In the case of ISA buses, ddi_dmae_1stparty() configures a channel in the system's DMA engine to operate in a ``slave'' (``cascade'') mode.
When operating in ddi_dmae_1stparty() mode, the DMA channel must first be allocated using ddi_dmae_alloc() and then configured using ddi_dmae_1stparty(). The driver then programs the device to perform the I/O, including the necessary DMA address and count values obtained from the ddi_dma_cookie(9S).
The ddi_dmae_getattr() function fills in the DMA attribute structure, pointed to by attrp, with the DMA attributes of the system DMA engine. Drivers for devices that perform their own bus mastering or use first-party DMA must create and initialize their own DMA attribute structures; they should not use ddi_dmae_getattr(). The DMA attribute structure must be passed to the DMA resource allocation functions to provide the information necessary to break the DMA request into DMA windows and DMA cookies. See ddi_dma_cookie_iter(9F) and ddi_dma_getwin(9F).
DDI_SUCCESS
DDI_FAILURE
DDI_DMA_NORESOURCES
If ddi_dmae_alloc() is called from interrupt context, then its dmae_waitfp argument and the callback function must not have the value DDI_DMA_SLEEP. Otherwise, all these routines can be called from user, interrupt, or kernel context.
See attributes(7) for descriptions of the following attributes:
ATTRIBUTE TYPE | ATTRIBUTE VALUE |
Architecture | x86 |
isa(5), attributes(7), ddi_dma_addr_bind_handle(9F), ddi_dma_buf_setup(9F), ddi_dma_cookie_iter(9F), ddi_dma_getwin(9F), ddi_dma_mem_alloc(9F), ddi_dma_attr(9S), ddi_dma_cookie(9S), ddi_dmae_req(9S)
January 18, 2020 | OmniOS |