staging: comedi: dt282x: use comedi_timeout()
The wait_for() macro in this driver is a bit nasty. It effects control flow which according to the CodingStyle is a _very_ bad idea. The mux_busy() and ad_done() macros are also bad since they rely on a local variable having a specific name. Remove these macros and use comedi_timeout() to wait for the analog input mux busy completion and end-of-conversion. Both of these are detected by reading the same register and testing different bits. Pass the bits to test as the 'context' to the callback function. The dt282x_ai_cmd() function also checks for the mux busy completion. The 'insn' is not available here but passing NULL is safe because nothing uses it. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
45b281e457
commit
d8644e418b
|
@ -63,7 +63,6 @@ Notes:
|
|||
|
||||
#include "comedi_fc.h"
|
||||
|
||||
#define DT2821_TIMEOUT 100 /* 500 us */
|
||||
#define DT2821_SIZE 0x10
|
||||
|
||||
/*
|
||||
|
@ -248,27 +247,6 @@ struct dt282x_private {
|
|||
* Some useless abstractions
|
||||
*/
|
||||
#define chan_to_DAC(a) ((a)&1)
|
||||
#define mux_busy() (inw(dev->iobase+DT2821_ADCSR)&DT2821_MUXBUSY)
|
||||
#define ad_done() (inw(dev->iobase+DT2821_ADCSR)&DT2821_ADDONE)
|
||||
|
||||
/*
|
||||
* danger! macro abuse... a is the expression to wait on, and b is
|
||||
* the statement(s) to execute if it doesn't happen.
|
||||
*/
|
||||
#define wait_for(a, b) \
|
||||
do { \
|
||||
int _i; \
|
||||
for (_i = 0; _i < DT2821_TIMEOUT; _i++) { \
|
||||
if (a) { \
|
||||
_i = 0; \
|
||||
break; \
|
||||
} \
|
||||
udelay(5); \
|
||||
} \
|
||||
if (_i) { \
|
||||
b \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int prep_ai_dma(struct comedi_device *dev, int chan, int size);
|
||||
static int prep_ao_dma(struct comedi_device *dev, int chan, int size);
|
||||
|
@ -530,6 +508,29 @@ static void dt282x_load_changain(struct comedi_device *dev, int n,
|
|||
outw(n - 1, dev->iobase + DT2821_CHANCSR);
|
||||
}
|
||||
|
||||
static int dt282x_ai_timeout(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned long context)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
status = inw(dev->iobase + DT2821_ADCSR);
|
||||
switch (context) {
|
||||
case DT2821_MUXBUSY:
|
||||
if ((status & DT2821_MUXBUSY) == 0)
|
||||
return 0;
|
||||
break;
|
||||
case DT2821_ADDONE:
|
||||
if (status & DT2821_ADDONE)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a single A/D conversion.
|
||||
* - Put channel/gain into channel-gain list
|
||||
|
@ -542,6 +543,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
|
|||
{
|
||||
const struct dt282x_board *board = comedi_board(dev);
|
||||
struct dt282x_private *devpriv = dev->private;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* XXX should we really be enabling the ad clock here? */
|
||||
|
@ -551,13 +553,22 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
|
|||
dt282x_load_changain(dev, 1, &insn->chanspec);
|
||||
|
||||
outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
|
||||
wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;);
|
||||
ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout, DT2821_MUXBUSY);
|
||||
if (ret) {
|
||||
comedi_error(dev, "timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < insn->n; i++) {
|
||||
outw(devpriv->supcsr | DT2821_STRIG,
|
||||
dev->iobase + DT2821_SUPCSR);
|
||||
wait_for(ad_done(), comedi_error(dev, "timeout\n");
|
||||
return -ETIME;);
|
||||
|
||||
ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout,
|
||||
DT2821_ADDONE);
|
||||
if (ret) {
|
||||
comedi_error(dev, "timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data[i] =
|
||||
inw(dev->iobase +
|
||||
|
@ -646,6 +657,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
|
|||
struct dt282x_private *devpriv = dev->private;
|
||||
struct comedi_cmd *cmd = &s->async->cmd;
|
||||
int timer;
|
||||
int ret;
|
||||
|
||||
if (devpriv->usedma == 0) {
|
||||
comedi_error(dev,
|
||||
|
@ -691,7 +703,11 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
|
|||
outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR);
|
||||
|
||||
outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
|
||||
wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;);
|
||||
ret = comedi_timeout(dev, s, NULL, dt282x_ai_timeout, DT2821_MUXBUSY);
|
||||
if (ret) {
|
||||
comedi_error(dev, "timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (cmd->scan_begin_src == TRIG_FOLLOW) {
|
||||
outw(devpriv->supcsr | DT2821_STRIG,
|
||||
|
|
Loading…
Reference in New Issue