diff options
author | H Hartley Sweeten <hsweeten@visionengravers.com> | 2014-02-10 11:49:39 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-14 09:28:46 -0800 |
commit | 304d2e4cc018cf90811821e8ff3e6d6242d0ece5 (patch) | |
tree | c3ceb2d18d7b1687c04a09d1b8bc6ada0f516664 | |
parent | d8644e418b2613b3eaf1e10fe6fd0d84018c2f8a (diff) | |
download | op-kernel-dev-304d2e4cc018cf90811821e8ff3e6d6242d0ece5.zip op-kernel-dev-304d2e4cc018cf90811821e8ff3e6d6242d0ece5.tar.gz |
staging: comedi: daqboard2000: use comedi_timeout()
Use comedi_timeout() to wait for the analog input pipe full, scanning,
amd end-of-conversion status. The status to check it passed as the
'context' to comedi_timeout().
Use comedi_timeout() to wait for the analog output end-of-conversion.
This also fixes a possible bug where invalid data is returned for the
analog input read if the conversion did not complete, The analog
output has a similar possible bug where the cached readback value is
incorrect if the conversion times out.
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>
-rw-r--r-- | drivers/staging/comedi/drivers/daqboard2000.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 6ff7d3e..a8f6036 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -333,14 +333,28 @@ static void setup_sampling(struct comedi_device *dev, int chan, int gain) writeAcqScanListEntry(dev, word3); } +static int daqboard2000_ai_status(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + struct daqboard2000_private *devpriv = dev->private; + unsigned int status; + + status = readw(devpriv->daq + acqControl); + if (status & context) + return 0; + return -EBUSY; +} + static int daqboard2000_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct daqboard2000_private *devpriv = dev->private; - unsigned int val; - int gain, chan, timeout; + int gain, chan; + int ret; int i; writew(DAQBOARD2000_AcqResetScanListFifo | @@ -367,25 +381,24 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, /* Enable reading from the scanlist FIFO */ writew(DAQBOARD2000_SeqStartScanList, devpriv->daq + acqControl); - for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + acqControl); - if (val & DAQBOARD2000_AcqConfigPipeFull) - break; - /* udelay(2); */ - } + + ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status, + DAQBOARD2000_AcqConfigPipeFull); + if (ret) + return ret; + writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl); - for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + acqControl); - if (val & DAQBOARD2000_AcqLogicScanning) - break; - /* udelay(2); */ - } - for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + acqControl); - if (val & DAQBOARD2000_AcqResultsFIFOHasValidData) - break; - /* udelay(2); */ - } + + ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status, + DAQBOARD2000_AcqLogicScanning); + if (ret) + return ret; + + ret = comedi_timeout(dev, s, insn, daqboard2000_ai_status, + DAQBOARD2000_AcqResultsFIFOHasValidData); + if (ret) + return ret; + data[i] = readw(devpriv->daq + acqResultsFIFO); writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); @@ -409,6 +422,21 @@ static int daqboard2000_ao_insn_read(struct comedi_device *dev, return i; } +static int daqboard2000_ao_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + struct daqboard2000_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int status; + + status = readw(devpriv->daq + dacControl); + if ((status & ((chan + 1) * 0x0010)) == 0) + return 0; + return -EBUSY; +} + static int daqboard2000_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -416,8 +444,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, { struct daqboard2000_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); - unsigned int val; - int timeout; + int ret; int i; for (i = 0; i < insn->n; i++) { @@ -431,12 +458,11 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, udelay(1000); #endif writew(data[i], devpriv->daq + dacSetting(chan)); - for (timeout = 0; timeout < 20; timeout++) { - val = readw(devpriv->daq + dacControl); - if ((val & ((chan + 1) * 0x0010)) == 0) - break; - /* udelay(2); */ - } + + ret = comedi_timeout(dev, s, insn, daqboard2000_ao_eoc, 0); + if (ret) + return ret; + devpriv->ao_readback[chan] = data[i]; #if 0 /* |