⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410_dma_3.c

📁 自己写的支持S3C2410下的实时DMA操作的linux平台驱动程序 功能完善
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************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 + -