forked from Minki/linux
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: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
97f4289ad0
commit
b3ff824a81
@ -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;
|
||||
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. */
|
||||
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); */
|
||||
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)) {
|
||||
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 */
|
||||
outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
|
||||
val = inb(dev->iobase + DMM32AT_DIOA);
|
||||
val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
|
||||
val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
|
||||
s->state = val;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
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 */
|
||||
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; */
|
||||
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;
|
||||
unsigned long iobase = dev->iobase + DT2817_DATA;
|
||||
unsigned int mask;
|
||||
unsigned int val;
|
||||
|
||||
/* 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);
|
||||
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];
|
||||
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 (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;
|
||||
|
||||
|
@ -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];
|
||||
mask = comedi_dio_update_state(s, data);
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user