Fixes for more buffer changes
authorDavid Schleef <ds@schleef.org>
Tue, 9 Jul 2002 02:58:45 +0000 (02:58 +0000)
committerDavid Schleef <ds@schleef.org>
Tue, 9 Jul 2002 02:58:45 +0000 (02:58 +0000)
comedi/drivers.c
comedi/drivers/cb_pcidas.c
comedi/drivers/das16m1.c
comedi/drivers/dt282x.c
comedi/drivers/ni_labpc.c
include/linux/comedidev.h

index 1385477576ca0c4d1ce5bfacebd8b419d4ef9ebc..f6d9c3c118d2c6fb488d6abbece5661b2e57df0c 100644 (file)
@@ -635,3 +635,18 @@ int comedi_buf_put(comedi_async *async, sampl_t x)
        return 1;
 }
 
+void comedi_buf_copy_from(comedi_async *async, void *dest, int nbytes)
+{
+       void *src;
+
+       src = async->prealloc_buf + async->buf_read_ptr;
+       if(async->buf_read_ptr + nbytes >= async->prealloc_bufsz){
+               memcpy(dest, src,
+                       async->prealloc_bufsz - async->buf_read_ptr - nbytes);
+               nbytes -= async->prealloc_bufsz - async->buf_read_ptr;
+               src = async->prealloc_buf;
+               dest += async->prealloc_bufsz - async->buf_read_ptr;
+       }
+       memcpy(dest, src, nbytes);
+}
+
index a68e23a4ec04db5d05978523bd734b5601356b3a..5a607f72557f403772ed811b92ab7b30f93f7c0f 100644 (file)
@@ -103,7 +103,6 @@ analog triggering on 1602 series
 // PCI vendor number of ComputerBoards/MeasurementComputing
 #define PCI_VENDOR_ID_CB       0x1307
 #define TIMER_BASE 100 // 10MHz master clock
-static const int max_fifo_size = 1024; // maximum fifo size of any supported board
 #define NUM_CHANNELS_8800 8
 #define NUM_CHANNELS_7376 1
 #define NUM_CHANNELS_8402 2
