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

📄 fmc.c~

📁 这是一个基于S3C2440 的VGA 驱动程序, 其中fc.c 是驱动程序,fc_test.c 是测试代码. 这是一个在LINUX frame buffer基础上利用 DMA 实现的高效驱动, 绝
💻 C~
字号:
#include <linux/kernel.h>	/* We're doing kernel work */
#include <linux/module.h>	/* Specifically, a module */
#include <linux/fs.h>#include <asm/uaccess.h>	/* for get_user and put_user */#include <asm-arm/io.h>#include <linux/mm.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <linux/stat.h>#include <linux/param.h>#include <linux/sched.h>#include <linux/time.h>#include <linux/timer.h>#include <linux/ioctl.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/dma-mapping.h>#include <linux/slab.h>#include <asm/dma.h>#include <asm/dma-mapping.h>
#include <asm/arch/dma.h>#include <asm/io.h>//#include "tp1.c"#include "fst2_c.c"//#include "fstc.c"//#include "pst_e.c"//#include "pst_3.c"#include "pst_c.c"//#include "smain_e.c"//#include "sm2.c"//#include "smv2.c"//#include "smv3.c"//#include "smv3_2.c"#include "smv4c.c"//#include "set3.c"#define SUCCESS 0
#define DEVICE_NAME "fmc"
#define BUF_LEN 80
#define RLEN    10#define BZBASE     0x08000000#define BZSIZE     0x158#define BZ_OFFSET  0x08#define INTERVAL   2#define LCDSADDR1   0x4d000014#define LCDSADDR2   0x4d000018#define LCDR1       0x4d000000#define LCDR2       0x4d000004#define LCDR3       0x4d000008#define LCDR4       0x4d00000c#define LCDR5       0x4d000010#define rINTMSK     0x4a000008	//Interrupt mask control#define rSRCPND     0x4a000000  //Interrupt request status#define rINTPND     0x4a000010	//Interrupt request status#define LCD_XSIZE_TFT 	(640)	
#define LCD_YSIZE_TFT 	(480)#define SCR_XSIZE_TFT 	(640)
#define SCR_YSIZE_TFT 	(480)
#define FM_IOC_MAGIC 'F'#define FM_IOC_VIDEO_SWITCH    _IOWR(FM_IOC_MAGIC, 1, int)typedef struct tagDMA                                       
{ 
    unsigned int  DISRC;             //0x0 
    unsigned int  DISRCC;            //0x4 
    unsigned int  DIDST;             //0x8 
    unsigned int  DIDSTC;            //0xc 
    unsigned int  DCON;              //0x10 
    unsigned int  DSTAT;             //0x14 
    unsigned int  DCSRC;             //0x18 
    unsigned int  DCDST;             //0x1c 
    unsigned int  DMASKTRIG;         //0x20 
}DMA; static struct s3c2410_dma_client s3c2410mem_dma_client = {	.name		= "s3c2410-mem",};irqreturn_t  intdone(int irq,void *dev_id,struct pt_regs *regs);static int Device_Open = 0;

static char Message[BUF_LEN];

static char *Message_Ptr;
struct vm_area_struct *vma;unsigned long addrs, lcda1,lcda2,lcdr1,lcdr2,lcdr3,lcdr4,lcdr5,buf_add;struct timer_list jiq_timer;int beep_time=0,cd=0;//unsigned char tfbuf[LCD_XSIZE_TFT*LCD_YSIZE_TFT*2];unsigned char* fbp;dma_addr_t dma_ad;extern int Request_a_DMA(int channel);extern void DMA_M2M(int ch,int srcAddr,int dstAddr,int tc,int dsz,int burst);extern void PaintBi_ValueBitmap(unsigned char* pp,unsigned int x,unsigned int y,unsigned int width,unsigned int high,unsigned int color0,unsigned int color1);extern void PaintBitmap(unsigned char* pp,int x,int y,int width,int high);static int device_open(struct inode *inode, struct file *filp)
{        unsigned int buf_l,i;        printk("In open\n");
	/*if (Device_Open)        {            printk("fm_re_open! error!!--Open_count=%d\n",Device_Open);
		return -EBUSY;        }*/
	Device_Open++;

