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

📄 d11_dma.c

📁 在linux环境下arm2410的 dma驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**********************************************************
*
*			emp-d11 dma  linux driver program
*
**********************************************************
*/


#include <linux/config.h>
#include <linux/module.h>		// must be include.
#include <linux/kernel.h>		// define printk()
#include <linux/init.h>			// define module_init &module_exit
#include <linux/ioctl.h>			// define ioctl number.
#include <linux/vmalloc.h>		// define kmallloc ...
#include <linux/poll.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>		// for proc filesystem.

#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>			// define irq number. ex IRQ_EINTx etc.
#include <asm/dma.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/types.h>

#include "d11.h"

// define tracy function
#ifdef DEBUG
	#define DPRINTK( x... )	printk("d11_dma:" ##x)
#else
	#define DPRINTK( x... )
#endif


#define DEVICE_NAME 		"d11_dma"
#define DMA_MINOR			1

static int  d11_dma_major = 0;		/* Define major device number -- auto allocate!*/

struct image_dma_t image_review_buf;
static unsigned int d11_dma_ucount = 0;
static unsigned char flag_unfreeze = 0;
wait_queue_head_t d11_dma_queue;

static struct proc_dir_entry *d11_dma_proc_entry;

#define FPGA_DMA0	0x28000000	/* fpga's dma source address */

/*
****************************************************************
*
*			EINT2 ISR
*
****************************************************************
*/
static void handler_isr_eint2(int irq, void* dev_irq, struct pt_regs* reg)
{
	dma_addr_t d11_dma_phy;
	
	DPRINTK("d11b dma module EINT2 happen!\n");
	
	#if 0
	if(flag_unfreeze){
		flag_unfreeze = 0;
		DMTRIG0 |= 4;	
		d11_dma_phy = image_review_buf.image_dma_mmphy[image_review_buf.tail_index];
		DIDST0 = d11_dma_phy;
		DMTRIG0 = (0<<2) + (1<<1) + 0;	// |= 2;	
	}
	#endif
	
	#if 0
	Eint2_Done++;
	
	if (FlagUnfreeze==1){
		FlagUnfreeze=0;
 		rDMASKTRIG0= rDMASKTRIG0|4;     
 		// 重新初始化DMA,纠正刚开机时数据传输错位的问题。
		Dma0Xdreq(); 
	}
	#endif
}

/*
***************  Only for dma test *****************************
*/
void dma_tester(void)
{
	int i,j;
	unsigned char *pattern;

	pattern = (unsigned char *)vmalloc(IMG_SIZE);
	
	for(j=0; j<IMG_SIZE; j++)
	{
		pattern[j] = 0x80;
	}
	for(i=0; i<IMG_MAX_NR; i++)
	{
		memcpy(image_review_buf.image_dma_mmblk[i], pattern, IMG_SIZE);
	}
	vfree(pattern);
}

/*
****************************************************************
*
*			DMA0 done ISR
*
****************************************************************
*/
void handler_Dma0Done(int irq, void* dev_irq, struct pt_regs* reg)
{
	dma_addr_t 	   d11_dma_phy = 0;
	
	DPRINTK("d11b dma0 transfer finished!\n");

	
	if(!image_review_buf.freeze){
		
		image_review_buf.nr_images++;
		if(image_review_buf.nr_images > (image_review_buf.nr_mmblks)){
			image_review_buf.nr_images = image_review_buf.nr_mmblks;
			
			image_review_buf.head_index++;		
			if(image_review_buf.head_index > (image_review_buf.nr_mmblks)){
				image_review_buf.head_index = 0;
			}
			
		}
		else{
		}
		
		image_review_buf.tail_index++;
		if(image_review_buf.tail_index > (image_review_buf.nr_mmblks)){
				image_review_buf.tail_index = 0;
		}
		
		DPRINTK("image count = %d\n",image_review_buf.nr_images);
	}
	else{
		image_review_buf.nr_images = 0;
		//image_review_buf.head_index = image_review_buf.tail_index = 0;
	}
	
	//d11_dma_buf = image_review_buf.image_dma_mmblk[image_review_buf.tail_index];
	d11_dma_phy = image_review_buf.image_dma_mmphy[image_review_buf.tail_index];
	
	//DPRINTK("dma0 dst kerneladdr[%d]= 0x%lx\n", image_review_buf.tail_index, (unsigned long)d11_dma_buf);
	DPRINTK("dma0 dst phyaddr[%d] = 0x%lx\n", image_review_buf.tail_index, d11_dma_phy);	
		
	DIDST0 = d11_dma_phy;
	DMTRIG0 |= 2;	
	
}

static unsigned int d11_dma_poll(struct file *filp, struct poll_table_struct *wait)
{
	unsigned int mask = 0;
	poll_wait(filp, &d11_dma_queue, wait);

	mask |= POLLIN | POLLWRNORM;		//can read always. (test)
	return mask;
}

void d11_dma_vma_open(struct vm_area_struct *vma)
{
	
}

void d11_dma_vma_close(struct vm_area_struct *vma)
{
	
}

