**Warning:** this is dirty working draft version and is subject to change in future.
The DMA engine device driver should include "gpdma_if.h", %%<%%sys/dev/gpdma/gpdma.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 gpdma_transfer_status//
int validate_transfer(device_t dev, int channel, struct gpdma_transfer *xfer)
Returns 0 if supplied transfer can be done using //channel// on engine //dev//,
or nonzero if cannot. This method is optional - default implementation returns
0.
DMA engines registers themselves using //gpdma_register_driver// function in
their attach method. //gpdma_register_driver// is defined as follows:
int gpdma_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 gpdma_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 gpdma_unregister_driver(device_t dev);
===== Required data structures: =====
typedef struct gpdma_engine *gpdma_engine_t;
typedef int (*gpdma_callback_t)(int status, void *arg);
enum gpdma_op {
DMAE_FILL = 0x1,
DMAE_COPY = 0x2,
DMAE_XOR = 0x4,
};
enum gpdma_transfer_status {
DMAE_TRANSFER_COMPLETED,
DMAE_TRANSFER_COMPLETED_STRIDE,
DMAE_TRANSFER_COMPLETED_LINK,
DMAE_TRANSFER_CANCELLED,
DMAE_TRANSFER_IN_PROGRESS,
DMAE_TRANSFER_ERROR,
};
enum gpdma_buffer_type {
DMAEBUF_BLOCK = 0x1,
DMAEBUF_FRAME = 0x2,
DMAEBUF_FIFO = 0x4,
};
struct gpdma_buffer {
struct gpdma_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 gpdma_transfer {
int dt_type;
int dt_op;
int dt_flags;
#define GPDMA_TRANSFER_EXTTRIG 0x1 /* transfer is triggered by external source */
#define GPDMA_TRANSFER_REPEAT 0x2 /* repeat transfer until cancel */
#define GPDMA_TRANSFER_NOINTR 0x4 /* don't generate callbacks */
#define GPDMA_TRANSFER_STRIDE_CALLBACK 0x8 /* callback on every stride */
#define GPDMA_TRANSFER_LINK_CALLBACK 0x10 /* callback on every linked transfer */
gpdma_callback_t dt_callback;
void * dt_callback_arg;
struct gpdma_buffer dt_buffers[8];
#define GPDMA_BUF_DST 0
#define GPDMA_BUF_SRC 1
struct gpdma_transfer * dt_next;
/* Private fields: */
struct gpdma_engine * dt_engine;
struct resource * dt_res;
};