From 1187de46441a4705013eaebf01101faa38652565 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Thu, 19 Apr 2007 19:41:27 +0000 Subject: [PATCH] Made some changes to async buffer, to better accommodate output dma (added read allocation). Tweaked memory barrier usage for async buffer to try and improve its correctness. comedi_buf_munge() is now handled entirely inside comedi_buf_write_free(). Added some helper functions mite_sync_input_dma() and mite_sync_output_dma() for use in driver interrupt handlers. Added beginnings of support for NI general purpose counter input commands. --- comedi/comedi_fops.c | 45 ++------- comedi/comedi_ksyms.c | 4 +- comedi/drivers.c | 151 ++++++++++++++++++++-------- comedi/drivers/8255.c | 8 +- comedi/drivers/amplc_pci224.c | 2 +- comedi/drivers/cb_pcidas64.c | 2 +- comedi/drivers/comedi_fc.c | 10 +- comedi/drivers/dt282x.c | 15 +-- comedi/drivers/mite.c | 104 ++++++++++++++++++- comedi/drivers/mite.h | 5 + comedi/drivers/ni_660x.c | 2 + comedi/drivers/ni_mio_common.c | 99 ++++++------------ comedi/drivers/ni_pcimio.c | 2 - comedi/drivers/ni_tio.c | 94 +++++++++++++++++ comedi/drivers/ni_tio.h | 16 +++ comedi/kcomedilib/get.c | 10 +- comedi/kcomedilib/kcomedilib_main.c | 17 +--- include/linux/comedidev.h | 25 +++-- 18 files changed, 400 insertions(+), 211 deletions(-) diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c index 84d59137..d7eea148 100644 --- a/comedi/comedi_fops.c +++ b/comedi/comedi_fops.c @@ -81,7 +81,6 @@ void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s); static int do_cancel(comedi_device *dev,comedi_subdevice *s); static int comedi_fasync (int fd, struct file *file, int on); -static void init_async_buf( comedi_async *async ); static int comedi_ioctl(struct inode * inode,struct file * file, unsigned int cmd, unsigned long arg) @@ -499,6 +498,7 @@ static int do_bufinfo_ioctl(comedi_device *dev,void *arg) } if(bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)){ + bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read); comedi_buf_read_free(async, bi.bytes_read); if(!(s->subdev_flags&SDF_RUNNING) && @@ -510,7 +510,6 @@ static int do_bufinfo_ioctl(comedi_device *dev,void *arg) if(bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)){ bi.bytes_written = comedi_buf_write_alloc( async, bi.bytes_written ); - comedi_buf_munge(dev, s, async->buf_write_alloc_count - async->munge_count); comedi_buf_write_free(async, bi.bytes_written); } @@ -518,13 +517,6 @@ static int do_bufinfo_ioctl(comedi_device *dev,void *arg) bi.buf_write_ptr = async->buf_write_ptr; bi.buf_read_count = async->buf_read_count; bi.buf_read_ptr = async->buf_read_ptr; - /* FIXME this will bug if we ever have a subdevice that supports both read and write commands. - We need a flag saying which direction the current command is going (CMDF_WRITE?) */ - if((s->subdev_flags & SDF_CMD_READ)){ - unsigned int n_munge_bytes; - n_munge_bytes = bi.buf_write_count - s->async->munge_count; - comedi_buf_munge(dev, s, n_munge_bytes); - } copyback: if(copy_to_user(arg, &bi, sizeof(comedi_bufinfo))) @@ -964,7 +956,7 @@ static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file) goto cleanup; } - init_async_buf( async ); + comedi_reset_async_buf( async ); async->cb_mask = COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; if(async->cmd.flags & TRIG_WAKE_EOS){ @@ -1284,13 +1276,14 @@ static int comedi_mmap(struct file * file, struct vm_area_struct *vma) unsigned long size; int n_pages; int i; + comedi_subdevice *s; if(!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); return -ENODEV; } - comedi_subdevice *s = comedi_get_subdevice_by_minor(minor); + s = comedi_get_subdevice_by_minor(minor); if(s == NULL) { if(vma->vm_flags & VM_WRITE){ s = dev->write_subdev; @@ -1354,7 +1347,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) s = dev->read_subdev; async = s->async; if(!s->busy - || comedi_buf_read_n_available(s)>0 + || comedi_buf_read_n_available(async)>0 || !(s->subdev_flags&SDF_RUNNING)){ mask |= POLLIN | POLLRDNORM; } @@ -1364,7 +1357,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) async = s->async; if(!s->busy || !(s->subdev_flags&SDF_RUNNING) - || comedi_buf_write_n_available(s)>0){ + || comedi_buf_write_n_available(async) > 0){ mask |= POLLOUT | POLLWRNORM; } } @@ -1444,7 +1437,6 @@ static ssize_t comedi_write(struct file *file,const char *buf,size_t nbytes,loff n -= m; retval = -EFAULT; } - comedi_buf_munge(dev, s, async->buf_write_alloc_count - async->munge_count); comedi_buf_write_free(async, n); count+=n; @@ -1495,7 +1487,7 @@ static ssize_t comedi_read(struct file * file,char *buf,size_t nbytes,loff_t *of n=nbytes; - m = comedi_buf_read_n_available(s); + m = comedi_buf_read_n_available(async); //printk("%d available\n",m); if(async->buf_read_ptr + m > async->prealloc_bufsz){ m = async->prealloc_bufsz - async->buf_read_ptr; @@ -1524,7 +1516,6 @@ static ssize_t comedi_read(struct file * file,char *buf,size_t nbytes,loff_t *of schedule(); continue; } - comedi_buf_munge(dev, s, async->buf_write_count - async->munge_count); m = copy_to_user(buf, async->prealloc_buf + async->buf_read_ptr, n); if(m){ @@ -1532,6 +1523,7 @@ static ssize_t comedi_read(struct file * file,char *buf,size_t nbytes,loff_t *of retval = -EFAULT; } + comedi_buf_read_alloc(async, n); comedi_buf_read_free(async, n); count+=n; @@ -1569,7 +1561,7 @@ void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s) #endif if(async){ - init_async_buf( async ); + comedi_reset_async_buf( async ); }else{ printk("BUG: (?) do_become_nonbusy called with async=0\n"); } @@ -1878,22 +1870,3 @@ void comedi_event(comedi_device *dev,comedi_subdevice *s, unsigned int mask) } } } - -static void init_async_buf( comedi_async *async ) -{ - async->buf_write_alloc_count = 0; - async->buf_write_count = 0; - async->buf_read_count = 0; - - async->buf_write_ptr = 0; - async->buf_read_ptr = 0; - - async->cur_chan = 0; - async->scan_progress = 0; - async->munge_chan = 0; - async->munge_count = 0; - async->munge_ptr = 0; - - async->events = 0; -} - diff --git a/comedi/comedi_ksyms.c b/comedi/comedi_ksyms.c index fb9f07ae..7eab0db7 100644 --- a/comedi/comedi_ksyms.c +++ b/comedi/comedi_ksyms.c @@ -70,11 +70,11 @@ EXPORT_SYMBOL(comedi_buf_put); EXPORT_SYMBOL(comedi_buf_get); EXPORT_SYMBOL(comedi_buf_read_n_available); EXPORT_SYMBOL(comedi_buf_write_free); -EXPORT_SYMBOL(comedi_buf_munge); EXPORT_SYMBOL(comedi_buf_write_alloc); EXPORT_SYMBOL(comedi_buf_read_free); +EXPORT_SYMBOL(comedi_buf_read_alloc); EXPORT_SYMBOL(comedi_buf_memcpy_to); EXPORT_SYMBOL(comedi_buf_memcpy_from); - +EXPORT_SYMBOL(comedi_reset_async_buf); diff --git a/comedi/drivers.c b/comedi/drivers.c index b6afb43e..9fa40f60 100644 --- a/comedi/drivers.c +++ b/comedi/drivers.c @@ -194,7 +194,7 @@ attached: printk("BUG: dev->board_name=<%p>\n",dev->board_name); dev->board_name="BUG"; } - mb(); + smp_wmb(); dev->attached=1; return 0; @@ -276,6 +276,7 @@ static int postconfig(comedi_device *dev) return -ENOMEM; } memset(async, 0, sizeof(comedi_async)); + async->subdevice = s; s->async = async; #define DEFAULT_BUF_MAXSIZE (64*1024) @@ -484,15 +485,21 @@ int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s, /* munging is applied to data by core as it passes between user * and kernel space */ -unsigned int comedi_buf_munge( comedi_device *dev, comedi_subdevice *s, - unsigned int num_bytes ) +unsigned int comedi_buf_munge(comedi_async *async, + unsigned int num_bytes) { + comedi_subdevice *s = async->subdevice; unsigned int count = 0; + const unsigned num_sample_bytes = bytes_per_sample(s); - if( s->munge == NULL || ( s->async->cmd.flags & CMDF_RAWDATA ) ) - return count; + if( s->munge == NULL || ( async->cmd.flags & CMDF_RAWDATA ) ) + { + async->munge_count += num_bytes; + if((int)(async->munge_count - async->buf_write_count) > 0) BUG(); + return num_bytes; + } /* don't munge partial samples */ - num_bytes -= num_bytes % bytes_per_sample(s); + num_bytes -= num_bytes % num_sample_bytes; while( count < num_bytes ) { int block_size; @@ -503,33 +510,44 @@ unsigned int comedi_buf_munge( comedi_device *dev, comedi_subdevice *s, rt_printk("%s: %s: bug! block_size is negative\n", __FILE__, __FUNCTION__); break; } - if( (int)(s->async->munge_ptr + block_size - s->async->prealloc_bufsz) > 0 ) - block_size = s->async->prealloc_bufsz - s->async->munge_ptr; + if( (int)(async->munge_ptr + block_size - async->prealloc_bufsz) > 0 ) + block_size = async->prealloc_bufsz - async->munge_ptr; - s->munge( dev, s, s->async->prealloc_buf + s->async->munge_ptr, - block_size, s->async->munge_chan ); + s->munge(s->device, s, async->prealloc_buf + async->munge_ptr, + block_size, async->munge_chan ); - s->async->munge_chan += block_size / bytes_per_sample( s ); - s->async->munge_chan %= s->async->cmd.chanlist_len; - s->async->munge_count += block_size; - s->async->munge_ptr += block_size; - s->async->munge_ptr %= s->async->prealloc_bufsz; + smp_wmb(); //barrier insures data is munged in buffer before munge_count is incremented + + async->munge_chan += block_size / num_sample_bytes; + async->munge_chan %= async->cmd.chanlist_len; + async->munge_count += block_size; + async->munge_ptr += block_size; + async->munge_ptr %= async->prealloc_bufsz; count += block_size; } + if((int)(async->munge_count - async->buf_write_count) > 0) BUG(); return count; } -unsigned int comedi_buf_write_n_available(comedi_subdevice *s) +unsigned int comedi_buf_write_n_available(comedi_async *async) { - comedi_async *async=s->async; - unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; + unsigned int free_end; unsigned int nbytes; + if(async == NULL) return 0; + + free_end = async->buf_read_count + async->prealloc_bufsz; nbytes = free_end - async->buf_write_alloc_count; - nbytes -= nbytes % bytes_per_sample(s); + nbytes -= nbytes % bytes_per_sample(async->subdevice); + /* barrier insures the read of buf_read_count in this + query occurs before any following writes to the buffer which + might be based on the return value from this query. + */ + smp_mb(); return nbytes; } +/* allocates chunk for the writer from free buffer space */ unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes) { unsigned int free_end = async->buf_read_count + async->prealloc_bufsz; @@ -537,12 +555,14 @@ unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes) if((int)(async->buf_write_alloc_count + nbytes - free_end) > 0){ nbytes = free_end - async->buf_write_alloc_count; } - async->buf_write_alloc_count += nbytes; - + /* barrier insures the read of buf_read_count above occurs before + we write data to the write-alloc'ed buffer space */ + smp_mb(); return nbytes; } +/* allocates nothing unless it can completely fulfill the request */ unsigned int comedi_buf_write_alloc_strict(comedi_async *async, unsigned int nbytes) { @@ -551,29 +571,59 @@ unsigned int comedi_buf_write_alloc_strict(comedi_async *async, if((int)(async->buf_write_alloc_count + nbytes - free_end) > 0){ nbytes = 0; } - async->buf_write_alloc_count += nbytes; - + /* barrier insures the read of buf_read_count above occurs before + we write data to the write-alloc'ed buffer space */ + smp_mb(); return nbytes; } -/* transfers control of a chunk from writer to reader */ -void comedi_buf_write_free(comedi_async *async, unsigned int nbytes) +/* transfers a chunk from writer to filled buffer space */ +unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes) { + if((int)(async->buf_write_count + nbytes - async->buf_write_alloc_count) > 0) + { + rt_printk("comedi: attempted to write-free more bytes than have been write-allocated.\n"); + nbytes = async->buf_write_alloc_count - async->buf_write_count; + } async->buf_write_count += nbytes; async->buf_write_ptr += nbytes; + comedi_buf_munge(async, async->buf_write_count - async->munge_count); if(async->buf_write_ptr >= async->prealloc_bufsz){ async->buf_write_ptr %= async->prealloc_bufsz; async->events |= COMEDI_CB_EOBUF; } + return nbytes; } -/* transfers control of a chunk from reader to free area */ -void comedi_buf_read_free(comedi_async *async, unsigned int nbytes) +/* allocates a chunk for the reader from filled (and munged) buffer space */ +unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes) { + if((int)(async->buf_read_alloc_count + nbytes - async->munge_count) > 0) + { + nbytes = async->munge_count - async->buf_read_alloc_count; + } + async->buf_read_alloc_count += nbytes; + /* barrier insures read of munge_count occurs before we actually read + data out of buffer */ + smp_rmb(); + return nbytes; +} + +/* transfers control of a chunk from reader to free buffer space */ +unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes) +{ + // barrier insures data has been read out of buffer before read count is incremented + smp_mb(); + if((int)(async->buf_read_count + nbytes - async->buf_read_alloc_count) > 0) + { + rt_printk("comedi: attempted to read-free more bytes than have been read-allocated.\n"); + nbytes = async->buf_read_alloc_count - async->buf_read_count; + } async->buf_read_count += nbytes; async->buf_read_ptr += nbytes; async->buf_read_ptr %= async->prealloc_bufsz; + return nbytes; } void comedi_buf_memcpy_to( comedi_async *async, unsigned int offset, const void *data, @@ -600,7 +650,6 @@ void comedi_buf_memcpy_to( comedi_async *async, unsigned int offset, const void write_ptr = 0; } - barrier(); } void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset, @@ -612,7 +661,6 @@ void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset, if( read_ptr >= async->prealloc_bufsz ) read_ptr %= async->prealloc_bufsz; - barrier(); while( nbytes ) { unsigned int block_size; @@ -631,29 +679,27 @@ void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset, } } -static inline unsigned int _comedi_buf_read_n_available(comedi_async *async) +unsigned int comedi_buf_read_n_available(comedi_async *async) { - return async->buf_write_count - async->buf_read_count; -} - -unsigned int comedi_buf_read_n_available(comedi_subdevice *s) -{ - comedi_async *async = s->async; - unsigned int nbytes; + unsigned num_bytes; if(async == NULL) return 0; - - nbytes = _comedi_buf_read_n_available(async); - nbytes -= nbytes % bytes_per_sample(s); - return nbytes; + num_bytes = async->munge_count - async->buf_read_count; + /* barrier insures the read of munge_count in this + query occurs before any following reads of the buffer which + might be based on the return value from this query. + */ + smp_rmb(); + return num_bytes; } int comedi_buf_get(comedi_async *async, sampl_t *x) { - unsigned int n = _comedi_buf_read_n_available(async); + unsigned int n = comedi_buf_read_n_available(async); - if(nprealloc_buf + async->buf_read_ptr); comedi_buf_read_free(async, sizeof(sampl_t)); return 1; @@ -672,3 +718,22 @@ int comedi_buf_put(comedi_async *async, sampl_t x) return 1; } +void comedi_reset_async_buf(comedi_async *async) +{ + async->buf_write_alloc_count = 0; + async->buf_write_count = 0; + async->buf_read_alloc_count = 0; + async->buf_read_count = 0; + + async->buf_write_ptr = 0; + async->buf_read_ptr = 0; + + async->cur_chan = 0; + async->scan_progress = 0; + async->munge_chan = 0; + async->munge_count = 0; + async->munge_ptr = 0; + + async->events = 0; +} + diff --git a/comedi/drivers/8255.c b/comedi/drivers/8255.c index 963ce1e4..89d46103 100644 --- a/comedi/drivers/8255.c +++ b/comedi/drivers/8255.c @@ -150,7 +150,7 @@ static int subdev_8255_insn(comedi_device *dev,comedi_subdevice *s, if(data[0]){ s->state &= ~data[0]; s->state |= (data[0]&data[1]); - + if(data[0]&0xff) CALLBACK_FUNC(1,_8255_DATA,s->state&0xff,CALLBACK_ARG); if(data[0]&0xff00) @@ -249,7 +249,7 @@ static int subdev_8255_cmdtest(comedi_device *dev, comedi_subdevice *s, if(!cmd->stop_src || tmp!=cmd->stop_src)err++; if(err) return 1; - + /* step 2 */ if(err) return 2; @@ -323,7 +323,7 @@ int subdev_8255_init(comedi_device *dev,comedi_subdevice *s,int (*cb)(int,int,in s->state=0; s->io_bits=0; do_config(dev,s); - + return 0; } @@ -406,7 +406,7 @@ static int dev_8255_detach(comedi_device *dev) comedi_subdevice *s; printk("comedi%d: 8255: remove\n",dev->minor); - + for(i=0;in_subdevices;i++){ s=dev->subdevices+i; if(s->type!=COMEDI_SUBD_UNUSED){ diff --git a/comedi/drivers/amplc_pci224.c b/comedi/drivers/amplc_pci224.c index 77ebdea2..c815e305 100644 --- a/comedi/drivers/amplc_pci224.c +++ b/comedi/drivers/amplc_pci224.c @@ -609,7 +609,7 @@ pci224_ao_handle_fifo(comedi_device *dev, comedi_subdevice *s) bytes_per_scan = sizeof(sampl_t); } /* Determine number of scans available in buffer. */ - num_scans = comedi_buf_read_n_available(s) / bytes_per_scan; + num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan; if (!devpriv->ao_stop_continuous) { /* Fixed number of scans. */ if (num_scans > devpriv->ao_stop_count) { diff --git a/comedi/drivers/cb_pcidas64.c b/comedi/drivers/cb_pcidas64.c index 5ac162e5..9a51be38 100644 --- a/comedi/drivers/cb_pcidas64.c +++ b/comedi/drivers/cb_pcidas64.c @@ -3231,7 +3231,7 @@ static unsigned int load_ao_dma_buffer(comedi_device *dev, const comedi_cmd *cmd DEBUG_PRINT("attempting to load ao buffer %i (0x%x)\n", buffer_index, priv(dev)->ao_buffer_bus_addr[buffer_index]); - num_bytes = comedi_buf_read_n_available(dev->write_subdev); + num_bytes = comedi_buf_read_n_available(dev->write_subdev->async); if(num_bytes > DMA_BUFFER_SIZE) num_bytes = DMA_BUFFER_SIZE; if(cmd->stop_src == TRIG_COUNT && num_bytes > priv(dev)->ao_count) num_bytes = priv(dev)->ao_count; diff --git a/comedi/drivers/comedi_fc.c b/comedi/drivers/comedi_fc.c index 629c4b6c..d0f7abf2 100644 --- a/comedi/drivers/comedi_fc.c +++ b/comedi/drivers/comedi_fc.c @@ -32,7 +32,7 @@ static inline unsigned int bytes_per_scan( comedi_subdevice *subd ) { int num_samples; int bits_per_sample; - + switch( subd->type ) { case COMEDI_SUBD_DI: @@ -90,16 +90,10 @@ 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; if( num_bytes == 0 ) return 0; - bytes_available = comedi_buf_read_n_available(subd); - if( bytes_available < num_bytes ) - { - num_bytes = bytes_available; - } - + num_bytes = comedi_buf_read_alloc(async, num_bytes); comedi_buf_memcpy_from( async, 0, data, num_bytes); comedi_buf_read_free( async, num_bytes ); increment_scan_progress( subd, num_bytes ); diff --git a/comedi/drivers/dt282x.c b/comedi/drivers/dt282x.c index 4cf4db26..b681d301 100644 --- a/comedi/drivers/dt282x.c +++ b/comedi/drivers/dt282x.c @@ -457,16 +457,13 @@ static void dt282x_ao_dma_interrupt(comedi_device * dev) devpriv->current_dma_index=1-i; - size = comedi_buf_read_n_available(s); - if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize; + size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize); if( size == 0){ rt_printk("dt282x: AO underrun\n"); dt282x_ao_cancel(dev,s); s->async->events |= COMEDI_CB_OVERFLOW; return; } - comedi_buf_memcpy_from(s->async, 0, ptr, size); - comedi_buf_read_free(s->async, size); prep_ao_dma(dev,i,size); return; } @@ -1049,24 +1046,18 @@ static int dt282x_ao_inttrig(comedi_device *dev,comedi_subdevice *s, if(x!=0)return -EINVAL; - size = comedi_buf_read_n_available(s); - if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize; + size = cfc_read_array_from_buffer(s, devpriv->dma[0].buf, devpriv->dma_maxsize); if( size == 0){ rt_printk("dt282x: AO underrun\n"); return -EPIPE; } - comedi_buf_memcpy_from(s->async, 0, devpriv->dma[0].buf, size); - comedi_buf_read_free(s->async, size); prep_ao_dma(dev,0,size); - size = comedi_buf_read_n_available(s); - if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize; + size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf, devpriv->dma_maxsize); if( size == 0){ rt_printk("dt282x: AO underrun\n"); return -EPIPE; } - comedi_buf_memcpy_from(s->async, 0, devpriv->dma[1].buf, size); - comedi_buf_read_free(s->async, size); prep_ao_dma(dev,1,size); update_supcsr(DT2821_STRIG); diff --git a/comedi/drivers/mite.c b/comedi/drivers/mite.c index 57d47d68..81dd1449 100644 --- a/comedi/drivers/mite.c +++ b/comedi/drivers/mite.c @@ -222,6 +222,28 @@ void mite_list_devices(void) } +int mite_alloc_channel(struct mite_struct *mite) +{ + //FIXME spin lock so mite_free_channel can be called safely from interrupts + int i; + for(i = 0; i < mite->num_channels; ++i) + { + if(mite->channel_allocated[i] == 0) + { + mite->channel_allocated[i] = 1; + return i; + } + } + return -1; +} + +void mite_free_channel(struct mite_struct *mite, unsigned channel) +{ + //FIXME spin lock to prevent races with mite_alloc_channel + BUG_ON(channel >= mite->num_channels); + mite->channel_allocated[channel] = 0; +} + void mite_dma_arm( struct mite_struct *mite, unsigned int channel ) { int chor; @@ -230,7 +252,7 @@ void mite_dma_arm( struct mite_struct *mite, unsigned int channel ) /* arm */ chor = CHOR_START; writel(chor, mite->mite_io_addr + MITE_CHOR(channel)); - mite_dma_tcr(mite, channel); +// mite_dma_tcr(mite, channel); } @@ -392,7 +414,6 @@ u32 mite_bytes_written_to_memory_lb(struct mite_struct *mite, unsigned int chan) u32 device_byte_count; device_byte_count = mite_device_bytes_transferred(mite, chan); - rmb(); return device_byte_count - mite_bytes_in_transit(mite, chan); } @@ -402,7 +423,6 @@ u32 mite_bytes_written_to_memory_ub(struct mite_struct *mite, unsigned int chan) u32 in_transit_count; in_transit_count = mite_bytes_in_transit(mite, chan); - rmb(); return mite_device_bytes_transferred(mite, chan) - in_transit_count; } @@ -412,7 +432,6 @@ u32 mite_bytes_read_from_memory_lb(struct mite_struct *mite, unsigned int chan) u32 device_byte_count; device_byte_count = mite_device_bytes_transferred(mite, chan); - rmb(); return device_byte_count + mite_bytes_in_transit(mite, chan); } @@ -422,7 +441,6 @@ u32 mite_bytes_read_from_memory_ub(struct mite_struct *mite, unsigned int chan) u32 in_transit_count; in_transit_count = mite_bytes_in_transit(mite, chan); - rmb(); return mite_device_bytes_transferred(mite, chan) + in_transit_count; } @@ -447,6 +465,78 @@ void mite_dma_disarm(struct mite_struct *mite, unsigned int channel) writel(chor, mite->mite_io_addr + MITE_CHOR(channel)); } +int mite_sync_input_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async) +{ + int count; + unsigned int nbytes, old_alloc_count; + unsigned int bytes_per_scan = bytes_per_sample(async->subdevice) * async->cmd.chanlist_len; + + old_alloc_count = async->buf_write_alloc_count; + // write alloc as much as we can + comedi_buf_write_alloc(async, async->prealloc_bufsz); + + nbytes = mite_bytes_written_to_memory_lb(mite, mite_channel); + if((int)(mite_bytes_written_to_memory_ub(mite, mite_channel) - old_alloc_count) > 0) + { + rt_printk("mite: DMA overwrite of free area\n"); + async->events |= COMEDI_CB_OVERFLOW; + return -1; + } + + count = nbytes - async->buf_write_count; + /* it's possible count will be negative due to + * conservative value returned by mite_bytes_written_to_memory_lb */ + if( count <= 0 ) + { + return 0; + } + comedi_buf_write_free(async, count); + + async->scan_progress += count; + if(async->scan_progress >= bytes_per_scan) + { + async->scan_progress %= bytes_per_scan; + async->events |= COMEDI_CB_EOS; + } + async->events |= COMEDI_CB_BLOCK; + return 0; +} + +int mite_sync_output_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async) +{ + int count; + u32 nbytes_ub, nbytes_lb; + unsigned int old_alloc_count; + u32 stop_count = async->cmd.stop_arg * bytes_per_sample(async->subdevice); + + old_alloc_count = async->buf_read_alloc_count; + // read alloc as much as we can + comedi_buf_read_alloc(async, async->prealloc_bufsz); + nbytes_lb = mite_bytes_read_from_memory_lb(mite, mite_channel); + if(async->cmd.stop_src == TRIG_COUNT && + (int) (nbytes_lb - stop_count) > 0) + nbytes_lb = stop_count; + nbytes_ub = mite_bytes_read_from_memory_ub(mite, mite_channel); + if(async->cmd.stop_src == TRIG_COUNT && + (int) (nbytes_ub - stop_count) > 0) + nbytes_ub = stop_count; + if((int)(nbytes_ub - old_alloc_count) > 0) + { + rt_printk("mite: DMA underrun\n"); + async->events |= COMEDI_CB_OVERFLOW; + return -1; + } + count = nbytes_lb - async->buf_read_count; + if(count <= 0) + { + return 0; + } + comedi_buf_read_free(async, count); + + async->events |= COMEDI_CB_BLOCK; + return 0; +} + #ifdef DEBUG_MITE static void mite_decode(char **bit_str, unsigned int bits); @@ -593,6 +683,8 @@ void __exit cleanup_module(void) EXPORT_SYMBOL(mite_dma_tcr); EXPORT_SYMBOL(mite_dma_arm); EXPORT_SYMBOL(mite_dma_disarm); +EXPORT_SYMBOL(mite_sync_input_dma); +EXPORT_SYMBOL(mite_sync_output_dma); EXPORT_SYMBOL(mite_setup); EXPORT_SYMBOL(mite_unsetup); #if 0 @@ -602,6 +694,8 @@ EXPORT_SYMBOL(mite_setregs); #endif EXPORT_SYMBOL(mite_devices); EXPORT_SYMBOL(mite_list_devices); +EXPORT_SYMBOL(mite_alloc_channel); +EXPORT_SYMBOL(mite_free_channel); EXPORT_SYMBOL(mite_prep_dma); EXPORT_SYMBOL(mite_buf_change); EXPORT_SYMBOL(mite_bytes_written_to_memory_lb); diff --git a/comedi/drivers/mite.h b/comedi/drivers/mite.h index b024b708..50dd58c4 100644 --- a/comedi/drivers/mite.h +++ b/comedi/drivers/mite.h @@ -69,6 +69,7 @@ struct mite_struct{ void *daq_io_addr; struct mite_channel channels[MAX_MITE_DMA_CHANNELS]; + short channel_allocated[MAX_MITE_DMA_CHANNELS]; int num_channels; }; @@ -88,10 +89,14 @@ void mite_cleanup(void); int mite_setup(struct mite_struct *mite); void mite_unsetup(struct mite_struct *mite); void mite_list_devices(void); +int mite_alloc_channel(struct mite_struct *mite); +void mite_free_channel(struct mite_struct *mite, unsigned channel); int mite_dma_tcr(struct mite_struct *mite, unsigned int channel ); void mite_dma_arm(struct mite_struct *mite, unsigned int channel ); void mite_dma_disarm(struct mite_struct *mite, unsigned int channel ); +int mite_sync_input_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async); +int mite_sync_output_dma(struct mite_struct *mite, unsigned mite_channel, comedi_async *async); u32 mite_bytes_written_to_memory_lb(struct mite_struct *mite, unsigned int chan); u32 mite_bytes_written_to_memory_ub(struct mite_struct *mite, unsigned int chan); u32 mite_bytes_read_from_memory_lb(struct mite_struct *mite, unsigned int chan); diff --git a/comedi/drivers/ni_660x.c b/comedi/drivers/ni_660x.c index aa3c895b..959ac3f1 100644 --- a/comedi/drivers/ni_660x.c +++ b/comedi/drivers/ni_660x.c @@ -677,6 +677,8 @@ static int ni_660x_attach(comedi_device *dev,comedi_devconfig *it) devpriv->counters[i].read_register = ni_gpct_read_register; devpriv->counters[i].variant = ni_gpct_variant_660x; devpriv->counters[i].clock_period_ps = 0; + devpriv->counters[i].mite = devpriv->mite; + devpriv->counters[i].mite_channel = -1; }else { s->type = COMEDI_SUBD_UNUSED; diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index d69d88b5..c5e81d1e 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -462,81 +462,28 @@ static irqreturn_t ni_E_interrupt(int irq, void *d PT_REGS_ARG) #ifdef PCIDMA static void ni_sync_ai_dma(struct mite_struct *mite, comedi_device *dev) { - int count; comedi_subdevice *s = dev->subdevices + 0; - comedi_async *async = s->async; - unsigned int nbytes, old_alloc_count; - unsigned int bytes_per_scan = bytes_per_sample(s) * async->cmd.chanlist_len; - - old_alloc_count = async->buf_write_alloc_count; - // write alloc as much as we can - comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz); - - nbytes = mite_bytes_written_to_memory_lb(mite, AI_DMA_CHAN); - rmb(); - if( (int)(mite_bytes_written_to_memory_ub(mite, AI_DMA_CHAN) - old_alloc_count) > 0 ){ - rt_printk("ni_mio_common: DMA overwrite of free area\n"); + int retval = mite_sync_input_dma(mite, AI_DMA_CHAN, s->async); + if(retval < 0) + { ni_ai_reset(dev,s); - async->events |= COMEDI_CB_OVERFLOW; return; } - - count = nbytes - async->buf_write_count; - if( count <= 0 ){ - /* it's possible count will be negative due to - * conservative value returned by mite_bytes_transferred */ - return; - } - comedi_buf_write_free(async, count); - - async->scan_progress += count; - if( async->scan_progress >= bytes_per_scan ) - { - async->scan_progress %= bytes_per_scan; - async->events |= COMEDI_CB_EOS; - } - async->events |= COMEDI_CB_BLOCK; } static void mite_handle_b_linkc(struct mite_struct *mite, comedi_device *dev) { - int count; comedi_subdevice *s = dev->subdevices + 1; - comedi_async *async = s->async; - u32 nbytes_ub, nbytes_lb; - unsigned int new_write_count; - u32 stop_count = async->cmd.stop_arg * sizeof(sampl_t); writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(AO_DMA_CHAN)); - new_write_count = async->buf_write_count; - mb(); - nbytes_lb = mite_bytes_read_from_memory_lb(mite, AO_DMA_CHAN); - if(async->cmd.stop_src == TRIG_COUNT && - (int) (nbytes_lb - stop_count) > 0) - nbytes_lb = stop_count; - mb(); - nbytes_ub = mite_bytes_read_from_memory_ub(mite, AO_DMA_CHAN); - if(async->cmd.stop_src == TRIG_COUNT && - (int) (nbytes_ub - stop_count) > 0) - nbytes_ub = stop_count; - if((int)(nbytes_ub - devpriv->last_buf_write_count) > 0){ - rt_printk("ni_mio_common: DMA underrun\n"); + if(mite_sync_output_dma(mite, AO_DMA_CHAN, s->async) < 0) + { ni_ao_reset(dev,s); - async->events |= COMEDI_CB_OVERFLOW; return; } - mb(); - devpriv->last_buf_write_count = new_write_count; - - count = nbytes_lb - async->buf_read_count; - if(count < 0){ - return; - } - comedi_buf_read_free(async, count); - - async->events |= COMEDI_CB_BLOCK; } + // #define DEBUG_DMA_TIMING static int ni_ao_wait_for_dma_load( comedi_device *dev ) { @@ -926,7 +873,7 @@ static int ni_ao_fifo_half_empty(comedi_device *dev,comedi_subdevice *s) { int n; - n = comedi_buf_read_n_available(s); + n = comedi_buf_read_n_available(s->async); if(n==0){ s->async->events |= COMEDI_CB_OVERFLOW; return 0; @@ -953,7 +900,7 @@ static int ni_ao_prep_fifo(comedi_device *dev,comedi_subdevice *s) ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); /* load some data */ - n = comedi_buf_read_n_available(s); + n = comedi_buf_read_n_available(s->async); if(n==0)return 0; n /= sizeof(sampl_t); @@ -1205,13 +1152,19 @@ static void ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd) mite_dma_arm(mite, AI_DMA_CHAN); } -static void ni_ao_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd) +static void ni_ao_setup_MITE_dma(comedi_device *dev, comedi_cmd *cmd) { struct mite_struct *mite = devpriv->mite; struct mite_channel *mite_chan = &mite->channels[ AO_DMA_CHAN ]; comedi_subdevice *s = dev->subdevices + 1; - devpriv->last_buf_write_count = s->async->buf_write_count; + /* read alloc the entire buffer */ + comedi_buf_read_alloc(s->async, s->async->prealloc_bufsz); + /* Barrier is intended to insure comedi_buf_read_alloc + is done touching the async struct before we write + to the mite's registers and arm it. */ + smp_wmb(); + mite_chan->current_link = 0; mite_chan->dir = COMEDI_OUTPUT; if(boardtype.reg_type & (ni_reg_611x | ni_reg_6713)) @@ -3493,6 +3446,9 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) s->insn_read = ni_gpct_insn_read; s->insn_write = ni_gpct_insn_write; s->insn_config = ni_gpct_insn_config; + s->do_cmd = ni_gpct_cmd; + s->do_cmdtest = ni_gpct_cmdtest; + s->cancel = ni_gpct_cancel; s->private = &devpriv->counters[j]; devpriv->counters[j].dev = dev; @@ -3508,6 +3464,10 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) devpriv->counters[j].variant = ni_gpct_variant_e_series; } devpriv->counters[j].clock_period_ps = 0; +#ifdef PCIDMA + devpriv->counters[j].mite = devpriv->mite; +#endif + devpriv->counters[j].mite_channel = -1; ni_tio_init_counter(&devpriv->counters[j]); } @@ -4037,17 +3997,24 @@ static int ni_gpct_insn_write(comedi_device *dev, comedi_subdevice *s, static int ni_gpct_cmd(comedi_device *dev, comedi_subdevice *s) { - return 0; +#ifdef PCIDMA + struct ni_gpct *counter = s->private; + return ni_tio_cmd(counter, s->async); +#else + return -EIO; +#endif } static int ni_gpct_cmdtest(comedi_device *dev, comedi_subdevice *s, comedi_cmd *cmd) { - return 0; + struct ni_gpct *counter = s->private; + return ni_tio_cmdtest(counter); } static int ni_gpct_cancel(comedi_device *dev, comedi_subdevice *s) { - return 0; + struct ni_gpct *counter = s->private; + return ni_tio_cancel(counter); } /* diff --git a/comedi/drivers/ni_pcimio.c b/comedi/drivers/ni_pcimio.c index 46d9ab84..361843da 100644 --- a/comedi/drivers/ni_pcimio.c +++ b/comedi/drivers/ni_pcimio.c @@ -1043,8 +1043,6 @@ typedef struct{ struct mite_struct *mite; NI_PRIVATE_COMMON - - unsigned int last_buf_write_count; }ni_private; #define devpriv ((ni_private *)dev->private) diff --git a/comedi/drivers/ni_tio.c b/comedi/drivers/ni_tio.c index 44e2b0b0..3c9f851f 100644 --- a/comedi/drivers/ni_tio.c +++ b/comedi/drivers/ni_tio.c @@ -45,6 +45,7 @@ DAQ 6601/6602 User Manual (NI 322137B-01) */ #include "ni_tio.h" +#include "mite.h" static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, unsigned generic_clock_source); static unsigned ni_tio_generic_clock_src_select(struct ni_gpct *counter); @@ -298,6 +299,29 @@ static inline enum ni_gpct_register NITIO_Gi_Second_Gate_Reg(int counter_index) return 0; } +static inline enum ni_gpct_register NITIO_Gi_DMA_Config_Reg(int counter_index) +{ + switch(counter_index) + { + case 0: + return NITIO_G0_DMA_Config_Reg; + break; + case 1: + return NITIO_G1_DMA_Config_Reg; + break; + case 2: + return NITIO_G2_DMA_Config_Reg; + break; + case 3: + return NITIO_G3_DMA_Config_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + enum Gi_Auto_Increment_Reg_Bits { Gi_Auto_Increment_Mask = 0xff @@ -658,6 +682,13 @@ static inline unsigned Gi_Reset_Bit(unsigned counter_index) return 0x1 << (2 + (counter_index % 2)); } +enum Gi_DMA_Config_Reg_Bits +{ + Gi_DMA_Enable_Bit = 0x1, + Gi_DMA_Write_Bit = 0x2, + Gi_DMA_Int_Bit = 0x4 +}; + static const lsampl_t counter_status_mask = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING; static int __init ni_tio_init_module(void) @@ -1944,7 +1975,70 @@ int ni_tio_winsn(struct ni_gpct *counter, return 0; } +static int ni_tio_input_cmd(struct ni_gpct *counter, comedi_async *async) +{ + comedi_cmd *cmd = &async->cmd; + struct mite_channel *mite_chan = &counter->mite->channels[counter->mite_channel]; + + /* write alloc the entire buffer */ + comedi_buf_write_alloc(async, async->prealloc_bufsz); + + mite_chan->current_link = 0; + mite_chan->dir = COMEDI_INPUT; + mite_prep_dma(counter->mite, counter->mite_channel, 32, 32); + if(counter->variant == ni_gpct_variant_m_series || + counter->variant == ni_gpct_variant_660x) + { + counter->write_register(counter, Gi_DMA_Enable_Bit, NITIO_Gi_DMA_Config_Reg(counter->counter_index)); + } + /*start the MITE*/ + mite_dma_arm(counter->mite, counter->mite_channel); + return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); +} + +static int ni_tio_output_cmd(struct ni_gpct *counter, comedi_async *async) +{ + return 0; +} + +int ni_tio_cmd(struct ni_gpct *counter, comedi_async *async) +{ + comedi_cmd *cmd = &async->cmd; + + if(counter->mite == NULL || counter->mite_channel < 0) + { + rt_printk("ni_tio: commands only supported with DMA. Interrupt-driven commands not yet implemented.\n"); + return -EIO; + } + ni_tio_reset_count_and_disarm(counter); + if(cmd->flags & CMDF_WRITE) + { + return ni_tio_output_cmd(counter, async); + }else + { + return ni_tio_input_cmd(counter, async); + } +} + +int ni_tio_cmdtest(struct ni_gpct *counter) +{ + return 0; +} + +int ni_tio_cancel(struct ni_gpct *counter) +{ + if(counter->mite == NULL || counter->mite_channel < 0) return 0; + mite_dma_disarm(counter->mite, counter->mite_channel); + return 0; +} + +void ni_tio_interrupt_handler(struct ni_gpct *counter, struct mite_struct *mite, unsigned mite_channel) +{} + EXPORT_SYMBOL_GPL(ni_tio_rinsn); EXPORT_SYMBOL_GPL(ni_tio_winsn); +EXPORT_SYMBOL_GPL(ni_tio_cmd); +EXPORT_SYMBOL_GPL(ni_tio_cmdtest); +EXPORT_SYMBOL_GPL(ni_tio_cancel); EXPORT_SYMBOL_GPL(ni_tio_insn_config); EXPORT_SYMBOL_GPL(ni_tio_init_counter); diff --git a/comedi/drivers/ni_tio.h b/comedi/drivers/ni_tio.h index b2a8609e..2bb50312 100644 --- a/comedi/drivers/ni_tio.h +++ b/comedi/drivers/ni_tio.h @@ -25,6 +25,9 @@ #include +// forward declarations +struct mite_struct; + enum ni_gpct_register { NITIO_G0_Autoincrement_Reg, @@ -75,6 +78,14 @@ enum ni_gpct_register NITIO_G23_Joint_Status1_Reg, NITIO_G01_Joint_Status2_Reg, NITIO_G23_Joint_Status2_Reg, + NITIO_G0_DMA_Config_Reg, + NITIO_G1_DMA_Config_Reg, + NITIO_G2_DMA_Config_Reg, + NITIO_G3_DMA_Config_Reg, + NITIO_G0_DMA_Status_Reg, + NITIO_G1_DMA_Status_Reg, + NITIO_G2_DMA_Status_Reg, + NITIO_G3_DMA_Status_Reg, NITIO_Num_Registers, }; @@ -95,6 +106,8 @@ struct ni_gpct unsigned (*read_register)(struct ni_gpct *this, enum ni_gpct_register reg); enum ni_gpct_variant variant; uint64_t clock_period_ps; /* clock period in picoseconds */ + struct mite_struct *mite; + int mite_channel; /* -1 when no channel is allocated to the counter */ unsigned regs[MAX_NUM_NITIO_REGS]; }; @@ -108,6 +121,9 @@ extern int ni_tio_insn_config(struct ni_gpct *counter, extern int ni_tio_winsn(struct ni_gpct *counter, comedi_insn *insn, lsampl_t * data); +extern int ni_tio_cmd(struct ni_gpct *counter, comedi_async *async); +extern int ni_tio_cmdtest(struct ni_gpct *counter); +extern int ni_tio_cancel(struct ni_gpct *counter); #endif /* _COMEDI_NI_TIO_H */ diff --git a/comedi/kcomedilib/get.c b/comedi/kcomedilib/get.c index b08979f3..d8f1beec 100644 --- a/comedi/kcomedilib/get.c +++ b/comedi/kcomedilib/get.c @@ -191,8 +191,7 @@ int comedi_get_buffer_contents( comedi_t *d, unsigned int subdevice ) if( subdevice >= dev->n_subdevices ) return -1; async = s->async; if(async == NULL) return 0; - num_bytes = comedi_buf_read_n_available(s); - comedi_buf_munge( dev, s, async->buf_write_count - async->munge_count ); + num_bytes = comedi_buf_read_n_available(s->async); return num_bytes; } @@ -211,7 +210,8 @@ int comedi_set_user_int_count(comedi_t *d,unsigned int subdevice,unsigned int bu num_bytes = buf_user_count - async->buf_read_count; if( num_bytes < 0 ) return -1; - comedi_buf_read_free( async, num_bytes ); + comedi_buf_read_alloc(async, num_bytes); + comedi_buf_read_free(async, num_bytes); return 0; } @@ -227,7 +227,8 @@ int comedi_mark_buffer_read( comedi_t *d, unsigned int subdevice, async = s->async; if( async == NULL ) return -1; - comedi_buf_read_free( async, num_bytes ); + comedi_buf_read_alloc(async, num_bytes); + comedi_buf_read_free(async, num_bytes); return 0; } @@ -244,7 +245,6 @@ int comedi_mark_buffer_written( comedi_t *d, unsigned int subdevice, async = s->async; if( async == NULL ) return -1; bytes_written = comedi_buf_write_alloc(async, num_bytes); - comedi_buf_munge(dev, s, async->buf_write_alloc_count - async->munge_count); comedi_buf_write_free(async, bytes_written); if(bytes_written != num_bytes) return -1; return 0; diff --git a/comedi/kcomedilib/kcomedilib_main.c b/comedi/kcomedilib/kcomedilib_main.c index 78cab126..195ebe7f 100644 --- a/comedi/kcomedilib/kcomedilib_main.c +++ b/comedi/kcomedilib/kcomedilib_main.c @@ -118,21 +118,6 @@ int comedi_fileno(comedi_t *d) return dev->minor; } -static void init_async_buf( comedi_async *async ) -{ - async->buf_read_count = 0; - async->buf_write_count = 0; - async->buf_write_alloc_count = 0; - async->buf_read_ptr = 0; - async->buf_write_ptr = 0; - async->cur_chan = 0; - async->scan_progress = 0; - async->munge_chan = 0; - async->munge_count = 0; - async->munge_ptr = 0; - async->events = 0; -} - int comedi_command(comedi_t *d,comedi_cmd *cmd) { comedi_device *dev = (comedi_device *)d; @@ -164,7 +149,7 @@ int comedi_command(comedi_t *d,comedi_cmd *cmd) s->subdev_flags |= SDF_RUNNING; - init_async_buf( async ); + comedi_reset_async_buf( async ); return s->do_cmd(dev,s); } diff --git a/include/linux/comedidev.h b/include/linux/comedidev.h index 38cfd26c..6e33a42d 100644 --- a/include/linux/comedidev.h +++ b/include/linux/comedidev.h @@ -149,15 +149,18 @@ struct comedi_subdevice_struct{ }; struct comedi_async_struct{ + comedi_subdevice *subdevice; + void *prealloc_buf; /* pre-allocated buffer */ unsigned int prealloc_bufsz; /* buffer size, in bytes */ unsigned long *buf_page_list; /* physical address of each page */ unsigned int max_bufsize; /* maximum buffer size, bytes */ unsigned int mmap_count; /* current number of mmaps of prealloc_buf */ - volatile unsigned int buf_write_count; /* byte count for writer (write completed) */ - volatile unsigned int buf_write_alloc_count; /* byte count for writer (allocated for writing) */ - volatile unsigned int buf_read_count; /* byte count for reader (read completed)*/ + unsigned int buf_write_count; /* byte count for writer (write completed) */ + unsigned int buf_write_alloc_count; /* byte count for writer (allocated for writing) */ + unsigned int buf_read_count; /* byte count for reader (read completed)*/ + unsigned int buf_read_alloc_count; /* byte count for reader (allocated for reading)*/ unsigned int buf_write_ptr; /* buffer marker for writer */ unsigned int buf_read_ptr; /* buffer marker for reader */ @@ -372,13 +375,13 @@ struct comedi_lrange_struct{ static inline int alloc_subdevices(comedi_device *dev, unsigned int num_subdevices) { const int size = sizeof(comedi_subdevice) * num_subdevices; + unsigned i; dev->n_subdevices = num_subdevices; dev->subdevices = kmalloc(size,GFP_KERNEL); if(!dev->subdevices) return -ENOMEM; memset(dev->subdevices,0,size); - unsigned i; for(i = 0; i < num_subdevices; ++i) { dev->subdevices[i].device = dev; @@ -406,18 +409,19 @@ static inline unsigned int bytes_per_sample( const comedi_subdevice *subd ) int comedi_buf_put(comedi_async *async, sampl_t x); int comedi_buf_get(comedi_async *async, sampl_t *x); -unsigned int comedi_buf_write_n_available(comedi_subdevice *s); +unsigned int comedi_buf_write_n_available(comedi_async *async); unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes); unsigned int comedi_buf_write_alloc_strict(comedi_async *async, unsigned int nbytes); -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_subdevice *s); +unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes); +unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes); +unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes); +unsigned int comedi_buf_read_n_available(comedi_async *async); 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 ); -unsigned int comedi_buf_munge( comedi_device *dev, comedi_subdevice *s, - unsigned int num_bytes ); + +void comedi_reset_async_buf(comedi_async *async); static inline void* comedi_aux_data(int options[], int n) { @@ -441,6 +445,7 @@ static inline void* comedi_aux_data(int options[], int n) address += options[COMEDI_DEVCONF_AUX_DATA1_LENGTH]; if(n >= 3) address += options[COMEDI_DEVCONF_AUX_DATA2_LENGTH]; + BUG_ON(n > 3); return (void*) address; } //#ifdef CONFIG_COMEDI_RT -- 2.26.2