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/pcl816.c | 57 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index e9d4704..b3a2af3 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -160,16 +160,25 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd); static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -/* -============================================================================== - ANALOG INPUT MODE0, 816 cards, slow version -*/ +static int pcl816_ai_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + unsigned int status; + + status = inb(dev->iobase + PCL816_STATUS); + if ((status & PCL816_STATUS_DRDY_MASK) == 0) + return 0; + return -EBUSY; +} + static int pcl816_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 + PCL816_CONTROL); @@ -185,30 +194,20 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, outb(0, dev->iobase + PCL816_AD_LO); /* start conversion */ - timeout = 100; - while (timeout--) { - if (!(inb(dev->iobase + PCL816_STATUS) & - PCL816_STATUS_DRDY_MASK)) { - /* return read value */ - data[n] = - ((inb(dev->iobase + - PCL816_AD_HI) << 8) | - (inb(dev->iobase + PCL816_AD_LO))); - /* clear INT (conversion end) flag */ - outb(0, dev->iobase + PCL816_CLRINT); - break; - } - udelay(1); - } - /* Return timeout error */ - if (!timeout) { + ret = comedi_timeout(dev, s, insn, pcl816_ai_eoc, 0); + if (ret) { comedi_error(dev, "A/D insn timeout\n"); data[0] = 0; /* clear INT (conversion end) flag */ outb(0, dev->iobase + PCL816_CLRINT); - return -EIO; + return ret; } + /* return read value */ + data[n] = ((inb(dev->iobase + PCL816_AD_HI) << 8) | + (inb(dev->iobase + PCL816_AD_LO))); + /* clear INT (conversion end) flag */ + outb(0, dev->iobase + PCL816_CLRINT); } return n; } @@ -224,22 +223,16 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) struct pcl816_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned char low, hi; - int timeout = 50; /* wait max 50us */ + int ret; - while (timeout--) { - if (!(inb(dev->iobase + PCL816_STATUS) & - PCL816_STATUS_DRDY_MASK)) - break; - udelay(1); - } - if (!timeout) { /* timeout, bail error */ + ret = comedi_timeout(dev, s, NULL, pcl816_ai_eoc, 0); + if (ret) { outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ comedi_error(dev, "A/D mode1/3 IRQ without DRDY!"); pcl816_ai_cancel(dev, s); s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; comedi_event(dev, s); return IRQ_HANDLED; - } /* get the sample */ -- 1.8.5.2 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel