|
|
#include <sys/dma.h>int dma_start(struct dmareq *arg);
struct dmareq { struct dmareq *d_nxt; /* reserved */ unsigned short d_chan; /* specifies channel */ unsigned short d_mode; /* direction of transfer */ paddr_t d_addr; /* physical source or destination */ long d_cnt; /* number of bytes or words */ int (*d_proc)(); /* address of routine to call */ char *d_params; /* pointer to params for d_proc */ };The dmareq structure contains enough information to specify the transfer, the address of a routine to call when the channel is available, and an address of further data that may be needed by the xxd_proc routine (the
d_proc
field of the structure).
Possible values for d_chan
are:
Channel 4 is not available. Other channels may be permanently allocated by system drivers. Consult the /usr/adm/messages file to determine which channels are in use. Use the printcfg(D3oddi) function in your driver's initialization routine to display the DMA channel that you select.
arg->d_proc
is called at
spl6(D3oddi)
with a pointer to arg as a parameter.
The
dma_start( )
function then returns a non-zero value.
If the channel is not available, the structure pointed to by arg is linked to the end of a list of pending requests, and dma_alloc(D3oddi) returns 0.
If the routine was not able to allocate the channel immediately, but had to queue your request, this routine will return a 0.
d_chan
d_mode
d_proc
When the channel is allocated, xxd_proc is called with a pointer to the dmareq structure as its argument. At this point, the DMA channel has been allocated as if the driver had done so with dma_alloc(D3oddi).
The kernel functions contained in the xxd_proc routine are executed at spl6(D3oddi) and should observe all the normal rules of an interrupt routine. Specifically, this means that no assumptions about the currently running process may be made. In addition, the interrupt priority level should not be lowered, and sleep(D3oddi), delay(D3oddi), or other routines that call sleep cannot be used in this routine.
xxd_proc
:
extern int foo_proc();/* set up dma structure */ struct dmareq foo_req = { /* DMA request structure: */ (struct dmareq *)0, /* d_nxt */ DMA_CH1, /* d_chan */ DMA_Rdmode, /* d_mode */ (paddr_t)0, /* d_addr */ (long)0, /* d_cnt */ foo_proc, /* d_proc */ (char *)0, /* d_params */ }; ... dma_start( &foo_req ); /* we don't care if we are queued or not */ return;