📄 zt_io.c
字号:
#include <linux/module.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <asm/irq.h>#include <asm/arch/hardware.h>#include <asm/arch/irqs.h>#include <asm/io.h>#include <9200/AT91RM9200.h>#include <asm/uaccess.h>#include <linux/vmalloc.h>//#include <9200/AT91RM9200_inc.h>//#include <9200/lib_AT91RM9200.h>#define AT91C_BASE_PMC 0xFFFFFC00 // (PMC) Base Address#define AT91C_BASE_PIOC 0xFFFFF800 // (PIOC) Base Address#define AT91C_BASE_PIOB 0xFFFFF600 // (PIOB) Base Address#define MAX_DEV_NUM 6#define NUMPERTIME 4096#define MAX_DATA_NUM 409600typedef struct zt_io_dev{ u8* baseaddrb; u16* baseaddr; u32* at91_csr7; u32* st_wdmr; u32* st_cr; u16 *d1; spinlock_t lock; u32 irqtimes; u16 reg; u16 firstflag; u16 irq; u16 irqs; u32 storeindex; u32 retrieveindex; u8 wraparound; u8 adled; u8 num;}zt_io_dev,*pzt_io_dev;AT91_REG *per,*oer,*sodr,*codr,*smr3,*imr,*iccr,*idcr,*ffsr,*svr3,*fvr;//*isr,*ffsr,*cisr;AT91_REG *ierb,*perb,*idrb,*isrb,*pcer;const char*drvname[]={"zt_io-0","zt_io-1","zt_io-2","zt_io-3","zt_io-4","zt_io-5","zt_io-6"};void ztio_ad_int(int irq,void* dev_id,struct pt_regs *ress){ volatile u32 ret=0; int i=0; pzt_io_dev d=(pzt_io_dev)dev_id; ret=*isrb; if(!d)goto irqout; if(*(d->baseaddr+0x83) & 0x2)return; d->irqtimes++; spin_lock_irq(&d->lock); if(!d)goto irqout; if(!(*(d->baseaddr+0x83) & 0x4)){ d->firstflag=3; d->reg=*(d->baseaddr+0x83); goto irqout; } if(!(*(d->baseaddr+0x83) & 0x2)){ if((d->storeindex==d->retrieveindex) && d->wraparound){ d->firstflag=4; goto irqout; }else{ for(i=0;i<NUMPERTIME;i++){d->d1[(d->storeindex)++]=*(d->baseaddr+0x82);} if(d->storeindex>=MAX_DATA_NUM){ d->storeindex-=MAX_DATA_NUM; d->wraparound=1; } } d->firstflag=2; if(!(*(d->baseaddr+0x83) & 0x2)){ d->firstflag=6; goto irqout; } }else{ d->firstflag=5; d->reg=*(d->baseaddr+0x83); goto irqout; } spin_unlock_irq(&d->lock); return;irqout: (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_8 | AT91C_SMC2_BAT; *(d->baseaddrb+0x101)=0; (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_16 | AT91C_SMC2_BAT; free_irq(d->irq,d); d->irqs=0; spin_unlock_irq(&daq2005ad[num].lock);}ssize_t zt_io_write(struct file* f,const char* c,size_t st,loff_t* loff){ u32 errno; pzt_io_dev d=(pzt_io_dev)f->private_data; u32 address,v; if(st==8){ if((errno=copy_from_user(&address,c,4))!=0){ printk("<1>write 1copy_from_user error!\n"); return 0; } if((errno=copy_from_user(&v,c+4,4))!=0){ printk("<1>write 2copy_from_user error!,%x\n",errno); return 0; } if(address==0x400){ u16 t=v*1000/(128*1000000/32768); *d->st_wdmr=0x10000 | t; printk("<1>\n\n%d\n\n",t); } if(address==0x404){ *d->st_cr=v; if(!v)*d->st_wdmr=0; } (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_8 | AT91C_SMC2_BAT; *(d->baseaddrb+address)=v; (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_16 | AT91C_SMC2_BAT;// printk("<1>write byte %p!\n",d->baseaddr+address); } if(st==16){ if((errno=copy_from_user(&address,c,4))!=0){ printk("<1>write 1copy_from_user error!\n"); return 0; } if((errno=copy_from_user(&v,c+4,4))!=0){// printk("<1>write 2copy_from_user error!,%x\n",errno); return 0; } *(d->baseaddr+(address>>1))=v;// printk("<1>write word %p!\n",d->baseaddr+(address>>1)); } if(address==1000){ if(v){ if(!d->irqs){ printk("<1>daq2005ad_write:request_irq\n"); d->irqtimes=0;d->firstflag=0;d->storeindex=0;d->retrieveindex=0;d->wraparound=0; if(request_irq(d->irq,ztio_ad_int,SA_SHIRQ,drvname[d->num],d)){ printk("<1>daq2005ad_open:request_irq false\n"); } d->irqs=1; }else{printk("<1>daq2005ad_write:irq already request!!\n");} }else{ if(d->irqs){ printk("<1>daq2005ad_write:free_irq\n"); *(d->baseaddrb+0x101)=0; (*sodr)|=(AT91C_PIO_PC14); free_irq(d->irq,d); disable_irq(d->irq); d->irqs=0; }else{printk("<1>daq2005ad_write:irq already request!!\n");} } } if(address==1001) (*sodr)|=(AT91C_PIO_PC14); if(address==1002) (*codr)|=(AT91C_PIO_PC14); return st;}ssize_t zt_io_read(struct file* f,char* c,size_t st,loff_t* loff){ pzt_io_dev d=(pzt_io_dev)f->private_data; u32 address,v,retc; u32 errno; if(st==8){ if(copy_from_user(&address,c,4))printk("<1>read copy_from_user error!\n"); (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_8 | AT91C_SMC2_BAT; v=*(d->baseaddrb+address); (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_16 | AT91C_SMC2_BAT; if(copy_to_user(c+4,&v,4))printk("<1>read copy _from_user error!\n"); printk("<1>read byte %p!\n",d->baseaddr+address); } if(st==16){ if(copy_from_user(&address,c,4))printk("<1>read copy_from_user error!\n"); v=*(d->baseaddr+(address>>1)); if(copy_to_user(c+4,&v,4))printk("<1>read copy _from_user error!\n"); printk("<1>read word %p!\n",d->baseaddr+(address>>1)); } retc=st; if(st>8192){ spin_lock_irq(&d->lock); if((d->retrieveindex==d->storeindex) && d->wraparound){ printk("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); return -5; }else if(d->wraparound){// printk("%5x,%5x,%5x,%5x\n",d->p1,d->p2,*(d->addr10),d->wflag1); retc=MAX_DATA_NUM-d->retrieveindex; if((errno=copy_to_user(c,d->d1+d->retrieveindex,retc*2))!=0) {printk("<1>big read copy_to_user error!%d\n",retc);return -4;} d->retrieveindex=0; d->wraparound=0; }else if(d->retrieveindex==d->storeindex){ retc=0; printk("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); }else{ retc=d->storeindex-d->retrieveindex; if((errno=copy_to_user(c,d->d1+d->retrieveindex,retc*2))!=0) {printk("<1>big read copy_to_user error!%d\n",retc);return -4;} d->retrieveindex=d->storeindex; }// printk("%5x,%5x,%5x,%5x\n",d->p1,d->p2,*(d->addr10),d->wflag1); } spin_unlock_irq(&d->lock); return retc;}int zt_io_open(struct inode *inode,struct file *filp){ int num=MINOR(inode->i_rdev); pzt_io_dev d; if(num>MAX_DEV_NUM)return -ENODEV; d=kmalloc(sizeof(zt_io_dev),1); d->d1=(u16*)vmalloc(MAX_DATA_NUM*sizeof(u16)); d->firstflag=0;d->storeindex=0;d->retrieveindex=0;d->wraparound=0; if(!(d->d1)){ vfree(d->d1); printk("<1>vmalloc error: data1:%p\n",d->d1); return -ENODEV; } d->baseaddr = ioremap(0x80000000,0x400); d->baseaddrb =(u8*)d->baseaddr; d->at91_csr7 = ioremap(0xffffff8c,4); (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_16 | AT91C_SMC2_BAT; d->st_wdmr = ioremap(0xfffffd08,4); d->st_cr = ioremap(0xfffffd00,4); d->irq=3; d->irqs=0; d->num=num; *pcer=8; filp->private_data=(void*)d; return 0;}int zt_io_release(struct inode *inode,struct file *filp){ pzt_io_dev d=filp->private_data; if(d->irqs){ printk("<1>daq2005ad_release:free_irq\n"); (*sodr)|=(AT91C_PIO_PC14); free_irq(d->irq,d); disable_irq(d->irq); d->irqs=0; } spin_lock_irq(&d->lock); printk("<1>zt_io_close:fifo:%x,irq:%d,first:%d\n",*(d->baseaddr+0x83),d->irqtimes,d->firstflag); (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_8 | AT91C_SMC2_BAT; *(d->baseaddrb+0x101)=0; (*d->at91_csr7)=10 | AT91C_SMC2_WSEN | AT91C_SMC2_DBW_16 | AT91C_SMC2_BAT; iounmap(d->baseaddr); iounmap(d->at91_csr7); vfree(d->d1); d->d1=NULL; kfree(d); filp->private_data=NULL; spin_unlock_irq(&d->lock); return 0;}struct file_operations zt_io_fops={read:zt_io_read,write:zt_io_write,open:zt_io_open,release:zt_io_release,};int zt_io_major;static int __init zt_io_init(void){ zt_io_major=register_chrdev(253,"zt_io",&zt_io_fops); if(zt_io_major<0){ printk("zt_io:can't get major %d",zt_io_major); return zt_io_major; } per = ioremap(AT91C_BASE_PIOC+0,4); oer = ioremap(AT91C_BASE_PIOC+0x10,4); sodr = ioremap(AT91C_BASE_PIOC+0x30,4); codr = ioremap(AT91C_BASE_PIOC+0x34,4); perb = ioremap(AT91C_BASE_PIOB+0,4); ierb = ioremap(AT91C_BASE_PIOB+0x40,4); isrb = ioremap(AT91C_BASE_PIOB+0x4C,4); *ierb=(1<<28); pcer = ioremap(AT91C_BASE_PMC+0x10,4); smr3 = ioremap(AT91C_BASE_AIC+3*4,4); imr = ioremap(AT91C_BASE_AIC+0x110,4); iccr = ioremap(AT91C_BASE_AIC+0x128,4); idcr = ioremap(AT91C_BASE_AIC+0x124,4); ffsr = ioremap(AT91C_BASE_AIC+0x148,4); svr3 = ioremap(AT91C_BASE_AIC+0x80+3*4,4); fvr = ioremap(AT91C_BASE_AIC+0x104,4); (*per)|=(AT91C_PIO_PC14) | AT91C_PIO_PC15; (*oer)|=(AT91C_PIO_PC14) | AT91C_PIO_PC15; (*sodr)|=(AT91C_PIO_PC14); return 0;}static void __exit zt_io_exit(void){ (*codr)|=(AT91C_PIO_PC14); unregister_chrdev(253,"zt_io");}module_init(zt_io_init);module_exit(zt_io_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -