示例#1
0
文件: pcl711.c 项目: AllenDou/linux
static void pcl711_set_changain(struct comedi_device *dev, int chan)
{
	const struct pcl711_board *board = comedi_board(dev);
	int chan_register;

	outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN);

	chan_register = CR_CHAN(chan);

	if (board->is_8112) {

		/*
		 *  Set the correct channel.  The two channel banks are switched
		 *  using the mask value.
		 *  NB: To use differential channels, you should use
		 *  mask = 0x30, but I haven't written the support for this
		 *  yet. /JJ
		 */

		if (chan_register >= 8)
			chan_register = 0x20 | (chan_register & 0x7);
		else
			chan_register |= 0x10;
	} else {
		outb(chan_register, dev->iobase + PCL711_MUX);
	}
}
示例#2
0
static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
	const struct das16_board *board = comedi_board(dev);
	unsigned long flags;

	spin_lock_irqsave(&dev->spinlock, flags);
	/* disable interrupts, dma and pacer clocked conversions */
	devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
	if (devpriv->dma_chan)
		disable_dma(devpriv->dma_chan);

	/*  disable SW timer */
	if (devpriv->timer_mode && devpriv->timer_running) {
		devpriv->timer_running = 0;
		del_timer(&devpriv->timer);
	}

	/* disable burst mode */
	if (board->size > 0x400)
		outb(0, dev->iobase + DAS1600_BURST);


	spin_unlock_irqrestore(&dev->spinlock, flags);

	return 0;
}
示例#3
0
文件: pcl711.c 项目: AllenDou/linux
static irqreturn_t pcl711_interrupt(int irq, void *d)
{
	int lo, hi;
	int data;
	struct comedi_device *dev = d;
	const struct pcl711_board *board = comedi_board(dev);
	struct comedi_subdevice *s = &dev->subdevices[0];

	if (!dev->attached) {
		comedi_error(dev, "spurious interrupt");
		return IRQ_HANDLED;
	}

	hi = inb(dev->iobase + PCL711_AD_HI);
	lo = inb(dev->iobase + PCL711_AD_LO);
	outb(0, dev->iobase + PCL711_CLRINTR);

	data = (hi << 8) | lo;

	/* FIXME! Nothing else sets ntrig! */
	if (!(--devpriv->ntrig)) {
		if (board->is_8112)
			outb(1, dev->iobase + PCL711_MODE);
		else
			outb(0, dev->iobase + PCL711_MODE);

		s->async->events |= COMEDI_CB_EOA;
	}
	comedi_event(dev, s);
	return IRQ_HANDLED;
}
示例#4
0
文件: das08.c 项目: AllenDou/linux
static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
			  struct comedi_insn *insn, unsigned int *data)
{
	const struct das08_board_struct *thisboard = comedi_board(dev);
	struct das08_private_struct *devpriv = dev->private;
	int i, n;
	int chan;
	int range;
	int lsb, msb;

	chan = CR_CHAN(insn->chanspec);
	range = CR_RANGE(insn->chanspec);

	/* clear crap */
	inb(dev->iobase + DAS08_LSB);
	inb(dev->iobase + DAS08_MSB);

	/* set multiplexer */
	/*  lock to prevent race with digital output */
	spin_lock(&dev->spinlock);
	devpriv->do_mux_bits &= ~DAS08_MUX_MASK;
	devpriv->do_mux_bits |= DAS08_MUX(chan);
	outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
	spin_unlock(&dev->spinlock);

	if (s->range_table->length > 1) {
		/* set gain/range */
		range = CR_RANGE(insn->chanspec);
		outb(devpriv->pg_gainlist[range],
		     dev->iobase + DAS08AO_GAIN_CONTROL);
	}

