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:
1 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.
1 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.
1 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.
1 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.
1 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
1 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:
1 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:
- tag - engine root DMA tag
and can be unregistered (at device detach) using:
1 int gpdma_unregister_driver(device_t dev);
Required data structures:
1 typedef struct gpdma_engine *gpdma_engine_t;
2 typedef int (*gpdma_callback_t)(int status, void *arg);
3
4 enum gpdma_op {
5 DMAE_FILL = 0x1,
6 DMAE_COPY = 0x2,
7 DMAE_XOR = 0x4,
8 };
9
10 enum gpdma_transfer_status {
11 DMAE_TRANSFER_COMPLETED,
12 DMAE_TRANSFER_COMPLETED_STRIDE,
13 DMAE_TRANSFER_COMPLETED_LINK,
14 DMAE_TRANSFER_CANCELLED,
15 DMAE_TRANSFER_IN_PROGRESS,
16 DMAE_TRANSFER_ERROR,
17 };
18
19 enum gpdma_buffer_type {
20 DMAEBUF_BLOCK = 0x1,
21 DMAEBUF_FRAME = 0x2,
22 DMAEBUF_FIFO = 0x4,
23 };
24
25 struct gpdma_buffer {
26 struct gpdma_transfer * db_transfer;
27 int db_type;
28 int db_flags;
29 bus_addr_t db_addr;
30 bus_size_t db_length;
31 bus_size_t db_stride_width;
32 bus_size_t db_stride_spacing;
33 bus_size_t db_fifo_width;
34 void * db_immediate;
35
36 /* Private fields: */
37 bus_dma_tag_t db_dmatag;
38 bus_dmamap_t db_dmamap;
39 };
40
41 struct gpdma_transfer {
42 int dt_type;
43 int dt_op;
44 int dt_flags;
45 #define GPDMA_TRANSFER_EXTTRIG 0x1 /* transfer is triggered by external source */
46 #define GPDMA_TRANSFER_REPEAT 0x2 /* repeat transfer until cancel */
47 #define GPDMA_TRANSFER_NOINTR 0x4 /* don't generate callbacks */
48 #define GPDMA_TRANSFER_STRIDE_CALLBACK 0x8 /* callback on every stride */
49 #define GPDMA_TRANSFER_LINK_CALLBACK 0x10 /* callback on every linked transfer */
50 gpdma_callback_t dt_callback;
51 void * dt_callback_arg;
52 struct gpdma_buffer dt_buffers[8];
53 #define GPDMA_BUF_DST 0
54 #define GPDMA_BUF_SRC 1
55 struct gpdma_transfer * dt_next;
56
57 /* Private fields: */
58 struct gpdma_engine * dt_engine;
59 struct resource * dt_res;
60 };