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:
committed by
Greg Kroah-Hartman
parent
97f4289ad0
commit
b3ff824a81
@@ -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,
|
|||||||
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,
|
|||||||
|
|
||||||
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
|
mask = comedi_dio_update_state(s, data);
|
||||||
* in data[1], each channel cooresponding to a bit. */
|
if (mask) {
|
||||||
if (data[0]) {
|
/* get access to the DIO regs */
|
||||||
s->state &= ~data[0];
|
outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
|
||||||
s->state |= data[0] & data[1];
|
|
||||||
/* Write out the new digital output lines */
|
/* if either part of dio is set for output */
|
||||||
/* outw(s->state,dev->iobase + DMM32AT_DIO); */
|
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;
|
||||||
|
s->state = val;
|
||||||
|
|
||||||
/* if either part of dio is set for output */
|
data[1] = 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 */
|
|
||||||
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,
|
|||||||
|
|
||||||
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;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
/* It's questionable whether it is more important in
|
mask = comedi_dio_update_state(s, data);
|
||||||
* a driver like this to be deterministic or fast.
|
if (mask) {
|
||||||
* We choose fast. */
|
if (mask & 0x000000ff)
|
||||||
|
outb(s->state & 0xff, iobase + 0);
|
||||||
if (data[0]) {
|
if (mask & 0x0000ff00)
|
||||||
changed = s->state;
|
outb((s->state >> 8) & 0xff, iobase + 1);
|
||||||
s->state &= ~data[0];
|
if (mask & 0x00ff0000)
|
||||||
s->state |= (data[0] & data[1]);
|
outb((s->state >> 16) & 0xff, iobase + 2);
|
||||||
changed ^= s->state;
|
if (mask & 0xff000000)
|
||||||
changed &= s->io_bits;
|
outb((s->state >> 24) & 0xff, iobase + 3);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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,
|
|||||||
|
|
||||||
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
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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]) {
|
mask = comedi_dio_update_state(s, data);
|
||||||
s->state &= ~data[0];
|
if (mask) {
|
||||||
s->state |= data[0] & data[1];
|
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,
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user