**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; };