@@ -1441,7 +1440,7 @@ static int cb_pcidas_ao_cmd(comedi_device *dev,comedi_subdevice *s)
 static int cb_pcidas_ao_inttrig(comedi_device *dev, comedi_subdevice *s, unsigned int trig_num)
 {
        unsigned int i, num_points = thisboard->fifo_size;
-       sampl_t data[max_fifo_size];
+       sampl_t d;
        comedi_async *async = s->async;
        comedi_cmd *cmd = &s->async->cmd;
 
@@ -1452,17 +1451,16 @@ static int cb_pcidas_ao_inttrig(comedi_device *dev, comedi_subdevice *s, unsigne
        if(cmd->stop_src == TRIG_COUNT &&
                devpriv->ao_count < num_points)
                num_points = devpriv->ao_count;
-       for(i = 0; i < num_points; i++)
-       {
-               if(comedi_buf_get(async, &data[i]))
-                       break;
+       
+       // write data to board's fifo
+       for(i = 0; i < num_points; i++) {
+               /* XXX check return value */
+               comedi_buf_get(async, &d);
+               outw(devpriv->ao_registers + DACDATA, d);
        }
-       if(cmd->stop_src == TRIG_COUNT)
-       {
+       if(cmd->stop_src == TRIG_COUNT) {
                devpriv->ao_count -= i;
        }
-       // write data to board's fifo
-       outsw(devpriv->ao_registers + DACDATA, data, i);
 
        // enable dac half-full and empty interrupts
        devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
@@ -1495,8 +1493,6 @@ static void cb_pcidas_interrupt(int irq, void *d, struct pt_regs *regs)
        comedi_async *async;
        int status, s5933_status;
        int half_fifo = thisboard->fifo_size / 2;
-       static const int max_half_fifo = 512;   // maximum possible half-fifo size
-       sampl_t data[max_half_fifo];
        unsigned int num_samples, i;
        static const int timeout = 10000;
 
@@ -1540,6 +1536,8 @@ static void cb_pcidas_interrupt(int irq, void *d, struct pt_regs *regs)
        // if fifo half-full
        if(status & ADHFI)
        {
+               int i;
+
                // read data
                num_samples = half_fifo;
                if(async->cmd.stop_src == TRIG_COUNT &&
@@ -1547,8 +1545,9 @@ static void cb_pcidas_interrupt(int irq, void *d, struct pt_regs *regs)
                {
                        num_samples = devpriv->count;
                }
-               insw(devpriv->adc_fifo + ADCDATA, data, num_samples);
-               comedi_buf_put_array(async, data, num_samples);
+               for(i=0;i<num_samples;i++){
+                       comedi_buf_put(async, inw(devpriv->adc_fifo + ADCDATA));
+               }
                devpriv->count -= num_samples;
                if(async->cmd.stop_src == TRIG_COUNT &&
                        devpriv->count == 0)
@@ -1566,8 +1565,7 @@ static void cb_pcidas_interrupt(int irq, void *d, struct pt_regs *regs)
                        // break if fifo is empty
                        if((ADNE & inw(devpriv->control_status + INT_ADCFIFO)) == 0)
                                break;
-                       data[0] = inw(devpriv->adc_fifo);
-                       comedi_buf_put(async, data[0]);
+                       comedi_buf_put(async, inw(devpriv->adc_fifo + ADCDATA));
                        if(async->cmd.stop_src == TRIG_COUNT &&
                                --devpriv->count == 0)
                        {               /* end of acquisition */
@@ -1605,8 +1603,6 @@ static void handle_ao_interrupt(comedi_device *dev, unsigned int status)
        comedi_async *async = s->async;
        comedi_cmd *cmd = &async->cmd;
        unsigned int half_fifo = thisboard->fifo_size / 2;
-       static const int max_half_fifo = max_fifo_size / 2;     // maximum possible half-fifo size
-       sampl_t data[max_half_fifo];
        unsigned int num_points, i;
 
        async->events = 0;
@@ -1628,22 +1624,23 @@ static void handle_ao_interrupt(comedi_device *dev, unsigned int status)
                }
        }else if(status & DAHFI)
        {
+               sampl_t d;
+
                // figure out how many points we are writing to fifo
                num_points = half_fifo;
                if(cmd->stop_src == TRIG_COUNT &&
                        devpriv->ao_count < num_points)
                        num_points = devpriv->ao_count;
+               // write data to board's fifo
                for(i = 0; i < num_points; i++)
                {
-                       if(comedi_buf_get(async, &data[i]))
-                               break;
+                       comedi_buf_get(async, &d);
+                       outw(devpriv->ao_registers + DACDATA, d);
                }
                if(async->cmd.stop_src == TRIG_COUNT)
                {
                        devpriv->ao_count -= i;
                }
-               // write data to board's fifo
-               outsw(devpriv->ao_registers + DACDATA, data, i);
                async->events |= COMEDI_CB_BLOCK;
                // clear half-full interrupt latch
                outw(devpriv->adc_fifo_bits | DAHFI, devpriv->control_status + INT_ADCFIFO);
index fad54005c1605a87f4751941f783fefeb71637d1..99dd324d8a38ae59dd44a9ed2af247bbf4f3f491 100644 (file)
@@ -497,7 +497,6 @@ static void das16m1_interrupt(int irq, void *d, struct pt_regs *regs)
 static void das16m1_handler(comedi_device *dev, unsigned int status)
 {
        int i;
-       sampl_t data[FIFO_SIZE];
        comedi_subdevice *s;
        comedi_async *async;
        comedi_cmd *cmd;
@@ -535,12 +534,13 @@ static void das16m1_handler(comedi_device *dev, unsigned int status)
        // make sure we dont try to get too many points if fifo has overrun
        if(num_samples > FIFO_SIZE)
                num_samples = FIFO_SIZE;
-       insw(dev->iobase, data, num_samples);
-       for(i = 0; i < num_samples; i++)
-       {
-               data[i] = AI_DATA(data[i]);
+       for(i = 0; i < num_samples; i++) {
+               sampl_t d;
+
+               d = inw(dev->iobase);
+               /* XXX check return value */
+               comedi_buf_put(async, AI_DATA(d));
        }
-       comedi_buf_put_array(async, data, num_samples);
        devpriv->adc_count += num_samples;
 
        if(cmd->stop_src == TRIG_COUNT)
index 3b4ddaa08a6604ade6f1101481817247ee3c3f15..7959efa2a9399273732a6e11047b4c1edf1f2718 100644 (file)
@@ -335,7 +335,7 @@ typedef struct {
                short *buf;     /* DMA buffer */
                int size;       /* size of current transfer */
        }dma[2];
-       int dma_maxsize;        /* max size of DMA transfer     */
+       int dma_maxsize;        /* max size of DMA transfer (in bytes) */
        int usedma;             /* driver uses DMA              */
        int current_dma_chan;
        int dma_dir;
@@ -391,21 +391,35 @@ static int dt282x_ns_to_timer(int *nanosec,int round_mode);
 
 static int dt282x_grab_dma(comedi_device *dev,int dma1,int dma2);
 
-static void dt282x_cleanup_buffer(comedi_device *dev,unsigned short *buf,unsigned int len)
+static void dt282x_copy_to_buffer(comedi_device *dev,sampl_t *buf,
+       unsigned int nbytes)
 {
+       comedi_async *async = dev->subdevices[0].async;
        unsigned int i;
        unsigned short mask=(1<<boardtype.adbits)-1;
        unsigned short sign=1<<(boardtype.adbits-1);
+       unsigned short *abuf;
+       int n;
 
        if(devpriv->ad_2scomp){
-               for(i=0;i<len;i++){
-                       buf[i]&=mask;
-                       buf[i]^=sign;
-               }
+               sign = 1<<(boardtype.adbits-1);
        }else{
-               for(i=0;i<len;i++){
-                       buf[i]&=mask;
+               sign = 0;
+       }
+
+       abuf = async->prealloc_buf + async->buf_write_ptr;
+       if(async->buf_write_ptr + nbytes >= async->prealloc_bufsz){
+               n = (async->prealloc_bufsz - async->buf_write_ptr - nbytes)/2;
+               for(i=0;i<n;i++){
+                       abuf[i] = (buf[i]&mask)^sign;
                }
+               nbytes -= n;
+               abuf = async->prealloc_buf;
+               buf = buf + i;
+       }
+       n = nbytes/2;
+       for(i=0;i<n;i++){
+               abuf[i] = (buf[i]&mask)^sign;
        }
 }
 
@@ -430,16 +444,18 @@ static void dt282x_ao_dma_interrupt(comedi_device * dev)
 
        devpriv->current_dma_chan=1-i;
 
-       size = comedi_buf_get_array( s->async, ptr, devpriv->dma_maxsize );
-       if( size < 0){
-               printk("dt282x: AO underrun\n");
+       size = comedi_buf_read_n_available(s->async);
+       if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;
+       if( size == 0){
+               rt_printk("dt282x: AO underrun\n");
                dt282x_ao_cancel(dev,s);
                s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
                comedi_event(dev,s,s->async->events);
                return;
        }
+       comedi_buf_copy_from(s->async, ptr, size);
+       comedi_buf_read_free(s->async, size);
        prep_ao_dma(dev,i,size);
-
        enable_dma(devpriv->dma[i].chan);
 
        comedi_event(dev,s,s->async->events);
@@ -451,6 +467,7 @@ static void dt282x_ai_dma_interrupt(comedi_device * dev)
        void *ptr;
        int size;
        int i;
+       int ret;
        comedi_subdevice *s=dev->subdevices;
 
        update_supcsr(DT2821_CLRDMADNE);
@@ -460,16 +477,25 @@ static void dt282x_ai_dma_interrupt(comedi_device * dev)
                return;
        }
 
-       i=devpriv->current_dma_chan;
-       ptr=devpriv->dma[i].buf;
-       size=devpriv->dma[i].size;
+       i = devpriv->current_dma_chan;
+       ptr = devpriv->dma[i].buf;
+       size = devpriv->dma[i].size;
 
        disable_dma(devpriv->dma[i].chan);
 
-       devpriv->current_dma_chan=1-i;
-       dt282x_cleanup_buffer(dev,ptr,size);
-       comedi_buf_put_array( s->async, ptr, size );
-       devpriv->nread-=size;
+       devpriv->current_dma_chan = 1-i;
+
+       ret = comedi_buf_write_alloc(s->async, size);
+       if(!ret){
+               rt_printk("dt282x: AI buffer overflow\n");
+               s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+               comedi_event(dev,s,s->async->events);
+               return;
+       }
+       dt282x_copy_to_buffer(dev, ptr, size);
+       comedi_buf_write_free(s->async, size);
+
+       devpriv->nread-=size/2;
 
        if(devpriv->nread<0){
                printk("dt282x: off by one\n");
@@ -516,9 +542,9 @@ static int prep_ai_dma(comedi_device * dev,int chan,int n)
 
        if(n==0)
                n = devpriv->dma_maxsize;
-       if (n >= devpriv->ntrig)
-               n = devpriv->ntrig;
-       devpriv->ntrig -= n;
+       if (n >= devpriv->ntrig*2)
+               n = devpriv->ntrig*2;
+       devpriv->ntrig -= n/2;
 
        devpriv->dma[chan].size = n;
        dma_chan = devpriv->dma[chan].chan;
@@ -527,7 +553,7 @@ static int prep_ai_dma(comedi_device * dev,int chan,int n)
        set_dma_mode(dma_chan, DMA_MODE_READ);
        flags=claim_dma_lock();
        set_dma_addr(dma_chan, dma_ptr);
-       set_dma_count(dma_chan, n << 1);
+       set_dma_count(dma_chan, n);
        release_dma_lock(flags);
 
        return n;
@@ -546,7 +572,7 @@ static int prep_ao_dma(comedi_device * dev,int chan,int n)
        set_dma_mode(dma_chan, DMA_MODE_WRITE);
        flags=claim_dma_lock();
        set_dma_addr(dma_chan, dma_ptr);
-       set_dma_count(dma_chan, n*2 );
+       set_dma_count(dma_chan, n );
        release_dma_lock(flags);
 
        return n;
@@ -558,6 +584,7 @@ static void dt282x_interrupt(int irq, void *d, struct pt_regs *regs)
        comedi_subdevice *s = dev->subdevices+0;
        unsigned int supcsr, adcsr, dacsr;
        sampl_t data;
+       int ret;
 
        adcsr=inw(dev->iobase + DT2821_ADCSR);
        if (adcsr & DT2821_ADERR) {
@@ -596,7 +623,10 @@ static void dt282x_interrupt(int irq, void *d, struct pt_regs *regs)
                if(devpriv->ad_2scomp){
                        data^=1<<(boardtype.adbits-1);
                }
-               comedi_buf_put( s->async, data );
+               ret = comedi_buf_put( s->async, data );
+               if(ret==0){
+                       s->async->events |= COMEDI_CB_ERROR;
+               }
 
                devpriv->nread--;
                if(!devpriv->nread){
@@ -993,16 +1023,28 @@ static int dt282x_ao_inttrig(comedi_device *dev,comedi_subdevice *s,
 
        if(x!=0)return -EINVAL;
 
-       size=comedi_buf_get_array( s->async, devpriv->dma[0].buf, devpriv->dma_maxsize);
-       if( size < 0 ) return size;
-
+       size = comedi_buf_read_n_available(s->async);
+       if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;
+       if( size == 0){
+               rt_printk("dt282x: AO underrun\n");
+               return -EPIPE;
+       }
+       comedi_buf_copy_from(s->async, devpriv->dma[0].buf, size);
+       comedi_buf_read_free(s->async, size);
        prep_ao_dma(dev,0,size);
        enable_dma(devpriv->dma[0].chan);
 
-       size=comedi_buf_get_array( s->async, devpriv->dma[1].buf, devpriv->dma_maxsize);
+       size = comedi_buf_read_n_available(s->async);
+       if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;
+       if( size == 0){
+               rt_printk("dt282x: AO underrun\n");
+               return -EPIPE;
+       }
+       comedi_buf_copy_from(s->async, devpriv->dma[1].buf, size);
+       comedi_buf_read_free(s->async, size);
        prep_ao_dma(dev,1,size);
        enable_dma(devpriv->dma[1].chan);
-       
+
        update_supcsr(DT2821_STRIG);
        s->async->inttrig=NULL;
 
@@ -1332,7 +1374,7 @@ static int dt282x_grab_dma(comedi_device *dev,int dma1,int dma2)
                return -EBUSY;
        devpriv->dma[1].chan=dma2;
 
-       devpriv->dma_maxsize = PAGE_SIZE >> 1;
+       devpriv->dma_maxsize = PAGE_SIZE;
        devpriv->dma[0].buf = (void *) get_free_page(GFP_KERNEL | GFP_DMA);
        devpriv->dma[1].buf = (void *) get_free_page(GFP_KERNEL | GFP_DMA);
        if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) {
index b2e7c52f22f5e71e895d40be94cd74f1fb74fe1d..a20516d4a5d459b34d646de37b61673f605c0cff 100644 (file)
@@ -1408,6 +1408,7 @@ static void labpc_drain_dma(comedi_device *dev)
        int status;
        unsigned long flags;
        unsigned int max_points, num_points, residue, leftover;
+       int i;
 
        status = devpriv->status1_bits;
 
@@ -1442,7 +1443,10 @@ static void labpc_drain_dma(comedi_device *dev)
        }
 
        /* write data to comedi buffer */
-       comedi_buf_put_array(async, devpriv->dma_buffer, num_points);
+       for(i=0;i<num_points;i++){
+               /* XXX check for errors */
+               comedi_buf_put(async, devpriv->dma_buffer[i]);
+       }
        if(async->cmd.stop_src == TRIG_COUNT) devpriv->count -= num_points;
 
        // set address and count for next transfer
index 1de7834cf54ccd402c6295ee040600ea08fbf117..cfdd96bff8175e7287fe8cffff8e26f869b7aebe 100644 (file)
@@ -334,6 +334,7 @@ unsigned int comedi_buf_write_alloc_strict(comedi_async *async, unsigned int nby
 void comedi_buf_write_free(comedi_async *async, unsigned int nbytes);
 void comedi_buf_read_free(comedi_async *async, unsigned int nbytes);
 unsigned int comedi_buf_read_n_available(comedi_async *async);
+void comedi_buf_copy_from(comedi_async *async, void *dest, int nbytes);
 
 
 //#ifdef CONFIG_COMEDI_RT