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

📄 das16m1.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}static int das16m1_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i, n;	int byte;	const int timeout = 1000;	/* disable interrupts and internal pacer */	devpriv->control_state &= ~INTE & ~PACER_MASK;	outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);	/* setup channel/gain queue */	outb(0, dev->iobase + DAS16M1_QUEUE_ADDR);	byte = Q_CHAN(CR_CHAN(insn->chanspec)) | Q_RANGE(CR_RANGE(insn->chanspec));	outb(byte, dev->iobase + DAS16M1_QUEUE_DATA);	for(n = 0; n < insn->n; n++)	{		/* clear IRQDATA bit */		outb(0, dev->iobase + DAS16M1_CLEAR_INTR);		/* trigger conversion */		outb(0, dev->iobase);		for(i = 0; i < timeout; i++)		{			if(inb(dev->iobase + DAS16M1_CS) & IRQDATA)				break;		}		if(i == timeout)		{			comedi_error(dev, "timeout");			return -ETIME;		}		data[n] = munge_sample( inw( dev->iobase ) );	}	return n;}static int das16m1_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	lsampl_t bits;	bits = inb(dev->iobase + DAS16M1_DIO) & 0xf;	data[1] = bits;	data[0] = 0;	return 2;}static int das16m1_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	lsampl_t wbits;	// only set bits that have been masked	data[0] &= 0xf;	wbits = devpriv->do_bits;	// zero bits that have been masked	wbits &= ~data[0];	// set masked bits	wbits |= data[0] & data[1];	devpriv->do_bits = wbits;	data[1] = wbits;	outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO);	return 2;}static int das16m1_poll(comedi_device *dev, comedi_subdevice *s){	unsigned long flags;	unsigned int status;	// prevent race with interrupt handler	comedi_spin_lock_irqsave(&dev->spinlock, flags);	status = inb(dev->iobase + DAS16M1_CS);	das16m1_handler(dev, status);	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);	return s->async->buf_write_count - s->async->buf_read_count;}static void das16m1_interrupt(int irq, void *d, struct pt_regs *regs){	int status;	comedi_device *dev = d;	if(dev->attached == 0)	{		comedi_error(dev, "premature interrupt");		return;	}	// prevent race with comedi_poll()	spin_lock(&dev->spinlock);	status = inb(dev->iobase + DAS16M1_CS);	if((status & (IRQDATA | OVRUN)) == 0)	{		comedi_error(dev, "spurious interrupt");		spin_unlock(&dev->spinlock);		return;	}	das16m1_handler(dev, status);	/* clear interrupt */	outb(0, dev->iobase + DAS16M1_CLEAR_INTR);	spin_unlock(&dev->spinlock);}static void munge_sample_array( sampl_t *array, unsigned int num_elements ){	unsigned int i;	for(i = 0; i < num_elements; i++)	{		array[i] = munge_sample( array[i] );	}}static void das16m1_handler(comedi_device *dev, unsigned int status){	comedi_subdevice *s;	comedi_async *async;	comedi_cmd *cmd;	u16 num_samples;	u16 hw_counter;	s = dev->read_subdev;	async = s->async;	async->events = 0;	cmd = &async->cmd;	// figure out how many samples are in fifo	hw_counter = i8254_read(dev->iobase + DAS16M1_8254_FIRST, 1);	/* make sure hardware counter reading is not bogus due to initial value	 * not having been loaded yet */	if(devpriv->adc_count == 0 && hw_counter == devpriv->initial_hw_count)	{		num_samples = 0;	}else	{		/* The calculation of num_samples looks odd, but it uses the following facts.		 * 16 bit hardware counter is initialized with value of zero (which really		 * means 0x1000).  The counter decrements by one on each conversion		 * (when the counter decrements from zero it goes to 0xffff).  num_samples		 * is a 16 bit variable, so it will roll over in a similar fashion to the		 * hardware counter.  Work it out, and this is what you get. */		num_samples = - hw_counter - devpriv->adc_count;	}	// check if we only need some of the points	if(cmd->stop_src == TRIG_COUNT)	{		if(num_samples > cmd->stop_arg * cmd->chanlist_len)			num_samples = cmd->stop_arg * cmd->chanlist_len;	}	// make sure we dont try to get too many points if fifo has overrun	if(num_samples > FIFO_SIZE)		num_samples = FIFO_SIZE;	insw( dev->iobase, devpriv->ai_buffer, num_samples );	munge_sample_array( devpriv->ai_buffer, num_samples );	cfc_write_array_to_buffer( s, devpriv->ai_buffer, num_samples * sizeof( sampl_t ) );	devpriv->adc_count += num_samples;	if(cmd->stop_src == TRIG_COUNT)	{		if(devpriv->adc_count >= cmd->stop_arg * cmd->chanlist_len)		{		/* end of acquisition */				das16m1_cancel(dev, s);				async->events |= COMEDI_CB_EOA;		}	}	/* this probably won't catch overruns since the card doesn't generate	 * overrun interrupts, but we might as well try */	if(status & OVRUN)	{		das16m1_cancel(dev, s);		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;		comedi_error(dev, "fifo overflow");	}	comedi_event(dev, s, async->events);}/* This function takes a time in nanoseconds and sets the     * * 2 pacer clocks to the closest frequency possible. It also  * * returns the actual sampling period.                        */static unsigned int das16m1_set_pacer(comedi_device *dev, unsigned int ns, int rounding_flags){	i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),		&(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK);	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */	i8254_load(dev->iobase + DAS16M1_8254_SECOND, 1, devpriv->divisor1, 2);	i8254_load(dev->iobase + DAS16M1_8254_SECOND, 2, devpriv->divisor2, 2);	return ns;}static int das16m1_irq_bits(unsigned int irq){	int ret;	switch(irq)	{		case 10:			ret = 0x0;			break;		case 11:			ret = 0x1;			break;		case 12:			ret = 0x2;			break;		case 15:			ret = 0x3;			break;		case 2:			ret = 0x4;			break;		case 3:			ret = 0x5;			break;		case 5:			ret = 0x6;			break;		case 7:			ret = 0x7;			break;		default:			return -1;			break;	}	return (ret << 4);}/* * Options list: *   0  I/O base *   1  IRQ */static int das16m1_attach(comedi_device *dev, comedi_devconfig *it){	comedi_subdevice *s;	int ret, irq;	int iobase;	iobase = it->options[0];	printk("comedi%d: das16m1:", dev->minor);	if((ret = alloc_private(dev, sizeof(struct das16m1_private_struct))) < 0)		return ret;	dev->board_name = thisboard->name;	printk(" io 0x%x-0x%x 0x%x-0x%x",		   iobase, iobase + DAS16M1_SIZE,		   iobase + DAS16M1_82C55, iobase + DAS16M1_82C55 + DAS16M1_SIZE2);	if(check_region(iobase, DAS16M1_SIZE) < 0) {		printk(" I/O port conflict\n");		return -EIO;	}	if(check_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2) < 0){		printk(" I/O port conflict\n");		return -EIO;	}	request_region(iobase, DAS16M1_SIZE, driver_das16m1.driver_name);	request_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2, driver_das16m1.driver_name);	dev->iobase = iobase;	/* now for the irq */	irq = it->options[1];	// make sure it is valid	if(das16m1_irq_bits(irq) >= 0)	{		ret = comedi_request_irq(irq, das16m1_interrupt, 0,			driver_das16m1.driver_name, dev);		if(ret < 0)		{			printk(", irq unavailable\n");			return ret;		}		dev->irq = irq;		printk(", irq %d\n", irq);	}else if(irq == 0){		printk(", no irq\n");	}else {		printk(", invalid irq\n"			" valid irqs are 2, 3, 5, 7, 10, 11, 12, or 15\n");		return -EINVAL;	}	if((ret = alloc_subdevices(dev, 4)) < 0)		return ret;	s = dev->subdevices + 0;	dev->read_subdev = s;	/* ai */	s->type = COMEDI_SUBD_AI;	s->subdev_flags = SDF_READABLE;	s->n_chan = 8;	s->subdev_flags = SDF_DIFF;	s->len_chanlist = 256;	s->maxdata = (1 << 12) - 1;	s->range_table = &range_das16m1;	s->insn_read = das16m1_ai_rinsn;	s->do_cmdtest = das16m1_cmd_test;	s->do_cmd = das16m1_cmd_exec;	s->cancel = das16m1_cancel;	s->poll = das16m1_poll;	s = dev->subdevices + 1;	/* di */	s->type = COMEDI_SUBD_DI;	s->subdev_flags = SDF_READABLE;	s->n_chan = 4;	s->maxdata = 1;	s->range_table = &range_digital;	s->insn_bits = das16m1_di_rbits;	s = dev->subdevices + 2;	/* do */	s->type = COMEDI_SUBD_DO;	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;	s->n_chan = 4;	s->maxdata = 1;	s->range_table = &range_digital;	s->insn_bits = das16m1_do_wbits;	s = dev->subdevices + 3;	/* 8255 */	subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase + DAS16M1_82C55));	// disable upper half of hardware conversion counter so it doesn't mess with us	outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL);	// initialize digital output lines	outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO);	/* set the interrupt level */	if(dev->irq)		devpriv->control_state = das16m1_irq_bits(dev->irq);	else		devpriv->control_state = 0;	outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);	return 0;}static int das16m1_detach(comedi_device *dev){	printk("comedi%d: das16m1: remove\n", dev->minor);//	das16m1_reset(dev);	if(dev->subdevices)		subdev_8255_cleanup(dev,dev->subdevices + 3);	if(dev->irq)		comedi_free_irq(dev->irq, dev);	if(dev->iobase){		release_region(dev->iobase , DAS16M1_SIZE);		release_region(dev->iobase + DAS16M1_82C55, DAS16M1_SIZE2);	}	return 0;}

⌨️ 快捷键说明

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