static int das1800_attach()

in drivers/das1800.c [1160:1334]


static int das1800_attach(struct comedi_device *dev,
			  struct comedi_devconfig *it)
{
	const struct das1800_board *board;
	struct das1800_private *devpriv;
	struct comedi_subdevice *s;
	unsigned int irq = it->options[1];
	bool is_16bit;
	int ret;
	int i;

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

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

	ret = das1800_probe(dev);
	if (ret)
		return ret;
	board = dev->board_ptr;

	is_16bit = board->id == DAS1800_ID_HR || board->id == DAS1800_ID_HR_DA;

	/* waveform 'ao' boards have additional io ports */
	if (board->id == DAS1800_ID_AO) {
		unsigned long iobase2 = dev->iobase + IOBASE2;

		ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
		if (ret)
			return ret;
		devpriv->iobase2 = iobase2;
	}

	if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
	    irq == 15) {
		ret = request_irq(irq, das1800_interrupt, 0,
				  dev->board_name, dev);
		if (ret == 0) {
			dev->irq = irq;

			switch (irq) {
			case 3:
				devpriv->irq_dma_bits |= 0x8;
				break;
			case 5:
				devpriv->irq_dma_bits |= 0x10;
				break;
			case 7:
				devpriv->irq_dma_bits |= 0x18;
				break;
			case 10:
				devpriv->irq_dma_bits |= 0x28;
				break;
			case 11:
				devpriv->irq_dma_bits |= 0x30;
				break;
			case 15:
				devpriv->irq_dma_bits |= 0x38;
				break;
			}
		}
	}

	/* an irq and one dma channel is required to use dma */
	if (dev->irq & it->options[2])
		das1800_init_dma(dev, it);

	devpriv->fifo_buf = kmalloc_array(FIFO_SIZE,
					  sizeof(*devpriv->fifo_buf),
					  GFP_KERNEL);
	if (!devpriv->fifo_buf)
		return -ENOMEM;

	dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
				      I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
	if (!dev->pacer)
		return -ENOMEM;

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

	/*
	 * Analog Input subdevice
	 *
	 * The "hc" type boards have 64 analog input channels and a 64
	 * entry QRAM fifo.
	 *
	 * All the other board types have 16 on-board channels. Each channel
	 * can be expanded to 16 channels with the addition of an EXP-1800
	 * expansion board for a total of 256 channels. The QRAM fifo on
	 * these boards has 256 entries.
	 *
	 * From the datasheets it's not clear what the comedi channel to
	 * actual physical channel mapping is when EXP-1800 boards are used.
	 */
	s = &dev->subdevices[0];
	s->type		= COMEDI_SUBD_AI;
	s->subdev_flags	= SDF_READABLE | SDF_DIFF | SDF_GROUND;
	if (board->id != DAS1800_ID_HC)
		s->subdev_flags	|= SDF_COMMON;
	s->n_chan	= (board->id == DAS1800_ID_HC) ? 64 : 256;
	s->maxdata	= is_16bit ? 0xffff : 0x0fff;
	s->range_table	= board->is_01_series ? &das1801_ai_range
					      : &das1802_ai_range;
	s->insn_read	= das1800_ai_insn_read;
	if (dev->irq) {
		dev->read_subdev = s;
		s->subdev_flags	|= SDF_CMD_READ;
		s->len_chanlist	= s->n_chan;
		s->do_cmd	= das1800_ai_cmd;
		s->do_cmdtest	= das1800_ai_cmdtest;
		s->poll		= das1800_ai_poll;
		s->cancel	= das1800_ai_cancel;
		s->munge	= das1800_ai_munge;
	}

	/* Analog Output subdevice */
	s = &dev->subdevices[1];
	if (board->id == DAS1800_ID_ST_DA || board->id == DAS1800_ID_HR_DA) {
		s->type		= COMEDI_SUBD_AO;
		s->subdev_flags	= SDF_WRITABLE;
		s->n_chan	= (board->id == DAS1800_ID_ST_DA) ? 4 : 2;
		s->maxdata	= is_16bit ? 0xffff : 0x0fff;
		s->range_table	= &range_bipolar10;
		s->insn_write	= das1800_ao_insn_write;

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

		/* initialize all channels to 0V */
		for (i = 0; i < s->n_chan; i++) {
			/* spinlock is not necessary during the attach */
			outb(DAC(i), dev->iobase + DAS1800_SELECT);
			outw(0, dev->iobase + DAS1800_DAC);
		}
	} else if (board->id == DAS1800_ID_AO) {
		/*
		 * 'ao' boards have waveform analog outputs that are not
		 * currently supported.
		 */
		s->type		= COMEDI_SUBD_UNUSED;
	} else {
		s->type		= COMEDI_SUBD_UNUSED;
	}

	/* Digital Input subdevice */
	s = &dev->subdevices[2];
	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	= das1800_di_insn_bits;

	/* Digital Output subdevice */
	s = &dev->subdevices[3];
	s->type		= COMEDI_SUBD_DO;
	s->subdev_flags	= SDF_WRITABLE;
	s->n_chan	= (board->id == DAS1800_ID_HC) ? 8 : 4;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= das1800_do_insn_bits;

	das1800_ai_cancel(dev, dev->read_subdev);

	/*  initialize digital out channels */
	outb(0, dev->iobase + DAS1800_DIGITAL);

	return 0;
};