Use comedi_timeout() to wait for the analog input end-of-conversion. The interrupt routine also uses the timeout check to make sure data is actually available. Using NULL here for the 'insn' is safe since nothing uses it. Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/comedi/drivers/pcl818.c | 56 +++++++++++++++++---------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index fa1758a..bb51cde 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -336,16 +336,25 @@ static int pcl818_ai_cancel(struct comedi_device *dev, static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1, unsigned int divisor2); -/* -============================================================================== - ANALOG INPUT MODE0, 818 cards, slow version -*/ +static int pcl818_ai_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + unsigned int status; + + status = inb(dev->iobase + PCL818_STATUS); + if (status & 0x10) + return 0; + return -EBUSY; +} + static int pcl818_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + int ret; int n; - int timeout; /* software trigger, DMA and INT off */ outb(0, dev->iobase + PCL818_CONTROL); @@ -364,18 +373,14 @@ static int pcl818_ai_insn_read(struct comedi_device *dev, /* start conversion */ outb(0, dev->iobase + PCL818_AD_LO); - timeout = 100; - while (timeout--) { - if (inb(dev->iobase + PCL818_STATUS) & 0x10) - goto conv_finish; - udelay(1); + ret = comedi_timeout(dev, s, insn, pcl818_ai_eoc, 0); + if (ret) { + comedi_error(dev, "A/D insn timeout"); + /* clear INT (conversion end) flag */ + outb(0, dev->iobase + PCL818_CLRINT); + return ret; } - comedi_error(dev, "A/D insn timeout"); - /* clear INT (conversion end) flag */ - outb(0, dev->iobase + PCL818_CLRINT); - return -EIO; -conv_finish: data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) | (inb(dev->iobase + PCL818_AD_LO) >> 4)); } @@ -463,21 +468,18 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned char low; - int timeout = 50; /* wait max 50us */ + int ret; - while (timeout--) { - if (inb(dev->iobase + PCL818_STATUS) & 0x10) - goto conv_finish; - udelay(1); + ret = comedi_timeout(dev, s, NULL, pcl818_ai_eoc, 0); + if (ret) { + outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */ + comedi_error(dev, "A/D mode1/3 IRQ without DRDY!"); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; } - outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */ - comedi_error(dev, "A/D mode1/3 IRQ without DRDY!"); - pcl818_ai_cancel(dev, s); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_event(dev, s); - return IRQ_HANDLED; -conv_finish: low = inb(dev->iobase + PCL818_AD_LO); comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4))); /* get one sample */ outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ -- 1.8.5.2 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel