Commit 16d6b587 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: quatech_daqp_cs: don't use interrupts for ai (*insn_read)

The comedi (*insn_read) functions are supposed to do simple one-shot
reading of an analog input channel. Currently this driver enables
interrupts and uses wait_for_completion_interruptible() to allow the
interrupt routine to let the analog input (*insn_read) know that
the end-of-conversion has occured.

Simplify the function by using the comedi_timeout() helper to check
the aux status register to see when the conversion is finished.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3c56cdc5
...@@ -40,8 +40,6 @@ ...@@ -40,8 +40,6 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/semaphore.h>
#include <linux/completion.h>
#include "../comedi_pcmcia.h" #include "../comedi_pcmcia.h"
...@@ -147,8 +145,6 @@ struct daqp_private { ...@@ -147,8 +145,6 @@ struct daqp_private {
int stop; int stop;
enum { semaphore, buffer } interrupt_mode; enum { semaphore, buffer } interrupt_mode;
struct completion eos;
}; };
static const struct comedi_lrange range_daqp_ai = { static const struct comedi_lrange range_daqp_ai = {
...@@ -210,15 +206,6 @@ static unsigned int daqp_ai_get_sample(struct comedi_device *dev, ...@@ -210,15 +206,6 @@ static unsigned int daqp_ai_get_sample(struct comedi_device *dev,
return comedi_offset_munge(s, val); return comedi_offset_munge(s, val);
} }
/* Interrupt handler
*
* Operates in one of two modes. If devpriv->interrupt_mode is
* 'semaphore', just signal the devpriv->eos completion and return
* (one-shot mode). Otherwise (continuous mode), read data in from
* the card, transfer it to the buffer provided by the higher-level
* comedi kernel module, and signal various comedi callback routines,
* which run pretty quick.
*/
static enum irqreturn daqp_interrupt(int irq, void *dev_id) static enum irqreturn daqp_interrupt(int irq, void *dev_id)
{ {
struct comedi_device *dev = dev_id; struct comedi_device *dev = dev_id;
...@@ -233,7 +220,6 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) ...@@ -233,7 +220,6 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
switch (devpriv->interrupt_mode) { switch (devpriv->interrupt_mode) {
case semaphore: case semaphore:
complete(&devpriv->eos);
break; break;
case buffer: case buffer:
...@@ -296,14 +282,26 @@ static void daqp_ai_set_one_scanlist_entry(struct comedi_device *dev, ...@@ -296,14 +282,26 @@ static void daqp_ai_set_one_scanlist_entry(struct comedi_device *dev,
outb((val >> 8) & 0xff, dev->iobase + DAQP_SCANLIST_REG); outb((val >> 8) & 0xff, dev->iobase + DAQP_SCANLIST_REG);
} }
/* One-shot analog data acquisition routine */ static int daqp_ai_eos(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned long context)
{
unsigned int status;
status = inb(dev->iobase + DAQP_AUX_REG);
if (status & DAQP_AUX_CONVERSION)
return 0;
return -EBUSY;
}
static int daqp_ai_insn_read(struct comedi_device *dev, static int daqp_ai_insn_read(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 daqp_private *devpriv = dev->private; struct daqp_private *devpriv = dev->private;
int ret; int ret = 0;
int i; int i;
if (devpriv->stop) if (devpriv->stop)
...@@ -321,34 +319,35 @@ static int daqp_ai_insn_read(struct comedi_device *dev, ...@@ -321,34 +319,35 @@ static int daqp_ai_insn_read(struct comedi_device *dev,
daqp_ai_set_one_scanlist_entry(dev, insn->chanspec, 1); daqp_ai_set_one_scanlist_entry(dev, insn->chanspec, 1);
/* Reset data FIFO (see page 28 of DAQP User's Manual) */ /* Reset data FIFO (see page 28 of DAQP User's Manual) */
outb(DAQP_CMD_RSTF, dev->iobase + DAQP_CMD_REG); outb(DAQP_CMD_RSTF, dev->iobase + DAQP_CMD_REG);
/* Set trigger - one-shot, internal */ /* Set trigger - one-shot, internal, no interrupts */
outb(DAQP_CTRL_PACER_CLK_100KHZ | DAQP_CTRL_EOS_INT_ENA, outb(DAQP_CTRL_PACER_CLK_100KHZ, dev->iobase + DAQP_CTRL_REG);
dev->iobase + DAQP_CTRL_REG);
ret = daqp_clear_events(dev, 10000); ret = daqp_clear_events(dev, 10000);
if (ret) if (ret)
return ret; return ret;
init_completion(&devpriv->eos);
devpriv->interrupt_mode = semaphore;
for (i = 0; i < insn->n; i++) { for (i = 0; i < insn->n; i++) {
/* Start conversion */ /* Start conversion */
outb(DAQP_CMD_ARM | DAQP_CMD_FIFO_DATA, outb(DAQP_CMD_ARM | DAQP_CMD_FIFO_DATA,
dev->iobase + DAQP_CMD_REG); dev->iobase + DAQP_CMD_REG);
/* Wait for interrupt service routine to unblock completion */ ret = comedi_timeout(dev, s, insn, daqp_ai_eos, 0);
/* Maybe could use a timeout here, but it's interruptible */ if (ret)
if (wait_for_completion_interruptible(&devpriv->eos)) break;
return -EINTR;
/* clear the status event flags */
inb(dev->iobase + DAQP_STATUS_REG);
data[i] = daqp_ai_get_sample(dev, s); data[i] = daqp_ai_get_sample(dev, s);
} }
return insn->n; /* stop any conversions and clear the status event flags */
outb(DAQP_CMD_STOP, dev->iobase + DAQP_CMD_REG);
inb(dev->iobase + DAQP_STATUS_REG);
return ret ? ret : insn->n;
} }
/* This function converts ns nanoseconds to a counter value suitable /* This function converts ns nanoseconds to a counter value suitable
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment