Commit f21c5394 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: drivers: use comedi_dio_insn_config() for complex cases

Convert the drivers with complex, port programmable i/o, to use the
comedi_dio_insn_config() helper function.

All of these drivers have some sort of 'port' programmable i/o where multiple
i/o channels are configured as a group. The 'mask' associated with the group
is passed to comedi_dio_insn_config() so that all the channels are configured.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 42ef678b
...@@ -184,39 +184,29 @@ static void subdev_8255_do_config(struct comedi_device *dev, ...@@ -184,39 +184,29 @@ static void subdev_8255_do_config(struct comedi_device *dev,
static int subdev_8255_insn_config(struct comedi_device *dev, static int subdev_8255_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask; unsigned int mask;
unsigned int bits; int ret;
mask = 1 << CR_CHAN(insn->chanspec); if (chan < 8)
if (mask & 0x0000ff) mask = 0x0000ff;
bits = 0x0000ff; else if (chan < 16)
else if (mask & 0x00ff00) mask = 0x00ff00;
bits = 0x00ff00; else if (chan < 20)
else if (mask & 0x0f0000) mask = 0x0f0000;
bits = 0x0f0000;
else else
bits = 0xf00000; mask = 0xf00000;
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_INPUT: if (ret)
s->io_bits &= ~bits; return ret;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
subdev_8255_do_config(dev, s); subdev_8255_do_config(dev, s);
return 1; return insn->n;
} }
static int subdev_8255_cmdtest(struct comedi_device *dev, static int subdev_8255_cmdtest(struct comedi_device *dev,
......
...@@ -60,36 +60,22 @@ static int apci16xx_insn_config(struct comedi_device *dev, ...@@ -60,36 +60,22 @@ static int apci16xx_insn_config(struct comedi_device *dev,
struct comedi_insn *insn, struct comedi_insn *insn,
unsigned int *data) unsigned int *data)
{ {
unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec); unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int bits; unsigned int mask;
int ret;
/* if (chan < 8)
* Each 8-bit "port" is configurable as either input or mask = 0x000000ff;
* output. Changing the configuration of any channel in else if (chan < 16)
* a port changes the entire port. mask = 0x0000ff00;
*/ else if (chan < 24)
if (chan_mask & 0x000000ff) mask = 0x00ff0000;
bits = 0x000000ff;
else if (chan_mask & 0x0000ff00)
bits = 0x0000ff00;
else if (chan_mask & 0x00ff0000)
bits = 0x00ff0000;
else else
bits = 0xff000000; mask = 0xff000000;
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_INPUT: if (ret)
s->io_bits &= ~bits; return ret;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_INPUT : COMEDI_OUTPUT;
return insn->n;
default:
return -EINVAL;
}
outl(s->io_bits, dev->iobase + APCI16XX_DIR_REG(s->index)); outl(s->io_bits, dev->iobase + APCI16XX_DIR_REG(s->index));
......
...@@ -686,37 +686,27 @@ static int apci3xxx_dio_insn_config(struct comedi_device *dev, ...@@ -686,37 +686,27 @@ static int apci3xxx_dio_insn_config(struct comedi_device *dev,
unsigned int *data) unsigned int *data)
{ {
unsigned int chan = CR_CHAN(insn->chanspec); unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask = 1 << chan; unsigned int mask;
unsigned int bits; int ret;
/* /*
* Port 0 (channels 0-7) are always inputs * Port 0 (channels 0-7) are always inputs
* Port 1 (channels 8-15) are always outputs * Port 1 (channels 8-15) are always outputs
* Port 2 (channels 16-23) are programmable i/o * Port 2 (channels 16-23) are programmable i/o
*
* Changing any channel in port 2 changes the entire port.
*/ */
if (mask & 0xff0000) if (chan < 16) {
bits = 0xff0000; if (data[0] != INSN_CONFIG_DIO_QUERY)
else
bits = 0;
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~bits;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
default:
return -EINVAL; return -EINVAL;
} else {
/* changing any channel in port 2 changes the entire port */
mask = 0xff0000;
} }
ret = comedi_dio_insn_config(dev, s, insn, data, mask);
if (ret)
return ret;
/* update port 2 configuration */ /* update port 2 configuration */
if (bits)
outl((s->io_bits >> 24) & 0xff, dev->iobase + 224); outl((s->io_bits >> 24) & 0xff, dev->iobase + 224);
return insn->n; return insn->n;
......
...@@ -180,38 +180,29 @@ static int pci1723_dio_insn_config(struct comedi_device *dev, ...@@ -180,38 +180,29 @@ static int pci1723_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn, unsigned int *data)
{ {
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask; unsigned int mask;
unsigned int bits; unsigned short mode;
unsigned short dio_mode; int ret;
mask = 1 << CR_CHAN(insn->chanspec); if (chan < 8)
if (mask & 0x00FF) mask = 0x00ff;
bits = 0x00FF;
else else
bits = 0xFF00; mask = 0xff00;
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_INPUT: if (ret)
s->io_bits &= ~bits; return ret;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
default:
return -EINVAL;
}
/* update hardware DIO mode */ /* update hardware DIO mode */
dio_mode = 0x0000; /* low byte output, high byte output */ mode = 0x0000; /* assume output */
if ((s->io_bits & 0x00FF) == 0) if (!(s->io_bits & 0x00ff))
dio_mode |= 0x0001; /* low byte input */ mode |= 0x0001; /* low byte input */
if ((s->io_bits & 0xFF00) == 0) if (!(s->io_bits & 0xff00))
dio_mode |= 0x0002; /* high byte input */ mode |= 0x0002; /* high byte input */
outw(dio_mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET); outw(mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET);
return 1;
return insn->n;
} }
/* /*
......
...@@ -976,34 +976,26 @@ static int dio200_subdev_8255_config(struct comedi_device *dev, ...@@ -976,34 +976,26 @@ static int dio200_subdev_8255_config(struct comedi_device *dev,
struct comedi_insn *insn, struct comedi_insn *insn,
unsigned int *data) unsigned int *data)
{ {
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask; unsigned int mask;
unsigned int bits; int ret;
mask = 1 << CR_CHAN(insn->chanspec); if (chan < 8)
if (mask & 0x0000ff) mask = 0x0000ff;
bits = 0x0000ff; else if (chan < 16)
else if (mask & 0x00ff00) mask = 0x00ff00;
bits = 0x00ff00; else if (chan < 20)
else if (mask & 0x0f0000) mask = 0x0f0000;
bits = 0x0f0000;
else else
bits = 0xf00000; mask = 0xf00000;
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT: ret = comedi_dio_insn_config(dev, s, insn, data, mask);
s->io_bits &= ~bits; if (ret)
break; return ret;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
dio200_subdev_8255_set_dir(dev, s); dio200_subdev_8255_set_dir(dev, s);
return 1;
return insn->n;
} }
/* /*
......
...@@ -341,33 +341,22 @@ static int das16cs_dio_insn_bits(struct comedi_device *dev, ...@@ -341,33 +341,22 @@ static int das16cs_dio_insn_bits(struct comedi_device *dev,
static int das16cs_dio_insn_config(struct comedi_device *dev, static int das16cs_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
struct das16cs_private *devpriv = dev->private; struct das16cs_private *devpriv = dev->private;
int chan = CR_CHAN(insn->chanspec); unsigned int chan = CR_CHAN(insn->chanspec);
int bits; unsigned int mask;
int ret;
if (chan < 4) if (chan < 4)
bits = 0x0f; mask = 0x0f;
else else
bits = 0xf0; mask = 0xf0;
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_OUTPUT: if (ret)
s->io_bits |= bits; return ret;
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
(s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
break;
}
devpriv->status2 &= ~0x00c0; devpriv->status2 &= ~0x00c0;
devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0; devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
......
...@@ -551,32 +551,19 @@ static int dt2801_dio_insn_bits(struct comedi_device *dev, ...@@ -551,32 +551,19 @@ static int dt2801_dio_insn_bits(struct comedi_device *dev,
static int dt2801_dio_insn_config(struct comedi_device *dev, static int dt2801_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
int which = 0; int ret;
if (s == &dev->subdevices[3]) ret = comedi_dio_insn_config(dev, s, insn, data, 0xff);
which = 1; if (ret)
return ret;
/* configure */ dt2801_writecmd(dev, s->io_bits ? DT_C_SET_DIGOUT : DT_C_SET_DIGIN);
switch (data[0]) { dt2801_writedata(dev, (s == &dev->subdevices[3]) ? 1 : 0);
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits = 0xff;
dt2801_writecmd(dev, DT_C_SET_DIGOUT);
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits = 0;
dt2801_writecmd(dev, DT_C_SET_DIGIN);
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = s->io_bits ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
default:
return -EINVAL;
}
dt2801_writedata(dev, which);
return 1; return insn->n;
} }
/* /*
......
...@@ -642,32 +642,23 @@ static void dt3k_dio_config(struct comedi_device *dev, int bits) ...@@ -642,32 +642,23 @@ static void dt3k_dio_config(struct comedi_device *dev, int bits)
static int dt3k_dio_insn_config(struct comedi_device *dev, static int dt3k_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
int mask; unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask;
int ret;
mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0; if (chan < 4)
mask = 0x0f;
else
mask = 0xf0;
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_OUTPUT: if (ret)
s->io_bits |= mask; return ret;
break;
case INSN_CONFIG_DIO_INPUT: dt3k_dio_config(dev, (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3));
s->io_bits &= ~mask;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
(s->
io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
break;
}
mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
dt3k_dio_config(dev, mask);
return insn->n; return insn->n;
} }
......
...@@ -224,37 +224,26 @@ struct hpdi_private { ...@@ -224,37 +224,26 @@ struct hpdi_private {
volatile uint32_t bits[24]; volatile uint32_t bits[24];
/* number of bytes at which to generate COMEDI_CB_BLOCK events */ /* number of bytes at which to generate COMEDI_CB_BLOCK events */
volatile unsigned int block_size; volatile unsigned int block_size;
unsigned dio_config_output:1;
}; };
static int dio_config_insn(struct comedi_device *dev, static int dio_config_insn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data) unsigned int *data)
{ {
struct hpdi_private *devpriv = dev->private; int ret;
switch (data[0]) { switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
devpriv->dio_config_output = 1;
return insn->n;
break;
case INSN_CONFIG_DIO_INPUT:
devpriv->dio_config_output = 0;
return insn->n;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
devpriv->dio_config_output ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
case INSN_CONFIG_BLOCK_SIZE: case INSN_CONFIG_BLOCK_SIZE:
return dio_config_block_size(dev, data); return dio_config_block_size(dev, data);
break;
default: default:
ret = comedi_dio_insn_config(dev, s, insn, data, 0xffffffff);
if (ret)
return ret;
break; break;
} }
return -EINVAL; return insn->n;
} }
static void disable_plx_interrupts(struct comedi_device *dev) static void disable_plx_interrupts(struct comedi_device *dev)
...@@ -673,9 +662,7 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, ...@@ -673,9 +662,7 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd) struct comedi_cmd *cmd)
{ {
struct hpdi_private *devpriv = dev->private; if (s->io_bits)
if (devpriv->dio_config_output)
return -EINVAL; return -EINVAL;
else else
return di_cmd_test(dev, s, cmd); return di_cmd_test(dev, s, cmd);
...@@ -746,9 +733,7 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -746,9 +733,7 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ {
struct hpdi_private *devpriv = dev->private; if (s->io_bits)
if (devpriv->dio_config_output)
return -EINVAL; return -EINVAL;
else else
return di_cmd(dev, s); return di_cmd(dev, s);
......
...@@ -350,31 +350,22 @@ static int ii20k_dio_insn_config(struct comedi_device *dev, ...@@ -350,31 +350,22 @@ static int ii20k_dio_insn_config(struct comedi_device *dev,
struct comedi_insn *insn, struct comedi_insn *insn,
unsigned int *data) unsigned int *data)
{ {
unsigned int mask = 1 << CR_CHAN(insn->chanspec); unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int bits; unsigned int mask;
int ret;
if (mask & 0x000000ff) if (chan < 8)
bits = 0x000000ff; mask = 0x000000ff;
else if (mask & 0x0000ff00) else if (chan < 16)
bits = 0x0000ff00; mask = 0x0000ff00;
else if (mask & 0x00ff0000) else if (chan < 24)
bits = 0x00ff0000; mask = 0x00ff0000;
else else
bits = 0xff000000; mask = 0xff000000;
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_INPUT: if (ret)
s->io_bits &= ~bits; return ret;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
default:
return -EINVAL;
}
ii20k_dio_config(dev, s); ii20k_dio_config(dev, s);
......
...@@ -1358,98 +1358,57 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, ...@@ -1358,98 +1358,57 @@ static int me4000_dio_insn_bits(struct comedi_device *dev,
static int me4000_dio_insn_config(struct comedi_device *dev, static int me4000_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
unsigned long tmp; unsigned int chan = CR_CHAN(insn->chanspec);
int chan = CR_CHAN(insn->chanspec); unsigned int mask;
unsigned int tmp;
switch (data[0]) { int ret;
default:
return -EINVAL; if (chan < 8)
case INSN_CONFIG_DIO_QUERY: mask = 0x000000ff;
data[1] = else if (chan < 16)
(s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; mask = 0x0000ff00;
return insn->n; else if (chan < 24)
case INSN_CONFIG_DIO_INPUT: mask = 0x00ff0000;
case INSN_CONFIG_DIO_OUTPUT: else
break; mask = 0xff000000;
}
/* ret = comedi_dio_insn_config(dev, s, insn, data, mask);
* The input or output configuration of each digital line is if (ret)
* configured by a special insn_config instruction. chanspec return ret;
* contains the channel to be changed, and data[0] contains the
* value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
* On the ME-4000 it is only possible to switch port wise (8 bit)
*/
tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG); tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | ME4000_DIO_CTRL_BIT_MODE_1 |
if (data[0] == INSN_CONFIG_DIO_OUTPUT) { ME4000_DIO_CTRL_BIT_MODE_2 | ME4000_DIO_CTRL_BIT_MODE_3 |
if (chan < 8) { ME4000_DIO_CTRL_BIT_MODE_4 | ME4000_DIO_CTRL_BIT_MODE_5 |
s->io_bits |= 0xFF; ME4000_DIO_CTRL_BIT_MODE_6 | ME4000_DIO_CTRL_BIT_MODE_7);
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | if (s->io_bits & 0x000000ff)
ME4000_DIO_CTRL_BIT_MODE_1);
tmp |= ME4000_DIO_CTRL_BIT_MODE_0; tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
} else if (chan < 16) { if (s->io_bits & 0x0000ff00)
/*
* Chech for optoisolated ME-4000 version.
* If one the first port is a fixed output
* port and the second is a fixed input port.
*/
if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
return -ENODEV;
s->io_bits |= 0xFF00;
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
ME4000_DIO_CTRL_BIT_MODE_3);
tmp |= ME4000_DIO_CTRL_BIT_MODE_2; tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
} else if (chan < 24) { if (s->io_bits & 0x00ff0000)
s->io_bits |= 0xFF0000;
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
ME4000_DIO_CTRL_BIT_MODE_5);
tmp |= ME4000_DIO_CTRL_BIT_MODE_4; tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
} else if (chan < 32) { if (s->io_bits & 0xff000000)
s->io_bits |= 0xFF000000;
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
ME4000_DIO_CTRL_BIT_MODE_7);
tmp |= ME4000_DIO_CTRL_BIT_MODE_6; tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
} else {
return -EINVAL;
}
} else {
if (chan < 8) {
/* /*
* Chech for optoisolated ME-4000 version. * Check for optoisolated ME-4000 version.
* If one the first port is a fixed output * If one the first port is a fixed output
* port and the second is a fixed input port. * port and the second is a fixed input port.
*/ */
if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) if (inl(dev->iobase + ME4000_DIO_DIR_REG)) {
return -ENODEV; s->io_bits |= 0x000000ff;
s->io_bits &= ~0x0000ff00;
s->io_bits &= ~0xFF; tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
ME4000_DIO_CTRL_BIT_MODE_1);
} else if (chan < 16) {
s->io_bits &= ~0xFF00;
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 | tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
ME4000_DIO_CTRL_BIT_MODE_3); ME4000_DIO_CTRL_BIT_MODE_3);
} else if (chan < 24) {
s->io_bits &= ~0xFF0000;
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
ME4000_DIO_CTRL_BIT_MODE_5);
} else if (chan < 32) {
s->io_bits &= ~0xFF000000;
tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
ME4000_DIO_CTRL_BIT_MODE_7);
} else {
return -EINVAL;
}
} }
outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG); outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
return 1; return insn->n;
} }
/*============================================================================= /*=============================================================================
......
...@@ -186,38 +186,30 @@ static int me_dio_insn_config(struct comedi_device *dev, ...@@ -186,38 +186,30 @@ static int me_dio_insn_config(struct comedi_device *dev,
struct comedi_insn *insn, struct comedi_insn *insn,
unsigned int *data) unsigned int *data)
{ {
struct me_private_data *dev_private = dev->private; struct me_private_data *devpriv = dev->private;
unsigned int mask = 1 << CR_CHAN(insn->chanspec); unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int bits; unsigned int mask;
unsigned int port; int ret;
if (mask & 0x0000ffff) { if (chan < 16)
bits = 0x0000ffff; mask = 0x0000ffff;
port = ENABLE_PORT_A; else
} else { mask = 0xffff0000;
bits = 0xffff0000;
port = ENABLE_PORT_B;
}
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_INPUT: if (ret)
s->io_bits &= ~bits; return ret;
dev_private->control_2 &= ~port;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
dev_private->control_2 |= port;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
/* Update the port configuration */ if (s->io_bits & 0x0000ffff)
writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2); devpriv->control_2 |= ENABLE_PORT_A;
else
devpriv->control_2 &= ~ENABLE_PORT_A;
if (s->io_bits & 0xffff0000)
devpriv->control_2 |= ENABLE_PORT_B;
else
devpriv->control_2 &= ~ENABLE_PORT_B;
writew(devpriv->control_2, devpriv->me_regbase + ME_CONTROL_2);
return insn->n; return insn->n;
} }
......
...@@ -248,42 +248,35 @@ static int atao_dio_insn_bits(struct comedi_device *dev, ...@@ -248,42 +248,35 @@ static int atao_dio_insn_bits(struct comedi_device *dev,
static int atao_dio_insn_config(struct comedi_device *dev, static int atao_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
struct atao_private *devpriv = dev->private; struct atao_private *devpriv = dev->private;
int chan = CR_CHAN(insn->chanspec); unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask, bit; unsigned int mask;
int ret;
/* The input or output configuration of each digital line is
* configured by a special insn_config instruction. chanspec if (chan < 4)
* contains the channel to be changed, and data[0] contains the mask = 0x0f;
* value COMEDI_INPUT or COMEDI_OUTPUT. */ else
mask = 0xf0;
mask = (chan < 4) ? 0x0f : 0xf0;
bit = (chan < 4) ? DOUTEN1 : DOUTEN2; ret = comedi_dio_insn_config(dev, s, insn, data, mask);
if (ret)
switch (data[0]) { return ret;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= mask; if (s->io_bits & 0x0f)
devpriv->cfg3 |= bit; devpriv->cfg3 |= DOUTEN1;
break; else
case INSN_CONFIG_DIO_INPUT: devpriv->cfg3 &= ~DOUTEN1;
s->io_bits &= ~mask; if (s->io_bits & 0xf0)
devpriv->cfg3 &= ~bit; devpriv->cfg3 |= DOUTEN2;
break; else
case INSN_CONFIG_DIO_QUERY: devpriv->cfg3 &= ~DOUTEN2;
data[1] =
(s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
break;
}
outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); outw(devpriv->cfg3, dev->iobase + ATAO_CFG3);
return 1; return insn->n;
} }
/* /*
......
...@@ -184,39 +184,30 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s, ...@@ -184,39 +184,30 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s,
/* overriding the 8255 insn config */ /* overriding the 8255 insn config */
static int subdev_3724_insn_config(struct comedi_device *dev, static int subdev_3724_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask; unsigned int mask;
unsigned int bits; int ret;
mask = 1 << CR_CHAN(insn->chanspec); if (chan < 8)
if (mask & 0x0000ff) mask = 0x0000ff;
bits = 0x0000ff; else if (chan < 16)
else if (mask & 0x00ff00) mask = 0x00ff00;
bits = 0x00ff00; else if (chan < 20)
else if (mask & 0x0f0000) mask = 0x0f0000;
bits = 0x0f0000;
else else
bits = 0xf00000; mask = 0xf00000;
switch (data[0]) { ret = comedi_dio_insn_config(dev, s, insn, data, mask);
case INSN_CONFIG_DIO_INPUT: if (ret)
s->io_bits &= ~bits; return ret;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
do_3724_config(dev, s, insn->chanspec); do_3724_config(dev, s, insn->chanspec);
enable_chan(dev, s, insn->chanspec); enable_chan(dev, s, insn->chanspec);
return 1;
return insn->n;
} }
static int pcm3724_attach(struct comedi_device *dev, static int pcm3724_attach(struct comedi_device *dev,
......
...@@ -515,32 +515,35 @@ static int s526_dio_insn_bits(struct comedi_device *dev, ...@@ -515,32 +515,35 @@ static int s526_dio_insn_bits(struct comedi_device *dev,
static int s526_dio_insn_config(struct comedi_device *dev, static int s526_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data) struct comedi_insn *insn,
unsigned int *data)
{ {
unsigned int chan = CR_CHAN(insn->chanspec); unsigned int chan = CR_CHAN(insn->chanspec);
int group, mask; unsigned int mask;
int ret;
if (chan < 4)
mask = 0x0f;
else
mask = 0xf0;
ret = comedi_dio_insn_config(dev, s, insn, data, mask);
if (ret)
return ret;
group = chan >> 2;
mask = 0xF << (group << 2);
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
/* bit 10/11 set the group 1/2's mode */ /* bit 10/11 set the group 1/2's mode */
s->state |= 1 << (group + 10); if (s->io_bits & 0x0f)
s->io_bits |= mask; s->state |= (1 << 10);
break; else
case INSN_CONFIG_DIO_INPUT: s->state &= ~(1 << 10);
s->state &= ~(1 << (group + 10)); /* 1 is output, 0 is input. */ if (s->io_bits & 0xf0)
s->io_bits &= ~mask; s->state |= (1 << 11);
break; else
case INSN_CONFIG_DIO_QUERY: s->state &= ~(1 << 11);
data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
default:
return -EINVAL;
}
outw(s->state, dev->iobase + REG_DIO); outw(s->state, dev->iobase + REG_DIO);
return 1; return insn->n;
} }
static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
......
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