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

📄 zt_io.c

📁 pc104接口在arm9200开发板上的驱动程序
💻 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 + -