	Message_Ptr = Message;        lcda1=(unsigned long)ioremap(LCDSADDR1,8);        if(!lcda1)        {            printk("lcda1_remap error!!\n");            return -EIO;        }        buf_l=ioread32(lcda1+0);        fbp=(unsigned char*)((buf_l)<<1);        printk("BUF_add=%x\n",fbp);        lcda1=(unsigned long)ioremap((buf_l)<<1,0x96000);        if(!lcda1)        {            printk("lcda1_remap error!!\n");            return -EIO;        }  /*      buf_add=(void *)__get_free_pages(__GFP_DMA,8);        if(!buf_add) printk("No_free_memory!\n");        else         {            //PaintBi_ValueBitmap(fst,0,0,640,480,0x07ff,0x1f);            PaintBitmap(fstc,0,0,640,480);            dma_ad=dma_map_single(NULL,buf_add,PAGE_SIZE<<4,DMA_TO_DEVICE);            //buf_add=dma_ad;            printk("buf_add=%x\n",dma_ad);            //memset(buf_add,0,PAGE_SIZE<<4);        }*/	return SUCCESS;
}static void PutPixel(unsigned int x,unsigned int y,unsigned int c)
{
    if(x<SCR_XSIZE_TFT && y<SCR_YSIZE_TFT)    {
           *((unsigned char *)buf_add+(y*LCD_XSIZE_TFT+x)*2)=c%256;           *((unsigned char *)buf_add+(y*LCD_XSIZE_TFT+x)*2+1)=c/256;;
  //      frameBuffer16BitTft[(y)][(x)] = c;    }
}
void PaintBitmap(unsigned char* pp,int x,int y,int width,int high){    printk("In PaintBitmap\n");    int i,j,k;    for(j=0;j<high;j++)    {        for(i=0;i<width;i++)        {            k=*(pp+(j*width+i)*2)<<8;            PutPixel(i+x,j+y,k+(*(pp+(j*width+i)*2+1)));        }    }}void PaintBi_ValueBitmap(unsigned char* pp,unsigned int x,unsigned int y,unsigned int width,unsigned int high,unsigned int color0,unsigned int color1)    //xy
{
    int i,j,k,l;
    unsigned char tmp;
    for(j=0;j<high;j++)
    {
        for(i=0;i<width/8;i++)
        {
            k=*(pp+j*width/8+i);
            tmp=0x80;
            for(l=0;l<8;l++)
            {
                if(l>0)
                    tmp=tmp>>1;
                if(((tmp&k)&0xff)!=0)
                {
                    PutPixel(i*8+l+x,j+y,color1);
                }
                else
                {
                    PutPixel(i*8+l+x,j+y,color0);
                }
            }
        }
    }
}static ssize_t device_write(struct file *filp,
	     const char * buffer, size_t length, loff_t * offset)
{
	int i,mf=0;
        printk("In Write.\n");        buf_add=(void *)__get_free_pages(__GFP_DMA,8);        if(!buf_add) printk("No_free_memory!\n");        else         {            //PaintBi_ValueBitmap(fst,0,0,640,480,0x07ff,0x1f);            //PaintBitmap(fstc,0,0,640,480);            //dma_ad=dma_map_single(NULL,buf_add,PAGE_SIZE<<4,DMA_TO_DEVICE);            //buf_add=dma_ad;            printk("buf_add=%x\n",dma_ad);            //memset(buf_add,0,PAGE_SIZE<<4);        }
	for (i = 0; (i < length) && (i < BUF_LEN); i++)
		get_user(Message[i], buffer + i);
	Message_Ptr = Message;        switch(Message[0])        {            case 0:   PaintBitmap(fst2_c,0,0,640,480);                      break;            case 1:   PaintBitmap(pst_c,0,0,640,480);                      break;            case 2:   PaintBitmap(smv4c,0,0,640,480);                      break;            //case 3:   PaintBitmap(set3,0,0,640,480);            //          break;        }        i=0;        do        {            mf=Request_a_DMA(i);            if(mf!=0)             {                printk("Burst channel%d busy.\n",i);                i++;            }        }while((i<4)&&(mf!=0));        printk("BurstID=%d.\n",i);        if(i==4)        {              printk("All burst channel busy!!\n");              return -1;        }        dma_ad=dma_map_single(NULL,buf_add,PAGE_SIZE<<4,DMA_TO_DEVICE);
	DMA_M2M(i,dma_ad,fbp, 0x9600,2,1); //word,burst*/        dma_unmap_single(NULL,buf_add,PAGE_SIZE<<4,DMA_TO_DEVICE);        free_pages(buf_add,8);
	return i;
}static int device_release(struct inode *inode, struct file *filp)
{        
	if(Device_Open>0) Device_Open--;
        printk("In release Open_count=%d\n",Device_Open);//        free_pages(buf_add,8);
	//module_put(THIS_MODULE);
	return SUCCESS;
}int Request_a_DMA(int channel){    DMA *pDMA;     printk("In Request_a_DMA.\n");    switch(channel) 
    { 
        case 0: 
            pDMA=(unsigned long)ioremap(0x4b000000,0x40); 
            break; 
       case 1: 
            pDMA=(unsigned long)ioremap(0x4b000040,0x40); 
            break; 
       case 2: 
            pDMA=(unsigned long)ioremap(0x4b000080,0x40); 
            break; 
       case 3: 
            pDMA=(unsigned long)ioremap(0x4b0000c0,0x40); 
            break; 
    }         if(((pDMA->DSTAT)&0x300000)!=0) return 1;   //busy    else return 0;                              //ready}void DMA_M2M(int ch,int srcAddr,int dstAddr,int tc,int dsz,int burst) 
{ 
    DMA *pDMA; 
    int length,buf; 
    printk("In burst.\n");
    length=tc*(burst ? 4:1)*((dsz==0)+(dsz==1)*2+(dsz==2)*4); 
    switch(ch) 
    { 
        case 0: 
            pDMA=(unsigned long)ioremap(0x4b000000,0x40); 
            break; 
       case 1: 
            pDMA=(unsigned long)ioremap(0x4b000040,0x40); 
            break; 
       case 2: 
            pDMA=(unsigned long)ioremap(0x4b000080,0x40); 
            break; 
       case 3: 
            pDMA=(unsigned long)ioremap(0x4b0000c0,0x40); 
            break; 
    }         pDMA->DISRC=srcAddr; 
    pDMA->DISRCC=(0<<1)|(0<<0); // inc,AHB 
    pDMA->DIDST=dstAddr; 
    pDMA->DIDSTC=(0<<1)|(0<<0); // inc,AHB 
    pDMA->DCON=tc|(1<<31)|(1<<30)|(0<<29)|(burst<<28)|(1<<27)|(0<<23)|(1<<22)|(dsz<<20)|(tc); 
//HS,AHB,TC no-interrupt,whole, SW request mode,relaod off 
    pDMA->DMASKTRIG=(1<<1)|1; //DMA on, SW_TRIG 
    printk("Burst started!\n");    buf=ioread32(pDMA+0x14);
    while((buf&0xfffff)!=0)    {        buf=ioread32(pDMA+0x14);    } ;     //CTRR_TC
    printk("Burst finished\n"); 
}
struct file_operations Fops = {
//	.read = device_read,
	.write = device_write,
//	.ioctl = device_ioctl,
	.open = device_open,
	.release = device_release,	/* a.k.a. close */
};int ret_val;
int init_module()
{
	

	ret_val = register_chrdev(0, DEVICE_NAME, &Fops);
	if (ret_val < 0) {
		printk("failed with %d\n",ret_val);
		return ret_val;
	}
	printk("The major device number is %d.\n", ret_val);
	printk("If you want to talk to the device driver,\n");
	printk("you'll have to create a device file. \n");
	printk("We suggest you use:\n");
	printk("mknod %s c %d 0\n", DEVICE_NAME, ret_val);
	printk("The device file name is important, because\n");
	printk("the ioctl program assumes that's the\n");
	printk("file you'll use.\n");
	return 0;
}


void cleanup_module()
{
	int ret;

	ret = unregister_chrdev(ret_val, DEVICE_NAME);

	if (ret < 0)
		printk("Error in module_unregister_chrdev: %d\n", ret);
}

⌨️ 快捷键说明

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