mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
d8644e418b
commit
304d2e4cc0
|
@ -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
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue