📄 d11_dma.c
字号:
/*
**********************************************************
*
* 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 + -