ddi_dmae(9F)
NAME
ddi_dmae − DMA engine functions
SYNOPSIS
int ddi_dmae_alloc(dev_info_t ∗dip, int chnl, int (∗dmae_waitfp)(), 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_getlim(dev_info_t ∗dip, ddi_dma_lim_t ∗limitsp);
ARGUMENTS
dip A dev_info pointer, which identifies the device driver that wants to use the DMA channel.
chnl A direct memory access (DMA) channel number. This number must be 0, 1, 2, 3, 5, 6, or 7. Only one device at a time may have a particular DMA channel allocated.
dmae_waitfp
A wait/callback_function pointer. If the requested DMA channel is not immediately available, the value of dmae_waitfp determines what action will be taken. If the value of dmae_waitfp is DDI_DMA_DONTWAIT, ddi_dmae_alloc() will return immediately. The value DDI_DMA_SLEEP will 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 specified in arg) from interrupt context.
arg The argument to be passed to the callback function.
dmaereqp
A pointer to a DMA engine request (ddi_dmae_req(9S)) structure. This structure is implementation specific and contains all the information necessary to set up the channel, except for the memory address and count. This structure is implemented with default values equal to zero, so that normally only dmaereqp->der_command has to be set with a read or write command value. 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.
cookiep
A pointer to a ddi_dma_cookie(9S) object, obtained from ddi_dma_segtocookie(9F), which contains address, count, and intermediate memory mapping information.
countp A pointer to an integer that will receive the count of the number of bytes not yet transferred in a DMA operation.
limitsp A pointer to a DMA limit structure. This structure will be filled in with the DMA limits of the parent nexus driver.
INTERFACE LEVEL
Solaris for x86 architecture specific. These interfaces are provisional and subject to change.
DESCRIPTION
On EISA buses there are three possible ways that a device can perform DMA engine functions. If the device is capable of acting as a bus master, then the driver should program the device’s DMA registers directly and not make use of the DMA engine functions described here. The driver should obtain the DMA address and count from ddi_dma_segtocookie(). See ddi_dma_cookie(9S) for a description of a DMA cookie.
The other two ways a device can perform DMA are available on both the EISA and the ISA buses. One mechanism, referred to as “third-party DMA,” uses of the DMA engine that is resident on the main system board. In this model, the device co-operates with the system’s DMA engine to effect the data transfers between the device and memory. The driver uses the functions documented here (except ddi_dmae_1stparty()) to initialize and program the DMA engine. For each DMA data transfer, the driver programs the DMA engine and then gives the device a command to initiate the transfer in co-operation with that engine.
Under the other mechanism, referred to as “first-party DMA,” the device performs its own DMA bus cycles, but uses a channel from the system’s DMA engine. The ddi_dmae_1stparty() function configures a channel in the system’s DMA engine to operate in a “slave” mode for that purpose. When operating in this mode, the DMA channel should be allocated using ddi_dmae_alloc() and 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 ddi_dma_segtocookie(). When the driver is finished with the channel, it should free it using ddi_dmae_release().
The ddi_dmae_alloc() function must be called prior to any other DMA engine function on a channel. If the channel is to be shared, it should be freed using ddi_dmae_release() after completion of the DMA/device operation. In any case the channel should be released before the driver completes detaching. No other driver may acquire the DMA channel until it is released.
When the callback function (∗dmae_waitfp)() is called, it should attempt to allocate the DMA channel again. If it succeeds or does not need the channel any more, it must return the value DDI_DMA_CALLBACK_DONE. If it does not want to allocate the channel immediately, but instead wishes to be called back again later, it must return the value DDI_DMA_CALLBACK_LATER. If it tries to allocate the channel, but fails to do so, it must return the value DDI_DMA_CALLBACK_RUNOUT.
Failure to observe this protocol will result in unpredictable behavior.
The callback function must provide its own data structure integrity when it is invoked.
The ddi_dmae_prog() function programs the DMA channel for an operation. This function allows access to various capabilities of the DMA engine hardware. 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 cookie obtained from ddi_dma_segtocookie(). 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).
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.
The ddi_dmae_getlim() function fills in the DMA limit structure, pointed to by limitsp, with the DMA limits of the parent bus. This limit structure must be passed to the DMA setup routines so that they will know how to break the DMA request into windows and segments. If the device has any particular restrictions on transfer size or granularity (for example, a disk sector size), the driver should further restrict the values in the structure members before passing them to the DMA setup routines. The driver should take care not to relax any of the restrictions embodied in the structure after it is filled in by ddi_dmae_getlim().
RETURN VALUES
Upon success, all of these routines return DDI_SUCCESS. Invalid arguments can result in a return value of DDI_FAILURE. ddi_dmae_alloc() may return DDI_DMA_NORESOURCES if the requested resources are not available and the value of dmae_waitfp is not DDI_DMA_SLEEP .
CONTEXT
If ddi_dmae_alloc() is called from interrupt context, dmae_waitfp argument may not have the value DDI_DMA_SLEEP. Otherwise, all these routines may be called from user or interrupt context.
SEE ALSO
ddi_dma_nextseg(9F), ddi_dma_nextwin(9F), ddi_dma_req(9S), ddi_dma_segtocookie(9F), ddi_dma_setup(9F), ddi_dma_cookie(9S), ddi_dma_lim(9S), ddi_dmae_req(9S)
SunOS 5.1/x86 — Last change: 31 May 1993