static int pci9118_common_attach()

in drivers/adl_pci9118.c [1504:1646]


static int pci9118_common_attach(struct comedi_device *dev,
				 int ext_mux, int softsshdelay)
{
	const struct pci9118_boardinfo *board = dev->board_ptr;
	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
	struct pci9118_private *devpriv;
	struct comedi_subdevice *s;
	int ret;
	int i;
	u16 u16w;

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

	ret = comedi_pci_enable(dev);
	if (ret)
		return ret;
	pci_set_master(pcidev);

	devpriv->iobase_a = pci_resource_start(pcidev, 0);
	dev->iobase = pci_resource_start(pcidev, 2);

	dev->pacer = comedi_8254_init(dev->iobase + PCI9118_TIMER_BASE,
				      I8254_OSC_BASE_4MHZ, I8254_IO32, 0);
	if (!dev->pacer)
		return -ENOMEM;

	pci9118_reset(dev);

	if (pcidev->irq) {
		ret = request_irq(pcidev->irq, pci9118_interrupt, IRQF_SHARED,
				  dev->board_name, dev);
		if (ret == 0) {
			dev->irq = pcidev->irq;

			pci9118_alloc_dma(dev);
		}
	}

	if (ext_mux > 0) {
		if (ext_mux > 256)
			ext_mux = 256;	/* max 256 channels! */
		if (softsshdelay > 0)
			if (ext_mux > 128)
				ext_mux = 128;
		devpriv->usemux = 1;
	} else {
		devpriv->usemux = 0;
	}

	if (softsshdelay < 0) {
		/* select sample&hold signal polarity */
		devpriv->softsshdelay = -softsshdelay;
		devpriv->softsshsample = 0x80;
		devpriv->softsshhold = 0x00;
	} else {
		devpriv->softsshdelay = softsshdelay;
		devpriv->softsshsample = 0x00;
		devpriv->softsshhold = 0x80;
	}

	pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
	pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
				/* Enable parity check for parity error */

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

	/* Analog Input subdevice */
	s = &dev->subdevices[0];
	s->type		= COMEDI_SUBD_AI;
	s->subdev_flags	= SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
	s->n_chan	= (devpriv->usemux) ? ext_mux : 16;
	s->maxdata	= board->ai_is_16bit ? 0xffff : 0x0fff;
	s->range_table	= board->is_hg ? &pci9118hg_ai_range
				       : &pci9118_ai_range;
	s->insn_read	= pci9118_ai_insn_read;
	if (dev->irq) {
		dev->read_subdev = s;
		s->subdev_flags	|= SDF_CMD_READ;
		s->len_chanlist	= 255;
		s->do_cmdtest	= pci9118_ai_cmdtest;
		s->do_cmd	= pci9118_ai_cmd;
		s->cancel	= pci9118_ai_cancel;
		s->munge	= pci9118_ai_munge;
	}

	if (s->maxdata == 0xffff) {
		/*
		 * 16-bit samples are from an ADS7805 A/D converter.
		 * Minimum sampling rate is 10us.
		 */
		devpriv->ai_ns_min = 10000;
	} else {
		/*
		 * 12-bit samples are from an ADS7800 A/D converter.
		 * Minimum sampling rate is 3us.
		 */
		devpriv->ai_ns_min = 3000;
	}

	/* Analog Output subdevice */
	s = &dev->subdevices[1];
	s->type		= COMEDI_SUBD_AO;
	s->subdev_flags	= SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
	s->n_chan	= 2;
	s->maxdata	= 0x0fff;
	s->range_table	= &range_bipolar10;
	s->insn_write	= pci9118_ao_insn_write;

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

	/* the analog outputs were reset to 0V, make the readback match */
	for (i = 0; i < s->n_chan; i++)
		s->readback[i] = 2047;

	/* 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	= pci9118_di_insn_bits;

	/* Digital Output subdevice */
	s = &dev->subdevices[3];
	s->type		= COMEDI_SUBD_DO;
	s->subdev_flags	= SDF_WRITABLE;
	s->n_chan	= 4;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= pci9118_do_insn_bits;

	/* get the current state of the digital outputs */
	s->state = inl(dev->iobase + PCI9118_DIO_REG) >> 4;

	return 0;
}