linux3.4.2之DMA驱动完整程序

  1 /*
  2 *参考arch/arm/mach-s3c24xx/dma-s3c2410.c
  3 */
  4 #include <linux/module.h>
  5 #include <linux/kernel.h>
  6 #include <linux/fs.h>
  7 #include <linux/init.h>
  8 #include <linux/delay.h>
  9 #include <linux/irq.h>
 10 #include <asm/uaccess.h>
 11 #include <asm/irq.h>
 12 #include <asm/io.h>
 13 #include <linux/poll.h>
 14 #include <plat/regs-dma.h>
 15 #include <mach/dma.h>
 16 #include <plat/dma-s3c24xx.h>
 17 #include <linux/cdev.h>
 18 #include <linux/backing-dev.h>
 19 #include <linux/wait.h>
 20 #include <linux/interrupt.h>
 21 
 22 #define DMA_BASE 0x4b000000
 23 #define BUFF_SIZE 512
 24 
 25 static unsigned char *src_addr;//
 26 static unsigned char *dst_addr;//目的
 27 static int major;
 28 static dma_addr_t psrc_addr;
 29 static dma_addr_t pdst_addr;
 30 
 31 static struct class *dma_class;
 32 static int dma_ok;
 33 #define MEM_COPY_NO_DMA 0
 34 #define MEM_COPY_BY_DMA 1
 35 static DECLARE_WAIT_QUEUE_HEAD(dma_waitq);
 36 
 37 struct dma_regs {
 38          unsigned long disrc;
 39          unsigned long disrcc;
 40          unsigned long didst;
 41          unsigned long didstc;
 42          unsigned long dcon;
 43          unsigned long dstat;
 44          unsigned long dcsrc;
 45          unsigned long dcdst;
 46          unsigned long dmasktrig;         
 47 };
 48 
 49 static volatile struct dma_regs *dma_regs;
 50 
 51 long dma_ioctl(struct file *file, unsigned int cmd, unsigned long dat)
 52 {
 53     int i;
 54     memset(src_addr,0xaa,BUFF_SIZE);  //从src开始的BUFF_SIZE空间每个字节都设置为0xaa
 55     memset(dst_addr,0x55,BUFF_SIZE);
 56 
 57     if(cmd == MEM_COPY_NO_DMA){
 58          for(i = 0; i < BUFF_SIZE; i++){
 59               dst_addr[i] = src_addr[i];
 60          }
 61           if(0 == memcmp(src_addr,dst_addr,BUFF_SIZE)){
 62              printk("no dma transfer has finished!\n");
 63           }else{
 64              printk("no dma transfer failed!\n");
 65            }
 66     }else if(cmd == MEM_COPY_BY_DMA){
 67     
 68      dma_ok = 0;
 69      
 70      dma_regs->disrc  = psrc_addr;
 71      dma_regs->didst  = pdst_addr;
 72      dma_regs->dcon   = (1<<30) | (1<<29) | (1<<27) | (BUFF_SIZE);
 73 
 74       //启动DMA
 75      dma_regs->dmasktrig = (1<<1) | (1<<0);
 76 
 77      /*等待DMA传输完成*/
 78      wait_event_interruptible(dma_waitq, dma_ok);
 79 
 80      if(0 == memcmp(src_addr,dst_addr,BUFF_SIZE)){
 81          printk("dma transfer has finished!\n");
 82      }else{
 83          printk("dma transfer failed!\n");
 84      }
 85      
 86     }
 87     return 0;
 88 }
 89 
 90 ssize_t dma_read(struct file *file, char __user *buff, size_t size, loff_t *loff)
 91 {
 92      int err;
 93      err = copy_to_user(buff,dst_addr,size);
 94      if(err){
 95         return -1;
 96      }
 97      return 1;
 98 }
 99 
100 static struct file_operations dma_fop = {
101            .owner = THIS_MODULE,
102            .read  = dma_read,
103            .unlocked_ioctl = dma_ioctl,
104 };
105 
106 irqreturn_t dma_irq(int irq, void *devid)
107 {
108      dma_ok = 1;
109      wake_up_interruptible(&dma_waitq);
110      return IRQ_HANDLED;
111 }
112 
113 static int dma_drv_init(void)
114 {
115 
116      dma_regs = ioremap(DMA_BASE,sizeof(struct dma_regs));
117    
118      src_addr = dma_alloc_writecombine(NULL,BUFF_SIZE, &psrc_addr,GFP_KERNEL);
119      dst_addr = dma_alloc_writecombine(NULL,BUFF_SIZE, &pdst_addr,GFP_KERNEL);
120 
121      if(request_irq(IRQ_DMA0,dma_irq,0,"dma_irq",NULL)){
122         printk("request dma irq failed!\n");
123         free_irq(IRQ_DMA0,NULL);
124         return -1;
125      }
126      
127      major = register_chrdev(0, "dma-z", &dma_fop);
128      dma_class = class_create(THIS_MODULE, "DMA");
129      device_create(dma_class, NULL, MKDEV(major,0), NULL, "dma0");
130      
131      return 0;
132 }
133 
134 static void dma_drv_exit(void)
135 {
136     device_destroy(dma_class,MKDEV(major,0));
137     class_destroy(dma_class);
138     free_irq(IRQ_DMA0,NULL);
139     dma_free_writecombine(NULL, BUFF_SIZE,src_addr,psrc_addr);
140     dma_free_writecombine(NULL, BUFF_SIZE,dst_addr,pdst_addr);
141     iounmap(dma_regs);
142 }
143 
144 module_init(dma_drv_init);
145 module_exit(dma_drv_exit);
146 
147 MODULE_LICENSE("GPL");
148 MODULE_AUTHOR("1653699780@qq.com");

 

posted @ 2018-07-15 21:02  一条水煮鱼  阅读(264)  评论(0编辑  收藏  举报