Staging: comedi: adv_pci_dio: Support Advantech PCI-1735U
Add support for the Advantech PCI-1735U card, including support for a counter subdevice (based on an 82C54 counter timer chip). The counter subdevice needs more testing, as the only person I know who tried it couldn't get it to work! Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
b2e68b00d5
commit
d4da77a73c
|
@ -7,17 +7,17 @@
|
|||
*/
|
||||
/*
|
||||
Driver: adv_pci_dio
|
||||
Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP,
|
||||
PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754,
|
||||
PCI-1756, PCI-1762
|
||||
Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
|
||||
PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
|
||||
PCI-1754, PCI-1756, PCI-1762
|
||||
Author: Michal Dobes <dobes@tesnet.cz>
|
||||
Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
|
||||
PCI-1734, PCI-1736UP, PCI-1750,
|
||||
PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750,
|
||||
PCI-1751, PCI-1752, PCI-1753,
|
||||
PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
|
||||
PCI-1760, PCI-1762
|
||||
Status: untested
|
||||
Updated: Mon, 14 Apr 2008 10:43:08 +0100
|
||||
Updated: Tue, 04 May 2010 13:00:00 +0000
|
||||
|
||||
This driver supports now only insn interface for DI/DO/DIO.
|
||||
|
||||
|
@ -35,6 +35,7 @@ Configuration options:
|
|||
|
||||
#include "comedi_pci.h"
|
||||
#include "8255.h"
|
||||
#include "8253.h"
|
||||
|
||||
#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */
|
||||
|
||||
|
@ -49,7 +50,7 @@ Configuration options:
|
|||
|
||||
/* hardware types of the cards */
|
||||
enum hw_cards_id {
|
||||
TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736,
|
||||
TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
|
||||
TYPE_PCI1750,
|
||||
TYPE_PCI1751,
|
||||
TYPE_PCI1752,
|
||||
|
@ -67,7 +68,10 @@ enum hw_io_access {
|
|||
#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
|
||||
#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
|
||||
#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */
|
||||
#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per card */
|
||||
/* (could be more than one 8254 per subdevice) */
|
||||
|
||||
#define SIZE_8254 4 /* 8254 IO space length */
|
||||
#define SIZE_8255 4 /* 8255 IO space length */
|
||||
|
||||
#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */
|
||||
|
@ -85,6 +89,12 @@ enum hw_io_access {
|
|||
#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
|
||||
#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
|
||||
|
||||
/* Advantech PCI-1735U */
|
||||
#define PCI1735_DI 0 /* R: Digital input 0-31 */
|
||||
#define PCI1735_DO 0 /* W: Digital output 0-31 */
|
||||
#define PCI1735_C8254 4 /* R/W: 8254 counter */
|
||||
#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */
|
||||
|
||||
/* Advantech PCI-1736UP */
|
||||
#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
|
||||
#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
|
||||
|
@ -192,7 +202,8 @@ static int pci_dio_detach(struct comedi_device *dev);
|
|||
struct diosubd_data {
|
||||
int chans; /* num of chans */
|
||||
int addr; /* PCI address ofset */
|
||||
int regs; /* number of registers to read or 8255 subdevices */
|
||||
int regs; /* number of registers to read or 8255
|
||||
subdevices or 8254 chips */
|
||||
unsigned int specflags; /* addon subdevice flags */
|
||||
};
|
||||
|
||||
|
@ -206,6 +217,7 @@ struct dio_boardtype {
|
|||
struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */
|
||||
struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */
|
||||
struct diosubd_data boardid; /* card supports board ID switch */
|
||||
struct diosubd_data s8254[MAX_8254_SUBDEVS]; /* 8254 subdevices */
|
||||
enum hw_io_access io_access;
|
||||
};
|
||||
|
||||
|
@ -214,6 +226,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
|
|||
PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
|
||||
PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
|
||||
PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
|
||||
PCI_VENDOR_ID_ADVANTECH, 0x1735, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
|
||||
PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
|
||||
PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
|
||||
PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
|
||||
|
@ -235,14 +248,15 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||
IO_8b,
|
||||
},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
|
||||
TYPE_PCI1733,
|
||||
{{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
|
||||
TYPE_PCI1734,
|
||||
|
@ -250,6 +264,15 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
|
||||
TYPE_PCI1735,
|
||||
{{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
|
||||
{{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{ 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
|
||||
{{3, PCI1735_C8254, 1, 0}},
|
||||
IO_8b},
|
||||
{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
|
||||
TYPE_PCI1736,
|
||||
|
@ -257,14 +280,15 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI1736_BOARDID, 1, SDF_INTERNAL},
|
||||
IO_8b,
|
||||
},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
|
||||
TYPE_PCI1750,
|
||||
{{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
|
||||
{{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
|
||||
TYPE_PCI1751,
|
||||
|
@ -272,6 +296,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}},
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
|
||||
TYPE_PCI1752,
|
||||
|
@ -279,6 +304,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_16b},
|
||||
{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
||||
TYPE_PCI1753,
|
||||
|
@ -286,6 +312,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}},
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
||||
TYPE_PCI1753E,
|
||||
|
@ -293,6 +320,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}},
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
|
||||
TYPE_PCI1754,
|
||||
|
@ -300,6 +328,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_16b},
|
||||
{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
|
||||
TYPE_PCI1756,
|
||||
|
@ -307,6 +336,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_16b},
|
||||
{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
|
||||
TYPE_PCI1760,
|
||||
|
@ -314,6 +344,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_8b},
|
||||
{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
|
||||
TYPE_PCI1762,
|
||||
|
@ -321,6 +352,7 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
{{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{4, PCI1762_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
IO_16b}
|
||||
};
|
||||
|
||||
|
@ -437,6 +469,83 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
|
|||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci_8254_insn_read(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
{
|
||||
const struct diosubd_data *d = (const struct diosubd_data *)s->private;
|
||||
unsigned int chan, chip, chipchan;
|
||||
unsigned long flags;
|
||||
|
||||
chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
|
||||
chip = chan / 3; /* chip on subdevice */
|
||||
chipchan = chan - (3 * chip); /* channel on chip on subdevice */
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
|
||||
0, chipchan);
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci_8254_insn_write(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
{
|
||||
const struct diosubd_data *d = (const struct diosubd_data *)s->private;
|
||||
unsigned int chan, chip, chipchan;
|
||||
unsigned long flags;
|
||||
|
||||
chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
|
||||
chip = chan / 3; /* chip on subdevice */
|
||||
chipchan = chan - (3 * chip); /* channel on chip on subdevice */
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
|
||||
0, chipchan, data[0]);
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci_8254_insn_config(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
{
|
||||
const struct diosubd_data *d = (const struct diosubd_data *)s->private;
|
||||
unsigned int chan, chip, chipchan;
|
||||
unsigned long iobase;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
|
||||
chip = chan / 3; /* chip on subdevice */
|
||||
chipchan = chan - (3 * chip); /* channel on chip on subdevice */
|
||||
iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
switch (data[0]) {
|
||||
case INSN_CONFIG_SET_COUNTER_MODE:
|
||||
ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
|
||||
if (ret < 0)
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case INSN_CONFIG_8254_READ_STATUS:
|
||||
data[1] = i8254_status(iobase, 0, chipchan);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
return ret < 0 ? ret : insn->n;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
|
@ -708,6 +817,15 @@ static int pci_dio_reset(struct comedi_device *dev)
|
|||
outb(0, dev->iobase + PCI1734_IDO + 2);
|
||||
outb(0, dev->iobase + PCI1734_IDO + 3);
|
||||
break;
|
||||
case TYPE_PCI1735:
|
||||
outb(0, dev->iobase + PCI1735_DO); /* clear outputs */
|
||||
outb(0, dev->iobase + PCI1735_DO + 1);
|
||||
outb(0, dev->iobase + PCI1735_DO + 2);
|
||||
outb(0, dev->iobase + PCI1735_DO + 3);
|
||||
i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
|
||||
i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
|
||||
i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
|
||||
break;
|
||||
|
||||
case TYPE_PCI1736:
|
||||
outb(0, dev->iobase + PCI1736_IDO);
|
||||
|
@ -874,6 +992,26 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci_dio_add_8254(struct comedi_device *dev,
|
||||
struct comedi_subdevice * s,
|
||||
const struct diosubd_data *d, int subdev)
|
||||
{
|
||||
s->type = COMEDI_SUBD_COUNTER;
|
||||
s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
|
||||
s->n_chan = d->chans;
|
||||
s->maxdata = 65535;
|
||||
s->len_chanlist = d->chans;
|
||||
s->insn_read = pci_8254_insn_read;
|
||||
s->insn_write = pci_8254_insn_write;
|
||||
s->insn_config = pci_8254_insn_config;
|
||||
s->private = (void *)d;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
|
@ -979,6 +1117,9 @@ static int pci_dio_attach(struct comedi_device *dev,
|
|||
n_subdevices += this_board->sdio[i].regs;
|
||||
if (this_board->boardid.chans)
|
||||
n_subdevices++;
|
||||
for (i = 0; i < MAX_8254_SUBDEVS; i++)
|
||||
if (this_board->s8254[i].chans)
|
||||
n_subdevices++;
|
||||
}
|
||||
|
||||
ret = alloc_subdevices(dev, n_subdevices);
|
||||
|
@ -1022,6 +1163,13 @@ static int pci_dio_attach(struct comedi_device *dev,
|
|||
subdev++;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_8254_SUBDEVS; i++)
|
||||
if (this_board->s8254[i].chans) {
|
||||
s = dev->subdevices + subdev;
|
||||
pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev);
|
||||
subdev++;
|
||||
}
|
||||
|
||||
if (this_board->cardtype == TYPE_PCI1760)
|
||||
pci1760_attach(dev, it);
|
||||
|
||||
|
@ -1067,6 +1215,16 @@ static int pci_dio_detach(struct comedi_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (this_board->boardid.chans) {
|
||||
subdev++;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_8254_SUBDEVS; i++) {
|
||||
if (this_board->s8254[i].chans) {
|
||||
subdev++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->n_subdevices; i++) {
|
||||
s = dev->subdevices + i;
|
||||
s->private = NULL;
|
||||
|
|
Loading…
Reference in New Issue