📄 s3c2410_dma_3.c
字号:
/*****************************************Copyright (c)****************************************************------------------------------------- File Info ------------------------------------------------------** File name: s3c2410_dmadriver.c** Last modified Date: 2007-10-13** Last Version: 1.0** Descriptions: Driver DMA transition on S3C2410.以字符设备驱动为例** Based upon Linux 2.4.18. **------------------------------------------------------------------------------------------------------** Created by: Chenzhaoyang** Created date: 2007-10-19** Version: 2.3** Descriptions: Preliminary version.**** NOTE: 从地址0x28000008的FIFO响应REQ硬件中断,判断类型(read,or write?),启动DMA**** 读写互斥,2个内核缓冲区,循环缓冲;**** 设计思路:读、写驱动可以通过read/write,分别单独进行,也可通过ioctl操作; 可以在通过read, write传入地址,在用户进程与内核DMA缓冲区空间相互拷贝数据** 经测试可行*********************************************************************************************************/#ifndef __KERNEL__ #define __KERNEL__#endif#ifndef MODULE #define MODULE#endif#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/ctype.h>#include <linux/pagemap.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/processor.h>#include <linux/wrapper.h>/////////////////#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/major.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/io.h>#include <linux/irq.h>#include <linux/mm.h>#include <asm/semaphore.h>#include <linux/types.h>#include <linux/pm.h>#include <linux/delay.h>//#include <linux/wrapper.h>#include <linux/pagemap.h>#include <asm/page.h>//#include <asm/dma.h>#include "s3c2410_dma_3.h"MODULE_LICENSE("GPL");MODULE_DESCRIPTION("UESTC\nhttp://blog.csdn.net/youta_chen");MODULE_SUPPORTED_DEVICE("Linux 2.4.18 & s3c2410ARM2410");MODULE_AUTHOR("chenzhaoyang");#define ENCODE 0#define DECODE 1char* Cmd612Addr; //base+0x00char* Dat612Addr; //base+0x04char* Int612Addr; //base+0x0Cchar* Cfg612Addr; //base+0x10char* Mod612Addr; //base+0x18unsigned short boardtype;unsigned short boardversion;int RunMode; // 1-->decode 0--encodestatic int LVT612_EN_Init();static int LVT612_DE_Init();static void dma_buff_initizlize(void);static int LVT612_EN_Init(){ (*(volatile unsigned int*) (Cmd612Addr)) = 0x00; (*(volatile unsigned int*) (Dat612Addr)) = 0xfae0; udelay(10); (*(volatile unsigned int*) (Cmd612Addr)) = 0x00; (*(volatile unsigned int*) (Dat612Addr)) = 0x0880; //0xf2e0 (*(volatile unsigned int*) (Cmd612Addr)) = 0x01; (*(volatile unsigned int*) (Dat612Addr)) = 0x0088; (*(volatile unsigned int*) (Cmd612Addr)) = 0x02; (*(volatile unsigned int*) (Dat612Addr)) = 0x0011; (*(volatile unsigned int*) (Cmd612Addr)) = 0x03; (*(volatile unsigned int*) (Dat612Addr)) = 0x0120; (*(volatile unsigned int*) (Cmd612Addr)) = 0x04; (*(volatile unsigned int*) (Dat612Addr)) = 0x0011; (*(volatile unsigned int*) (Cmd612Addr)) = 0x05; (*(volatile unsigned int*) (Dat612Addr)) = 0x01bc; (*(volatile unsigned int*) (Cmd612Addr)) = 0x08; (*(volatile unsigned int*) (Dat612Addr)) = 0x0011; (*(volatile unsigned int*) (Cmd612Addr)) = 0x09; (*(volatile unsigned int*) (Dat612Addr)) = 0x0ff4; //Start (*(volatile unsigned int*) (Cmd612Addr)) = 0x00; (*(volatile unsigned int*) (Dat612Addr)) = 0xf2e0; //0xf2e0 return 0;}static int LVT612_DE_Init(){ (*(volatile unsigned int*) (Cmd612Addr)) = 0x00; (*(volatile unsigned int*) (Dat612Addr)) = 0xfae0; udelay(10); (*(volatile unsigned int*) (Cmd612Addr)) = 0x00; (*(volatile unsigned int*) (Dat612Addr)) = 0x0880; //0xf2e0 (*(volatile unsigned int*) (Cmd612Addr)) = 0x01; (*(volatile unsigned int*) (Dat612Addr)) = 0x0088; (*(volatile unsigned int*) (Cmd612Addr)) = 0x02; (*(volatile unsigned int*) (Dat612Addr)) = 0x0011; (*(volatile unsigned int*) (Cmd612Addr)) = 0x03; (*(volatile unsigned int*) (Dat612Addr)) = 0x0120; (*(volatile unsigned int*) (Cmd612Addr)) = 0x04; (*(volatile unsigned int*) (Dat612Addr)) = 0x0011; (*(volatile unsigned int*) (Cmd612Addr)) = 0x05; (*(volatile unsigned int*) (Dat612Addr)) = 0x01bc; (*(volatile unsigned int*) (Cmd612Addr)) = 0x08; (*(volatile unsigned int*) (Dat612Addr)) = 0x0011; (*(volatile unsigned int*) (Cmd612Addr)) = 0x09; (*(volatile unsigned int*) (Dat612Addr)) = 0x0ff4; //Start (*(volatile unsigned int*) (Cmd612Addr)) = 0x00; (*(volatile unsigned int*) (Dat612Addr)) = 0xf260; //0xf2e0 return 0;}/********************************************************************************************************** HardWare FIFO //DMA Initialize********************************************************************************************************/static int dma_setup_buf(dma_buf_t * dma_buf,unsigned int dma_ch,unsigned int bufsize){ dma_addr_t dmaphys = 0; dma_buf_t *dp = dma_buf; dp ->size = bufsize; dp ->start = consistent_alloc(GFP_KERNEL|GFP_DMA, bufsize, &dmaphys);//un zeroed if (!dp ->start) goto err; memset(dp ->start,0,bufsize); printk(KERN_INFO DEVICE_NAME "dma_setup_buf ->size %d,->start*%x,*->dmaphys *%x*.\n",dp ->size,(int)dp ->start ,dmaphys); dp ->dma_addr = dmaphys; dp ->user_space = NULL; dp ->dirty = 0; dp ->size_valid = 0; dp -> dma_ch = dma_ch; init_MUTEX(&dp->sem); return 0;err: printk(KERN_ERR ": unable to allocate dma memory\n "); return -ENOMEM;}//okstatic void dma_clear_buf(dma_buf_t * dma_buff,u_int num){ dma_buf_t *ds; dma_types[DMA_CH0]->DMASKTRIG = DMASKTRIG_STOP; ds = dma_buff; if (ds->start) { while (ds < (dma_buff + num)) { consistent_free(ds->start,ds->size,ds->dma_addr); ds->start = NULL; ds++; } } printk(KERN_INFO DEVICE_NAME ": s3c2410_clear_dma_buf.\n"); }void dma_buff_initizlize(void){ int i = 0 ; int quauter_size = PAGESIZE>>2; dma_setup_buf(&dma_buff_temp_2page,DMA_CH0,PAGESIZE*2); for (;i<S3C2410_DMA_NUMSBUF;i++) { s3c2410_dmabuffer_array_rd[i].size= quauter_size; s3c2410_dmabuffer_array_rd[i].start= dma_buff_temp_2page.start + quauter_size * i; //s3c2410_dmabuffer_array_rd[i].dma_addr= dma_buff_temp->dma_addr + quauter_size * i; s3c2410_dmabuffer_array_rd[i].user_space = dma_buff_temp_2page.user_space; s3c2410_dmabuffer_array_rd[i].dirty = dma_buff_temp_2page.dirty; s3c2410_dmabuffer_array_rd[i].dma_ch = dma_buff_temp_2page.dma_ch; init_MUTEX(&(s3c2410_dmabuffer_array_rd[i].sem)); printk("s3c2410_dmabuffer_array_rd.start --%x--\n",(int)s3c2410_dmabuffer_array_rd[i].start); }// FIFOSIZE dma_setup_buf(&s3c2410_dmabuffer_array_wr,DMA_CH0,quauter_size);//Initialize DMA0 buffers s3c2410_dmabuffer_array_wr.write_or_rd = DMA_BUF_WR; //sema_init(&s3c2410_dmabuffer_array_wr.sem,0); dma_setup_buf(&s3c2410_dma_buff_rd,DMA_CH0,quauter_size); s3c2410_dma_buff_rd.write_or_rd = DMA_BUF_RD; return ;}//ok/*********************************************************************************************************** Function name: DMA0_read,DMA1_write** Descriptions: ** DMA0_read:FIFO->mem DMA1_write:mem->FIFO********************************************************************************************************/static int s3c2410_dma_mmap(struct file *file, struct vm_area_struct *vma){ /* // struct video_device *dev = file->private_data; unsigned long start = vma->vm_start; unsigned long size = vma->vm_end - vma->vm_start; // struct usb_spca50x *spca50x = video_get_drvdata(dev); unsigned long offset = s3c2410_dmabuffer_array_rd->dma_addr; //vma->vm_pgoff << PAGE_SHIFT; if (size >((FIFOSIZE))) return -EINVAL; //get semphore This is an mutex operation if (down_interruptible(&sem_mmap)) return -EINTR; // offset += s3c2410_dmabuffer_array[1].dma_addr; //开始 逐页映射代码 while (size > 0) { if (remap_page_range(start, offset,PAGE_SIZE, PAGE_SHARED)) { return -EAGAIN; } start += PAGE_SIZE; offset += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } up(&sem_mmap);*/ return 0;}static int DMA0_read(void){ printk(KERN_INFO DEVICE_NAME "DMA0_read enter\n"); //spin_lock(&protect_dma_lock); down_interruptible(&dma0_sem); printk("protect_dma_lock is locked"); memcpy(&dma_buff_cur_int,&s3c2410_dma_buff_rd,sizeof(s3c2410_dma_buff_rd)); dma_types[DMA_CH0]->DISRC =(HARDWARE_FIFO_ADDR+ 0x08);//vir_tob_bus(HARDWARE_FIFO_ADDR+0X08);//DMA_BASE_ADDR(hw_fifo->dma_addr);//(dma_buff_cur -> dma_addr); dma_types[DMA_CH0]->DIDST = DMA_BASE_ADDR(s3c2410_dma_buff_rd.dma_addr); dma_types[DMA_CH0]->DISRCC = rXDREQ0_RD_SRC_CTL; dma_types[DMA_CH0]->DIDSTC = rXDREQ0_RD_DST_CTL; dma_types[DMA_CH0]->DCON = rXDREQ0_RD_CTL|TX_CNT(DMA_TRANS_NUM); dma_types[DMA_CH0]->DMASKTRIG = (DMA_STOP_CLR | CHANNEL_ON | DMA_SW_REQ_CLR); printk(KERN_INFO DEVICE_NAME "DMA0 Read start.\n"); return 0;}static int DMA1_write(void){ printk(KERN_INFO DEVICE_NAME "DMA0_write enter\n"); down_interruptible(&dma0_sem); //spin_lock(&protect_dma_lock); printk("protect_dma_lock is locked"); printk("DMA1 transfer cnt :%d\n",TX_CNT((s3c2410_dmabuffer_array_wr.size_valid)/16)); memcpy(&dma_buff_cur_int,&s3c2410_dmabuffer_array_wr,sizeof(s3c2410_dmabuffer_array_wr)); //printk("---memcpy ok--- \n"); dma_types[DMA_CH0]->DISRC = DMA_BASE_ADDR( s3c2410_dmabuffer_array_wr.dma_addr); dma_types[DMA_CH0]->DIDST =HARDWARE_FIFO_ADDR+0X08;//DMA_BASE_ADDR(hw_fifo->dma_addr); //dma_types[DMA_CH0]->DIDST =DMA_BASE_ADDR(s3c2410_dma_buff_rd.dma_addr);// dma_types[DMA_CH0]->DISRCC = rXDREQ0_WR_SRC_CTL; dma_types[DMA_CH0]->DIDSTC = rXDREQ0_WR_DST_CTL; dma_types[DMA_CH0]->DCON = rXDREQ0_WR_CTL|TX_CNT((s3c2410_dmabuffer_array_wr.size_valid)/16); dma_types[DMA_CH0]->DMASKTRIG = (DMA_STOP_CLR | CHANNEL_ON | DMA_SW_REQ_CLR);//开启DMA printk(KERN_INFO DEVICE_NAME "DMA0 write start.\n"); return 0;}void zero_dmabuffarray(int num_be){ int num_end = num_be?S3C2410_DMA_NUMSBUF:(S3C2410_DMA_NUMSBUF/2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -