aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers/adv_pci_dio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers/adv_pci_dio.c')
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c178
1 files changed, 88 insertions, 90 deletions
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 338c43e716ba..f70c67471c13 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -236,8 +236,6 @@ struct diosubd_data {
struct dio_boardtype {
const char *name; /* board name */
- int vendor_id; /* vendor/device PCI ID */
- int device_id;
int main_pci_region; /* main I/O PCI region */
enum hw_cards_id cardtype;
int nsubdevs;
@@ -250,10 +248,8 @@ struct dio_boardtype {
};
static const struct dio_boardtype boardtypes[] = {
- {
+ [TYPE_PCI1730] = {
.name = "pci1730",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1730,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1730,
.nsubdevs = 5,
@@ -263,30 +259,27 @@ static const struct dio_boardtype boardtypes[] = {
.sdo[1] = { 16, PCI1730_IDO, 2, 0, },
.boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1733] = {
.name = "pci1733",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1733,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1733,
.nsubdevs = 2,
.sdi[1] = { 32, PCI1733_IDI, 4, 0, },
.boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1734] = {
.name = "pci1734",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1734,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1734,
.nsubdevs = 2,
.sdo[1] = { 32, PCI1734_IDO, 4, 0, },
.boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1735] = {
.name = "pci1735",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1735,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1735,
.nsubdevs = 4,
@@ -295,10 +288,9 @@ static const struct dio_boardtype boardtypes[] = {
.boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, },
.s8254[0] = { 3, PCI1735_C8254, 1, 0, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1736] = {
.name = "pci1736",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1736,
.main_pci_region = PCI1736_MAINREG,
.cardtype = TYPE_PCI1736,
.nsubdevs = 3,
@@ -306,39 +298,35 @@ static const struct dio_boardtype boardtypes[] = {
.sdo[1] = { 16, PCI1736_IDO, 2, 0, },
.boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1739] = {
.name = "pci1739",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1739,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1739,
.nsubdevs = 2,
.sdio[0] = { 48, PCI1739_DIO, 2, 0, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1750] = {
.name = "pci1750",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1750,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1750,
.nsubdevs = 2,
.sdi[1] = { 16, PCI1750_IDI, 2, 0, },
.sdo[1] = { 16, PCI1750_IDO, 2, 0, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1751] = {
.name = "pci1751",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1751,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1751,
.nsubdevs = 3,
.sdio[0] = { 48, PCI1751_DIO, 2, 0, },
.s8254[0] = { 3, PCI1751_CNT, 1, 0, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1752] = {
.name = "pci1752",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1752,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1752,
.nsubdevs = 3,
@@ -346,29 +334,26 @@ static const struct dio_boardtype boardtypes[] = {
.sdo[1] = { 32, PCI1752_IDO2, 2, 0, },
.boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
.io_access = IO_16b,
- }, {
+ },
+ [TYPE_PCI1753] = {
.name = "pci1753",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1753,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1753,
.nsubdevs = 4,
.sdio[0] = { 96, PCI1753_DIO, 4, 0, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1753E] = {
.name = "pci1753e",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1753,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1753E,
.nsubdevs = 8,
.sdio[0] = { 96, PCI1753_DIO, 4, 0, },
.sdio[1] = { 96, PCI1753E_DIO, 4, 0, },
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1754] = {
.name = "pci1754",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1754,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1754,
.nsubdevs = 3,
@@ -376,10 +361,9 @@ static const struct dio_boardtype boardtypes[] = {
.sdi[1] = { 32, PCI1754_IDI2, 2, 0, },
.boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
.io_access = IO_16b,
- }, {
+ },
+ [TYPE_PCI1756] = {
.name = "pci1756",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1756,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1756,
.nsubdevs = 3,
@@ -387,19 +371,17 @@ static const struct dio_boardtype boardtypes[] = {
.sdo[1] = { 32, PCI1756_IDO, 2, 0, },
.boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
.io_access = IO_16b,
- }, {
+ },
+ [TYPE_PCI1760] = {
/* This card has its own 'attach' */
.name = "pci1760",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1760,
.main_pci_region = 0,
.cardtype = TYPE_PCI1760,
.nsubdevs = 4,
.io_access = IO_8b,
- }, {
+ },
+ [TYPE_PCI1762] = {
.name = "pci1762",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1762,
.main_pci_region = PCIDIO_MAINREG,
.cardtype = TYPE_PCI1762,
.nsubdevs = 3,
@@ -1076,31 +1058,50 @@ static int pci_dio_add_8254(struct comedi_device *dev,
return 0;
}
-static const void *pci_dio_find_boardinfo(struct comedi_device *dev,
- struct pci_dev *pcidev)
+static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
+ unsigned long cardtype)
{
- const struct dio_boardtype *this_board;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
- this_board = &boardtypes[i];
- if (this_board->vendor_id == pcidev->vendor &&
- this_board->device_id == pcidev->device)
- return this_board;
+ /*
+ * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion
+ * board available. Need to enable PCI device and request the main
+ * registers PCI BAR temporarily to perform the test.
+ */
+ if (cardtype != TYPE_PCI1753)
+ return cardtype;
+ if (pci_enable_device(pcidev) < 0)
+ return cardtype;
+ if (pci_request_region(pcidev, PCIDIO_MAINREG, "adv_pci_dio") == 0) {
+ /*
+ * This test is based on Advantech's "advdaq" driver source
+ * (which declares its module licence as "GPL" although the
+ * driver source does not include a "COPYING" file).
+ */
+ unsigned long reg =
+ pci_resource_start(pcidev, PCIDIO_MAINREG) + 53;
+
+ outb(0x05, reg);
+ if ((inb(reg) & 0x07) == 0x02) {
+ outb(0x02, reg);
+ if ((inb(reg) & 0x07) == 0x05)
+ cardtype = TYPE_PCI1753E;
+ }
+ pci_release_region(pcidev, PCIDIO_MAINREG);
}
- return NULL;
+ pci_disable_device(pcidev);
+ return cardtype;
}
static int pci_dio_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
+ unsigned long context)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- const struct dio_boardtype *this_board;
+ const struct dio_boardtype *this_board = NULL;
struct pci_dio_private *devpriv;
struct comedi_subdevice *s;
int ret, subdev, i, j;
- this_board = pci_dio_find_boardinfo(dev, pcidev);
+ if (context < ARRAY_SIZE(boardtypes))
+ this_board = &boardtypes[context];
if (!this_board)
return -ENODEV;
dev->board_ptr = this_board;
@@ -1111,7 +1112,7 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
return -ENOMEM;
dev->private = devpriv;
- ret = comedi_pci_enable(pcidev, dev->board_name);
+ ret = comedi_pci_enable(dev);
if (ret)
return ret;
dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region);
@@ -1172,7 +1173,6 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
static void pci_dio_detach(struct comedi_device *dev)
{
struct pci_dio_private *devpriv = dev->private;
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
struct comedi_subdevice *s;
int i;
@@ -1180,18 +1180,13 @@ static void pci_dio_detach(struct comedi_device *dev)
if (devpriv->valid)
pci_dio_reset(dev);
}
- if (dev->subdevices) {
- for (i = 0; i < dev->n_subdevices; i++) {
- s = &dev->subdevices[i];
- if (s->type == COMEDI_SUBD_DIO)
- subdev_8255_cleanup(dev, s);
- s->private = NULL;
- }
- }
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = &dev->subdevices[i];
+ if (s->type == COMEDI_SUBD_DIO)
+ comedi_spriv_free(dev, i);
+ s->private = NULL; /* some private data is static */
}
+ comedi_pci_disable(dev);
}
static struct comedi_driver adv_pci_dio_driver = {
@@ -1202,26 +1197,29 @@ static struct comedi_driver adv_pci_dio_driver = {
};
static int adv_pci_dio_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *id)
{
- return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
+ unsigned long cardtype;
+
+ cardtype = pci_dio_override_cardtype(dev, id->driver_data);
+ return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype);
}
static DEFINE_PCI_DEVICE_TABLE(adv_pci_dio_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1753) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1754) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1756) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) },
- { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1762) },
+ { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 },
+ { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 },
+ { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 },
+ { PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 },
+ { PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 },
+ { PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 },
+ { PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 },
+ { PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 },
+ { PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 },
+ { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 },
+ { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 },
+ { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 },
+ { PCI_VDEVICE(ADVANTECH, 0x1760), TYPE_PCI1760 },
+ { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);