Staging: comedi: pcl818: Correct AI scan counting and channel checks
authorIan Abbott <abbotti@mev.co.uk>
Wed, 20 Jan 2010 13:04:46 +0000 (13:04 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 4 Mar 2010 00:42:47 +0000 (16:42 -0800)
For AI commands, the scan counter should be updated after every
scan.  It was being updated after every sample except for DMA mode
where it was being updated after every repeated segment of the
channel list.

Also AI commands with multiple channels were being terminated with
an error prematurely except in DMA mode.  This was because the
driver was comparing channel numbers received from the hardware
(combined with the sample value) with the expected channel numbers
to check for a "channel dropout".  This test was failing
incorrectly because the driver was not keeping the current position
within the (repeated segment of the) channel list up to date.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/comedi/drivers/pcl818.c

index d0481013a837bb5fcc30da7a6cb8aedd70b85c80..40ac293ad89d55d9893c5ade5528b11b73bef744 100644 (file)
@@ -557,8 +557,14 @@ conv_finish:
                comedi_event(dev, s);
                return IRQ_HANDLED;
        }
-       if (s->async->cur_chan == 0) {
+       devpriv->act_chanlist_pos++;
+       if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+               devpriv->act_chanlist_pos = 0;
+       }
+       s->async->cur_chan++;
+       if (s->async->cur_chan >= devpriv->ai_n_chan) {
                /*  printk("E"); */
+               s->async->cur_chan = 0;
                devpriv->ai_act_scan--;
        }
 
@@ -627,9 +633,13 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 
                devpriv->act_chanlist_pos++;
                if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
-                       devpriv->ai_act_scan--;
                        devpriv->act_chanlist_pos = 0;
                }
+               s->async->cur_chan++;
+               if (s->async->cur_chan >= devpriv->ai_n_chan) {
+                       s->async->cur_chan = 0;
+                       devpriv->ai_act_scan--;
+               }
 
                if (!devpriv->neverending_ai)
                        if (devpriv->ai_act_scan == 0) {        /* all data sampled */
@@ -717,7 +727,14 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
                        comedi_buf_put(s->async, dmabuf[bufptr++] >> 4);        /*  get one sample */
                        bufptr &= (devpriv->dmasamplsize - 1);
 
-                       if (s->async->cur_chan == 0) {
+                       devpriv->act_chanlist_pos++;
+                       if (devpriv->act_chanlist_pos >=
+                                       devpriv->act_chanlist_len) {
+                               devpriv->act_chanlist_pos = 0;
+                       }
+                       s->async->cur_chan++;
+                       if (s->async->cur_chan >= devpriv->ai_n_chan) {
+                               s->async->cur_chan = 0;
                                devpriv->ai_act_scan--;
                        }
 
@@ -796,7 +813,13 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 
                comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));       /*  get one sample */
 
-               if (s->async->cur_chan == 0) {
+               devpriv->act_chanlist_pos++;
+               if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+                       devpriv->act_chanlist_pos = 0;
+               }
+               s->async->cur_chan++;
+               if (s->async->cur_chan >= devpriv->ai_n_chan) {
+                       s->async->cur_chan = 0;
                        devpriv->ai_act_scan--;
                }