	for (n = 0; n < insn->n; n++) {
		/* clear over-range bits for 16-bit boards */
		if (thisboard->ai_nbits == 16)
			if (inb(dev->iobase + DAS08_MSB) & 0x80)
				dev_info(dev->class_dev, "over-range\n");

		/* trigger conversion */
		outb_p(0, dev->iobase + DAS08_TRIG_12BIT);

		for (i = 0; i < TIMEOUT; i++) {
			if (!(inb(dev->iobase + DAS08_STATUS) & DAS08_EOC))
				break;
		}
		if (i == TIMEOUT) {
			dev_err(dev->class_dev, "timeout\n");
			return -ETIME;
		}
		msb = inb(dev->iobase + DAS08_MSB);
		lsb = inb(dev->iobase + DAS08_LSB);
		if (thisboard->ai_encoding == das08_encode12) {
			data[n] = (lsb >> 4) | (msb << 4);
		} else if (thisboard->ai_encoding == das08_pcm_encode12) {
/*
 * Read 32-bit register.
 */
static unsigned int dio200_read32(struct comedi_device *dev,
				  unsigned int offset)
{
	const struct dio200_board *thisboard = comedi_board(dev);

	offset <<= thisboard->mainshift;

	if (dev->mmio)
		return readl(dev->mmio + offset);
	return inl(dev->iobase + offset);
}
/*
 * Write 32-bit register.
 */
static void dio200_write32(struct comedi_device *dev, unsigned int offset,
			   unsigned int val)
{
	const struct dio200_board *thisboard = comedi_board(dev);

	offset <<= thisboard->mainshift;

	if (dev->mmio)
		writel(val, dev->mmio + offset);
	else
		outl(val, dev->iobase + offset);
}
示例#7
0
static void dio200_pci_detach(struct comedi_device *dev)
{
	const struct dio200_board *thisboard = comedi_board(dev);
	struct dio200_private *devpriv = dev->private;

	if (!thisboard || !devpriv)
		return;
	amplc_dio200_common_detach(dev);
	if (devpriv->io.regtype == mmio_regtype)
		iounmap(devpriv->io.u.membase);
	comedi_pci_disable(dev);
}
示例#8
0
static void pcl724_detach(struct comedi_device *dev)
{
	const struct pcl724_board *board = comedi_board(dev);
	int i;

	for (i = 0; i < dev->n_subdevices; i++)
		subdev_8255_cleanup(dev, dev->subdevices + i);
#ifdef PCL724_IRQ
	if (dev->irq)
		free_irq(dev->irq, dev);
#endif
	release_region(dev->iobase, board->io_range);
}
示例#9
0
void labpc_handle_dma_status(struct comedi_device *dev)
{
	const struct labpc_boardinfo *board = comedi_board(dev);
	struct labpc_private *devpriv = dev->private;

	/*
	 * if a dma terminal count of external stop trigger
	 * has occurred
	 */
	if (devpriv->stat1 & STAT1_GATA0 ||
	    (board->is_labpc1200 && devpriv->stat2 & STAT2_OUTA1))
		handle_isa_dma(dev);
}
示例#10
0
static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
			  struct comedi_insn *insn, unsigned int *data)
{
	const struct das16_board *board = comedi_board(dev);
	int i, n;
	int range;
	int chan;
	int msb, lsb;

	/*  disable interrupts and pacing */
	devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);

	/* set multiplexer */
	chan = CR_CHAN(insn->chanspec);
	chan |= CR_CHAN(insn->chanspec) << 4;
	outb(chan, dev->iobase + DAS16_MUX);

	/* set gain */
	if (board->ai_pg != das16_pg_none) {
		range = CR_RANGE(insn->chanspec);
		outb((das16_gainlists[board->ai_pg])[range],
		     dev->iobase + DAS16_GAIN);
	}

	for (n = 0; n < insn->n; n++) {
		/* trigger conversion */
		outb_p(0, dev->iobase + DAS16_TRIG);

		for (i = 0; i < DAS16_TIMEOUT; i++) {
			if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
				break;
		}
		if (i == DAS16_TIMEOUT) {
			printk("das16: timeout\n");
			return -ETIME;
		}
		msb = inb(dev->iobase + DAS16_AI_MSB);
		lsb = inb(dev->iobase + DAS16_AI_LSB);
		if (board->ai_nbits == 12)
			data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
		else
			data[n] = lsb | (msb << 8);

	}
示例#11
0
static int pcl724_attach(struct comedi_device *dev,
			 struct comedi_devconfig *it)
{
	const struct pcl724_board *board = comedi_board(dev);
	struct comedi_subdevice *s;
	unsigned long iobase;
	unsigned int iorange;
	int n_subdevices;
	int ret;
	int i;

	iorange = board->io_range;
	n_subdevices = board->numofports;

	/* Handle PCL-724 in 96 DIO configuration */
	if (board->can_have96 &&
	    (it->options[2] == 1 || it->options[2] == 96)) {
		iorange = 0x10;
		n_subdevices = 4;
	}

	ret = comedi_request_region(dev, it->options[0], iorange);
	if (ret)
		return ret;

	ret = comedi_alloc_subdevices(dev, n_subdevices);
	if (ret)
		return ret;

	for (i = 0; i < dev->n_subdevices; i++) {
		s = &dev->subdevices[i];
		if (board->is_pet48) {
			iobase = dev->iobase + (i * 0x1000);
			ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
					       iobase);
		} else {
			iobase = dev->iobase + (i * SIZE_8255);
			ret = subdev_8255_init(dev, s, NULL, iobase);
		}
		if (ret)
			return ret;
	}

	return 0;
}
示例#12
0
文件: pcl711.c 项目: AllenDou/linux
static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
			  struct comedi_insn *insn, unsigned int *data)
{
	const struct pcl711_board *board = comedi_board(dev);
	int i, n;
	int hi, lo;

