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

📄 pcl816.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if(!dev->attached) {		comedi_error(dev, "premature interrupt");		return;	}	switch (devpriv->int816_mode)  {    case INT_TYPE_AI1_DMA:    case INT_TYPE_AI3_DMA:		interrupt_pcl816_ai_mode13_dma (irq, d, regs);		return;    case INT_TYPE_AI1_INT:    case INT_TYPE_AI3_INT:		interrupt_pcl816_ai_mode13_int (irq, d, regs);		return;    }	outb (0, dev->iobase + PCL816_CLRINT);	/* clear INT request */	if ((!dev->irq) | (!devpriv->irq_free) | (!devpriv->irq_blocked) |      (!devpriv->int816_mode))    {		if (devpriv->irq_was_now_closed)	{			devpriv->irq_was_now_closed = 0;			// comedi_error(dev,"last IRQ..");			return;		}		comedi_error (dev, "bad IRQ!");		return; 	}	comedi_error (dev, "IRQ from unknow source!");}/*==============================================================================   COMMAND MODE*/static void pcl816_cmdtest_out(int e,comedi_cmd *cmd) {	rt_printk("pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n",e,cmd->start_src,cmd->scan_begin_src,cmd->convert_src);	rt_printk("pcl816 e=%d startarg=%d scanarg=%d convarg=%d\n",e,cmd->start_arg,cmd->scan_begin_arg,cmd->convert_arg);	rt_printk("pcl816 e=%d stopsrc=%x scanend=%x\n",e,cmd->stop_src,cmd->scan_end_src);	rt_printk("pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",e,cmd->stop_arg,cmd->scan_end_arg,cmd->chanlist_len);}/* ==============================================================================*/static int pcl816_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){	int err=0;	int tmp,divisor1,divisor2;DEBUG(	rt_printk("pcl816 pcl812_ai_cmdtest\n");	pcl816_cmdtest_out(-1, cmd););	/* step 1: make sure trigger sources are trivially valid */	tmp=cmd->start_src;	cmd->start_src &= TRIG_NOW;	if(!cmd->start_src || tmp!=cmd->start_src)err++;	tmp=cmd->scan_begin_src;	cmd->scan_begin_src &= TRIG_FOLLOW;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	if(!cmd->convert_src & (TRIG_EXT | TRIG_TIMER)) err++;	tmp=cmd->scan_end_src;	cmd->scan_end_src &= TRIG_COUNT;	if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;	tmp=cmd->stop_src;	cmd->stop_src &= TRIG_COUNT|TRIG_NONE;	if(!cmd->stop_src || tmp!=cmd->stop_src)err++;	if(err) {		return 1;	}	/* step 2: make sure trigger sources are unique and mutually compatible */	if(cmd->start_src!=TRIG_NOW) {		cmd->start_src=TRIG_NOW;		err++;	}	if(cmd->scan_begin_src!=TRIG_FOLLOW) {		cmd->scan_begin_src=TRIG_FOLLOW;		err++;	}	if(cmd->convert_src!=TRIG_EXT &&	   cmd->convert_src!=TRIG_TIMER) {			cmd->convert_src=TRIG_TIMER;			err++;	}		if(cmd->scan_end_src!=TRIG_COUNT) {		cmd->scan_end_src=TRIG_COUNT;		err++;	}	if(cmd->stop_src!=TRIG_NONE &&	   cmd->stop_src!=TRIG_COUNT) err++;	if(err) {		return 2;	}	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_arg!=0){		cmd->start_arg=0;		err++;	}	if(cmd->scan_begin_arg!=0){		cmd->scan_begin_arg=0;		err++;	}	if(cmd->convert_src==TRIG_TIMER){		if(cmd->convert_arg<this_board->ai_ns_min){			cmd->convert_arg=this_board->ai_ns_min;			err++;		}	} else { /* TRIG_EXT */		if(cmd->convert_arg!=0){			cmd->convert_arg=0;			err++;		}	}	if(!cmd->chanlist_len){		cmd->chanlist_len=1;		err++;	}	if(cmd->chanlist_len > this_board->n_aichan){		cmd->chanlist_len=this_board->n_aichan;		err++;	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		if(!cmd->stop_arg){			cmd->stop_arg=1;			err++;		}	} else { /* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err) {		return 3;	}	/* step 4: fix up any arguments */	if(cmd->convert_src==TRIG_TIMER){		tmp=cmd->convert_arg;		i8253_cascade_ns_to_timer (this_board->i8254_osc_base,			&divisor1, &divisor2, &cmd->convert_arg,			cmd->flags & TRIG_ROUND_MASK);		if(cmd->convert_arg<this_board->ai_ns_min)			cmd->convert_arg=this_board->ai_ns_min;		if(tmp!=cmd->convert_arg)err++;	}	if(err) {		return 4;	}	return 0;}static int pcl816_ai_cmd(comedi_device *dev,comedi_subdevice *s){	unsigned int	divisor1, divisor2, dma_flags, bytes, dmairq;	comedi_cmd 	*cmd=&s->async->cmd;		if(cmd->start_src!=TRIG_NOW) return -EINVAL;	if(cmd->scan_begin_src!=TRIG_FOLLOW) return -EINVAL;	if(cmd->scan_end_src!=TRIG_COUNT) return -EINVAL;	if(cmd->scan_end_arg!=cmd->chanlist_len) return -EINVAL;//	if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL;    if (devpriv->irq_blocked)    	return -EBUSY;	if (cmd->convert_src==TRIG_TIMER) {		if(cmd->convert_arg < this_board->ai_ns_min) 			cmd->convert_arg=this_board->ai_ns_min; 	     i8253_cascade_ns_to_timer (this_board->i8254_osc_base, &divisor1,				 &divisor2, &cmd->convert_arg, cmd->flags&TRIG_ROUND_MASK); 	     if (divisor1 == 1) {			// PCL816 crash if any divisor is set to 1 			  divisor1 = 2;			  divisor2 /= 2;		 }  		 if (divisor2 == 1) {		   divisor2 = 2;		   divisor1 /= 2;		 }	}	start_pacer(dev, -1, 0, 0); // stop pacer	if (!check_and_setup_channel_list (dev, s, cmd->chanlist, cmd->chanlist_len))	    return -EINVAL;	comedi_udelay (1);		    devpriv->ai_act_scan=0;    s->async->cur_chan=0;	devpriv->irq_blocked = 1;	devpriv->ai_poll_ptr=0;	devpriv->irq_was_now_closed = 0;		if (cmd->stop_src==TRIG_COUNT) { 		devpriv->ai_scans = cmd->stop_arg; 		devpriv->ai_neverending = 0; 	} else { 		devpriv->ai_scans = 0; 		devpriv->ai_neverending = 1; 	}	if ((cmd->flags & TRIG_WAKE_EOS)) { 	// don't we want wake up every scan?				printk("pl816: You wankt WAKE_EOS but I dont want handle it");		//		devpriv->ai_eos=1;		//if (devpriv->ai_n_chan==1)		//	devpriv->dma=0;	// DMA is useless for this situation	}	if (devpriv->dma) {		    bytes = devpriv->hwdmasize[0];		if (!devpriv->ai_neverending) {	      bytes = s->async->cmd.chanlist_len * s->async->cmd.chanlist_len * sizeof (sampl_t);	// how many     	  devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	// how many DMA pages we must fill   		  devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	//on last dma transfer must be moved 	      devpriv->dma_runs_to_end--;     	  if (devpriv->dma_runs_to_end >= 0)			bytes = devpriv->hwdmasize[0];		} else			devpriv->dma_runs_to_end = -1;		devpriv->next_dma_buf = 0;		set_dma_mode (devpriv->dma, DMA_MODE_READ);		dma_flags = claim_dma_lock ();		clear_dma_ff (devpriv->dma);		set_dma_addr (devpriv->dma, devpriv->hwdmaptr[0]);		set_dma_count (devpriv->dma, bytes);		release_dma_lock (dma_flags);		enable_dma (devpriv->dma);	}		start_pacer(dev, 1, divisor1, divisor2);	dmairq = ((devpriv->dma & 0x3)<<4) | (dev->irq & 0x7);	switch (cmd->convert_src) {	case TRIG_TIMER:        devpriv->int816_mode = INT_TYPE_AI1_DMA;        outb (0x32, dev->iobase + PCL816_CONTROL);  // Pacer+IRQ+DMA   	    outb(dmairq, dev->iobase + PCL816_STATUS);  // write irq and DMA to card		break;	default:		devpriv->int816_mode = INT_TYPE_AI3_DMA;		outb (0x34, dev->iobase + PCL816_CONTROL);	// Ext trig+IRQ+DMA		outb(dmairq, dev->iobase + PCL816_STATUS); // write irq to card		break;	}    DPRINTK("pcl816 END: pcl812_ai_cmd()\n");    return 0;}static int pcl816_ai_poll(comedi_device *dev,comedi_subdevice *s){	unsigned long flags;    unsigned int top1,top2,i;	if (!devpriv->dma) return 0; // poll is valid only for DMA transfer	comedi_spin_lock_irqsave(&dev->spinlock, flags);	for (i=0; i<20; i++) {		top1 = get_dma_residue(devpriv->dma); // where is now DMA		top2 = get_dma_residue(devpriv->dma);		if (top1 == top2) break;	}	if (top1 != top2) {		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);		return 0;	}	top1 = devpriv->hwdmasize [0] - top1; // where is now DMA in buffer	top1 >>= 1; // sample position	top2 = top1 - devpriv->ai_poll_ptr;	if (top2 < 1) { // no new samples		comedi_spin_unlock_irqrestore(&dev->spinlock,flags);		return 0;	}	transfer_from_dma_buf(dev, s, (sampl_t*)devpriv->dmabuf[devpriv->next_dma_buf],				devpriv->ai_poll_ptr, top2);	devpriv->ai_poll_ptr = top1; // new buffer position	comedi_spin_unlock_irqrestore(&dev->spinlock,flags);	return s->async->buf_write_count - s->async->buf_read_count;}/* ============================================================================== cancel any mode 1-4 AI*/static intpcl816_ai_cancel (comedi_device * dev, comedi_subdevice * s){//  DEBUG(rt_printk("pcl816_ai_cancel()\n");)    if (devpriv->irq_blocked > 0) {  switch (devpriv->int816_mode)	{	case INT_TYPE_AI1_DMA_RTC:	case INT_TYPE_AI3_DMA_RTC:	  set_rtc_irq_bit (0);	// stop RTC	  del_timer (&devpriv->rtc_irq_timer);	case INT_TYPE_AI1_DMA:	case INT_TYPE_AI3_DMA:	  disable_dma (devpriv->dma);	case INT_TYPE_AI1_INT:	case INT_TYPE_AI3_INT:	  outb (inb (dev->iobase + PCL816_CONTROL) & 0x73, dev->iobase + PCL816_CONTROL);	/* Stop A/D */	  comedi_udelay (1);	  outb (0, dev->iobase + PCL816_CONTROL);	/* Stop A/D */	  outb (0xb0, dev->iobase + PCL816_CTRCTL);	/* Stop pacer */	  outb (0x70, dev->iobase + PCL816_CTRCTL);	  outb (0, dev->iobase + PCL816_AD_LO);	  inb (dev->iobase + PCL816_AD_LO);	  inb (dev->iobase + PCL816_AD_HI);	  outb (0, dev->iobase + PCL816_CLRINT);	/* clear INT request */	  outb (0, dev->iobase + PCL816_CONTROL);	/* Stop A/D */	  devpriv->irq_blocked = 0;	  devpriv->irq_was_now_closed = devpriv->int816_mode;	  devpriv->int816_mode = 0;	  devpriv->last_int_sub = s;//	  s->busy = 0;	  break;	}	}    	DEBUG(rt_printk("comedi: pcl816_ai_cancel() successful\n");)	return 0;}/* ============================================================================== chech for PCL816*/static int pcl816_check (int iobase){  outb (0x00, iobase + PCL816_MUX);  comedi_udelay (1);  if (inb (iobase + PCL816_MUX) != 0x00)    return 1;			//there isn't card  outb (0x55, iobase + PCL816_MUX);  comedi_udelay (1);  if (inb (iobase + PCL816_MUX) != 0x55)    return 1;			//there isn't card  outb (0x00, iobase + PCL816_MUX);  comedi_udelay (1);  outb (0x18, iobase + PCL816_CONTROL);  comedi_udelay (1);  if (inb (iobase + PCL816_CONTROL) != 0x18)    return 1;			//there isn't card  return 0;			// ok, card exist}/* ============================================================================== reset whole PCL-816 cards*/static voidpcl816_reset (comedi_device * dev){//  outb (0, dev->iobase + PCL818_DA_LO);	// DAC=0V//  outb (0, dev->iobase + PCL818_DA_HI);//  comedi_udelay (1);//  outb (0, dev->iobase + PCL818_DO_HI);	// DO=$0000//  outb (0, dev->iobase + PCL818_DO_LO);//  comedi_udelay (1);  outb (0, dev->iobase + PCL816_CONTROL);  outb (0, dev->iobase + PCL816_MUX);  outb (0, dev->iobase + PCL816_CLRINT);  outb (0xb0, dev->iobase + PCL816_CTRCTL);	/* Stop pacer */  outb (0x70, dev->iobase + PCL816_CTRCTL);  outb (0x30, dev->iobase + PCL816_CTRCTL);  outb (0, dev->iobase + PCL816_RANGE);

⌨️ 快捷键说明

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