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

📄 rtd-dm7520.c

📁 rt 7520采集卡 linux驱动源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
}/*----------------------------------------------------------------*/#ifdef DEBUG/* DEBUG function for /proc/dm7520x output */void dm7520_getregs( int board,  uint32_t * itcsr, uint32_t * d0m,  uint32_t * d1m, uint32_t * d0s, uint32_t * d1s){ *itcsr=GETMEM32(board,LCFG,LCFG_ITCSR); *d0m=get_dma0mode(board); *d1m=get_dma1mode(board); *d0s=get_dma0status(board); *d1s=get_dma1status(board);}#endif //DEBUGvoid dm7520_incuse(void){ MOD_INC_USE_COUNT;}void dm7520_decuse(void){ MOD_DEC_USE_COUNT;}
static void wdma(int devminor, int dmach) {		 
	short bufferIndex;	if ((USEDTEMPBUFSIZE(devminor,dmach)-TEMPBUFOFFSET(devminor,dmach))<DMASIZE(devminor)) {
		TEMPBUFOFFSET(devminor,dmach) = 0;
	}
	bufferIndex = TEMPBUFOFFSET(devminor,dmach) / DMASIZE(devminor);
	memcpy(DMABUF(devminor,dmach),DMATEMPBUF(devminor,dmach)+TEMPBUFOFFSET(devminor,dmach), DMASIZE(devminor));
	TEMPBUFOFFSET(devminor,dmach)+=DMASIZE(devminor);#ifdef CHECK_FIFO_EMPTY		if ((dm7520_table[devminor].dmasetup[dmach].usedby==DM7520_WRITE_DA1)?DA1_FIFONE:DA2_FIFONE) {
#endif		if (0==dmach) {
		    start_dma0(devminor);
		}
		else {
		    start_dma1(devminor);
		}
		if (BUFFER_READY==TEMPBUFFLAG(devminor,dmach,bufferIndex)) 
			TEMPBUFFLAG(devminor,dmach,bufferIndex) = BUFFER_COPIED;
		else
			TEMPBUFFLAG(devminor,dmach,bufferIndex) = BUFFER_NOT_READY;
#ifdef CHECK_FIFO_EMPTY					}
	else {
		TEMPBUFFLAG(devminor,dmach,bufferIndex) = FIFO_EMPTY;
		TEMPBUFFLAG(devminor,dmach,CONTROLFLAGSIZE-1) = FIFO_EMPTY;
		printk("<1>FIFO EMPTY\n");	}		
#endif	}