	pcl711_set_changain(dev, insn->chanspec);

	for (n = 0; n < insn->n; n++) {
		/*
		 *  Write the correct mode (software polling) and start polling
		 *  by writing to the trigger register
		 */
		outb(1, dev->iobase + PCL711_MODE);

		if (!board->is_8112)
			outb(0, dev->iobase + PCL711_SOFTTRIG);

		i = PCL711_TIMEOUT;
		while (--i) {
			hi = inb(dev->iobase + PCL711_AD_HI);
			if (!(hi & PCL711_DRDY))
				goto ok;
			udelay(1);
		}
		printk(KERN_ERR "comedi%d: pcl711: A/D timeout\n", dev->minor);
		return -ETIME;

ok:
		lo = inb(dev->iobase + PCL711_AD_LO);

		data[n] = ((hi & 0xf) << 8) | lo;
	}

	return n;
}
示例#13
0
static unsigned int ni_65xx_num_ports(struct comedi_device *dev)
{
	const struct ni_65xx_board *board = comedi_board(dev);

	return board->num_dio_ports + board->num_di_ports + board->num_do_ports;
}
示例#14
0
static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
	const struct pcl724_board *board = comedi_board(dev);
	unsigned long iobase;
	unsigned int iorange;
	int ret, i, n_subdevices;
#ifdef PCL724_IRQ
	unsigned int irq;
#endif

	iobase = it->options[0];
	iorange = board->io_range;
	if ((board->can_have96) && ((it->options[1] == 1)
					 || (it->options[1] == 96)))
		iorange = PCL722_96_SIZE; /* PCL-724 in 96 DIO configuration */
	printk(KERN_INFO "comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor,
	       board->name, iobase);
	if (!request_region(iobase, iorange, "pcl724")) {
		printk("I/O port conflict\n");
		return -EIO;
	}

	dev->iobase = iobase;

	dev->board_name = board->name;

#ifdef PCL724_IRQ
	irq = 0;
	if (board->IRQbits != 0) {	/* board support IRQ */
		irq = it->options[1];
		if (irq) {	/* we want to use IRQ */
			if (((1 << irq) & board->IRQbits) == 0) {
				printk(KERN_WARNING
				       ", IRQ %u is out of allowed range, "
				       "DISABLING IT", irq);
				irq = 0;	/* Bad IRQ */
			} else {
				if (request_irq
				    (irq, interrupt_pcl724, 0, "pcl724", dev)) {
					printk(KERN_WARNING
					       ", unable to allocate IRQ %u, "
					       "DISABLING IT", irq);
					irq = 0;	/* Can't use IRQ */
				} else {
					printk(", irq=%u", irq);
				}
			}
		}
	}

	dev->irq = irq;
#endif

	printk("\n");

	n_subdevices = board->numofports;
	if ((board->can_have96) && ((it->options[1] == 1)
					 || (it->options[1] == 96)))
		n_subdevices = 4;	/*  PCL-724 in 96 DIO configuration */

	ret = comedi_alloc_subdevices(dev, n_subdevices);
	if (ret)
		return ret;

	for (i = 0; i < dev->n_subdevices; i++) {
		if (board->is_pet48) {
			subdev_8255_init(dev, dev->subdevices + i,
					 subdev_8255mapped_cb,
					 (unsigned long)(dev->iobase +
							 i * 0x1000));
		} else
			subdev_8255_init(dev, dev->subdevices + i,
					 subdev_8255_cb,
					 (unsigned long)(dev->iobase +
							 SIZE_8255 * i));
	}

	return 0;
}
示例#15
0
static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
{
	const struct das16_board *board = comedi_board(dev);
	struct comedi_async *async = s->async;
	struct comedi_cmd *cmd = &async->cmd;
	unsigned int byte;
	unsigned long flags;
	int range;

	if (devpriv->dma_chan == 0 || (dev->irq == 0
				       && devpriv->timer_mode == 0)) {
		comedi_error(dev,
				"irq (or use of 'timer mode') dma required to "
							"execute comedi_cmd");
		return -1;
	}
	if (cmd->flags & TRIG_RT) {
		comedi_error(dev, "isa dma transfers cannot be performed with "
							"TRIG_RT, aborting");
		return -1;
	}

	devpriv->adc_byte_count =
	    cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);

	/*  disable conversions for das1600 mode */
	if (board->size > 0x400)
		outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);

	/*  set scan limits */
	byte = CR_CHAN(cmd->chanlist[0]);
	byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
	outb(byte, dev->iobase + DAS16_MUX);

	/* set gain (this is also burst rate register but according to
	 * computer boards manual, burst rate does nothing, even on
	 * keithley cards) */
	if (board->ai_pg != das16_pg_none) {
		range = CR_RANGE(cmd->chanlist[0]);
		outb((das16_gainlists[board->ai_pg])[range],
		     dev->iobase + DAS16_GAIN);
	}

	/* set counter mode and counts */
	cmd->convert_arg =
	    das16_set_pacer(dev, cmd->convert_arg,
			    cmd->flags & TRIG_ROUND_MASK);
	DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);

	/* enable counters */
	byte = 0;
	/* Enable burst mode if appropriate. */
	if (board->size > 0x400) {
		if (cmd->convert_src == TRIG_NOW) {
			outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
			/*  set burst length */
			byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
		} else {
			outb(0, dev->iobase + DAS1600_BURST);
		}
	}
	outb(byte, dev->iobase + DAS16_PACER);

	/*  set up dma transfer */
	flags = claim_dma_lock();
	disable_dma(devpriv->dma_chan);
	/* clear flip-flop to make sure 2-byte registers for
	 * count and address get set correctly */
	clear_dma_ff(devpriv->dma_chan);
	devpriv->current_buffer = 0;
	set_dma_addr(devpriv->dma_chan,
		     devpriv->dma_buffer_addr[devpriv->current_buffer]);
	/*  set appropriate size of transfer */
	devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd);
	set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
	enable_dma(devpriv->dma_chan);
	release_dma_lock(flags);

	/*  set up interrupt */
	if (devpriv->timer_mode) {
		devpriv->timer_running = 1;
		devpriv->timer.expires = jiffies + timer_period();
		add_timer(&devpriv->timer);
		devpriv->control_state &= ~DAS16_INTE;
	} else {
		/* clear interrupt bit */
		outb(0x00, dev->iobase + DAS16_STATUS);
		/* enable interrupts */
		devpriv->control_state |= DAS16_INTE;
	}
	devpriv->control_state |= DMA_ENABLE;
	devpriv->control_state &= ~PACING_MASK;
	if (cmd->convert_src == TRIG_EXT)
		devpriv->control_state |= EXT_PACER;
	else
		devpriv->control_state |= INT_PACER;
	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);

	/* Enable conversions if using das1600 mode */
	if (board->size > 0x400)
		outb(0, dev->iobase + DAS1600_CONV);


	return 0;
}
示例#16
0
static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
			  struct comedi_cmd *cmd)
{
	const struct das16_board *board = comedi_board(dev);
	int err = 0, tmp;
	int gain, start_chan, i;
	int mask;