struct page *d11_dma_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write)
{
	int phy_index;
	int phy_offset;
	unsigned long blksize = image_review_buf.image_blksize;
	struct page *ptrpage = NOPAGE_SIGBUS;
	unsigned long phyaddr;
	unsigned long viroff = address - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT);
	//DPRINTK("viroff=0x%lx; blksize=0x%lx\n", viroff, blksize);
	phy_index = viroff / blksize;
	phy_offset = viroff % blksize;
	
	phyaddr = image_review_buf.image_dma_mmphy[phy_index] + phy_offset;

	/*
	if(phy_offset % 32*4*1024 == 0)
		DPRINTK("nopage: phyaddr=0x%lx\n",phyaddr);
	*/
	
	/*********   需要在此处追加检查phyaddr 合法范围的程序段***********/
	if(!phyaddr){
		return ptrpage;
	}
	ptrpage = virt_to_page(__va(phyaddr));
	get_page(ptrpage);
	return ptrpage;	
}


struct vm_operations_struct d11_dma_vm_ops = {
	open:  d11_dma_vma_open,
	close:  d11_dma_vma_close,
	nopage:   d11_dma_vma_nopage,
};

static unsigned int d11_dma_mmap(struct file *filp, struct vm_area_struct *vma)
{
	vma->vm_page_prot=pgprot_noncached(vma->vm_page_prot);
	vma->vm_flags |= VM_RESERVED;
	vma->vm_ops = &d11_dma_vm_ops;
	
	return 0;
}

ssize_t d11_dma_read(struct file *filp, char *buff, size_t count, loff_t *offp)
{
	return 0;
}

ssize_t d11_dma_write(struct file *filp, char *buff, size_t count, loff_t *offp)
{
	short head_tmp;
	unsigned short write_index = image_review_buf.tail_index;	
	copy_from_user(image_review_buf.image_dma_mmblk[write_index], buff, count);
	write_index++;
	if(write_index > image_review_buf.nr_mmblks) {
		write_index = 0;
	}
	image_review_buf.tail_index = write_index;
	
	if(image_review_buf.nr_images < image_review_buf.nr_mmblks) {
		image_review_buf.nr_images++;
	}
	
	/*****************  calculate the head_index of review area **********************/
	head_tmp = image_review_buf.tail_index - image_review_buf.nr_images;
	if(head_tmp >= 0) {
		image_review_buf.head_index = head_tmp;
	}
	else {
		image_review_buf.head_index = head_tmp + image_review_buf.nr_mmblks;
	}
	return count;
}

/*******************  PROC FS **********************************************/
static int d11_dma_proc_read(char* buf, char **start, off_t offset, int count, int *eof, void *data)
{
	int len = 0;
	len += sprintf(buf+len, "========= debug infomation for d11_dma ========\n");
	len += sprintf(buf+len, "INTMSK=0x%8x\n", INTMSK);
	len += sprintf(buf+len, "GPBCON=0x%8x\n", GPBCON);
	len += sprintf(buf+len, "GPBUP=0x%8x\n", GPBUP);
	len += sprintf(buf+len, "MISCCR=0x%8x\n", MISCCR);
	len += sprintf(buf+len, "DISRC0=0x%8x\n", DISRC0);
	len += sprintf(buf+len, "DISRCC0=0x%8x\n", DISRCC0);
	len += sprintf(buf+len, "DIDST0=0x%8x\n", DIDST0);
	len += sprintf(buf+len, "DIDSTC0=0x%8x\n", DIDSTC0);
	len += sprintf(buf+len, "DCON0=0x%8x\n", DCON0);
	len += sprintf(buf+len, "DMTRIG0=0x%8x\n", DMTRIG0);
	len += sprintf(buf+len, "=====================\n");
	len += sprintf(buf+len, "SRCPND=0x%8x\n", SRCPND);
	len += sprintf(buf+len, "INTPND=0x%8x\n", INTPND);
	len += sprintf(buf+len, "DSTAT0=0x%8x\n", DSTAT0);
	len += sprintf(buf+len, "DCSRC0=0x%8x\n", DCSRC0);
	len += sprintf(buf+len, "DCDST0=0x%8x\n", DCDST0);
	len += sprintf(buf+len, "=====================\n");
	len += sprintf(buf+len, "nr_mmblk=%d\n", image_review_buf.nr_mmblks);
	len += sprintf(buf+len, "nr_images=%d\n", image_review_buf.nr_images);
	len += sprintf(buf+len, "head_index=%d\n", image_review_buf.head_index);
	len += sprintf(buf+len, "tail_index=%d\n", image_review_buf.tail_index);
	len += sprintf(buf+len, "freeze=%d\n", image_review_buf.freeze);
	len += sprintf(buf+len, "=====================\n");
	len += sprintf(buf+len, "BWSCON=%8x\n", BWSCON);
	len += sprintf(buf+len, "BANKCON3=%8x\n", BANKCON3);
	len += sprintf(buf+len, "BANKCON5=%8x\n", BANKCON5);
	
	len += sprintf(buf+len, "LCDCON1=%8x\n", LCDCON1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -