Commit f3b81d54 authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman
Browse files

staging: comedi: adl_pci9118: split pci9118_attach()



Split most of the functionality of the attach routine `pci9118_attach()`
into a new function `pci9118_common_attach()` that can be called when
auto-attachment of devices is supported.  Move the enabling of the PCI
device and its i/o regions into this function.  Do the requesting of the
interrupt near the end of the function so it doesn't get enabled before
the device is ready.

Note that auto-attachment of PCI devices is currently broken in this
driver because the list of board names referred to by the `struct
comedi_driver` does not contain a "wildcard" entry matching the comedi
driver name.  This won't be a problem once support for the
`auto_attach()` method is added.

Signed-off-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f41d2573
Loading
Loading
Loading
Loading
+77 −66
Original line number Diff line number Diff line
@@ -1873,12 +1873,6 @@ static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
			    PCI_SLOT(pcidev->devfn) != slot)
				continue;
		}
		/*
		 * Look for device that isn't in use.
		 * Enable PCI device and request regions.
		 */
		if (comedi_pci_enable(pcidev, "adl_pci9118"))
			continue;
		return pcidev;
	}
	dev_err(dev->class_dev,
@@ -1909,56 +1903,33 @@ static void pci9118_report_attach(struct comedi_device *dev, unsigned int irq)
		 (devpriv->master ? "" : "no "), muxbuf);
}

static int pci9118_attach(struct comedi_device *dev,
			  struct comedi_devconfig *it)
static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
				 int master, int ext_mux, int softsshdelay,
				 int hw_err_mask)
{
	const struct boardtype *this_board = comedi_board(dev);
	struct pci9118_private *devpriv;
	struct pci_dev *pcidev;
	struct pci9118_private *devpriv = dev->private;
	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
	struct comedi_subdevice *s;
	int ret, pages, i;
	unsigned short master;
	unsigned int irq;
	u16 u16w;

	if (it->options[3] & 1)
		master = 0;	/* user don't want use bus master */
	else
		master = 1;

	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
	if (!devpriv)
		return -ENOMEM;
	dev->private = devpriv;

	pcidev = pci9118_find_pci(dev, it);
	if (!pcidev)
		return -EIO;
	comedi_set_hw_dev(dev, &pcidev->dev);

	dev->board_name = this_board->name;
	ret = comedi_pci_enable(pcidev, dev->board_name);
	if (ret) {
		dev_err(dev->class_dev,
			"cannot enable PCI device %s\n", pci_name(pcidev));
		return ret;
	}
	if (master)
		pci_set_master(pcidev);

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

	dev->board_name = this_board->name;

	pci9118_reset(dev);

	if (it->options[3] & 2)
		irq = 0;	/* user don't want use IRQ */
	if (irq > 0) {
		if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
				"ADLink PCI-9118", dev))
			dev_warn(dev->class_dev,
				 "unable to allocate IRQ %u, DISABLING IT\n",
				 irq);
		else
			dev->irq = irq;
	}

	if (master) {		/* alloc DMA buffers */
		devpriv->dma_doublebuf = 0;
		for (i = 0; i < 2; i++) {
@@ -1984,32 +1955,29 @@ static int pci9118_attach(struct comedi_device *dev,
				 "Can't allocate DMA buffer, DMA disabled!\n");
			master = 0;
		}

		if (devpriv->dmabuf_virt[1])
			devpriv->dma_doublebuf = 1;

	}

	devpriv->master = master;

	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 = ext_mux;
	} else {
		devpriv->usemux = 0;
	if (it->options[2] > 0) {
		devpriv->usemux = it->options[2];
		if (devpriv->usemux > 256)
			devpriv->usemux = 256;	/* max 256 channels! */
		if (it->options[4] > 0)
			if (devpriv->usemux > 128) {
				devpriv->usemux = 128;
					/* max 128 channels with softare S&H! */
			}
	}

	devpriv->softsshdelay = it->options[4];
	if (devpriv->softsshdelay < 0) {
	if (softsshdelay < 0) {
		/* select sample&hold signal polarity */
		devpriv->softsshdelay = -devpriv->softsshdelay;
		devpriv->softsshdelay = -softsshdelay;
		devpriv->softsshsample = 0x80;
		devpriv->softsshhold = 0x00;
	} else {
		devpriv->softsshdelay = softsshdelay;
		devpriv->softsshsample = 0x00;
		devpriv->softsshhold = 0x80;
	}
@@ -2036,12 +2004,7 @@ static int pci9118_attach(struct comedi_device *dev,
	s->range_table = this_board->rangelist_ai;
	s->cancel = pci9118_ai_cancel;
	s->insn_read = pci9118_insn_read_ai;
	if (dev->irq) {
		s->subdev_flags |= SDF_CMD_READ;
		s->do_cmdtest = pci9118_ai_cmdtest;
		s->do_cmd = pci9118_ai_cmd;
	s->munge = pci9118_ai_munge;
	}

	s = &dev->subdevices[1];
	s->type = COMEDI_SUBD_AO;
@@ -2077,8 +2040,8 @@ static int pci9118_attach(struct comedi_device *dev,
	devpriv->i8254_osc_base = 250;	/* 250ns=4MHz */
	devpriv->ai_maskharderr = 0x10a;
					/* default measure crash condition */
	if (it->options[5])		/* disable some requested */
		devpriv->ai_maskharderr &= ~it->options[5];
	if (hw_err_mask)		/* disable some requested */
		devpriv->ai_maskharderr &= ~hw_err_mask;

	switch (this_board->ai_maxdata) {
	case 0xffff:
@@ -2088,10 +2051,58 @@ static int pci9118_attach(struct comedi_device *dev,
		devpriv->ai16bits = 0;
		break;
	}

	if (disable_irq)
		irq = 0;
	else
		irq = pcidev->irq;
	if (irq > 0) {
		if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
				dev->board_name, dev)) {
			dev_warn(dev->class_dev,
				 "unable to allocate IRQ %u, DISABLING IT\n",
				 irq);
		} else {
			dev->irq = irq;
			/* Enable AI commands */
			s = &dev->subdevices[0];
			s->subdev_flags |= SDF_CMD_READ;
			s->do_cmdtest = pci9118_ai_cmdtest;
			s->do_cmd = pci9118_ai_cmd;
		}
	}

	pci9118_report_attach(dev, irq);
	return 0;
}

static int pci9118_attach(struct comedi_device *dev,
			  struct comedi_devconfig *it)
{
	struct pci9118_private *devpriv;
	struct pci_dev *pcidev;
	int ext_mux, disable_irq, master, softsshdelay, hw_err_mask;

	ext_mux = it->options[2];
	master = ((it->options[3] & 1) == 0);
	disable_irq = ((it->options[3] & 2) != 0);
	softsshdelay = it->options[4];
	hw_err_mask = it->options[5];

	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
	if (!devpriv)
		return -ENOMEM;
	dev->private = devpriv;

	pcidev = pci9118_find_pci(dev, it);
	if (!pcidev)
		return -EIO;
	comedi_set_hw_dev(dev, &pcidev->dev);

	return pci9118_common_attach(dev, disable_irq, master, ext_mux,
				     softsshdelay, hw_err_mask);
}

static void pci9118_detach(struct comedi_device *dev)
{
	struct pci_dev *pcidev = comedi_to_pci_dev(dev);