	/* make sure triggers are valid */
	tmp = cmd->start_src;
	cmd->start_src &= TRIG_NOW;
	if (!cmd->start_src || tmp != cmd->start_src)
		err++;

	tmp = cmd->scan_begin_src;
	mask = TRIG_FOLLOW;
	/*  if board supports burst mode */
	if (board->size > 0x400)
		mask |= TRIG_TIMER | TRIG_EXT;
	cmd->scan_begin_src &= mask;
	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
		err++;

	tmp = cmd->convert_src;
	mask = TRIG_TIMER | TRIG_EXT;
	/*  if board supports burst mode */
	if (board->size > 0x400)
		mask |= TRIG_NOW;
	cmd->convert_src &= mask;
	if (!cmd->convert_src || tmp != cmd->convert_src)
		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->scan_begin_src != TRIG_TIMER &&
	    cmd->scan_begin_src != TRIG_EXT &&
	    cmd->scan_begin_src != TRIG_FOLLOW)
		err++;
	if (cmd->convert_src != TRIG_TIMER &&
	    cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
		err++;
	if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
		err++;

	/*  make sure scan_begin_src and convert_src dont conflict */
	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
		err++;
	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
		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_src == TRIG_FOLLOW) {
		/* internal trigger */
		if (cmd->scan_begin_arg != 0) {
			cmd->scan_begin_arg = 0;
			err++;
		}
	}

	if (cmd->scan_end_arg != cmd->chanlist_len) {
		cmd->scan_end_arg = cmd->chanlist_len;
		err++;
	}
	/*  check against maximum frequency */
	if (cmd->scan_begin_src == TRIG_TIMER) {
		if (cmd->scan_begin_arg <
		    board->ai_speed * cmd->chanlist_len) {
			cmd->scan_begin_arg =
			    board->ai_speed * cmd->chanlist_len;
			err++;
		}
	}
	if (cmd->convert_src == TRIG_TIMER) {
		if (cmd->convert_arg < board->ai_speed) {
			cmd->convert_arg = board->ai_speed;
			err++;
		}
	}

	if (cmd->stop_src == TRIG_NONE) {
		if (cmd->stop_arg != 0) {
			cmd->stop_arg = 0;
			err++;
		}
	}
	if (err)
		return 3;

	/*  step 4: fix up arguments */
	if (cmd->scan_begin_src == TRIG_TIMER) {
		unsigned int tmp = cmd->scan_begin_arg;
		/*  set divisors, correct timing arguments */
		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
					       &(devpriv->divisor1),
					       &(devpriv->divisor2),
					       &(cmd->scan_begin_arg),
					       cmd->flags & TRIG_ROUND_MASK);
		err += (tmp != cmd->scan_begin_arg);
	}
	if (cmd->convert_src == TRIG_TIMER) {
		unsigned int tmp = cmd->convert_arg;
		/*  set divisors, correct timing arguments */
		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
					       &(devpriv->divisor1),
					       &(devpriv->divisor2),
					       &(cmd->convert_arg),
					       cmd->flags & TRIG_ROUND_MASK);
		err += (tmp != cmd->convert_arg);
	}
	if (err)
		return 4;

	/*  check channel/gain list against card's limitations */
	if (cmd->chanlist) {
		gain = CR_RANGE(cmd->chanlist[0]);
		start_chan = CR_CHAN(cmd->chanlist[0]);
		for (i = 1; i < cmd->chanlist_len; i++) {
			if (CR_CHAN(cmd->chanlist[i]) !=
			    (start_chan + i) % s->n_chan) {
				comedi_error(dev,
						"entries in chanlist must be "
						"consecutive channels, "
						"counting upwards\n");
				err++;
			}
			if (CR_RANGE(cmd->chanlist[i]) != gain) {
				comedi_error(dev,
						"entries in chanlist must all "
						"have the same gain\n");
				err++;
			}
		}
	}
	if (err)
		return 5;

	return 0;
}
示例#17
0
文件: dt2811.c 项目: AllenDou/linux
/*
  options[0]   Board base address
  options[1]   IRQ
  options[2]   Input configuration
		 0 == single-ended
		 1 == differential
		 2 == pseudo-differential
  options[3]   Analog input range configuration
		 0 == bipolar 5  (-5V -- +5V)
		 1 == bipolar 2.5V  (-2.5V -- +2.5V)
		 2 == unipolar 5V  (0V -- +5V)
  options[4]   Analog output 0 range configuration
		 0 == bipolar 5  (-5V -- +5V)
		 1 == bipolar 2.5V  (-2.5V -- +2.5V)
		 2 == unipolar 5V  (0V -- +5V)
  options[5]   Analog output 1 range configuration
		 0 == bipolar 5  (-5V -- +5V)
		 1 == bipolar 2.5V  (-2.5V -- +2.5V)
		 2 == unipolar 5V  (0V -- +5V)
*/
static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
	/* int i, irq; */
	/* unsigned long irqs; */
	/* long flags; */

	const struct dt2811_board *board = comedi_board(dev);
	int ret;
	struct comedi_subdevice *s;
	unsigned long iobase;

	iobase = it->options[0];

	printk(KERN_INFO "comedi%d: dt2811:base=0x%04lx\n", dev->minor, iobase);

	if (!request_region(iobase, DT2811_SIZE, driver_name)) {
		printk(KERN_ERR "I/O port conflict\n");
		return -EIO;
	}

	dev->iobase = iobase;
	dev->board_name = board->name;

