|
@@ -430,11 +430,14 @@ struct pci224_private {
|
|
|
static int pci224_attach(struct comedi_device *dev,
|
|
|
struct comedi_devconfig *it);
|
|
|
static int pci224_detach(struct comedi_device *dev);
|
|
|
+static int pci224_attach_pci(struct comedi_device *dev,
|
|
|
+ struct pci_dev *pci_dev);
|
|
|
static struct comedi_driver driver_amplc_pci224 = {
|
|
|
.driver_name = DRIVER_NAME,
|
|
|
.module = THIS_MODULE,
|
|
|
.attach = pci224_attach,
|
|
|
.detach = pci224_detach,
|
|
|
+ .attach_pci = pci224_attach_pci,
|
|
|
.board_name = &pci224_boards[0].name,
|
|
|
.offset = sizeof(struct pci224_board),
|
|
|
.num_names = ARRAY_SIZE(pci224_boards),
|
|
@@ -1311,6 +1314,20 @@ static irqreturn_t pci224_interrupt(int irq, void *d)
|
|
|
return IRQ_RETVAL(retval);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * This function looks for a board matching the supplied PCI device.
|
|
|
+ */
|
|
|
+static const struct pci224_board
|
|
|
+*pci224_find_pci_board(struct pci_dev *pci_dev)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(pci224_boards); i++)
|
|
|
+ if (pci_dev->device == pci224_boards[i].devid)
|
|
|
+ return &pci224_boards[i];
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This function looks for a PCI device matching the requested board name,
|
|
|
* bus and slot.
|
|
@@ -1336,17 +1353,12 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot,
|
|
|
}
|
|
|
if (thisboard->model == any_model) {
|
|
|
/* Match any supported model. */
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < ARRAY_SIZE(pci224_boards); i++) {
|
|
|
- if (pci_dev->device == pci224_boards[i].devid) {
|
|
|
- /* Change board_ptr to matched board. */
|
|
|
- dev->board_ptr = &pci224_boards[i];
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (i == ARRAY_SIZE(pci224_boards))
|
|
|
+ const struct pci224_board *board_ptr;
|
|
|
+ board_ptr = pci224_find_pci_board(pci_dev);
|
|
|
+ if (board_ptr == NULL)
|
|
|
continue;
|
|
|
+ /* Change board_ptr to matched board. */
|
|
|
+ dev->board_ptr = board_ptr;
|
|
|
} else {
|
|
|
/* Match specific model name. */
|
|
|
if (thisboard->devid != pci_dev->device)
|
|
@@ -1370,35 +1382,16 @@ pci224_find_pci(struct comedi_device *dev, int bus, int slot,
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Attach is called by the Comedi core to configure the driver
|
|
|
- * for a particular board. If you specified a board_name array
|
|
|
- * in the driver structure, dev->board_ptr contains that
|
|
|
- * address.
|
|
|
+ * Common part of attach and attach_pci.
|
|
|
*/
|
|
|
-static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|
|
+static int pci224_attach_common(struct comedi_device *dev,
|
|
|
+ struct pci_dev *pci_dev, int *options)
|
|
|
{
|
|
|
struct comedi_subdevice *s;
|
|
|
- struct pci_dev *pci_dev;
|
|
|
unsigned int irq;
|
|
|
- int bus = 0, slot = 0;
|
|
|
unsigned n;
|
|
|
int ret;
|
|
|
|
|
|
- printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DRIVER_NAME);
|
|
|
-
|
|
|
- bus = it->options[0];
|
|
|
- slot = it->options[1];
|
|
|
- ret = alloc_private(dev, sizeof(struct pci224_private));
|
|
|
- if (ret < 0) {
|
|
|
- printk(KERN_ERR "comedi%d: error! out of memory!\n",
|
|
|
- dev->minor);
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- ret = pci224_find_pci(dev, bus, slot, &pci_dev);
|
|
|
- if (ret < 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
devpriv->pci_dev = pci_dev;
|
|
|
ret = comedi_pci_enable(pci_dev, DRIVER_NAME);
|
|
|
if (ret < 0) {
|
|
@@ -1483,24 +1476,26 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|
|
if (!s->range_table_list)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- for (n = 2; n < 3 + s->n_chan; n++) {
|
|
|
- if (it->options[n] < 0 || it->options[n] > 1) {
|
|
|
- printk(KERN_WARNING "comedi%d: %s: warning! "
|
|
|
- "bad options[%u]=%d\n",
|
|
|
- dev->minor, DRIVER_NAME, n,
|
|
|
- it->options[n]);
|
|
|
+ if (options) {
|
|
|
+ for (n = 2; n < 3 + s->n_chan; n++) {
|
|
|
+ if (options[n] < 0 || options[n] > 1) {
|
|
|
+ printk(KERN_WARNING
|
|
|
+ "comedi%d: %s: warning! bad options[%u]=%d\n",
|
|
|
+ dev->minor, DRIVER_NAME, n,
|
|
|
+ options[n]);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
for (n = 0; n < s->n_chan; n++) {
|
|
|
- if (n < COMEDI_NDEVCONFOPTS - 3 &&
|
|
|
- it->options[3 + n] == 1) {
|
|
|
- if (it->options[2] == 1)
|
|
|
+ if (n < COMEDI_NDEVCONFOPTS - 3 && options &&
|
|
|
+ options[3 + n] == 1) {
|
|
|
+ if (options[2] == 1)
|
|
|
range_table_list[n] = &range_pci234_ext;
|
|
|
else
|
|
|
range_table_list[n] = &range_bipolar5;
|
|
|
|
|
|
} else {
|
|
|
- if (it->options[2] == 1) {
|
|
|
+ if (options && options[2] == 1) {
|
|
|
range_table_list[n] =
|
|
|
&range_pci234_ext2;
|
|
|
} else {
|
|
@@ -1511,14 +1506,14 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|
|
devpriv->hwrange = hwrange_pci234;
|
|
|
} else {
|
|
|
/* PCI224 range options. */
|
|
|
- if (it->options[2] == 1) {
|
|
|
+ if (options && options[2] == 1) {
|
|
|
s->range_table = &range_pci224_external;
|
|
|
devpriv->hwrange = hwrange_pci224_external;
|
|
|
} else {
|
|
|
- if (it->options[2] != 0) {
|
|
|
+ if (options && options[2] != 0) {
|
|
|
printk(KERN_WARNING "comedi%d: %s: warning! "
|
|
|
"bad options[2]=%d\n",
|
|
|
- dev->minor, DRIVER_NAME, it->options[2]);
|
|
|
+ dev->minor, DRIVER_NAME, options[2]);
|
|
|
}
|
|
|
s->range_table = &range_pci224_internal;
|
|
|
devpriv->hwrange = hwrange_pci224_internal;
|
|
@@ -1552,6 +1547,66 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * _attach is called by the Comedi core to configure the driver
|
|
|
+ * for a particular board. If you specified a board_name array
|
|
|
+ * in the driver structure, dev->board_ptr contains that
|
|
|
+ * address.
|
|
|
+ */
|
|
|
+static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|
|
+{
|
|
|
+ struct pci_dev *pci_dev;
|
|
|
+ int bus, slot;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DRIVER_NAME);
|
|
|
+
|
|
|
+ bus = it->options[0];
|
|
|
+ slot = it->options[1];
|
|
|
+ ret = alloc_private(dev, sizeof(struct pci224_private));
|
|
|
+ if (ret < 0) {
|
|
|
+ printk(KERN_ERR "comedi%d: error! out of memory!\n",
|
|
|
+ dev->minor);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = pci224_find_pci(dev, bus, slot, &pci_dev);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return pci224_attach_common(dev, pci_dev, it->options);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * _attach_pci is called by comedi_pci_auto_config() in the Comedi core
|
|
|
+ * to configure a comedi device for a probed PCI device.
|
|
|
+ * dev->board_ptr is NULL on entry.
|
|
|
+ */
|
|
|
+static int
|
|
|
+pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ printk(KERN_DEBUG "comedi%d: %s: attach_pci %s\n", dev->minor,
|
|
|
+ DRIVER_NAME, pci_name(pci_dev));
|
|
|
+
|
|
|
+ ret = alloc_private(dev, sizeof(struct pci224_private));
|
|
|
+ if (ret < 0) {
|
|
|
+ printk(KERN_ERR "comedi%d: error! out of memory!\n",
|
|
|
+ dev->minor);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ dev->board_ptr = pci224_find_pci_board(pci_dev);
|
|
|
+ if (dev->board_ptr == NULL) {
|
|
|
+ printk(KERN_ERR
|
|
|
+ "comedi%d: %s: BUG! cannot determine board type!\n",
|
|
|
+ dev->minor, DRIVER_NAME);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ return pci224_attach_common(dev, pci_dev, NULL);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* _detach is called to deconfigure a device. It should deallocate
|
|
|
* resources.
|