DMA transfers can be memory-to-memory, memory-to-peripherals and peripherals to memory. The code here implements the memory-to-memory data transfer through the DMA driver.
/*function Description:when We call Dmatest_read (), it'll transmit src memory datato DST memory,then print DST memory dat A by Dma_callback_func (void) function.*/#include <linux/module.h> #include <linux/init.h> #include < linux/fs.h> #include <linux/sched.h> #include <linux/device.h> #include <linux/string.h># include<linux/errno.h> #include <linux/types.h> #include <linux/slab.h> #include <linux/ dmaengine.h> #include <linux/dma-mapping.h> #include <asm/uaccess.h> #define DEVICE_NAME "Dma_test" unsigned char dmatest_major;static struct class *dmatest_class;struct Dma_chan *chan; Bus addressdma_addr_t dma_src;dma_addr_t dma_dst;//virtual addresschar *src = Null;char *dst = NULL; struct Dma_device * Dev;struct dma_async_tx_descriptor *tx = null;enum dma_ctrl_flags flags;dma_cookie_t cookie;//When DMA transfer finished , this function would be called.void dma_callback_func (void) {int i;for (i = 0; i < i++) {PRINTK (kern_info "%c", Dst[i] );}}int dmatest_open (struct inode *inode, struct file *filp) {return 0;} int dmatest_release (struct inode *inode, struct file *filp) {return 0;} Static ssize_t dmatest_read (struct file *filp, char __user *buf, size_t size, loff_t *ppos) {int ret = 0;//alloc a Desc,and Set dst_addr,src_addr,data_size.tx = dev->device_prep_dma_memcpy (chan, Dma_dst, DMA_SRC,, Flags), if (!TX) { PRINTK (kern_info "Failed to prepare DMA memcpy");} Tx->callback = Dma_callback_func;//set call back Functiontx->callback_param = Null;cookie = Tx->tx_submit (TX); Submit the Descif (Dma_submit_error (cookie)) {PRINTK (kern_info "Failed to do DMA Tx_submit");} Dma_async_issue_pending (chan);//begin DMA transferreturn ret;} Static ssize_t dmatest_write (struct file *filp, const char __user *buf, size_t size, loff_t *ppos) {int ret = 0;return ret; }static const struct File_operations dmatest_fops = {. Owner = This_module,.read = Dmatest_read,.write = Dmatest_write,.ope n = dmatest_open,.release = Dmatest_release,};int DmatEst_init (void) {int i;dma_cap_mask_t mask;//the first parameter 0 means allocate major device number Automaticallydmatest_ Major = Register_chrdev (0,device_name,&dmatest_fops), if (Dmatest_major < 0) return dmatest_major;//create a Dmatest Classdmatest_class = class_create (this_module,device_name); if (Is_err (Dmatest_class)) Return-1;//create A Dmatest device from this classdevice_create (Dmatest_class,null,mkdev (dmatest_major,0), null,device_name);//alloc 512B src memory and DST memorysrc = Dma_alloc_coherent (NULL,, &DMA_SRC, Gfp_kernel);p rintk (kern_info "src = 0x%x, DMA_SRC = 0x%x\n ", SRC, dma_src);d st = dma_alloc_coherent (NULL, MB, &DMA_DST, Gfp_kernel);p rintk (kern_info" DST = 0x% X, DMA_DST = 0x%x\n ", DST, DMA_DST); for (i = 0; i < i++) {* (src + i) = ' A ';} Dma_cap_zero (Mask);d Ma_cap_set (dma_memcpy, mask);//direction:memory to Memorychan = Dma_request_channel (Mask,NULL, NULL); Request a DMA CHANNELPRINTK (KERN_INFO "DMA Channel ID =%d\n", chan->chan_id); flags = DMA_ctrl_ack | Dma_prep_interrupt;dev = Chan->device;return 0;} void Dmatest_exit (void) {Unregister_chrdev (dmatest_major,device_name);//release Major DEVICE Numberdevice_destroy ( Dmatest_class,mkdev (dmatest_major,0));//destroy Globalmem Deviceclass_destroy (dmatest_class);//destroy Globalmem Class//free Memory and DMA channeldma_free_coherent (NULL, up to, SRC, &dma_src);d ma_free_coherent (null,%, DST, &DMA_DST);d Ma_release_channel (Chan); Module_init (Dmatest_init); Module_exit (Dmatest_exit); Module_license ("GPL");
DMA driver test code under Linux