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

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
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment