From 11f6fcf4f5d9687d2db030126db77735617be82c Mon Sep 17 00:00:00 2001 From: David Schleef Date: Tue, 9 Jul 2002 02:58:45 +0000 Subject: [PATCH] Fixes for more buffer changes --- comedi/drivers.c | 15 ++++++ comedi/drivers/cb_pcidas.c | 41 +++++++-------- comedi/drivers/das16m1.c | 12 ++--- comedi/drivers/dt282x.c | 104 ++++++++++++++++++++++++++----------- comedi/drivers/ni_labpc.c | 6 ++- include/linux/comedidev.h | 1 + 6 files changed, 119 insertions(+), 60 deletions(-) diff --git a/comedi/drivers.c b/comedi/drivers.c index 13854775..f6d9c3c1 100644 --- a/comedi/drivers.c +++ b/comedi/drivers.c @@ -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); +} + diff --git a/comedi/drivers/cb_pcidas.c b/comedi/drivers/cb_pcidas.c index a68e23a4..5a607f72 100644 --- a/comedi/drivers/cb_pcidas.c +++ b/comedi/drivers/cb_pcidas.c @@ -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;iadc_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); diff --git a/comedi/drivers/das16m1.c b/comedi/drivers/das16m1.c index fad54005..99dd324d 100644 --- a/comedi/drivers/das16m1.c +++ b/comedi/drivers/das16m1.c @@ -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) diff --git a/comedi/drivers/dt282x.c b/comedi/drivers/dt282x.c index 3b4ddaa0..7959efa2 100644 --- a/comedi/drivers/dt282x.c +++ b/comedi/drivers/dt282x.c @@ -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<ad_2scomp){ - for(i=0;iprealloc_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;iprealloc_buf; + buf = buf + i; + } + n = nbytes/2; + for(i=0;icurrent_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) { diff --git a/comedi/drivers/ni_labpc.c b/comedi/drivers/ni_labpc.c index b2e7c52f..a20516d4 100644 --- a/comedi/drivers/ni_labpc.c +++ b/comedi/drivers/ni_labpc.c @@ -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;idma_buffer[i]); + } if(async->cmd.stop_src == TRIG_COUNT) devpriv->count -= num_points; // set address and count for next transfer diff --git a/include/linux/comedidev.h b/include/linux/comedidev.h index 1de7834c..cfdd96bf 100644 --- a/include/linux/comedidev.h +++ b/include/linux/comedidev.h @@ -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 -- 2.26.2