From: Frank Mori Hess Date: Sun, 14 Jul 2002 22:33:37 +0000 (+0000) Subject: fixing end of scan events in some drivers X-Git-Tag: r0_7_66~150 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=5cbdb38980e0bed27c2e77e5b5461447092c3e5e;p=comedi.git fixing end of scan events in some drivers --- diff --git a/comedi/Config.in b/comedi/Config.in index 98048955..cf155b14 100644 --- a/comedi/Config.in +++ b/comedi/Config.in @@ -127,3 +127,4 @@ if [ "$CONFIG_COMEDI_RT" = "y" ];then dep_tristate 'Real-time command emulator (timer)' CONFIG_COMEDI_RT_TIMER $CONFIG_COMEDI fi +define_bool CONFIG_COMEDI_FC m diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c index 03e8645a..e7eabfb9 100644 --- a/comedi/comedi_fops.c +++ b/comedi/comedi_fops.c @@ -882,8 +882,6 @@ static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file) init_async_buf( async ); - async->cur_chan = 0; - async->data = async->prealloc_buf; async->data_len=async->prealloc_bufsz; @@ -1839,5 +1837,8 @@ static void init_async_buf( comedi_async *async ) async->buf_write_ptr = 0; async->buf_read_ptr = 0; + + async->cur_chan = 0; + async->scan_progress = 0; } diff --git a/comedi/comedi_ksyms.c b/comedi/comedi_ksyms.c index 219d8946..3d7ed16f 100644 --- a/comedi/comedi_ksyms.c +++ b/comedi/comedi_ksyms.c @@ -71,7 +71,8 @@ EXPORT_SYMBOL(comedi_buf_copy_from); EXPORT_SYMBOL(comedi_buf_write_free); EXPORT_SYMBOL(comedi_buf_write_alloc); EXPORT_SYMBOL(comedi_buf_read_free); - +EXPORT_SYMBOL(comedi_buf_memcpy_to); +EXPORT_SYMBOL(comedi_buf_memcpy_from); #endif diff --git a/comedi/drivers.c b/comedi/drivers.c index f6d9c3c1..9e627f58 100644 --- a/comedi/drivers.c +++ b/comedi/drivers.c @@ -605,6 +605,59 @@ void comedi_buf_read_free(comedi_async *async, unsigned int nbytes) } } +void comedi_buf_memcpy_to( comedi_async *async, unsigned int offset, const void *data, + unsigned int num_bytes ) +{ + unsigned int write_ptr = async->buf_write_ptr + offset; + + if( write_ptr > async->data_len ) + write_ptr %= async->data_len; + + while( num_bytes ) + { + unsigned int block_size; + + if( write_ptr + num_bytes > async->data_len) + block_size = async->data_len - write_ptr; + else + block_size = num_bytes; + + memcpy( async->data + write_ptr, data, block_size ); + + data += block_size; + num_bytes -= block_size; + + write_ptr = 0; + } +} + +void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset, + void *dest, unsigned int nbytes) +{ + void *src; + unsigned int read_ptr = async->buf_read_ptr + offset; + + if( read_ptr > async->data_len ) + read_ptr %= async->data_len; + + while( nbytes ) + { + unsigned int block_size; + + src = async->data + read_ptr; + + if( nbytes >= async->data_len - read_ptr ) + block_size = async->data_len - read_ptr; + else + block_size = nbytes; + + memcpy(dest, src, block_size ); + nbytes -= block_size; + dest += block_size; + read_ptr = 0; + } +} + unsigned int comedi_buf_read_n_available(comedi_async *async) { unsigned int read_end = async->buf_write_count; @@ -637,16 +690,5 @@ int comedi_buf_put(comedi_async *async, sampl_t x) 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); + comedi_buf_memcpy_from( async, 0, dest, nbytes ); } - diff --git a/comedi/drivers/Makefile.in b/comedi/drivers/Makefile.in index c690ba48..f4989e6c 100644 --- a/comedi/drivers/Makefile.in +++ b/comedi/drivers/Makefile.in @@ -1,5 +1,5 @@ -expsyms(mite.o 8255.o amcc_s5933.o) +expsyms(mite.o 8255.o amcc_s5933.o comedi_fc.o) select(CONFIG_COMEDI_8255 8255.o) select(CONFIG_COMEDI_ADL_PCI9111 adl_pci9111.o) @@ -10,6 +10,7 @@ select(CONFIG_COMEDI_CB_PCIDAS cb_pcidas.o) select(CONFIG_COMEDI_CB_PCIDAS64 cb_pcidas64.o) select(CONFIG_COMEDI_CB_PCIDDA cb_pcidda.o) select(CONFIG_COMEDI_CB_PCIMDDA cb_pcimdda.o) +select(CONFIG_COMEDI_FC comedi_fc.o) select(CONFIG_COMEDI_CONTEC_PCI_DIO contec_pci_dio.o) select(CONFIG_COMEDI_DAQBOARD2000 daqboard2000.o) select(CONFIG_COMEDI_DAS08 das08.o) diff --git a/comedi/drivers/cb_pcidas.c b/comedi/drivers/cb_pcidas.c index 5a607f72..f24baa81 100644 --- a/comedi/drivers/cb_pcidas.c +++ b/comedi/drivers/cb_pcidas.c @@ -96,6 +96,7 @@ analog triggering on 1602 series #include "8253.h" #include "8255.h" #include "amcc_s5933.h" +#include "comedi_fc.h" #undef CB_PCIDAS_DEBUG // disable debugging code //#define CB_PCIDAS_DEBUG // enable debugging code @@ -103,6 +104,8 @@ analog triggering on 1602 series // PCI vendor number of ComputerBoards/MeasurementComputing #define PCI_VENDOR_ID_CB 0x1307 #define TIMER_BASE 100 // 10MHz master clock +#define AI_BUFFER_SIZE 1024 // maximum fifo size of any supported board +#define AO_BUFFER_SIZE 1024 // maximum fifo size of any supported board #define NUM_CHANNELS_8800 8 #define NUM_CHANNELS_7376 1 #define NUM_CHANNELS_8402 2 @@ -425,6 +428,8 @@ typedef struct volatile unsigned int adc_fifo_bits; // bits to write to interupt/adcfifo register volatile unsigned int s5933_intcsr_bits; // bits to write to amcc s5933 interrupt control/status register volatile unsigned int ao_control_bits; // bits to write to ao control and status register + sampl_t ai_buffer[ AI_BUFFER_SIZE ]; + sampl_t ao_buffer[ AO_BUFFER_SIZE ]; // divisors of master clock for analog output pacing unsigned int ao_divisor1; unsigned int ao_divisor2; @@ -1439,8 +1444,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 d; + unsigned int num_bytes, num_points = thisboard->fifo_size; comedi_async *async = s->async; comedi_cmd *cmd = &s->async->cmd; @@ -1448,19 +1452,21 @@ static int cb_pcidas_ao_inttrig(comedi_device *dev, comedi_subdevice *s, unsigne return -EINVAL; // load up fifo - if(cmd->stop_src == TRIG_COUNT && - devpriv->ao_count < num_points) + 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++) { - /* XXX check return value */ - comedi_buf_get(async, &d); - outw(devpriv->ao_registers + DACDATA, d); - } - if(cmd->stop_src == TRIG_COUNT) { - devpriv->ao_count -= i; + + num_bytes = cfc_read_array_from_buffer( s, devpriv->ao_buffer, + num_points * sizeof( sampl_t ) ); + num_points = num_bytes / sizeof( sampl_t ); + + if(cmd->stop_src == TRIG_COUNT) + { + devpriv->ao_count -= num_points; } + // write data to board's fifo + outsw( devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes ); // enable dac half-full and empty interrupts devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; @@ -1536,8 +1542,6 @@ 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 && @@ -1545,9 +1549,8 @@ static void cb_pcidas_interrupt(int irq, void *d, struct pt_regs *regs) { num_samples = devpriv->count; } - for(i=0;iadc_fifo + ADCDATA)); - } + insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer, num_samples); + cfc_write_array_to_buffer( s, devpriv->ai_buffer, num_samples * sizeof( sampl_t ) ); devpriv->count -= num_samples; if(async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) @@ -1565,7 +1568,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; - comedi_buf_put(async, inw(devpriv->adc_fifo + ADCDATA)); + cfc_write_to_buffer( s, inw( devpriv->adc_fifo ) ); if(async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) { /* end of acquisition */ @@ -1603,7 +1606,7 @@ 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; - unsigned int num_points, i; + unsigned int num_points; async->events = 0; @@ -1624,24 +1627,22 @@ static void handle_ao_interrupt(comedi_device *dev, unsigned int status) } }else if(status & DAHFI) { - sampl_t d; + unsigned int num_bytes; // 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++) - { - comedi_buf_get(async, &d); - outw(devpriv->ao_registers + DACDATA, d); - } + num_bytes = cfc_read_array_from_buffer( s, devpriv->ao_buffer, num_points * sizeof( sampl_t ) ); + num_points = num_bytes / sizeof( sampl_t ); + if(async->cmd.stop_src == TRIG_COUNT) { - devpriv->ao_count -= i; + devpriv->ao_count -= num_points; } - async->events |= COMEDI_CB_BLOCK; + // write data to board's fifo + outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_points); // clear half-full interrupt latch outw(devpriv->adc_fifo_bits | DAHFI, devpriv->control_status + INT_ADCFIFO); } diff --git a/comedi/drivers/cb_pcidas64.c b/comedi/drivers/cb_pcidas64.c index 4e898fd9..1cb9e269 100644 --- a/comedi/drivers/cb_pcidas64.c +++ b/comedi/drivers/cb_pcidas64.c @@ -85,6 +85,7 @@ TODO: #include "8253.h" #include "8255.h" #include "plx9080.h" +#include "comedi_fc.h" #undef PCIDAS64_DEBUG // disable debugging code //#define PCIDAS64_DEBUG // enable debugging code @@ -1915,7 +1916,7 @@ static void pio_drain_ai_fifo_16(comedi_device *dev) for(i = 0; i < num_samples; i++) { - comedi_buf_put(async, readw(priv(dev)->main_iobase + ADC_FIFO_REG)); + cfc_write_to_buffer( s, readw(priv(dev)->main_iobase + ADC_FIFO_REG)); } } while (read_segment != write_segment); @@ -1947,11 +1948,11 @@ static void pio_drain_ai_fifo_32(comedi_device *dev) for(i = 0; read_code != write_code && i < max_transfer; ) { fifo_data = readl(priv(dev)->dio_counter_iobase + ADC_FIFO_REG); - comedi_buf_put(async, fifo_data & 0xffff); + cfc_write_to_buffer( s, fifo_data & 0xffff); i++; if(i < max_transfer) { - comedi_buf_put(async, (fifo_data >> 16) & 0xffff); + cfc_write_to_buffer( s, (fifo_data >> 16) & 0xffff); i++; } read_code = readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff; @@ -1998,7 +1999,8 @@ static void drain_dma_buffers(comedi_device *dev, unsigned int channel) num_samples = priv(dev)->ai_count; priv(dev)->ai_count -= num_samples; } - comedi_buf_put_array(async, priv(dev)->ai_buffer[priv(dev)->dma_index], num_samples); + cfc_write_array_to_buffer( dev->read_subdev, + priv(dev)->ai_buffer[ priv(dev)->dma_index ], num_samples * sizeof( sampl_t ) ); priv(dev)->dma_index = (priv(dev)->dma_index + 1) % DMA_RING_COUNT; DEBUG_PRINT("next buffer addr 0x%lx\n", (unsigned long) priv(dev)->ai_buffer_phys_addr[priv(dev)->dma_index]); diff --git a/comedi/drivers/comedi_fc.c b/comedi/drivers/comedi_fc.c new file mode 100644 index 00000000..e3e964b6 --- /dev/null +++ b/comedi/drivers/comedi_fc.c @@ -0,0 +1,120 @@ +/* + cfc.c + + This is a place for code driver writers wish to share between + two or more drivers. cfc is short + for comedi-frank-common. + + Author: Frank Mori Hess + Copyright (C) 2002 Frank Mori Hess + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +************************************************************************/ + +#include +#include +#include "comedi_fc.h" + +static inline unsigned int bytes_per_sample( comedi_subdevice *subd ) +{ + if( subd->flags & SDF_LSAMPL ) + return sizeof( lsampl_t ); + else + return sizeof( sampl_t ); +} + +static inline unsigned int bytes_per_scan( comedi_subdevice *subd ) +{ + return subd->async->cmd.chanlist_len * bytes_per_sample( subd ); +} + +static void increment_scan_progress( comedi_subdevice *subd, unsigned int num_bytes ) +{ + comedi_async *async = subd->async; + unsigned int scan_length = bytes_per_scan( subd ); + + async->scan_progress += num_bytes; + if( async->scan_progress >= scan_length ) + { + async->scan_progress %= scan_length; + async->events |= COMEDI_CB_EOS; + } +} + +/* Writes an array of data points to comedi's buffer */ +unsigned int cfc_write_array_to_buffer( comedi_subdevice *subd, void *data, + unsigned int num_bytes ) +{ + comedi_async *async = subd->async; + unsigned int retval; + + retval = comedi_buf_write_alloc( async, num_bytes ); + if( retval != num_bytes ) + { + async->events |= COMEDI_CB_ERROR; + return 0; + } + + comedi_buf_memcpy_to( async, 0, data, num_bytes); + + comedi_buf_write_free( async, num_bytes ); + + increment_scan_progress( subd, num_bytes ); + + if( num_bytes ) async->events |= COMEDI_CB_BLOCK; + + return num_bytes; +} + +unsigned int cfc_read_array_from_buffer( comedi_subdevice *subd, void *data, + unsigned int num_bytes ) +{ + comedi_async *async = subd->async; + unsigned int bytes_available; + + bytes_available = comedi_buf_read_n_available( async ); + if( bytes_available < num_bytes ) + { + num_bytes = bytes_available; + } + + comedi_buf_memcpy_from( async, 0, data, num_bytes); + + comedi_buf_read_free( async, num_bytes ); + + increment_scan_progress( subd, num_bytes ); + + if( num_bytes ) async->events |= COMEDI_CB_BLOCK; + + return num_bytes; +} + +MODULE_AUTHOR("Frank Mori Hess "); +MODULE_DESCRIPTION("Shared functoins for Comedi low-level drivers"); +MODULE_LICENSE("GPL"); + +static int __init comedi_fc_init_module(void) +{ + return 0; +} +static void __exit comedi_fc_cleanup_module(void) +{ +} +module_init(comedi_fc_init_module); +module_exit(comedi_fc_cleanup_module); + +EXPORT_SYMBOL( cfc_write_array_to_buffer ); +EXPORT_SYMBOL( cfc_read_array_from_buffer ); diff --git a/comedi/drivers/comedi_fc.h b/comedi/drivers/comedi_fc.h new file mode 100644 index 00000000..5e49c7ca --- /dev/null +++ b/comedi/drivers/comedi_fc.h @@ -0,0 +1,46 @@ +/* + cfc.h + + This is a place for code driver writers wish to share between + two or more drivers. + If it ever grows beyond a couple inline functions, I'll make + a cfc.o module to go with this header file. cfc is short + for comedi-frank-common. + + Author: Frank Mori Hess + Copyright (C) 2002 Frank Mori Hess + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +************************************************************************/ + +#include "linux/comedidev.h" + +/* Writes an array of data points to comedi's buffer */ +unsigned int cfc_write_array_to_buffer( comedi_subdevice *subd, void *data, + unsigned int num_bytes ); + +inline unsigned int cfc_write_to_buffer( comedi_subdevice *subd, sampl_t data ) +{ + return cfc_write_array_to_buffer( subd, &data, sizeof( data ) ); +}; + +inline unsigned int cfc_write_long_to_buffer( comedi_subdevice *subd, lsampl_t data ) +{ + return cfc_write_array_to_buffer( subd, &data, sizeof( data ) ); +}; + +unsigned int cfc_read_array_from_buffer( comedi_subdevice *subd, void *data, + unsigned int num_bytes ); diff --git a/comedi/drivers/comedi_rt_timer.c b/comedi/drivers/comedi_rt_timer.c index 20af4a4c..2b0195e5 100644 --- a/comedi/drivers/comedi_rt_timer.c +++ b/comedi/drivers/comedi_rt_timer.c @@ -212,7 +212,10 @@ static int timer_data_read(comedi_device *dev, comedi_cmd *cmd, comedi_error(dev, "read error"); return -EIO; } - comedi_buf_put(s->async, data); + if( s->flags % SDF_LSAMPL ) + cfc_write_long_to_buffer( s, data ); + else + cfc_write_to_buffer( s, data ); return 0; } @@ -222,11 +225,20 @@ static int timer_data_write(comedi_device *dev, comedi_cmd *cmd, unsigned int index) { comedi_subdevice *s = dev->write_subdev; - int ret; + unsigned int num_bytes; sampl_t data; + lsampl_t long_data; + + if( s->flags & SDF_LSAMPL ) + { + num_bytes = cfc_read_array_from_buffer( s, &long_data, sizeof( long_data ) ); + }else + num_bytes = cfc_read_array_from_buffer( s, &data, sizeof( data ) ); + long_data = data; + } - ret = comedi_buf_get(s->async, &data); - if(ret < 0) { + if(num_bytes == 0) + { comedi_error(dev, "buffer underrun"); return -EAGAIN; } @@ -234,7 +246,7 @@ static int timer_data_write(comedi_device *dev, comedi_cmd *cmd, CR_CHAN(cmd->chanlist[index]), CR_RANGE(cmd->chanlist[index]), CR_AREF(cmd->chanlist[index]), - data); + long_data); if(ret<0){ comedi_error(dev, "write error"); return -EIO; @@ -256,7 +268,11 @@ static int timer_dio_read(comedi_device *dev, comedi_cmd *cmd, comedi_error(dev, "read error"); return -EIO; } - comedi_buf_put(s->async, data); + + if( s->flags % SDF_LSAMPL ) + cfc_write_long_to_buffer( s, data ); + else + cfc_write_to_buffer( s, data ); return 0; } diff --git a/comedi/drivers/comedi_test.c b/comedi/drivers/comedi_test.c index 627910ef..8c211322 100644 --- a/comedi/drivers/comedi_test.c +++ b/comedi/drivers/comedi_test.c @@ -62,6 +62,7 @@ zero volts). #include #include #include +#include "comedi_fc.h" /* Board descriptions */ typedef struct waveform_board_struct{ @@ -159,7 +160,7 @@ static void waveform_ai_interrupt(unsigned long arg) { for( j = 0; j < cmd->chanlist_len; j++) { - comedi_buf_put(async, + cfc_write_to_buffer( dev->read_subdev, fake_waveform(dev, CR_CHAN(cmd->chanlist[j]), CR_RANGE(cmd->chanlist[j]), devpriv->usec_current + i * devpriv->scan_period + j * devpriv->convert_period)); } @@ -174,8 +175,6 @@ static void waveform_ai_interrupt(unsigned long arg) devpriv->usec_current += elapsed_time; devpriv->usec_current %= devpriv->usec_period; - async->events |= COMEDI_CB_BLOCK; - if((async->events & COMEDI_CB_EOA) == 0 && devpriv->timer_running) mod_timer(&devpriv->timer, jiffies + 1); else diff --git a/comedi/drivers/das16.c b/comedi/drivers/das16.c index 986a9878..b9edb8be 100644 --- a/comedi/drivers/das16.c +++ b/comedi/drivers/das16.c @@ -56,13 +56,13 @@ Options: gain) [6] - analog output range lowest voltage in microvolts (optional) [7] - analog output range highest voltage in microvolts (optional) - [8] - use timer mode for DMA, needed e.g. for buggy DMA controller - in NS CS5530A (Geode Companion). If set, also allows + [8] - use timer mode for DMA, needed e.g. for buggy DMA controller + in NS CS5530A (Geode Companion). If set, also allows comedi_command() to be run without an irq. Passing a zero for an option is the same as leaving it unspecified. -Both a dma channel and an irq (or use of 'timer mode', option 8) are required +Both a dma channel and an irq (or use of 'timer mode', option 8) are required for timed or externally triggered conversions. */ /* @@ -90,6 +90,7 @@ Computer boards manuals also available from their website www.measurementcomputi #include #include "8253.h" #include "8255.h" +#include "comedi_fc.h" #undef DEBUG //#define DEBUG @@ -1152,15 +1153,26 @@ static void das16_timer_interrupt(unsigned long arg) mod_timer(&devpriv->timer, jiffies + timer_period); } +static void munge_ai_data( comedi_device *dev, sampl_t *data, unsigned int num_points) +{ + unsigned int i; + + if( thisboard->ai_nbits == 12) + { + for(i = 0; i < num_points; i++) + { + data[i] = ( data[i] >> 4 ) & 0xfff; + } + } +} + static void das16_interrupt( comedi_device *dev ) { - int i; unsigned long flags; comedi_subdevice *s = dev->read_subdev; comedi_async *async; comedi_cmd *cmd; int num_points, num_bytes, residue; - sampl_t dpnt; unsigned int target_xfer; if(dev->attached == 0) @@ -1203,15 +1215,9 @@ static void das16_interrupt( comedi_device *dev ) async->events |= COMEDI_CB_EOA; } - for(i = 0; i < num_points; i++) - { - /* write data point to comedi buffer */ - dpnt = devpriv->dma_buffer[i]; - if(thisboard->ai_nbits == 12) - dpnt = (dpnt >> 4) & 0xfff; - comedi_buf_put(async, dpnt); - devpriv->adc_count--; - } + munge_ai_data( dev, devpriv->dma_buffer, num_points ); + cfc_write_array_to_buffer( s, devpriv->dma_buffer, num_points * sizeof( sampl_t ) ); + devpriv->adc_count -= num_points; // figure out how many bytes for next transfer target_xfer = devpriv->target_transfer_size; diff --git a/comedi/drivers/das16m1.c b/comedi/drivers/das16m1.c index 99dd324d..bb8a4985 100644 --- a/comedi/drivers/das16m1.c +++ b/comedi/drivers/das16m1.c @@ -68,6 +68,7 @@ irq can be omitted, although the cmd interface will not work without it. #include #include "8255.h" #include "8253.h" +#include "comedi_fc.h" #define DAS16M1_SIZE 16 #define DAS16M1_SIZE2 8 @@ -98,7 +99,6 @@ irq can be omitted, although the cmd interface will not work without it. #define DAS16M1_AI 0 // 16-bit wide register #define AI_CHAN(x) ((x) & 0xf) -#define AI_DATA(x) (((x) >> 4) & 0xfff) #define DAS16M1_CS 2 #define EXT_TRIG_BIT 0x1 #define OVRUN 0x20 @@ -186,6 +186,7 @@ struct das16m1_private_struct { * needed to keep track of whether new count has been loaded into * counter yet (loaded by first sample conversion) */ u16 initial_hw_count; + sampl_t ai_buffer[ FIFO_SIZE ]; unsigned int do_bits; // saves status of digital output bits unsigned int divisor1; // divides master clock to obtain conversion speed unsigned int divisor2; // divides master clock to obtain conversion speed @@ -195,6 +196,11 @@ struct das16m1_private_struct { COMEDI_INITCLEANUP(driver_das16m1); +static inline sampl_t munge_sample( sampl_t data ) +{ + return ( data >> 4 ) & 0xfff; +} + static int das16m1_cmd_test(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd) { unsigned int err=0, tmp, i; @@ -413,7 +419,7 @@ static int das16m1_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn * comedi_error(dev, "timeout"); return -ETIME; } - data[n] = AI_DATA(inw(dev->iobase)); + data[n] = munge_sample( inw( dev->iobase ) ); } return n; @@ -494,9 +500,18 @@ static void das16m1_interrupt(int irq, void *d, struct pt_regs *regs) spin_unlock(&dev->spinlock); } +static void munge_sample_array( sampl_t *array, unsigned int num_elements ) +{ + unsigned int i; + + for(i = 0; i < num_elements; i++) + { + array[i] = munge_sample( array[i] ); + } +} + static void das16m1_handler(comedi_device *dev, unsigned int status) { - int i; comedi_subdevice *s; comedi_async *async; comedi_cmd *cmd; @@ -534,13 +549,9 @@ 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; - 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)); - } + insw( dev->iobase, devpriv->ai_buffer, num_samples ); + munge_sample_array( devpriv->ai_buffer, num_samples ); + cfc_write_array_to_buffer( s, devpriv->ai_buffer, num_samples * sizeof( sampl_t ) ); devpriv->adc_count += num_samples; if(cmd->stop_src == TRIG_COUNT) diff --git a/comedi/drivers/das1800.c b/comedi/drivers/das1800.c index dfdef7fb..59bf21f9 100644 --- a/comedi/drivers/das1800.c +++ b/comedi/drivers/das1800.c @@ -114,10 +114,11 @@ TODO: #include #include #include "8253.h" +#include "comedi_fc.h" // misc. defines #define DAS1800_SIZE 16 //uses 16 io addresses -#define HALF_FIFO 512 // 1024 sample fifo +#define FIFO_SIZE 1024 // 1024 sample fifo #define TIMER_BASE 200 // 5 Mhz master clock #define UNIPOLAR 0x4 // bit that determines whether input range is uni/bipolar #define DMA_BUF_SIZE 0x1ff00 // size in bytes of dma buffers @@ -195,7 +196,7 @@ static int das1800_ai_poll(comedi_device *dev,comedi_subdevice *s); static void das1800_ai_handler(comedi_device *dev); static void das1800_handle_dma(comedi_device *dev, comedi_subdevice *s, unsigned int status); static void das1800_flush_dma(comedi_device *dev, comedi_subdevice *s); -static void das1800_flush_dma_channel(comedi_device *dev, comedi_subdevice *s, unsigned int channel, u16 *buffer); +static void das1800_flush_dma_channel(comedi_device *dev, comedi_subdevice *s, unsigned int channel, uint16_t *buffer); static void das1800_handle_fifo_half_full(comedi_device *dev, comedi_subdevice *s); static void das1800_handle_fifo_not_empty(comedi_device *dev, comedi_subdevice *s); static int das1800_ai_do_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd); @@ -472,9 +473,9 @@ typedef struct{ unsigned int dma0; /* dma channels used */ unsigned int dma1; volatile unsigned int dma_current; /* dma channel currently in use */ - u16 *dma_buf0; /* pointers to dma buffers */ - u16 *dma_buf1; - u16 *dma_current_buf; /* pointer to dma buffer currently being used */ + uint16_t *ai_buf0; /* pointers to dma buffers */ + uint16_t *ai_buf1; + uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ int iobase2; /* secondary io address used for analog out on 'ao' boards */ short ao_update_bits; /* remembers the last write to the 'update' dac */ @@ -517,16 +518,90 @@ static comedi_driver driver_das1800={ */ COMEDI_INITCLEANUP(driver_das1800); +int das1800_init_dma( comedi_device *dev, unsigned int dma0, unsigned int dma1 ) +{ + unsigned long flags; + + // need an irq to do dma + if( dev->irq && dma0 ) + { + //encode dma0 and dma1 into 2 digit hexadecimal for switch + switch((dma0 & 0x7) | (dma1 << 4)) + { + case 0x5: // dma0 == 5 + devpriv->dma_bits |= DMA_CH5; + break; + case 0x6: // dma0 == 6 + devpriv->dma_bits |= DMA_CH6; + break; + case 0x7: // dma0 == 7 + devpriv->dma_bits |= DMA_CH7; + break; + case 0x65: // dma0 == 5, dma1 == 6 + devpriv->dma_bits |= DMA_CH5_CH6; + break; + case 0x76: // dma0 == 6, dma1 == 7 + devpriv->dma_bits |= DMA_CH6_CH7; + break; + case 0x57: // dma0 == 7, dma1 == 5 + devpriv->dma_bits |= DMA_CH7_CH5; + break; + default: + printk(" only supports dma channels 5 through 7\n" + " Dual dma only allows the following combinations:\n" + " dma 5,6 / 6,7 / or 7,5\n"); + return -EINVAL; + break; + } + if( request_dma( dma0, driver_das1800.driver_name ) ) + { + printk( " failed to allocate dma channel %i\n", dma0 ); + return -EINVAL; + } + devpriv->dma0 = dma0; + devpriv->dma_current = dma0; + if( dma1 ) + { + if( request_dma( dma1, driver_das1800.driver_name ) ) + { + printk( " failed to allocate dma channel %i\n", dma1 ); + return -EINVAL; + } + devpriv->dma1 = dma1; + } + devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if(devpriv->ai_buf0 == NULL) + return -ENOMEM; + devpriv->dma_current_buf = devpriv->ai_buf0; + if( dma1 ) + { + devpriv->ai_buf1 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if(devpriv->ai_buf1 == NULL) + return -ENOMEM; + } + flags = claim_dma_lock(); + disable_dma(devpriv->dma0); + set_dma_mode(devpriv->dma0, DMA_MODE_READ); + if( dma1 ) + { + disable_dma(devpriv->dma1); + set_dma_mode(devpriv->dma1, DMA_MODE_READ); + } + release_dma_lock(flags); + } + return 0; +} + static int das1800_attach(comedi_device *dev, comedi_devconfig *it) { comedi_subdevice *s; - unsigned long flags; int iobase = it->options[0]; int irq = it->options[1]; int dma0 = it->options[2]; int dma1 = it->options[3]; int iobase2; int board; + int retval; /* allocate and initialize dev->private */ if(alloc_private(dev, sizeof(das1800_private)) < 0) @@ -624,76 +699,14 @@ static int das1800_attach(comedi_device *dev, comedi_devconfig *it) break; } - //dma stuff - // need an irq to do dma - if(irq) + retval = das1800_init_dma( dev, dma0, dma1 ); + if( retval < 0 ) return retval; + + if( devpriv->ai_buf0 == NULL ) { - if(dma0) - { - //encode dma0 and dma1 into 2 digit hexadecimal for switch - switch((dma0 & 0x7) | (dma1 << 4)) - { - case 0x5: // dma0 == 5 - devpriv->dma_bits |= DMA_CH5; - break; - case 0x6: // dma0 == 6 - devpriv->dma_bits |= DMA_CH6; - break; - case 0x7: // dma0 == 7 - devpriv->dma_bits |= DMA_CH7; - break; - case 0x65: // dma0 == 5, dma1 == 6 - devpriv->dma_bits |= DMA_CH5_CH6; - break; - case 0x76: // dma0 == 6, dma1 == 7 - devpriv->dma_bits |= DMA_CH6_CH7; - break; - case 0x57: // dma0 == 7, dma1 == 5 - devpriv->dma_bits |= DMA_CH7_CH5; - break; - default: - printk(" only supports dma channels 5 through 7\n" - " Dual dma only allows the following combinations:\n" - " dma 5,6 / 6,7 / or 7,5\n"); - return -EINVAL; - break; - } - if(request_dma(dma0, driver_das1800.driver_name)) - { - printk(" failed to allocate dma channel %i\n", dma0); - return -EINVAL; - } - devpriv->dma0 = dma0; - devpriv->dma_current = dma0; - if(dma1) - { - if(request_dma(dma1, driver_das1800.driver_name)) - { - printk(" failed to allocate dma channel %i\n", dma1); - return -EINVAL; - } - devpriv->dma1 = dma1; - } - devpriv->dma_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if(devpriv->dma_buf0 == NULL) - return -ENOMEM; - devpriv->dma_current_buf = devpriv->dma_buf0; - if(dma1) - { - devpriv->dma_buf1 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if(devpriv->dma_buf1 == NULL) - return -ENOMEM; - } - flags = claim_dma_lock(); - disable_dma(devpriv->dma0); - set_dma_mode(devpriv->dma0, DMA_MODE_READ); - if(dma1) - { - disable_dma(devpriv->dma1); - set_dma_mode(devpriv->dma1, DMA_MODE_READ); - } - release_dma_lock(flags); - } + devpriv->ai_buf0 = kmalloc( FIFO_SIZE * sizeof( uint16_t ), GFP_KERNEL ); + if(devpriv->ai_buf0 == NULL) + return -ENOMEM; } dev->n_subdevices = 4; @@ -782,10 +795,10 @@ static int das1800_detach(comedi_device *dev) free_dma(devpriv->dma0); if(devpriv->dma1) free_dma(devpriv->dma1); - if(devpriv->dma_buf0) - kfree(devpriv->dma_buf0); - if(devpriv->dma_buf1) - kfree(devpriv->dma_buf1); + if(devpriv->ai_buf0) + kfree(devpriv->ai_buf0); + if(devpriv->ai_buf1) + kfree(devpriv->ai_buf1); } printk("comedi%d: %s: remove\n", dev->minor, driver_das1800.driver_name); @@ -997,12 +1010,12 @@ static void das1800_handle_dma(comedi_device *dev, comedi_subdevice *s, unsigned if(devpriv->dma_current == devpriv->dma0) { devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->dma_buf1; + devpriv->dma_current_buf = devpriv->ai_buf1; } else { devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->dma_buf0; + devpriv->dma_current_buf = devpriv->ai_buf0; } } } @@ -1010,14 +1023,35 @@ static void das1800_handle_dma(comedi_device *dev, comedi_subdevice *s, unsigned return; } +static inline uint16_t munge_bipolar_sample( const comedi_device *dev, uint16_t sample ) +{ + sample += 1 << ( thisboard->resolution - 1 ); + return sample; +} + +static void munge_data( comedi_device *dev, uint16_t *array, unsigned int num_elements ) +{ + unsigned int i; + int unipolar; + + /* see if card is using a unipolar or bipolar range so we can munge data correctly */ + unipolar = inb( dev->iobase + DAS1800_CONTROL_C ) & UB; + + /* convert to unsigned type if we are in a bipolar mode */ + if( !unipolar ) + { + for( i = 0; i < num_elements; i++ ) + { + array[i] = munge_bipolar_sample( dev, array[i] ); + } + } +} + /* Utility function used by das1800_flush_dma() and das1800_handle_dma(). * Assumes dma lock is held */ -static void das1800_flush_dma_channel(comedi_device *dev, comedi_subdevice *s, unsigned int channel, u16 *buffer) +static void das1800_flush_dma_channel(comedi_device *dev, comedi_subdevice *s, unsigned int channel, uint16_t *buffer) { - unsigned int numPoints; - int unipolar; - int i; - const int bytes_per_sample = 2; + unsigned int num_bytes, num_samples; comedi_cmd *cmd = &s->async->cmd; disable_dma(channel); @@ -1027,25 +1061,17 @@ static void das1800_flush_dma_channel(comedi_device *dev, comedi_subdevice *s, u clear_dma_ff(channel); // figure out how many points to read - numPoints = (devpriv->dma_transfer_size - get_dma_residue(channel)) / - bytes_per_sample; - /* if we only need some of the points */ - if(cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints) - numPoints = devpriv->count; + num_bytes = devpriv->dma_transfer_size - get_dma_residue( channel ); + num_samples = num_bytes / sizeof( sampl_t ); - /* see if card is using a unipolar or bipolar range so we can munge data correctly */ - unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; + /* if we only need some of the points */ + if( cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples ) + num_samples = devpriv->count; - // read data from dma buffer - for( i = 0; i < numPoints; i++) - { - /* convert to unsigned type if we are in a bipolar mode */ - if(!unipolar); - buffer[i] += 1 << (thisboard->resolution - 1); - comedi_buf_put(s->async, buffer[i]); - if(s->async->cmd.stop_src == TRIG_COUNT) - devpriv->count--; - } + munge_data( dev, buffer, num_samples ); + cfc_write_array_to_buffer( s, buffer, num_bytes ); + if(s->async->cmd.stop_src == TRIG_COUNT) + devpriv->count -= num_samples; return; } @@ -1066,12 +1092,12 @@ static void das1800_flush_dma(comedi_device *dev, comedi_subdevice *s) if(devpriv->dma_current == devpriv->dma0) { devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->dma_buf1; + devpriv->dma_current_buf = devpriv->ai_buf1; } else { devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->dma_buf0; + devpriv->dma_current_buf = devpriv->ai_buf0; } das1800_flush_dma_channel(dev, s, devpriv->dma_current, devpriv->dma_current_buf); } @@ -1086,28 +1112,18 @@ static void das1800_flush_dma(comedi_device *dev, comedi_subdevice *s) static void das1800_handle_fifo_half_full(comedi_device *dev, comedi_subdevice *s) { - int i; /* loop index */ int numPoints = 0; /* number of points to read */ - u16 data[HALF_FIFO]; - int unipolar; comedi_cmd *cmd = &s->async->cmd; - unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; - - numPoints = HALF_FIFO; + numPoints = FIFO_SIZE / 2; /* if we only need some of the points */ if(cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints) numPoints = devpriv->count; - insw(dev->iobase + DAS1800_FIFO, data, numPoints); - for( i = 0; i < numPoints; i++) - { - /* write data point to buffer */ - /* convert to unsigned type if we are in a bipolar mode */ - if(!unipolar); - data[i] += 1 << (thisboard->resolution - 1); - comedi_buf_put(s->async, data[i]); - if(cmd->stop_src == TRIG_COUNT) devpriv->count--; - } + insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints); + munge_data( dev, devpriv->ai_buf0, numPoints ); + cfc_write_array_to_buffer( s, devpriv->ai_buf0, numPoints * sizeof( devpriv->ai_buf0[0] ) ); + if( cmd->stop_src == TRIG_COUNT ) + devpriv->count -= numPoints; return; } @@ -1119,15 +1135,15 @@ static void das1800_handle_fifo_not_empty(comedi_device *dev, comedi_subdevice * unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; - while(inb(dev->iobase + DAS1800_STATUS) & FNE) + while( inb( dev->iobase + DAS1800_STATUS ) & FNE ) { if(cmd->stop_src == TRIG_COUNT && devpriv->count == 0) break; - dpnt = inw(dev->iobase + DAS1800_FIFO); + dpnt = inw( dev->iobase + DAS1800_FIFO ); /* convert to unsigned type if we are in a bipolar mode */ if(!unipolar); - dpnt += 1 << (thisboard->resolution - 1); - comedi_buf_put(s->async, dpnt); + dpnt = munge_bipolar_sample( dev, dpnt ); + cfc_write_to_buffer( s, dpnt ); if(cmd->stop_src == TRIG_COUNT) devpriv->count--; } @@ -1438,11 +1454,11 @@ static void setup_dma(comedi_device *dev, comedi_cmd cmd) /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(devpriv->dma0); - set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->dma_buf0)); + set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0)); // set appropriate size of transfer set_dma_count(devpriv->dma0, devpriv->dma_transfer_size); devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->dma_buf0; + devpriv->dma_current_buf = devpriv->ai_buf0; enable_dma(devpriv->dma0); // set up dual dma if appropriate if(dual_dma) @@ -1451,7 +1467,7 @@ static void setup_dma(comedi_device *dev, comedi_cmd cmd) /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(devpriv->dma1); - set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->dma_buf1)); + set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1)); // set appropriate size of transfer set_dma_count(devpriv->dma1, devpriv->dma_transfer_size); enable_dma(devpriv->dma1); diff --git a/comedi/drivers/das800.c b/comedi/drivers/das800.c index bc0a3177..b1980f56 100644 --- a/comedi/drivers/das800.c +++ b/comedi/drivers/das800.c @@ -75,6 +75,7 @@ cmd triggers supported: #include #include #include "8253.h" +#include "comedi_fc.h" #define DAS800_SIZE 8 #define TIMER_BASE 1000 @@ -415,7 +416,7 @@ static void das800_interrupt(int irq, void *d, struct pt_regs *regs) if(devpriv->count > 0 || devpriv->forever == 1) { /* write data point to buffer */ - comedi_buf_put(async, dataPoint); + cfc_write_to_buffer( s, dataPoint); if(devpriv->count > 0) devpriv->count--; } } diff --git a/comedi/drivers/ni_at_a2150.c b/comedi/drivers/ni_at_a2150.c index 86ae6de0..6cd12a1f 100644 --- a/comedi/drivers/ni_at_a2150.c +++ b/comedi/drivers/ni_at_a2150.c @@ -1,6 +1,6 @@ /* ni_at_a2150.c driver for National Instruments AT-A2150 boards - Copyright (C) 2001 Frank Mori Hess + Copyright (C) 2001, 2002 Frank Mori Hess COMEDI - Linux Control and Measurement Device Interface Copyright (C) 2000 David A. Schleef @@ -78,6 +78,7 @@ TRIG_WAKE_EOS #include #include #include "8253.h" +#include "comedi_fc.h" #define A2150_SIZE 28 #define A2150_DMA_BUFFER_SIZE 0xff00 // size in bytes of dma buffer @@ -299,7 +300,7 @@ static void a2150_interrupt(int irq, void *d, struct pt_regs *regs) dpnt = devpriv->dma_buffer[i]; // convert from 2's complement to unsigned coding dpnt ^= 0x8000; - comedi_buf_put(async, dpnt); + cfc_write_to_buffer( s, dpnt ); if(cmd->stop_src == TRIG_COUNT) { if(--devpriv->count == 0) diff --git a/comedi/drivers/ni_labpc.c b/comedi/drivers/ni_labpc.c index a20516d4..e2c5ceae 100644 --- a/comedi/drivers/ni_labpc.c +++ b/comedi/drivers/ni_labpc.c @@ -67,8 +67,8 @@ NI manuals: */ -#define LABPC_DEBUG // enable debugging messages -//#undef LABPC_DEBUG +#undef LABPC_DEBUG +//#define LABPC_DEBUG // enable debugging messages #include #include @@ -88,6 +88,7 @@ NI manuals: #include "8253.h" #include "8255.h" #include "mite.h" +#include "comedi_fc.h" #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) @@ -738,11 +739,14 @@ static int labpc_attach(comedi_device *dev, comedi_devconfig *it) s->insn_read = labpc_eeprom_read_insn; s->insn_write = labpc_eeprom_write_insn; + for(i = 0; i < EEPROM_SIZE; i++) + { + devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); + } #ifdef LABPC_DEBUG printk(" eeprom:"); for(i = 0; i < EEPROM_SIZE; i++) { - devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); printk(" %i:0x%x ", i, devpriv->eeprom_data[i]); } printk("\n"); @@ -1380,7 +1384,7 @@ static int labpc_drain_fifo(comedi_device *dev) lsb = thisboard->read_byte(dev->iobase + ADC_FIFO_REG); msb = thisboard->read_byte(dev->iobase + ADC_FIFO_REG); data = (msb << 8) | lsb; - comedi_buf_put(async, data); + cfc_write_to_buffer( dev->read_subdev, data ); // quit if we have all the data we want if(async->cmd.stop_src == TRIG_COUNT) { @@ -1443,9 +1447,9 @@ static void labpc_drain_dma(comedi_device *dev) } /* write data to comedi buffer */ - for(i=0;idma_buffer[i]); + for( i = 0; i < num_points; i++) + { + cfc_write_to_buffer( s, devpriv->dma_buffer[i] ); } if(async->cmd.stop_src == TRIG_COUNT) devpriv->count -= num_points; diff --git a/comedi/kcomedilib/kcomedilib_main.c b/comedi/kcomedilib/kcomedilib_main.c index d7627558..0e4a2460 100644 --- a/comedi/kcomedilib/kcomedilib_main.c +++ b/comedi/kcomedilib/kcomedilib_main.c @@ -124,6 +124,8 @@ static void init_async_buf( comedi_async *async ) async->buf_free_count = 0; async->buf_read_ptr = 0; async->buf_write_ptr = 0; + async->cur_chan = 0; + async->scan_progress = 0; } int comedi_command(comedi_t *d,comedi_cmd *cmd) @@ -160,7 +162,6 @@ int comedi_command(comedi_t *d,comedi_cmd *cmd) async->data = cmd->data; async->data_len = cmd->data_len; - async->cur_chan = 0; return s->do_cmd(dev,s); } diff --git a/include/linux/comedidev.h b/include/linux/comedidev.h index cfdd96bf..b8472910 100644 --- a/include/linux/comedidev.h +++ b/include/linux/comedidev.h @@ -139,6 +139,8 @@ struct comedi_async_struct{ unsigned int buf_read_ptr; /* buffer marker for reader */ unsigned int cur_chan; /* useless channel marker for interrupt */ + /* number of bytes that have been received for current scan */ + unsigned int scan_progress; void *data; unsigned int data_len; @@ -335,6 +337,10 @@ 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); +void comedi_buf_memcpy_to( comedi_async *async, unsigned int offset, const void *source, + unsigned int num_bytes ); +void comedi_buf_memcpy_from( comedi_async *async, unsigned int offset, void *destination, + unsigned int num_bytes ); //#ifdef CONFIG_COMEDI_RT