static int atmio16d_attach()

in drivers/ni_atmio16d.c [569:697]


static int atmio16d_attach(struct comedi_device *dev,
			   struct comedi_devconfig *it)
{
	const struct atmio16_board_t *board = dev->board_ptr;
	struct atmio16d_private *devpriv;
	struct comedi_subdevice *s;
	int ret;

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

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

	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
	if (!devpriv)
		return -ENOMEM;

	/* reset the atmio16d hardware */
	reset_atmio16d(dev);

	if (it->options[1]) {
		ret = request_irq(it->options[1], atmio16d_interrupt, 0,
				  dev->board_name, dev);
		if (ret == 0)
			dev->irq = it->options[1];
	}

	/* set device options */
	devpriv->adc_mux = it->options[5];
	devpriv->adc_range = it->options[6];

	devpriv->dac0_range = it->options[7];
	devpriv->dac0_reference = it->options[8];
	devpriv->dac0_coding = it->options[9];
	devpriv->dac1_range = it->options[10];
	devpriv->dac1_reference = it->options[11];
	devpriv->dac1_coding = it->options[12];

	/* setup sub-devices */
	s = &dev->subdevices[0];
	/* ai subdevice */
	s->type = COMEDI_SUBD_AI;
	s->subdev_flags = SDF_READABLE | SDF_GROUND;
	s->n_chan = (devpriv->adc_mux ? 16 : 8);
	s->insn_read = atmio16d_ai_insn_read;
	s->maxdata = 0xfff;	/* 4095 decimal */
	switch (devpriv->adc_range) {
	case adc_bipolar10:
		s->range_table = &range_atmio16d_ai_10_bipolar;
		break;
	case adc_bipolar5:
		s->range_table = &range_atmio16d_ai_5_bipolar;
		break;
	case adc_unipolar10:
		s->range_table = &range_atmio16d_ai_unipolar;
		break;
	}
	if (dev->irq) {
		dev->read_subdev = s;
		s->subdev_flags |= SDF_CMD_READ;
		s->len_chanlist = 16;
		s->do_cmdtest = atmio16d_ai_cmdtest;
		s->do_cmd = atmio16d_ai_cmd;
		s->cancel = atmio16d_ai_cancel;
	}

	/* ao subdevice */
	s = &dev->subdevices[1];
	s->type = COMEDI_SUBD_AO;
	s->subdev_flags = SDF_WRITABLE;
	s->n_chan = 2;
	s->maxdata = 0xfff;	/* 4095 decimal */
	s->range_table_list = devpriv->ao_range_type_list;
	switch (devpriv->dac0_range) {
	case dac_bipolar:
		devpriv->ao_range_type_list[0] = &range_bipolar10;
		break;
	case dac_unipolar:
		devpriv->ao_range_type_list[0] = &range_unipolar10;
		break;
	}
	switch (devpriv->dac1_range) {
	case dac_bipolar:
		devpriv->ao_range_type_list[1] = &range_bipolar10;
		break;
	case dac_unipolar:
		devpriv->ao_range_type_list[1] = &range_unipolar10;
		break;
	}
	s->insn_write = atmio16d_ao_insn_write;

	ret = comedi_alloc_subdev_readback(s);
	if (ret)
		return ret;

	/* Digital I/O */
	s = &dev->subdevices[2];
	s->type = COMEDI_SUBD_DIO;
	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
	s->n_chan = 8;
	s->insn_bits = atmio16d_dio_insn_bits;
	s->insn_config = atmio16d_dio_insn_config;
	s->maxdata = 1;
	s->range_table = &range_digital;

	/* 8255 subdevice */
	s = &dev->subdevices[3];
	if (board->has_8255) {
		ret = subdev_8255_init(dev, s, NULL, 0x00);
		if (ret)
			return ret;
	} else {
		s->type = COMEDI_SUBD_UNUSED;
	}

/* don't yet know how to deal with counter/timers */
#if 0
	s = &dev->subdevices[4];
	/* do */
	s->type = COMEDI_SUBD_TIMER;
	s->n_chan = 0;
	s->maxdata = 0
#endif

	return 0;
}