Move buffer inlines to comedi/drivers.c. Rewrite as consistent
authorDavid Schleef <ds@schleef.org>
Tue, 9 Jul 2002 00:31:41 +0000 (00:31 +0000)
committerDavid Schleef <ds@schleef.org>
Tue, 9 Jul 2002 00:31:41 +0000 (00:31 +0000)
primitives.  Change buf_dirty_count to buf_free_count.

comedi/comedi_fops.c
comedi/comedi_ksyms.c
comedi/drivers.c
comedi/drivers/adl_pci9118.c
comedi/drivers/ni_mio_common.c
comedi/kcomedilib/kcomedilib_main.c
include/linux/comedidev.h

index d53a7ff8411482d704e7294d977a32ec5deb9328..d11226c61461323ffaa6626515d6bd537919a486 100644 (file)
@@ -1312,7 +1312,6 @@ static ssize_t comedi_write_v22(struct file *file,const char *buf,size_t nbytes,
        comedi_async *async;
        int n,m,count=0,retval=0;
        DECLARE_WAITQUEUE(wait,current);
-       int sample_size;
 
        dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
 
@@ -1326,14 +1325,6 @@ static ssize_t comedi_write_v22(struct file *file,const char *buf,size_t nbytes,
        s = dev->write_subdev;
        async = s->async;
 
-       if(s->subdev_flags&SDF_LSAMPL){
-               sample_size=sizeof(lsampl_t);
-       }else{
-               sample_size=sizeof(sampl_t);
-       }
-       if(nbytes%sample_size)
-               nbytes-=nbytes%sample_size;
-
        if(!nbytes)return 0;
 
        if(!s->busy)
@@ -1348,9 +1339,11 @@ static ssize_t comedi_write_v22(struct file *file,const char *buf,size_t nbytes,
 
                n=nbytes;
 
-               m = async->data_len + async->buf_read_count - async->buf_write_count;
-               if( async->buf_write_ptr + m > async->data_len )
+               m = n;
+               if(async->buf_write_ptr + m > async->data_len){
                        m = async->data_len - async->buf_write_ptr;
+               }
+               m = comedi_buf_write_alloc(async, m);
 
                if(m < n) n = m;
 
@@ -1375,13 +1368,13 @@ static ssize_t comedi_write_v22(struct file *file,const char *buf,size_t nbytes,
                        schedule();
                        continue;
                }
-               m = 0;
-               if( write_to_async_buffer( async, buf, n, 1 ) )
-               {
-                       m = n;
+
+               m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
+                       buf, n);
+               if(m){
+                       n -= m;
                        retval = -EFAULT;
                }
-               n-=m;
 
                count+=n;
                nbytes-=n;
@@ -1403,7 +1396,6 @@ static ssize_t comedi_read_v22(struct file * file,char *buf,size_t nbytes,loff_t
        comedi_async *async;
        int n,m,count=0,retval=0;
        DECLARE_WAITQUEUE(wait,current);
-       int sample_size;
 
        dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
 
@@ -1417,14 +1409,6 @@ static ssize_t comedi_read_v22(struct file * file,char *buf,size_t nbytes,loff_t
        if(s == NULL)return -EIO;
        async = s->async;
 
-       if(s->subdev_flags&SDF_LSAMPL){
-               sample_size=sizeof(lsampl_t);
-       }else{
-               sample_size=sizeof(sampl_t);
-       }
-       if(nbytes%sample_size)
-               nbytes-=nbytes%sample_size;
-
        if(!nbytes)return 0;
 
        if(!s->busy)
@@ -1439,13 +1423,12 @@ static ssize_t comedi_read_v22(struct file * file,char *buf,size_t nbytes,loff_t
 
                n=nbytes;
 
-               m = async->buf_write_count - async->buf_read_count;
-               if( m > async->data_len )
-                       m = async->data_len;
-
-#if 0
-printk("m is %d\n",m);
-#endif
+               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;
+               }
+//printk("%d contiguous\n",m);
                if(m<n)n=m;
 
                if(n==0){
@@ -1469,22 +1452,16 @@ printk("m is %d\n",m);
                        schedule();
                        continue;
                }
-               m=0;
-               retval = read_from_async_buffer( async, buf, n, 1 );
-               if( retval )
-               {
-                       m = n;
-               }
-               n-=m;
 
-               /* check for buffer overflow */
-               if( retval == -EIO )
-               {
-                       do_cancel(dev, dev->read_subdev);
-                       DPRINTK("buffer overflow\n");
-                       break;
+               m = copy_to_user(buf, async->prealloc_buf +
+                       async->buf_read_ptr, n);
+               if(m){
+                       n -= m;
+                       retval = -EFAULT;
                }
 
+               comedi_buf_read_free(async, n);
+
                count+=n;
                nbytes-=n;
 
@@ -1803,6 +1780,8 @@ void comedi_event(comedi_device *dev,comedi_subdevice *s, unsigned int mask)
        mask = s->async->events;
        s->async->events = 0;
 
+       mask |= COMEDI_CB_BLOCK;
+
        //DPRINTK("comedi_event %x\n",mask);
 
        if( (s->subdev_flags & SDF_RUNNING) == 0)
@@ -1853,10 +1832,11 @@ void comedi_event(comedi_device *dev,comedi_subdevice *s, unsigned int mask)
 
 static void init_async_buf( comedi_async *async )
 {
-       async->buf_read_count = 0;
+       async->buf_free_count = 0;
        async->buf_write_count = 0;
-       async->buf_dirty_count = 0;
-       async->buf_read_ptr = 0;
+       async->buf_read_count = 0;
+
        async->buf_write_ptr = 0;
+       async->buf_read_ptr = 0;
 }
 
index 46681172922760d762bb7ea53d985ccd4e307416..08e7438f93023c1283087447f9509a019bbe4f66 100644 (file)
@@ -64,6 +64,10 @@ EXPORT_SYMBOL(comedi_devices);
 EXPORT_SYMBOL(big_comedi_lock);
 EXPORT_SYMBOL(check_chanlist);
 
+EXPORT_SYMBOL(comedi_buf_put);
+EXPORT_SYMBOL(comedi_buf_get);
+EXPORT_SYMBOL(comedi_buf_read_n_available);
+
 #endif
 
 
index 0a752541ae7f87357bf9250db934b0458ec84255..1385477576ca0c4d1ce5bfacebd8b419d4ef9ebc 100644 (file)
@@ -391,3 +391,247 @@ static int buf_alloc(comedi_device *dev, comedi_subdevice *s,
        return 0;
 }
 
+
+
+#if 0
+int write_to_async_buffer( comedi_async *async, const void *array,
+       unsigned int num_bytes, unsigned int from_user_space )
+{
+       async->buf_dirty_count += num_bytes;
+       while( num_bytes )
+       {
+               unsigned int block_size;
+
+               block_size = num_bytes;
+               if( async->buf_write_ptr + block_size > async->data_len)
+                       block_size = async->data_len - async->buf_write_ptr;
+
+               if( from_user_space )
+               {
+                       if( copy_from_user( async->data + async->buf_write_ptr, array, block_size ) )
+                               return -EFAULT;
+               }else
+                       memcpy( async->data + async->buf_write_ptr, array, block_size );
+
+               array += block_size;
+               num_bytes -= block_size;
+               async->buf_write_count += block_size;
+               async->buf_write_ptr += block_size;
+               if( async->buf_write_ptr == async->data_len )
+               {
+                       async->buf_write_ptr = 0;
+               }
+       }
+
+       return 0;
+}
+
+int read_from_async_buffer( comedi_async *async, void *destination,
+       unsigned int num_bytes, unsigned int from_user_space )
+{
+       unsigned int bytes_available = async->buf_write_count - async->buf_read_count;
+       unsigned int remaining = bytes_available;
+
+       if( bytes_available == 0 ) return -EAGAIN;
+
+       while( remaining )
+       {
+               unsigned int block_size;
+
+               block_size = remaining;
+               if( async->buf_read_ptr + block_size > async->data_len )
+                       block_size = async->data_len - async->buf_read_ptr;
+
+               if( from_user_space )
+               {
+                       if( copy_to_user( destination, async->data + async->buf_read_ptr, block_size ) )
+                               return -EFAULT;
+               }else
+                       memcpy( destination, async->data + async->buf_read_ptr, block_size );
+
+               destination += block_size;
+               remaining -= block_size;
+               async->buf_read_ptr += block_size;
+               if( async->buf_read_ptr == async->data_len )
+               {
+                       async->buf_read_ptr = 0;
+               }
+       }
+       // check if buffer has overrun
+       if( async->buf_dirty_count - async->buf_read_count > async->data_len )
+               return -EIO;
+       async->buf_read_count += bytes_available;
+
+       return bytes_available - remaining;
+}
+
+/* Writes an array of data points to comedi's buffer, used for input.
+ * Can be more efficient than putting comedi_buf_put() in a loop. */
+void __comedi_buf_put_array(comedi_async *async, void* array,
+       unsigned int num_bytes, unsigned int bytes_per_sample )
+{
+       if( async->buf_write_ptr + num_bytes  >= async->data_len )
+       {
+               async->events |= COMEDI_CB_EOBUF;
+       }
+
+       write_to_async_buffer( async, array, num_bytes, 0 );
+
+       async->cur_chan += num_bytes / bytes_per_sample;
+       if( async->cur_chan >= async->cmd.chanlist_len )
+       {
+               async->cur_chan %= async->cmd.chanlist_len;
+               async->events |= COMEDI_CB_EOS;
+       }
+       async->events |= COMEDI_CB_BLOCK;
+}
+
+void comedi_buf_put_array(comedi_async *async, sampl_t *array,
+       unsigned int num_samples )
+{
+       __comedi_buf_put_array( async, array, num_samples * sizeof( sampl_t ), sizeof( sampl_t ) );
+}
+
+void comedi_buf_put_long_array(comedi_async *async, lsampl_t *array,
+       unsigned int num_samples )
+{
+       __comedi_buf_put_array( async, array, num_samples * sizeof( lsampl_t ), sizeof( lsampl_t ) );
+}
+
+/* writes a data point to comedi's buffer, used for input */
+void comedi_buf_put(comedi_async *async, sampl_t x)
+{
+       comedi_buf_put_array( async, &x, 1 );
+}
+
+/* writes a long data point to comedi's buffer, used for input */
+void comedi_buf_put_long(comedi_async *async, lsampl_t x)
+{
+       comedi_buf_put_long_array( async, &x, 1 );
+}
+
+/* Reads a data point from comedi's buffer, used for output.
+ * returns negative value on error. */
+int comedi_buf_get_array(comedi_async *async, sampl_t *array, unsigned int num_samples)
+{
+       unsigned int num_bytes = num_samples * sizeof( sampl_t );
+       int retval;
+       unsigned int read_ptr = async->buf_read_ptr;
+
+       retval = read_from_async_buffer( async, array, num_bytes, 0 );
+
+       if( retval < 0 )
+       {
+               async->events |= COMEDI_CB_ERROR;
+               return retval;
+       }
+
+       num_bytes = retval;
+       num_samples = retval / sizeof( sampl_t );
+
+       if( read_ptr + num_bytes >= async->data_len)
+       {
+               async->events |= COMEDI_CB_EOBUF;
+       }
+
+       async->cur_chan += num_samples;
+       if( async->cur_chan >= async->cmd.chanlist_len)
+       {
+               async->cur_chan %= async->cmd.chanlist_len;
+               async->events |= COMEDI_CB_EOS;
+       }
+
+       async->events |= COMEDI_CB_BLOCK;
+
+       return retval / sizeof( sampl_t );
+}
+
+/* Reads a data point from comedi's buffer, used for output.
+ * returns negative value on error. */
+int comedi_buf_get(comedi_async *async, sampl_t *x)
+{
+       return comedi_buf_get_array(async, x, 1);
+}
+#endif
+
+
+/* begin ds */
+
+unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes)
+{
+       unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+
+       if((int)(async->buf_free_count + nbytes - free_end) > 0){
+               nbytes = free_end - async->buf_free_count;
+       }
+
+       async->buf_free_count += nbytes;
+
+       return nbytes;
+}
+
+unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
+       unsigned int nbytes)
+{
+       unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+
+       if((int)(async->buf_free_count + nbytes - free_end) > 0){
+               nbytes = 0;
+       }
+
+       async->buf_free_count += nbytes;
+
+       return nbytes;
+}
+
+/* transfers control of a chunk from writer to reader */
+void comedi_buf_write_free(comedi_async *async, unsigned int nbytes)
+{
+       async->buf_write_count += nbytes;
+       async->buf_write_ptr += nbytes;
+       if(async->buf_write_ptr >= async->prealloc_bufsz){
+               async->buf_write_ptr -= async->prealloc_bufsz;
+               async->events |= COMEDI_CB_EOBUF;
+       }
+}
+
+/* transfers control of a chunk from  reader to free area */
+void comedi_buf_read_free(comedi_async *async, unsigned int nbytes)
+{
+       async->buf_read_count += nbytes;
+       async->buf_read_ptr += nbytes;
+       if(async->buf_read_ptr >= async->prealloc_bufsz){
+               async->buf_read_ptr -= async->prealloc_bufsz;
+       }
+}
+
+unsigned int comedi_buf_read_n_available(comedi_async *async)
+{
+       unsigned int read_end = async->buf_write_count;
+
+       return read_end - async->buf_read_count;
+}
+
+int comedi_buf_get(comedi_async *async, sampl_t *x)
+{
+       unsigned int n = comedi_buf_read_n_available(async);
+
+       if(n<sizeof(sampl_t))return 0;
+       *x = *(sampl_t *)(async->prealloc_buf + async->buf_read_ptr);
+       comedi_buf_read_free(async, sizeof(sampl_t));
+       return 1;
+}
+
+int comedi_buf_put(comedi_async *async, sampl_t x)
+{
+       unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t));
+
+       if(n<sizeof(sampl_t)){
+               async->events |= COMEDI_CB_ERROR;
+               return 0;
+       }
+       *(sampl_t *)(async->prealloc_buf + async->buf_write_ptr) = x;
+       comedi_buf_write_free(async, sizeof(sampl_t));
+       return 1;
+}
+
index 5fbfcfc7455b41a956b7f18a91a5e5d5903c5d1d..8c53d37964f161a3b1c70a56d4fa2edcde36f1b5 100644 (file)
@@ -681,7 +681,7 @@ static int move_block_from_dma_12bit_32b(comedi_device *dev, comedi_subdevice *s
                        }
 #endif
                        sampl=((sampl & 0xfff0)<<12)|((sampl & 0xfff00000)>>20);
-                       comedi_buf_put_long( s->async, sampl );
+                       comedi_buf_put( s->async, sampl );
                }
                sp+=cc<<1;
                if (cc>=chans) {
@@ -731,7 +731,8 @@ static int move_block_from_dma_16bit_32b(comedi_device *dev, comedi_subdevice *s
                for (;cc<chns;cc++) {
                        sampl=**dma; (*dma)++;
                        sampl=(((sampl & 0xffff)<<16)|((sampl & 0xffff0000)>>16))^0x80008000;
-                       comedi_buf_put_long( s->async, sampl );
+                       /* XXX broken */
+                       comedi_buf_put( s->async, sampl );
                }
                sp+=cc<<1;
                if (cc>=chans) {
index 312f73569c7104ae7c656db82c123c194c141dd2..7ba3b4309dd69d0efe10dc6bc39313c8ad6a702e 100644 (file)
@@ -346,7 +346,7 @@ static void ni_E_interrupt(int irq,void *d,struct pt_regs * regs)
 #ifdef PCIDMA
 static void mite_handle_a_linkc(struct mite_struct *mite, comedi_device *dev)
 {
-       unsigned int count;
+       int count;
        comedi_subdevice *s = dev->subdevices + 0;
        comedi_async *async = s->async;
 
@@ -357,8 +357,6 @@ static void mite_handle_a_linkc(struct mite_struct *mite, comedi_device *dev)
                printk("BUG: too many samples in interrupt (%d)\n",count);
                return;
        }
-       // XXX buf_dirty_count should really be incremented earlier...
-       async->buf_dirty_count += count;
        async->buf_write_count += count;
 
        if(async->cmd.flags & CMDF_RAWDATA){
@@ -665,7 +663,7 @@ static void ni_ai_fifo_read(comedi_device *dev,comedi_subdevice *s,
        for(i=0;i<n;i++){
                d=ni_readw(ADC_FIFO_Data_Register);
                d+=devpriv->ai_xorlist[ async->cur_chan ];
-               comedi_buf_put( async, d );
+               comedi_buf_put(async, d);
        }
 }
 
@@ -708,16 +706,16 @@ static void ni_handle_fifo_dregs(comedi_device *dev)
 
                        /* This may get the hi/lo data in the wrong order */
                        data = (dl>>16) + devpriv->ai_xorlist[async->cur_chan];
-                       comedi_buf_put( s->async, data );
+                       comedi_buf_put(s->async, data);
                        data = (dl&0xffff) + devpriv->ai_xorlist[async->cur_chan];
-                       comedi_buf_put( s->async, data );
+                       comedi_buf_put(s->async, data);
                }
 
                /* Check if there's a single sample stuck in the FIFO */
                if(ni_readb(Status_611x)&0x80){
                        dl=ni_readl(ADC_FIFO_Data_611x);
                        data = (dl&0xffff) + devpriv->ai_xorlist[async->cur_chan];
-                       comedi_buf_put( s->async, data );
+                       comedi_buf_put(s->async, data);
                }
        }else{
                while(1){
@@ -728,7 +726,7 @@ static void ni_handle_fifo_dregs(comedi_device *dev)
                                }
                                data=ni_readw(ADC_FIFO_Data_Register);
                                data+=devpriv->ai_xorlist[async->cur_chan];
-                               comedi_buf_put( s->async, data );
+                               comedi_buf_put(s->async, data);
                        }
                }
        }
index 45d79ba8b533858942934a03a8d9cd8615776877..d7627558bdceeff50b607974369f0f577a348d1f 100644 (file)
@@ -121,7 +121,7 @@ static void init_async_buf( comedi_async *async )
 {
        async->buf_read_count = 0;
        async->buf_write_count = 0;
-       async->buf_dirty_count = 0;
+       async->buf_free_count = 0;
        async->buf_read_ptr = 0;
        async->buf_write_ptr = 0;
 }
index 2e1311a1ee8c0625f3dc591a474bfd74eaea7939..1de7834cf54ccd402c6295ee040600ea08fbf117 100644 (file)
@@ -131,27 +131,13 @@ struct comedi_async_struct{
        unsigned int    max_bufsize;            /* maximum buffer size, bytes */
        unsigned int    mmap_count;     /* current number of mmaps of prealloc_buf */
 
-       /* To avoid races and provide reliable overrun detection, read / writes
-        * to buffer should make use of the read_from_async_buffer() and
-        * write_to_async_buffer() functions and proceed
-        * as follows:
-        *
-        * Writing:
-        *   1) if appropriate, check space in buffer, using read/write count members
-        *   2) call write_to_async_buffer()
-        * Reading:
-        *   1) if appropriate, check how much data is in buffer, using read/write
-        *      count members
-        *   2) call read_from_async_buffer()
-        *   3) if appropriate, check return value for buffer overrun
-        *
-        * Note: there should be exactly one reader and one writer
-        */
-       unsigned int buf_write_ptr;     /* buffer marker for writer */
-       unsigned int buf_read_ptr;              /* buffer marker for reader */
+       volatile unsigned int buf_free_count;   /* byte count for free space */
        volatile unsigned int buf_write_count;  /* byte count for writer (write completed) */
-       volatile unsigned int buf_dirty_count;  /* byte count for writer (write in progress) */
-       volatile unsigned int buf_read_count;           /* byte count for reader */
+       volatile unsigned int buf_read_count;   /* byte count for reader */
+
+       unsigned int buf_write_ptr;     /* buffer marker for writer */
+       unsigned int buf_read_ptr;      /* buffer marker for reader */
+
        unsigned int cur_chan;          /* useless channel marker for interrupt */
 
        void            *data;
@@ -177,10 +163,10 @@ struct comedi_driver_struct{
        int (*attach)(comedi_device *,comedi_devconfig *);
        int (*detach)(comedi_device *);
 
-       // number of elements in board_name and board_id arrays
+       /* number of elements in board_name and board_id arrays */
        unsigned int num_names;
        void *board_name;
-       // offset in bytes from one board name pointer to the next
+       /* offset in bytes from one board name pointer to the next */
        int offset;
 };
 
@@ -190,7 +176,6 @@ struct comedi_device_struct{
        void *private;
        kdev_t minor;
        char *board_name;
-       //int board;
        const void * board_ptr;
        int attached;
        int rt;
@@ -264,10 +249,10 @@ static inline void comedi_proc_init(void) {}
 static inline void comedi_proc_cleanup(void) {}
 #endif
 
-// subdevice runflags
+/* subdevice runflags */
 #define SRF_USER               0x00000001
 #define SRF_RT                 0x00000002
-// indicates an COMEDI_CB_ERROR event has occurred since the last command was started
+/* indicates an COMEDI_CB_ERROR event has occurred since the last command was started */
 #define SRF_ERROR              0x00000004
 
 /*
@@ -325,180 +310,30 @@ static inline int alloc_private(comedi_device *dev,int size)
        return 0;
 }
 
-/* To avoid races and provide reliable overrun detection, read / writes
-* to buffer should proceed generally as follows:
-* Writing:
-*   1) if appropriate, check space in buffer, using read/write count members
-*   2) increment dirty count
-*   3) write data to buffer
-*   4) increment write count
-*   5) keep track of where to write with write ptr
-* Reading:
-*   1) read data from buffer, using read/write count members to determine how much
-*   3) if appropriate, check for overrun using read/dirty count members
-*   4) increment read count
-*   2) keep track of where to read with read ptr
-*
-* Note: there should be exactly one reader and one writer
-*/
-static inline int write_to_async_buffer( comedi_async *async, const void *array,
-       unsigned int num_bytes, unsigned int from_user_space )
-{
-       async->buf_dirty_count += num_bytes;
-       while( num_bytes )
-       {
-               unsigned int block_size;
-
-               block_size = num_bytes;
-               if( async->buf_write_ptr + block_size > async->data_len)
-                       block_size = async->data_len - async->buf_write_ptr;
-
-               if( from_user_space )
-               {
-                       if( copy_from_user( async->data + async->buf_write_ptr, array, block_size ) )
-                               return -EFAULT;
-               }else
-                       memcpy( async->data + async->buf_write_ptr, array, block_size );
-
-               array += block_size;
-               num_bytes -= block_size;
-               async->buf_write_count += block_size;
-               async->buf_write_ptr += block_size;
-               if( async->buf_write_ptr == async->data_len )
-               {
-                       async->buf_write_ptr = 0;
-               }
-       }
-
-       return 0;
-}
-
-static inline int read_from_async_buffer( comedi_async *async, void *destination,
-       unsigned int num_bytes, unsigned int from_user_space )
-{
-       unsigned int bytes_available = async->buf_write_count - async->buf_read_count;
-       unsigned int remaining = bytes_available;
-
-       if( bytes_available == 0 ) return -EAGAIN;
-
-       while( remaining )
-       {
-               unsigned int block_size;
-
-               block_size = remaining;
-               if( async->buf_read_ptr + block_size > async->data_len )
-                       block_size = async->data_len - async->buf_read_ptr;
-
-               if( from_user_space )
-               {
-                       if( copy_to_user( destination, async->data + async->buf_read_ptr, block_size ) )
-                               return -EFAULT;
-               }else
-                       memcpy( destination, async->data + async->buf_read_ptr, block_size );
-
-               destination += block_size;
-               remaining -= block_size;
-               async->buf_read_ptr += block_size;
-               if( async->buf_read_ptr == async->data_len )
-               {
-                       async->buf_read_ptr = 0;
-               }
-       }
-       // check if buffer has overrun
-       if( async->buf_dirty_count - async->buf_read_count > async->data_len )
-               return -EIO;
-       async->buf_read_count += bytes_available;
-
-       return bytes_available - remaining;
-}
-
-/* Writes an array of data points to comedi's buffer, used for input.
- * Can be more efficient than putting comedi_buf_put() in a loop. */
-static inline void __comedi_buf_put_array(comedi_async *async, void* array,
-       unsigned int num_bytes, unsigned int bytes_per_sample )
-{
-       if( async->buf_write_ptr + num_bytes  >= async->data_len )
-       {
-               async->events |= COMEDI_CB_EOBUF;
-       }
-
-       write_to_async_buffer( async, array, num_bytes, 0 );
-
-       async->cur_chan += num_bytes / bytes_per_sample;
-       if( async->cur_chan >= async->cmd.chanlist_len )
-       {
-               async->cur_chan %= async->cmd.chanlist_len;
-               async->events |= COMEDI_CB_EOS;
-       }
-       async->events |= COMEDI_CB_BLOCK;
-}
-
-static inline void comedi_buf_put_array(comedi_async *async, sampl_t *array,
-       unsigned int num_samples )
-{
-       __comedi_buf_put_array( async, array, num_samples * sizeof( sampl_t ), sizeof( sampl_t ) );
-}
-
-static inline void comedi_buf_put_long_array(comedi_async *async, lsampl_t *array,
-       unsigned int num_samples )
-{
-       __comedi_buf_put_array( async, array, num_samples * sizeof( lsampl_t ), sizeof( lsampl_t ) );
-}
-
-// writes a data point to comedi's buffer, used for input
-static inline void comedi_buf_put(comedi_async *async, sampl_t x)
-{
-       comedi_buf_put_array( async, &x, 1 );
-}
-
-// writes a long data point to comedi's buffer, used for input
-static inline void comedi_buf_put_long(comedi_async *async, lsampl_t x)
-{
-       comedi_buf_put_long_array( async, &x, 1 );
-}
-
-/* Reads a data point from comedi's buffer, used for output.
- * returns negative value on error. */
-static inline int comedi_buf_get_array(comedi_async *async, sampl_t *array, unsigned int num_samples)
-{
-       unsigned int num_bytes = num_samples * sizeof( sampl_t );
-       int retval;
-       unsigned int read_ptr = async->buf_read_ptr;
-
-       retval = read_from_async_buffer( async, array, num_bytes, 0 );
-
-       if( retval < 0 )
-       {
-               async->events |= COMEDI_CB_ERROR;
-               return retval;
-       }
-
-       num_bytes = retval;
-       num_samples = retval / sizeof( sampl_t );
-
-       if( read_ptr + num_bytes >= async->data_len)
-       {
-               async->events |= COMEDI_CB_EOBUF;
-       }
-
-       async->cur_chan += num_samples;
-       if( async->cur_chan >= async->cmd.chanlist_len)
-       {
-               async->cur_chan %= async->cmd.chanlist_len;
-               async->events |= COMEDI_CB_EOS;
-       }
-
-       async->events |= COMEDI_CB_BLOCK;
-
-       return retval / sizeof( sampl_t );
-}
+#if 0
+int write_to_async_buffer( comedi_async *async, const void *array,
+       unsigned int num_bytes, unsigned int from_user_space );
+int read_from_async_buffer( comedi_async *async, void *destination,
+       unsigned int num_bytes, unsigned int from_user_space );
+void __comedi_buf_put_array(comedi_async *async, void* array,
+       unsigned int num_bytes, unsigned int bytes_per_sample );
+void comedi_buf_put_array(comedi_async *async, sampl_t *array,
+       unsigned int num_samples );
+void comedi_buf_put_long_array(comedi_async *async, lsampl_t *array,
+       unsigned int num_samples );
+#endif
+int comedi_buf_put(comedi_async *async, sampl_t x);
+#if 0
+void comedi_buf_put_long(comedi_async *async, lsampl_t x);
+int comedi_buf_get_array(comedi_async *async, sampl_t *array, unsigned int num_samples);
+#endif
+int comedi_buf_get(comedi_async *async, sampl_t *x);
 
-/* Reads a data point from comedi's buffer, used for output.
- * returns negative value on error. */
-static inline int comedi_buf_get(comedi_async *async, sampl_t *x)
-{
-       return comedi_buf_get_array( async, x, 1);
-}
+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_async *async);
 
 
 //#ifdef CONFIG_COMEDI_RT