This is an old revision of the document!
Warning: this is dirty working draft version and is subject to change in future.
The DMA engine device driver should include “dmae_if.h”, <sys/dev/dmae/dmae.h> header files and support following kobject methods:
int setup_channel(device_t dev, int channel, struct dmae_transfer *xfer)
Sets up provided transfer on selected channel number, but doesn't start transfer. Transfer can be started by calling apporiated method or by external (hardware) trigger. Returns 0 on success, nonzero on error.
int clear_channel(device_t dev, int channel)
Clears previously set transfer on channel and effectively disables any kind of operation on that channel. Returns 0 on success, nonzero on error.
int start_channel(device_t dev, int channel)
Starts DMA transfer on channel or enables starting transfer from external triggers (if DMAE_TRANSFER_EXTTRIG is set in xfer→dt_flags). Returns 0 on success, nonzero on error.
int stop_channel(device_t dev, int channel)
Stops previously started (but not completed) transfer. Returns 0 on success, nonzero on error. This method is optional - default implementation returns ENOTSUP.
int poll_channel(device_t dev, int channel, int *status)
Returns channel status. Returns 0 if obtained correct status or nonzero if any error occured or channel status is unavailable. *status is filled with one of enum dmae_transfer_status
int validate_transfer(device_t dev, int channel, struct dmae_transfer *xfer)
Returns 0 if supplied transfer can be done usin channel on engine dev, or nonzero if cannot.
DMA engines registers themselves using dmae_register_driver function in their attach method. dmae_register_driver is defined as follows:
int dmae_register_driver(device_t dev, struct dmae_capabilities *caps, bus_dma_tag_t tag);
- dev - DMA engine device
- caps - DMA capabilities structure defined as follows:
struct dmae_capabilities {
uint32_t dc_ops; /* one or more from 'enum dmae_op' */
uint32_t dc_buffers; /* one or more from 'enum dmae_buffer_type' */
uint32_t dc_flags;
#define DMAECAP_REPEAT 0x1
#define DMAECAP_LINK 0x2
int dc_nchannels;
};
- tag - engine root DMA tag
and can be unregistered (at device detach) using:
int dmae_unregister_driver(device_t dev);
Required data structures:
typedef struct dmae_engine *dmae_engine_t;
typedef int (*dmae_callback_t)(int status, void *arg);
enum dmae_op {
DMAE_FILL = 0x1,
DMAE_COPY = 0x2,
DMAE_XOR = 0x4,
};
enum dmae_transfer_status {
DMAE_TRANSFER_COMPLETED,
DMAE_TRANSFER_COMPLETED_STRIDE,
DMAE_TRANSFER_COMPLETED_LINK,
DMAE_TRANSFER_CANCELLED,
DMAE_TRANSFER_IN_PROGRESS,
DMAE_TRANSFER_ERROR,
};
enum dmae_buffer_type {
DMAEBUF_BLOCK = 0x1,
DMAEBUF_FRAME = 0x2,
DMAEBUF_FIFO = 0x4,
};
struct dmae_buffer {
struct dmae_transfer * db_transfer;
int db_type;
int db_flags;
bus_addr_t db_addr;
bus_size_t db_length;
bus_size_t db_stride_width;
bus_size_t db_stride_spacing;
bus_size_t db_fifo_width;
void * db_immediate;
/* Private fields: */
bus_dma_tag_t db_dmatag;
bus_dmamap_t db_dmamap;
};
struct dmae_transfer {
int dt_type;
int dt_op;
int dt_flags;
#define DMAE_TRANSFER_EXTTRIG 0x1 /* transfer is triggered by external source */
#define DMAE_TRANSFER_REPEAT 0x2 /* repeat transfer until cancel */
#define DMAE_TRANSFER_NOINTR 0x4 /* don't generate callbacks */
#define DMAE_TRANSFER_STRIDE_CALLBACK 0x8 /* callback on every stride */
#define DMAE_TRANSFER_LINK_CALLBACK 0x10 /* callback on every linked transfer */
dmae_callback_t dt_callback;
void * dt_callback_arg;
struct dmae_buffer dt_buffers[8];
#define DMAE_BUF_DST 0
#define DMAE_BUF_SRC 1
struct dmae_transfer * dt_next;
/* Private fields: */
struct dmae_engine * dt_engine;
struct resource * dt_res;
};