static voiddm7520_interrupt(int irq, void *dev_id, struct pt_regs *regs) {    static uint32_t	dmastatus;    static uint32_t	itoverrun;    static uint32_t	dummy;    static uint32_t	itcsr;    DM7520_STAT		*devptr = (DM7520_STAT *) dev_id;    int			devminor;    int			dmach;    devminor = devptr - &(dm7520_table[0]);    if ((devminor < 0) || (devminor >= MAXDM7520)) {	return;    }    itstatus = GETMEM32(devminor, LAS0, LAS0_IT) & 0x0000FFFF;    itcsr = GETMEM32(devminor, LCFG, LCFG_ITCSR);    dmastatus = itcsr & (PIRQS_DMA0 | PIRQS_DMA1);    if (! (itstatus | dmastatus)) {	return; // Not our interrupt    }    if (dmastatus) {	dummy = GETMEM32(devminor, LCFG, LCFG_DMACSR);	 	if (dmastatus & PIRQS_DMA0) {	    dummy |= 0x00000008;	    PUTMEM32(devminor, LCFG, LCFG_DMACSR, dummy);  // clear interrupt	    dmach = 0;	} else { // PIRQS_DMA1	    dummy |= 0x00000800;	    PUTMEM32(devminor, LCFG, LCFG_DMACSR, dummy);  // clear interrupt	    dmach = 1;	}	if (dm7520_table[devminor].dmasetup[dmach].direction == DMAD_FROMCARD) {	    wake_up(&(dm7520_table[devminor].readq));	} else {	    wdma(devminor, dmach);	}    }    PUTMEM32(devminor, LAS0, LAS0_CLEAR, 0xffffffff);    dummy = GETMEM32(devminor, LAS0, LAS0_CLEAR);    itoverrun = GETMEM32(devminor, LAS0, LAS0_OVERRUN) & 0x0000FFFF;    if (itoverrun) {	dm7520_table[devminor].errcode = ERR_IT_OVERRUN;	PUTMEM32(devminor, LAS0, LAS0_IT, 0);	PUTMEM32(devminor, LAS0, LAS0_OVERRUN, 0);    }    /*     * TODO: async notifications should be done in bottom half     */    if (devptr->async_queue) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/*	 * The kernel shipped with Redhat 6.2 (2.2.14-5.0) has a patch applied	 * to it which changes kill_fasync.  It needs 3 args, like the 2.4	 * version, but the first arg must not be passed by reference.  I think	 * this change was a backport from the 2.3 kernel series, which was	 * still under development when RH6.2 was released. Note that I check	 * for only Redhat's 2.2.14.  This problem may exist with other distros	 * that ship patched kernels.	 */#define RH_KERNEL_VERSION_H defined(__rh_kernel_version_h__)#define KERNEL_IS_2_2_14 (LINUX_VERSION_CODE == KERNEL_VERSION(2, 2, 14))#if RH_KERNEL_VERSION_H && KERNEL_IS_2_2_14	kill_fasync(devptr->async_queue, SIGIO, POLL_IN);#else	kill_fasync(devptr->async_queue, SIGIO);#endif#undef RH_KERNEL_VERSION_H#undef IS_KERNEL_2_2_14#else	kill_fasync(&(devptr->async_queue), SIGIO, POLL_IN);#endif   }}static int dm7520_open(struct inode *inode, struct file *file){  short devminor,devmajor;
  devmajor=inode->i_rdev>>8;  devminor=inode->i_rdev&0xFF;  if (devminor >= MAXDM7520) return -ENXIO;  if (!dm7520_table[devminor].present) return -ENXIO;  if (dm7520_table[devminor].opened) return -EBUSY;  dm7520_table[devminor].opened++;  dm7520_table[devminor].readchan=DM7520_READ_AD;	//AD by default//  dm7520_table[devminor].writechan=DM7520_WRITE_DA1;  dm7520_table[devminor].errcode=0;  init_waitqueue_head(&(dm7520_table[devminor].inq));  init_waitqueue_head(&(dm7520_table[devminor].outq));  init_waitqueue_head(&(dm7520_table[devminor].readq));  init_waitqueue_head(&(dm7520_table[devminor].writeq));
 //----------------------------  dm7520_table[devminor].dmasetup[0].dmainuse=0;    dm7520_table[devminor].dmasetup[0].usedby=-1;
  dm7520_table[devminor].dmasetup[0].tempBufOffset = 0;		//used for writing DMA
  dm7520_table[devminor].dmasetup[0].tempBufSize = 0;		//used for writing DMA  dm7520_table[devminor].dmasetup[1].dmainuse=0;    dm7520_table[devminor].dmasetup[1].usedby=-1;
  dm7520_table[devminor].dmasetup[1].tempBufOffset = 0;		//used for writing DMA
  dm7520_table[devminor].dmasetup[1].tempBufSize = 0;		//used for writing DMA


  //-----------------------------------------------  memset(dm7520_table[devminor].dmasetup[0].dmabuf,0,DMASIZE(devminor));  memset(dm7520_table[devminor].dmasetup[1].dmabuf,0,DMASIZE(devminor));  reset_card(devminor);  dm7520_incuse();  return SUCCESS;}
static int dm7520_release(struct inode *inode, struct file *file){  short devminor,devmajor;  int dmach;  devmajor=inode->i_rdev>>8;  devminor=inode->i_rdev&0xFF;   if (devminor >= MAXDM7520) return -ENXIO;  if (!dm7520_table[devminor].present) return -ENXIO;  if (!dm7520_table[devminor].opened) return -EBUSY;   dm7520_fasync(-1, file, 0);  reset_card(devminor);  dm7520_table[devminor].dmasetup[0].dmainuse=0;  dm7520_table[devminor].dmasetup[1].dmainuse=0;  disable_dma(devminor,0);  disable_dma(devminor,1);  for (dmach=0;dmach<2;dmach++)    {      dm7520_table[devminor].dmasetup[dmach].dmainuse=0;     dm7520_table[devminor].dmasetup[dmach].direction=0;     dm7520_table[devminor].dmasetup[dmach].dmaladdr=0;	 dm7520_table[devminor].dmasetup[dmach].tempBufOffset = 0;		//used for writing DMA
     dm7520_table[devminor].dmasetup[dmach].tempBufSize = 0;		//used for writing DMA          dm7520_table[devminor].dmasetup[dmach].usedby=-1;    }   dm7520_table[devminor].opened--;  dm7520_table[devminor].errcode=0;//  dm7520_table[devminor].readchan=DM7520_READ_AD;//  dm7520_table[devminor].writechan=DM7520_WRITE_DA1;  init_waitqueue_head(&(dm7520_table[devminor].inq));  init_waitqueue_head(&(dm7520_table[devminor].outq));  init_waitqueue_head(&(dm7520_table[devminor].readq));  init_waitqueue_head(&(dm7520_table[devminor].writeq));  dm7520_decuse();  return 0;}static intdm7520_read(short devminor, int16_t *user_buf, int length) {    int		bytes_read;    char	*buffer = (char *) user_buf;    int		i;    int		dmach;    int		halffifobyte = DMASIZE(devminor); //size of 1/2 fifo in bytes    int size;    bytes_read = 0;    /*     * length is actually the number of samples to read, so convert it to     * bytes     */    length = length * 2;    if (devminor >= MAXDM7520) return -ENXIO;    if (! dm7520_table[devminor].present) return -ENXIO;    if (! dm7520_table[devminor].opened) return -EBUSY;    if (0 != dm7520_table[devminor].errcode)	return (dm7520_table[devminor].errcode);    bytes_read = 0;    if (length < 0)	return(0);    for (dmach = 0; dmach < 2; dmach++) {	if (	    dm7520_table[devminor].dmasetup[dmach].usedby	    ==	    dm7520_table[devminor].readchan	) {	    break;	}    }    if (! (dmach < 2)) {  //NON-DMA mode	do {	    if (dm7520_table[devminor].readchan == DM7520_READ_AD) {		while ((bytes_read < length) && ADC_FIFONE) {		    if (			put_user(			    GETMEM16(devminor, LAS1, LAS1_ADC_FIFO), user_buf			)			!=			0		    ) {			return -EFAULT;		    }		    user_buf++;		    bytes_read += 2;		}	    } else {		while ((bytes_read < length) && HDIN_FIFONE) {		    if (			put_user(			    GETMEM16(devminor, LAS1, LAS1_HDIO_FIFO), user_buf			)			!=			0		    ) {			return -EFAULT;		    }		    user_buf++;		    bytes_read += 2;		}	    }	    if (bytes_read >= length) return (bytes_read / 2);	    interruptible_sleep_on_timeout(		&(dm7520_table[devminor].readq), dm7520_table[devminor].jiffie_r	    );	    if (signal_pending(current))		return -ERESTARTSYS;	} while (1);    } else {  //DMA mode	  i = length;	do {	    if (dm7520_table[devminor].readchan == DM7520_READ_AD) {		if(! AD_FIFONF) {		    dm7520_table[devminor].errcode = -ENOBUFS;		    printk(			KERN_INFO			"dm7520: dma: AD fifo got full before previous "			"circle finished\n"		    );		    return (bytes_read / 2);		}	    } else {		if(! HD_FIFONF) {		    dm7520_table[devminor].errcode = -ENOBUFS;		    printk(			KERN_INFO			"dm7520: dma: HD fifo got full before previous circle "			"finished\n"		    );		    return (bytes_read / 2);		}	    }	    if (dmach == 0) {		enable_dma0(devminor);		if (		    dm7520_table[devminor].readchan		    ==		    DM7520_READ_HD		) {		    reset_dma0(devminor);		}		start_dma0(devminor);	    } else {		enable_dma1(devminor);		if (		    dm7520_table[devminor].readchan		    ==		    DM7520_READ_HD		) {		    reset_dma1(devminor);		}		start_dma1(devminor);	    }	    interruptible_sleep_on(&(dm7520_table[devminor].readq));	    if (signal_pending(current)) {		printk(KERN_INFO "dm7520: dma - time out\n");		return -ERESTARTSYS;	    }	    size = (halffifobyte > i) ? i : halffifobyte;	    if (copy_to_user(buffer, (char *) DMABUF(devminor,dmach), size)) {		return -EFAULT;	    }	    bytes_read += size;	    i -= size;	    buffer += size;	    if (bytes_read >= length) {		return (bytes_read / 2);	    }	} while (1);    }}static int dm7520_ioctl( struct inode *inode, struct file *file,                  unsigned int ioctl_num, unsigned long ioctl_param){  dm7520_request req;  dm7520_request *temp = &req;  dm7520_read_request readreq;  dm7520_read_request *readtemp = &readreq;  short devminor,devmajor;  int dmach;  int channel;  uint32_t dmapaddr = 0; // phisical address of dma buffer
  devminor=MINOR(file->f_dentry->d_inode->i_rdev);  devmajor=MAJOR(file->f_dentry->d_inode->i_rdev);  if (devminor >= MAXDM7520) return -ENXIO;  if (!dm7520_table[devminor].present) return -ENXIO;  if (!dm7520_table[devminor].opened) return -EBUSY;//  temp = (dm7520_request *) ioctl_param;	if (DM7520IOCREAD==ioctl_num) {    	if (copy_from_user((void*)readtemp, (void*)ioctl_param, sizeof(dm7520_read_request)))	    	return -EFAULT;      return dm7520_read(devminor, readtemp->pBuf, readtemp->size);   }   else {    if (copy_from_user((void*)temp, (void*)ioctl_param, sizeof(dm7520_request)))	    return -EFAULT;   }  switch (ioctl_num) {    case DM7520IOCGETREG:	  if (temp->las>LASMAX) return -EINVAL;      if (LAS1==temp->las)        temp->data=GETMEM16(devminor,temp->las,temp->addr);      else {        if (LAS0_IT==temp->addr) {	    temp->data = itstatus;	    itstatus = 0;	}	else    	    temp->data=GETMEM32(devminor,temp->las,temp->addr);//     printk(KERN_INFO "getreg: minor=%X, las=%X, addr=%X, data=%X \n",//    		    devminor,temp->las,temp->addr,temp->data);	}      if(copy_to_user((void*)ioctl_param,(void*)temp,sizeof(dm7520_request)))            return -EFAULT;      break;

⌨️ 快捷键说明

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