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);
static int subdev_8255_insn(struct comedi_device *dev,
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;
unsigned long iobase = spriv->iobase;
unsigned int mask;
unsigned int bits;
unsigned int v;
mask = data[0];
bits = data[1];
mask = comedi_dio_update_state(s, data);
if (mask) {
v = s->state;
v &= ~mask;
v |= (bits & mask);
if (mask & 0xff)
spriv->io(1, _8255_DATA, v & 0xff, iobase);
spriv->io(1, _8255_DATA, s->state & 0xff, iobase);
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)
spriv->io(1, _8255_DATA + 2, (v >> 16) & 0xff, iobase);
s->state = v;
spriv->io(1, _8255_DATA + 2, (s->state >> 16) & 0xff,
iobase);
}
v = spriv->io(0, _8255_DATA, 0, iobase);
......
......@@ -941,31 +941,34 @@ static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
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,
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;
unsigned int mask;
unsigned int val;
if (data[0]) {
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
if (data[0] & 0xff)
mask = comedi_dio_update_state(s, data);
if (mask) {
if (mask & 0xff)
dio200_write8(dev, subpriv->ofs, s->state & 0xff);
if (data[0] & 0xff00)
if (mask & 0xff00)
dio200_write8(dev, subpriv->ofs + 1,
(s->state >> 8) & 0xff);
if (data[0] & 0xff0000)
if (mask & 0xff0000)
dio200_write8(dev, subpriv->ofs + 2,
(s->state >> 16) & 0xff);
}
data[1] = dio200_read8(dev, subpriv->ofs);
data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8;
data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16;
return 2;
val = dio200_read8(dev, subpriv->ofs);
val |= dio200_read8(dev, subpriv->ofs + 1) << 8;
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,
static int dmm32at_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
struct dmm32at_private *devpriv = dev->private;
unsigned char diobits;
/* The insn data is a mask in data[0] and the new data
* in data[1], each channel cooresponding to a bit. */
if (data[0]) {
s->state &= ~data[0];
s->state |= data[0] & data[1];
/* Write out the new digital output lines */
/* outw(s->state,dev->iobase + DMM32AT_DIO); */
}
unsigned int mask;
unsigned int val;
mask = comedi_dio_update_state(s, data);
if (mask) {
/* get access to the DIO regs */
outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
/* if either part of dio is set for output */
if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
diobits = (s->state & 0x00ff0000) >> 16;
outb(diobits, dev->iobase + DMM32AT_DIOC);
val = (s->state & 0x00ff0000) >> 16;
outb(val, dev->iobase + DMM32AT_DIOC);
}
if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
diobits = (s->state & 0x0000ff00) >> 8;
outb(diobits, dev->iobase + DMM32AT_DIOB);
val = (s->state & 0x0000ff00) >> 8;
outb(val, 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 */
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; */
val = (s->state & 0x000000ff);
outb(val, dev->iobase + DMM32AT_DIOA);
}
}
val = inb(dev->iobase + DMM32AT_DIOA);
val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
s->state = val;
data[1] = val;
return insn->n;
}
......
......@@ -80,36 +80,31 @@ static int dt2817_dio_insn_config(struct comedi_device *dev,
static int dt2817_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int changed;
/* It's questionable whether it is more important in
* a driver like this to be deterministic or fast.
* We choose fast. */
if (data[0]) {
changed = s->state;
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
changed ^= s->state;
changed &= s->io_bits;
if (changed & 0x000000ff)
outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0);
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);
unsigned long iobase = dev->iobase + DT2817_DATA;
unsigned int mask;
unsigned int val;
mask = comedi_dio_update_state(s, data);
if (mask) {
if (mask & 0x000000ff)
outb(s->state & 0xff, iobase + 0);
if (mask & 0x0000ff00)
outb((s->state >> 8) & 0xff, iobase + 1);
if (mask & 0x00ff0000)
outb((s->state >> 16) & 0xff, iobase + 2);
if (mask & 0xff000000)
outb((s->state >> 24) & 0xff, iobase + 3);
}
data[1] = inb(dev->iobase + DT2817_DATA + 0);
data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8);
data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16);
data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24);
val = inb(iobase + 0);
val |= (inb(iobase + 1) << 8);
val |= (inb(iobase + 2) << 16);
val |= (inb(iobase + 3) << 24);
data[1] = val;
return insn->n;
}
......
......@@ -163,29 +163,29 @@ static int ni6527_di_insn_bits(struct comedi_device *dev,
static int ni6527_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
struct ni6527_private *devpriv = dev->private;
unsigned int mask;
if (data[0]) {
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
/* The open relay state on the board cooresponds to 1,
* but in Comedi, it is represented by 0. */
if (data[0] & 0x0000ff) {
writeb((s->state ^ 0xff),
mask = comedi_dio_update_state(s, data);
if (mask) {
/* Outputs are inverted */
if (mask & 0x0000ff) {
writeb(s->state ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(3));
}
if (data[0] & 0x00ff00) {
if (mask & 0x00ff00) {
writeb((s->state >> 8) ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(4));
}
if (data[0] & 0xff0000) {
if (mask & 0xff0000) {
writeb((s->state >> 16) ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(5));
}
}
data[1] = s->state;
return insn->n;
......
......@@ -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,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
if (data[0]) {
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
unsigned int mask;
unsigned int val;
if (data[0] & 0xff)
mask = comedi_dio_update_state(s, data);
if (mask) {
if (mask & 0xff)
outb(s->state & 0xff, dev->iobase + DIO_W);
}
data[1] = s->state & 0xff;
data[1] |= inb(dev->iobase + DIO_R) << 8;
val = s->state & 0xff;
val |= inb(dev->iobase + DIO_R) << 8;
data[1] = val;
return insn->n;
}
......
......@@ -422,19 +422,20 @@ static int pcl711_di_insn_bits(struct comedi_device *dev,
return insn->n;
}
/* Digital port write - Untested on 8112 */
static int pcl711_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
if (data[0]) {
s->state &= ~data[0];
s->state |= data[0] & data[1];
}
if (data[0] & 0x00ff)
unsigned int mask;
mask = comedi_dio_update_state(s, data);
if (mask) {
if (mask & 0x00ff)
outb(s->state & 0xff, dev->iobase + PCL711_DO_LO);
if (data[0] & 0xff00)
if (mask & 0xff00)
outb((s->state >> 8), dev->iobase + PCL711_DO_HI);
}
data[1] = s->state;
......
......@@ -196,18 +196,19 @@ static int pcl726_di_insn_bits(struct comedi_device *dev,
static int pcl726_do_insn_bits(struct comedi_device *dev,
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);
unsigned int mask;
if (data[0]) {
s->state &= ~data[0];
s->state |= data[0] & data[1];
}
if (data[1] & 0x00ff)
mask = comedi_dio_update_state(s, data);
if (mask) {
if (mask & 0x00ff)
outb(s->state & 0xff, dev->iobase + board->do_lo);
if (data[1] & 0xff00)
if (mask & 0xff00)
outb((s->state >> 8), dev->iobase + board->do_hi);
}
data[1] = s->state;
......
......@@ -167,20 +167,17 @@ static int pcl730_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
unsigned long reg = (unsigned long)s->private;
unsigned int mask = data[0];
unsigned int bits = data[1];
unsigned int mask;
mask = comedi_dio_update_state(s, data);
if (mask) {
s->state &= ~mask;
s->state |= (bits & mask);
if (mask & 0x00ff)
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);
if ((mask & 0xff0000) && (s->n_chan > 16))
if ((mask & 0xff0000) & (s->n_chan > 16))
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);
}
......
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