fixed off by one error in calculation of fifo size, fixed TRIG_WAKE_EOS
authorFrank Mori Hess <fmhess@speakeasy.net>
Fri, 11 Oct 2002 00:37:29 +0000 (00:37 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Fri, 11 Oct 2002 00:37:29 +0000 (00:37 +0000)
with non 4020 boards

comedi/drivers/cb_pcidas64.c

index 2e5eefe1d823aabce0fbfa7701a77619d75053c4..c0503fec754abd5e566688ec07368da41676a127 100644 (file)
@@ -2220,17 +2220,23 @@ static void pio_drain_ai_fifo_16(comedi_device *dev)
 
        do
        {
-               /* Get most significant bits (grey code).  Different boards use different code
-               * so use a scheme that doesn't depend on encoding */
-               prepost_bits = readw(priv(dev)->main_iobase + PREPOST_REG);
                // get least significant 15 bits
                read_index = readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
                write_index = readw(priv(dev)->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
+               /* Get most significant bits (grey code).  Different boards use different code
+                * so use a scheme that doesn't depend on encoding.  This read must
+                * occur after reading least significant 15 bits to avoid race
+                * with fifo switching to next segment. */
+               prepost_bits = readw(priv(dev)->main_iobase + PREPOST_REG);
 
                /* if read and write pointers are not on the same fifo segment, read to the
                * end of the read segment */
                read_segment = adc_upper_read_ptr_code( prepost_bits );
                write_segment = adc_upper_write_ptr_code( prepost_bits );
+
+               DEBUG_PRINT( " rd seg %i, wrt seg %i, rd idx %i, wrt idx %i\n",
+                       read_segment, write_segment, read_index, write_index );
+
                if(read_segment != write_segment)
                        num_samples = priv(dev)->ai_fifo_segment_length - read_index;
                else
@@ -2273,7 +2279,7 @@ static void pio_drain_ai_fifo_32(comedi_device *dev)
        comedi_async *async = s->async;
        comedi_cmd *cmd = &async->cmd;
        unsigned int i;
-       unsigned int max_transfer = 1e5;
+       unsigned int max_transfer = 100000;
        uint32_t fifo_data;
        int write_code = readw(priv(dev)->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
        int read_code = readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
@@ -2415,10 +2421,16 @@ static void handle_interrupt(int irq, void *d, struct pt_regs *regs)
                DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits);
        }
 
-       // clean up dregs if we were stopped by hardware sample counter
        if( status & ADC_DONE_BIT )
-       {
                DEBUG_PRINT("adc done interrupt\n");
+
+       // drain fifo with pio
+       if( ( status & ADC_DONE_BIT ) ||
+               ( ( cmd->flags & TRIG_WAKE_EOS ) &&
+               ( status & ADC_INTR_PENDING_BIT ) &&
+               ( board(dev)->layout != LAYOUT_4020 ) ) )
+       {
+               DEBUG_PRINT("pio fifo drain\n");
                comedi_spin_lock_irqsave( &dev->spinlock, flags );
                if( priv(dev)->ai_cmd_running )
                {
@@ -2893,10 +2905,10 @@ static int set_ai_fifo_segment_length( comedi_device *dev, unsigned int num_entr
        if( num_entries < increment_size ) num_entries = increment_size;
        if( num_entries > fifo->max_segment_length ) num_entries = fifo->max_segment_length;
 
-       // 0 -- 256 entries, 1 == 512 entries, etc
-       num_increments = ( num_entries - increment_size / 2 ) / increment_size;
+       // 1 == 256 entries, 2 == 512 entries, etc
+       num_increments = ( num_entries + increment_size / 2 ) / increment_size;
 
-       bits = (~num_entries) & fifo->fifo_size_reg_mask;
+       bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask;
        priv(dev)->fifo_size_bits &= ~fifo->fifo_size_reg_mask;
        priv(dev)->fifo_size_bits |= bits;
        writew( priv(dev)->fifo_size_bits, priv(dev)->main_iobase + FIFO_SIZE_REG );