staging: comedi: cb_pcidas: introduce cb_pcidas64_ao_fill_buffer()
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Wed, 22 Oct 2014 21:36:37 +0000 (14:36 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Oct 2014 08:01:19 +0000 (16:01 +0800)
Introduce a helper function to read the analog output samples from the
async buffer.

This fixes a bug in load_ao_dma_buffer(). That function was decrementing
the 'ao_count' by the number of bytes, not the number of samples, that
were read from the async buffer.

Use comedi_buf_read_samples() to read the analog output samples from
the async buffer.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/cb_pcidas64.c

index eafbe9f56060943961a3c57f27c612cf48c61c70..06e846f389925f97fd3e1ed03df241f184856c2b 100644 (file)
@@ -2912,32 +2912,46 @@ static void restart_ao_dma(struct comedi_device *dev)
        dma_start_sync(dev, 0);
 }
 
+static unsigned int cb_pcidas64_ao_fill_buffer(struct comedi_device *dev,
+                                              struct comedi_subdevice *s,
+                                              unsigned short *dest,
+                                              unsigned int max_bytes)
+{
+       struct pcidas64_private *devpriv = dev->private;
+       struct comedi_cmd *cmd = &s->async->cmd;
+       unsigned int nsamples = max_bytes / bytes_per_sample(s);
+       unsigned int actual_bytes;
+
+       if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < nsamples)
+               nsamples = devpriv->ao_count;
+
+       actual_bytes = comedi_buf_read_samples(s, dest, nsamples);
+       nsamples = actual_bytes / bytes_per_sample(s);
+       if (cmd->stop_src == TRIG_COUNT)
+               devpriv->ao_count -= nsamples;
+
+       return nsamples;
+}
+
 static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
                                       const struct comedi_cmd *cmd)
 {
        struct pcidas64_private *devpriv = dev->private;
-       unsigned int num_bytes, buffer_index, prev_buffer_index;
+       struct comedi_subdevice *s = dev->write_subdev;
+       unsigned int buffer_index = devpriv->ao_dma_index;
+       unsigned int prev_buffer_index = prev_ao_dma_index(dev);
+       unsigned int nsamples;
+       unsigned int nbytes;
        unsigned int next_bits;
 
-       buffer_index = devpriv->ao_dma_index;
-       prev_buffer_index = prev_ao_dma_index(dev);
-
-       num_bytes = comedi_buf_read_n_available(dev->write_subdev);
-       if (num_bytes > DMA_BUFFER_SIZE)
-               num_bytes = DMA_BUFFER_SIZE;
-       if (cmd->stop_src == TRIG_COUNT && num_bytes > devpriv->ao_count)
-               num_bytes = devpriv->ao_count;
-       num_bytes -= num_bytes % bytes_in_sample;
-
-       if (num_bytes == 0)
+       nsamples = cb_pcidas64_ao_fill_buffer(dev, s,
+                                             devpriv->ao_buffer[buffer_index],
+                                             DMA_BUFFER_SIZE);
+       if (nsamples == 0)
                return 0;
 
-       num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
-                                              devpriv->
-                                              ao_buffer[buffer_index],
-                                              num_bytes);
-       devpriv->ao_dma_desc[buffer_index].transfer_size =
-               cpu_to_le32(num_bytes);
+       nbytes = nsamples * bytes_per_sample(s);
+       devpriv->ao_dma_desc[buffer_index].transfer_size = cpu_to_le32(nbytes);
        /* set end of chain bit so we catch underruns */
        next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next);
        next_bits |= PLX_END_OF_CHAIN_BIT;
@@ -2949,9 +2963,8 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
        devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits);
 
        devpriv->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT;
-       devpriv->ao_count -= num_bytes;
 
-       return num_bytes;
+       return nbytes;
 }
 
 static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
@@ -3191,7 +3204,9 @@ static void set_dac_interval_regs(struct comedi_device *dev,
 static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 {
        struct pcidas64_private *devpriv = dev->private;
-       unsigned int num_bytes;
+       struct comedi_subdevice *s = dev->write_subdev;
+       unsigned int nsamples;
+       unsigned int nbytes;
        int i;
 
        /* clear queue pointer too, since external queue has
@@ -3199,22 +3214,22 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
        writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
        writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG);
 
-       num_bytes = (DAC_FIFO_SIZE / 2) * bytes_in_sample;
-       if (cmd->stop_src == TRIG_COUNT &&
-           num_bytes / bytes_in_sample > devpriv->ao_count)
-               num_bytes = devpriv->ao_count * bytes_in_sample;
-       num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
-                                              devpriv->ao_bounce_buffer,
-                                              num_bytes);
-       for (i = 0; i < num_bytes / bytes_in_sample; i++) {
+       nsamples = cb_pcidas64_ao_fill_buffer(dev, s,
+                                             devpriv->ao_bounce_buffer,
+                                             DAC_FIFO_SIZE);
+       if (nsamples == 0)
+               return -1;
+
+       for (i = 0; i < nsamples; i++) {
                writew(devpriv->ao_bounce_buffer[i],
                       devpriv->main_iobase + DAC_FIFO_REG);
        }
-       devpriv->ao_count -= num_bytes / bytes_in_sample;
+
        if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count == 0)
                return 0;
-       num_bytes = load_ao_dma_buffer(dev, cmd);
-       if (num_bytes == 0)
+
+       nbytes = load_ao_dma_buffer(dev, cmd);
+       if (nbytes == 0)
                return -1;
        load_ao_dma(dev, cmd);