#if 0
	outb(0, dev->iobase + DT2811_ADCSR);
	udelay(100);
	i = inb(dev->iobase + DT2811_ADDATLO);
	i = inb(dev->iobase + DT2811_ADDATHI);
#endif

#if 0
	irq = it->options[1];
	if (irq < 0) {
		save_flags(flags);
		sti();
		irqs = probe_irq_on();

		outb(DT2811_CLRERROR | DT2811_INTENB,
		     dev->iobase + DT2811_ADCSR);
		outb(0, dev->iobase + DT2811_ADGCR);

		udelay(100);

		irq = probe_irq_off(irqs);
		restore_flags(flags);

		/*outb(DT2811_CLRERROR|DT2811_INTENB,
			dev->iobase+DT2811_ADCSR);*/

		if (inb(dev->iobase + DT2811_ADCSR) & DT2811_ADERROR)
			printk(KERN_ERR "error probing irq (bad)\n");
		dev->irq = 0;
		if (irq > 0) {
			i = inb(dev->iobase + DT2811_ADDATLO);
			i = inb(dev->iobase + DT2811_ADDATHI);
			printk(KERN_INFO "(irq = %d)\n", irq);
			ret = request_irq(irq, dt2811_interrupt, 0,
					  driver_name, dev);
			if (ret < 0)
				return -EIO;
			dev->irq = irq;
		} else if (irq == 0) {
			printk(KERN_INFO "(no irq)\n");
		} else {
			printk(KERN_ERR "( multiple irq's -- this is bad! )\n");
		}
	}
