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");