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

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

Use comedi_dio_update_state() to handle the boilerplate code to update
the subdevice s->state for more complex cases where the hardware is only
updated based on the 'mask' of the channels that are modified.
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 97f4289a
...@@ -126,30 +126,24 @@ EXPORT_SYMBOL_GPL(subdev_8255_interrupt); ...@@ -126,30 +126,24 @@ EXPORT_SYMBOL_GPL(subdev_8255_interrupt);
static int subdev_8255_insn(struct comedi_device *dev, static int subdev_8255_insn(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 subdev_8255_private *spriv = s->private; struct subdev_8255_private *spriv = s->private;
unsigned long iobase = spriv->iobase; unsigned long iobase = spriv->iobase;
unsigned int mask; unsigned int mask;
unsigned int bits;
unsigned int v; unsigned int v;
mask = data[0]; mask = comedi_dio_update_state(s, data);
bits = data[1];
if (mask) { if (mask) {
v = s->state;
v &= ~mask;
v |= (bits & mask);
if (mask & 0xff) if (mask & 0xff)
spriv->io(1, _8255_DATA, v & 0xff, iobase); spriv->io(1, _8255_DATA, s->state & 0xff, iobase);
if (mask & 0xff00) if (mask & 0xff00)
spriv->io(1, _8255_DATA + 1, (v >> 8) & 0xff, iobase); spriv->io(1, _8255_DATA + 1, (s->state >> 8) & 0xff,
iobase);
if (mask & 0xff0000) if (mask & 0xff0000)
spriv->io(1, _8255_DATA + 2, (v >> 16) & 0xff, iobase); spriv->io(1, _8255_DATA + 2, (s->state >> 16) & 0xff,
iobase);
s->state = v;
} }
v = spriv->io(0, _8255_DATA, 0, iobase); v = spriv->io(0, _8255_DATA, 0, iobase);
......
...@@ -941,31 +941,34 @@ static void dio200_subdev_8255_set_dir(struct comedi_device *dev, ...@@ -941,31 +941,34 @@ static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
dio200_write8(dev, subpriv->ofs + 3, config); dio200_write8(dev, subpriv->ofs + 3, config);
} }
/*
* Handle 'insn_bits' for an '8255' DIO subdevice.
*/
static int dio200_subdev_8255_bits(struct comedi_device *dev, static int dio200_subdev_8255_bits(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 dio200_subdev_8255 *subpriv = s->private; struct dio200_subdev_8255 *subpriv = s->private;
unsigned int mask;
unsigned int val;
if (data[0]) { mask = comedi_dio_update_state(s, data);
s->state &= ~data[0]; if (mask) {
s->state |= (data[0] & data[1]); if (mask & 0xff)
if (data[0] & 0xff)
dio200_write8(dev, subpriv->ofs, s->state & 0xff); dio200_write8(dev, subpriv->ofs, s->state & 0xff);
if (data[0] & 0xff00) if (mask & 0xff00)
dio200_write8(dev, subpriv->ofs + 1, dio200_write8(dev, subpriv->ofs + 1,
(s->state >> 8) & 0xff); (s->state >> 8) & 0xff);
if (data[0] & 0xff0000) if (mask & 0xff0000)
dio200_write8(dev, subpriv->ofs + 2, dio200_write8(dev, subpriv->ofs + 2,
(s->state >> 16) & 0xff); (s->state >> 16) & 0xff);
} }
data[1] = dio200_read8(dev, subpriv->ofs);
data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8; val = dio200_read8(dev, subpriv->ofs);
data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16; val |= dio200_read8(dev, subpriv->ofs + 1) << 8;
return 2; val |= dio200_read8(dev, subpriv->ofs + 2) << 16;
data[1] = val;
return insn->n;
} }
/* /*
......
...@@ -596,52 +596,40 @@ static int dmm32at_ao_rinsn(struct comedi_device *dev, ...@@ -596,52 +596,40 @@ static int dmm32at_ao_rinsn(struct comedi_device *dev,
static int dmm32at_dio_insn_bits(struct comedi_device *dev, static int dmm32at_dio_insn_bits(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 dmm32at_private *devpriv = dev->private; struct dmm32at_private *devpriv = dev->private;
unsigned char diobits; unsigned int mask;
unsigned int val;
/* The insn data is a mask in data[0] and the new data
* in data[1], each channel cooresponding to a bit. */ mask = comedi_dio_update_state(s, data);
if (data[0]) { if (mask) {
s->state &= ~data[0]; /* get access to the DIO regs */
s->state |= data[0] & data[1]; outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
/* Write out the new digital output lines */
/* outw(s->state,dev->iobase + DMM32AT_DIO); */ /* if either part of dio is set for output */
if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
val = (s->state & 0x00ff0000) >> 16;
outb(val, dev->iobase + DMM32AT_DIOC);
}
if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
val = (s->state & 0x0000ff00) >> 8;
outb(val, dev->iobase + DMM32AT_DIOB);
}
if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
val = (s->state & 0x000000ff);
outb(val, dev->iobase + DMM32AT_DIOA);
}
} }
/* get access to the DIO regs */ val = inb(dev->iobase + DMM32AT_DIOA);
outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
/* if either part of dio is set for output */ s->state = val;
if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
diobits = (s->state & 0x00ff0000) >> 16;
outb(diobits, dev->iobase + DMM32AT_DIOC);
}
if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
diobits = (s->state & 0x0000ff00) >> 8;
outb(diobits, dev->iobase + DMM32AT_DIOB);
}
if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
diobits = (s->state & 0x000000ff);
outb(diobits, dev->iobase + DMM32AT_DIOA);
}
/* now read the state back in */ data[1] = val;
s->state = inb(dev->iobase + DMM32AT_DIOC);
s->state <<= 8;
s->state |= inb(dev->iobase + DMM32AT_DIOB);
s->state <<= 8;
s->state |= inb(dev->iobase + DMM32AT_DIOA);
data[1] = s->state;
/* on return, data[1] contains the value of the digital
* input and output lines. */
/* data[1]=inw(dev->iobase + DMM32AT_DIO); */
/* or we could just return the software copy of the output values if
* it was a purely digital output subdevice */
/* data[1]=s->state; */
return insn->n; return insn->n;
} }
......
...@@ -80,36 +80,31 @@ static int dt2817_dio_insn_config(struct comedi_device *dev, ...@@ -80,36 +80,31 @@ static int dt2817_dio_insn_config(struct comedi_device *dev,
static int dt2817_dio_insn_bits(struct comedi_device *dev, static int dt2817_dio_insn_bits(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 changed; unsigned long iobase = dev->iobase + DT2817_DATA;
unsigned int mask;
/* It's questionable whether it is more important in unsigned int val;
* a driver like this to be deterministic or fast.
* We choose fast. */ mask = comedi_dio_update_state(s, data);
if (mask) {
if (data[0]) { if (mask & 0x000000ff)
changed = s->state; outb(s->state & 0xff, iobase + 0);
s->state &= ~data[0]; if (mask & 0x0000ff00)
s->state |= (data[0] & data[1]); outb((s->state >> 8) & 0xff, iobase + 1);
changed ^= s->state; if (mask & 0x00ff0000)
changed &= s->io_bits; outb((s->state >> 16) & 0xff, iobase + 2);
if (changed & 0x000000ff) if (mask & 0xff000000)
outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0); outb((s->state >> 24) & 0xff, iobase + 3);
if (changed & 0x0000ff00)
outb((s->state >> 8) & 0xff,
dev->iobase + DT2817_DATA + 1);
if (changed & 0x00ff0000)
outb((s->state >> 16) & 0xff,
dev->iobase + DT2817_DATA + 2);
if (changed & 0xff000000)
outb((s->state >> 24) & 0xff,
dev->iobase + DT2817_DATA + 3);
} }
data[1] = inb(dev->iobase + DT2817_DATA + 0);
data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8); val = inb(iobase + 0);
data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16); val |= (inb(iobase + 1) << 8);
data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24); val |= (inb(iobase + 2) << 16);
val |= (inb(iobase + 3) << 24);
data[1] = val;
return insn->n; return insn->n;
} }
......
...@@ -163,29 +163,29 @@ static int ni6527_di_insn_bits(struct comedi_device *dev, ...@@ -163,29 +163,29 @@ static int ni6527_di_insn_bits(struct comedi_device *dev,
static int ni6527_do_insn_bits(struct comedi_device *dev, static int ni6527_do_insn_bits(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 ni6527_private *devpriv = dev->private; struct ni6527_private *devpriv = dev->private;
unsigned int mask;
if (data[0]) { mask = comedi_dio_update_state(s, data);
s->state &= ~data[0]; if (mask) {
s->state |= (data[0] & data[1]); /* Outputs are inverted */
if (mask & 0x0000ff) {
/* The open relay state on the board cooresponds to 1, writeb(s->state ^ 0xff,
* but in Comedi, it is represented by 0. */
if (data[0] & 0x0000ff) {
writeb((s->state ^ 0xff),
devpriv->mite->daq_io_addr + Port_Register(3)); devpriv->mite->daq_io_addr + Port_Register(3));
} }
if (data[0] & 0x00ff00) { if (mask & 0x00ff00) {
writeb((s->state >> 8) ^ 0xff, writeb((s->state >> 8) ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(4)); devpriv->mite->daq_io_addr + Port_Register(4));
} }
if (data[0] & 0xff0000) { if (mask & 0xff0000) {
writeb((s->state >> 16) ^ 0xff, writeb((s->state >> 16) ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(5)); devpriv->mite->daq_io_addr + Port_Register(5));
} }
} }
data[1] = s->state; data[1] = s->state;
return insn->n; return insn->n;
......
...@@ -72,18 +72,22 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf ...@@ -72,18 +72,22 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf
static int daq700_dio_insn_bits(struct comedi_device *dev, static int daq700_dio_insn_bits(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)
{ {
if (data[0]) { unsigned int mask;
s->state &= ~data[0]; unsigned int val;
s->state |= (data[0] & data[1]);
if (data[0] & 0xff) mask = comedi_dio_update_state(s, data);
if (mask) {
if (mask & 0xff)
outb(s->state & 0xff, dev->iobase + DIO_W); outb(s->state & 0xff, dev->iobase + DIO_W);
} }
data[1] = s->state & 0xff; val = s->state & 0xff;
data[1] |= inb(dev->iobase + DIO_R) << 8; val |= inb(dev->iobase + DIO_R) << 8;
data[1] = val;
return insn->n; return insn->n;
} }
......
...@@ -422,19 +422,20 @@ static int pcl711_di_insn_bits(struct comedi_device *dev, ...@@ -422,19 +422,20 @@ static int pcl711_di_insn_bits(struct comedi_device *dev,
return insn->n; return insn->n;
} }
/* Digital port write - Untested on 8112 */
static int pcl711_do_insn_bits(struct comedi_device *dev, static int pcl711_do_insn_bits(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)
{ {
if (data[0]) { unsigned int mask;
s->state &= ~data[0];
s->state |= data[0] & data[1]; mask = comedi_dio_update_state(s, data);
if (mask) {
if (mask & 0x00ff)
outb(s->state & 0xff, dev->iobase + PCL711_DO_LO);
if (mask & 0xff00)
outb((s->state >> 8), dev->iobase + PCL711_DO_HI);
} }
if (data[0] & 0x00ff)
outb(s->state & 0xff, dev->iobase + PCL711_DO_LO);
if (data[0] & 0xff00)
outb((s->state >> 8), dev->iobase + PCL711_DO_HI);
data[1] = s->state; data[1] = s->state;
......
...@@ -196,18 +196,19 @@ static int pcl726_di_insn_bits(struct comedi_device *dev, ...@@ -196,18 +196,19 @@ static int pcl726_di_insn_bits(struct comedi_device *dev,
static int pcl726_do_insn_bits(struct comedi_device *dev, static int pcl726_do_insn_bits(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)
{ {
const struct pcl726_board *board = comedi_board(dev); const struct pcl726_board *board = comedi_board(dev);
unsigned int mask;
if (data[0]) {
s->state &= ~data[0]; mask = comedi_dio_update_state(s, data);
s->state |= data[0] & data[1]; if (mask) {
if (mask & 0x00ff)
outb(s->state & 0xff, dev->iobase + board->do_lo);
if (mask & 0xff00)
outb((s->state >> 8), dev->iobase + board->do_hi);
} }
if (data[1] & 0x00ff)
outb(s->state & 0xff, dev->iobase + board->do_lo);
if (data[1] & 0xff00)
outb((s->state >> 8), dev->iobase + board->do_hi);
data[1] = s->state; data[1] = s->state;
......
...@@ -167,20 +167,17 @@ static int pcl730_do_insn_bits(struct comedi_device *dev, ...@@ -167,20 +167,17 @@ static int pcl730_do_insn_bits(struct comedi_device *dev,
unsigned int *data) unsigned int *data)
{ {
unsigned long reg = (unsigned long)s->private; unsigned long reg = (unsigned long)s->private;
unsigned int mask = data[0]; unsigned int mask;
unsigned int bits = data[1];
mask = comedi_dio_update_state(s, data);
if (mask) { if (mask) {
s->state &= ~mask;
s->state |= (bits & mask);
if (mask & 0x00ff) if (mask & 0x00ff)
outb(s->state & 0xff, dev->iobase + reg); outb(s->state & 0xff, dev->iobase + reg);
if ((mask & 0xff00) && (s->n_chan > 8)) if ((mask & 0xff00) & (s->n_chan > 8))
outb((s->state >> 8) & 0xff, dev->iobase + reg + 1); outb((s->state >> 8) & 0xff, dev->iobase + reg + 1);
if ((mask & 0xff0000) && (s->n_chan > 16)) if ((mask & 0xff0000) & (s->n_chan > 16))
outb((s->state >> 16) & 0xff, dev->iobase + reg + 2); outb((s->state >> 16) & 0xff, dev->iobase + reg + 2);
if ((mask & 0xff000000) && (s->n_chan > 24)) if ((mask & 0xff000000) & (s->n_chan > 24))
outb((s->state >> 24) & 0xff, dev->iobase + reg + 3); outb((s->state >> 24) & 0xff, dev->iobase + reg + 3);
} }
......
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