#endif

	ret = comedi_alloc_subdevices(dev, 4);
	if (ret)
		return ret;

	ret = alloc_private(dev, sizeof(struct dt2811_private));
	if (ret < 0)
		return ret;

	switch (it->options[2]) {
	case 0:
		devpriv->adc_mux = adc_singleended;
		break;
	case 1:
		devpriv->adc_mux = adc_diff;
		break;
	case 2:
		devpriv->adc_mux = adc_pseudo_diff;
		break;
	default:
		devpriv->adc_mux = adc_singleended;
		break;
	}
	switch (it->options[4]) {
	case 0:
		devpriv->dac_range[0] = dac_bipolar_5;
		break;
	case 1:
		devpriv->dac_range[0] = dac_bipolar_2_5;
		break;
	case 2:
		devpriv->dac_range[0] = dac_unipolar_5;
		break;
	default:
		devpriv->dac_range[0] = dac_bipolar_5;
		break;
	}
	switch (it->options[5]) {
	case 0:
		devpriv->dac_range[1] = dac_bipolar_5;
		break;
	case 1:
		devpriv->dac_range[1] = dac_bipolar_2_5;
		break;
	case 2:
		devpriv->dac_range[1] = dac_unipolar_5;
		break;
	default:
		devpriv->dac_range[1] = dac_bipolar_5;
		break;
	}

	s = &dev->subdevices[0];
	/* initialize the ADC subdevice */
	s->type = COMEDI_SUBD_AI;
	s->subdev_flags = SDF_READABLE | SDF_GROUND;
	s->n_chan = devpriv->adc_mux == adc_diff ? 8 : 16;
	s->insn_read = dt2811_ai_insn;
	s->maxdata = 0xfff;
	switch (it->options[3]) {
	case 0:
	default:
		s->range_table = board->bip_5;
		break;
	case 1:
		s->range_table = board->bip_2_5;
		break;
	case 2:
		s->range_table = board->unip_5;
		break;
	}

	s = &dev->subdevices[1];
	/* ao subdevice */
	s->type = COMEDI_SUBD_AO;
	s->subdev_flags = SDF_WRITABLE;
	s->n_chan = 2;
	s->insn_write = dt2811_ao_insn;
	s->insn_read = dt2811_ao_insn_read;
	s->maxdata = 0xfff;
	s->range_table_list = devpriv->range_type_list;
	devpriv->range_type_list[0] = dac_range_types[devpriv->dac_range[0]];
	devpriv->range_type_list[1] = dac_range_types[devpriv->dac_range[1]];

	s = &dev->subdevices[2];
	/* di subdevice */
	s->type = COMEDI_SUBD_DI;
	s->subdev_flags = SDF_READABLE;
	s->n_chan = 8;
	s->insn_bits = dt2811_di_insn_bits;
	s->maxdata = 1;
	s->range_table = &range_digital;

	s = &dev->subdevices[3];
	/* do subdevice */
	s->type = COMEDI_SUBD_DO;
	s->subdev_flags = SDF_WRITABLE;
	s->n_chan = 8;
	s->insn_bits = dt2811_do_insn_bits;
	s->maxdata = 1;
	s->state = 0;
	s->range_table = &range_digital;

	return 0;
}
static inline const struct dio200_layout *
dio200_dev_layout(struct comedi_device *dev)
{
	return dio200_board_layout(comedi_board(dev));
}