First pass at revised buffer system, hopefully didn't create too many new
authorFrank Mori Hess <fmhess@speakeasy.net>
Fri, 5 Jul 2002 23:01:50 +0000 (23:01 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Fri, 5 Jul 2002 23:01:50 +0000 (23:01 +0000)
bugs.  Tested analog input command with comedi_test module, haven't tried
analog output.

15 files changed:
comedi/comedi_fops.c
comedi/drivers/adl_pci9118.c
comedi/drivers/comedi_parport.c
comedi/drivers/das16m1.c
comedi/drivers/das1800.c
comedi/drivers/das6402.c
comedi/drivers/dt282x.c
comedi/drivers/ni_mio_common.c
comedi/drivers/ni_pcidio.c
comedi/drivers/pcl812.c
comedi/drivers/pcl816.c
comedi/drivers/rtd520.c
comedi/kcomedilib/get.c
comedi/kcomedilib/kcomedilib_main.c
include/linux/comedidev.h

index f9fa648ac0b9bd91a94762133dc5259e7ca1e895..d53a7ff8411482d704e7294d977a32ec5deb9328 100644 (file)
@@ -75,6 +75,7 @@ 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)
@@ -457,32 +458,34 @@ static int do_bufinfo_ioctl(comedi_device *dev,void *arg)
        if(bi.bytes_read){
 
                // check for buffer underflow
-               m = async->buf_int_count - async->buf_user_count;
+               m = async->buf_write_count - async->buf_read_count;
                if(bi.bytes_read > m)
                {
                        DPRINTK("buffer underflow\n");
                        return -EIO;
                }
 
-               async->buf_user_ptr += bi.bytes_read;
-               async->buf_user_count += bi.bytes_read;
+               async->buf_read_ptr += bi.bytes_read;
+               if( async->buf_read_ptr >= async->data_len )
+                       async->buf_read_ptr %= async->data_len;
+               async->buf_read_count += bi.bytes_read;
 
                // check for buffer overflow
-               if(m > async->data_len){
-                       async->buf_user_count = async->buf_int_count;
-                       async->buf_user_ptr = async->buf_int_ptr;
+               if( m > async->data_len )
+               {
                        do_cancel(dev, dev->read_subdev);
                        DPRINTK("buffer overflow\n");
                        return -EIO;
                }
-               if(!(s->subdev_flags&SDF_RUNNING) && async->buf_int_count==async->buf_user_count){
+               if(!(s->subdev_flags&SDF_RUNNING) && async->buf_write_count==async->buf_read_count){
                        do_become_nonbusy(dev,s);
                }
        }
-       bi.buf_int_count = async->buf_int_count;
-       bi.buf_int_ptr = async->buf_int_ptr;
-       bi.buf_user_count = async->buf_user_count;
-       bi.buf_user_ptr = async->buf_user_ptr;
+       // XXX fix bufinfo struct
+       bi.buf_int_count = async->buf_write_count;
+       bi.buf_int_ptr = async->buf_write_ptr;
+       bi.buf_user_count = async->buf_read_count;
+       bi.buf_user_ptr = async->buf_read_ptr;
 
 copyback:
        if(copy_to_user(arg, &bi, sizeof(comedi_bufinfo)))
@@ -877,20 +880,18 @@ static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file)
        async->cmd.data_len=async->prealloc_bufsz;
 #endif
 
-       async->data = async->prealloc_buf;
-       async->data_len=async->prealloc_bufsz;
-
-       async->buf_int_ptr=0;
-       async->buf_int_count=0;
-       async->buf_user_ptr=0;
-       async->buf_user_count=0;
+       init_async_buf( async );
 
        async->cur_chan = 0;
 
+       async->data = async->prealloc_buf;
+       async->data_len=async->prealloc_bufsz;
+
        async->cb_mask = COMEDI_CB_EOA|COMEDI_CB_BLOCK|COMEDI_CB_ERROR;
        if(async->cmd.flags & TRIG_WAKE_EOS){
                async->cb_mask |= COMEDI_CB_EOS;
        }
+
        async->events = 0;
 
        s->runflags=SRF_USER;
@@ -1144,7 +1145,7 @@ static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file)
        
        reads:
                nothing
-       
+
        writes:
                nothing
 
@@ -1284,7 +1285,7 @@ static unsigned int comedi_poll_v22(struct file *file, poll_table * wait)
                s = dev->read_subdev;
                async = s->async;
                if(!s->busy ||
-                  (async->buf_user_count < async->buf_int_count) ||
+                  (async->buf_read_count < async->buf_write_count) ||
                   !(s->subdev_flags&SDF_RUNNING)){
                        mask |= POLLIN | POLLRDNORM;
                }
@@ -1294,7 +1295,7 @@ static unsigned int comedi_poll_v22(struct file *file, poll_table * wait)
                async = s->async;
                if(!s->busy ||
                   !(s->subdev_flags&SDF_RUNNING) ||
-                  (async->buf_user_count < async->buf_int_count +
+                  (async->buf_write_count < async->buf_read_count +
                    async->prealloc_bufsz)){
                        mask |= POLLOUT | POLLWRNORM;
                }
@@ -1347,9 +1348,9 @@ static ssize_t comedi_write_v22(struct file *file,const char *buf,size_t nbytes,
 
                n=nbytes;
 
-               m = async->data_len + async->buf_int_count - async->buf_user_count;
-               if( async->buf_user_ptr + m > async->data_len )
-                       m = async->data_len - async->buf_user_ptr;
+               m = async->data_len + async->buf_read_count - async->buf_write_count;
+               if( async->buf_write_ptr + m > async->data_len )
+                       m = async->data_len - async->buf_write_ptr;
 
                if(m < n) n = m;
 
@@ -1374,18 +1375,16 @@ static ssize_t comedi_write_v22(struct file *file,const char *buf,size_t nbytes,
                        schedule();
                        continue;
                }
-               m=copy_from_user(async->data+async->buf_user_ptr,buf,n);
-               if(m) retval=-EFAULT;
+               m = 0;
+               if( write_to_async_buffer( async, buf, n, 1 ) )
+               {
+                       m = n;
+                       retval = -EFAULT;
+               }
                n-=m;
 
                count+=n;
                nbytes-=n;
-               async->buf_user_ptr+=n;
-               async->buf_user_count+=n;
-
-               if(async->buf_user_ptr>=async->data_len ){
-                       async->buf_user_ptr=0;
-               }
 
                buf+=n;
                break;  /* makes device work like a pipe */
@@ -1440,9 +1439,9 @@ static ssize_t comedi_read_v22(struct file * file,char *buf,size_t nbytes,loff_t
 
                n=nbytes;
 
-               m = async->buf_int_ptr - async->buf_user_ptr;
-               if( m < 0 )
-                       m = async->data_len - async->buf_user_ptr;
+               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);
@@ -1470,15 +1469,17 @@ printk("m is %d\n",m);
                        schedule();
                        continue;
                }
-               m=copy_to_user(buf,async->data+async->buf_user_ptr,n);
-               if(m) retval=-EFAULT;
+               m=0;
+               retval = read_from_async_buffer( async, buf, n, 1 );
+               if( retval )
+               {
+                       m = n;
+               }
                n-=m;
 
                /* check for buffer overflow */
-               if(async->buf_int_count - async->buf_user_count > async->data_len){
-                       async->buf_user_count = async->buf_int_count;
-                       async->buf_user_ptr = async->buf_int_ptr;
-                       retval=-EIO;
+               if( retval == -EIO )
+               {
                        do_cancel(dev, dev->read_subdev);
                        DPRINTK("buffer overflow\n");
                        break;
@@ -1486,19 +1487,13 @@ printk("m is %d\n",m);
 
                count+=n;
                nbytes-=n;
-               async->buf_user_ptr+=n;
-               async->buf_user_count+=n;
-
-               if(async->buf_user_ptr>=async->data_len ){
-                       async->buf_user_ptr=0;
-               }
 
                buf+=n;
                break;  /* makes device work like a pipe */
        }
        if(!(s->subdev_flags&SDF_RUNNING) &&
                !(s->runflags & SRF_ERROR) &&
-               async->buf_int_count - async->buf_user_count == 0)
+               async->buf_read_count - async->buf_write_count == 0)
        {
                do_become_nonbusy(dev,s);
        }
@@ -1525,10 +1520,7 @@ void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s)
 #endif
 
        if(async){
-               async->buf_user_ptr=0;
-               async->buf_int_ptr=0;
-               async->buf_user_count=0;
-               async->buf_int_count=0;
+               init_async_buf( async );
        }else{
                printk("BUG: (?) do_become_nonbusy called with async=0\n");
        }
@@ -1859,3 +1851,12 @@ 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_write_count = 0;
+       async->buf_dirty_count = 0;
+       async->buf_read_ptr = 0;
+       async->buf_write_ptr = 0;
+}
+
index afe9438cba02d92ae5368b0be44b1b190a56479e..5fbfcfc7455b41a956b7f18a91a5e5d5903c5d1d 100644 (file)
@@ -301,7 +301,7 @@ typedef struct{
        unsigned char           cnt0_users;     // bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO)
        unsigned char           exttrg_users;   // bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO)
        unsigned int            cnt0_divisor;   // actual CNT0 divisor
-       int                     (*dma_ai_read_block)(comedi_device *, comedi_subdevice *, lsampl_t **, lsampl_t *, unsigned int *, unsigned int *); // ptr to actual transfer function from DMA buffer
+       int                     (*dma_ai_read_block)(comedi_device *, comedi_subdevice *, void *, int *, int *); // ptr to actual transfer function from DMA buffer
        void                    (*int_ai_func)(comedi_device *, comedi_subdevice *,unsigned short, unsigned int, unsigned short); // ptr to actual interrupt AI function
        unsigned char           ai16bits;       // =1 16 bit card
        unsigned char           usedma;         // =1 use DMA transfer and not INT
@@ -333,7 +333,7 @@ static int pci9118_exttrg_del(comedi_device * dev, unsigned char source);
 static int pci9118_ai_cancel(comedi_device * dev, comedi_subdevice * s);
 static void pci9118_calc_divisors(char mode, comedi_device * dev, comedi_subdevice * s, 
        unsigned int *tim1, unsigned int *tim2, unsigned int flags, 
-       int chans, unsigned int *div1, unsigned int *div2, 
+       int chans, unsigned int *div1, unsigned int *div2,
        char usessh, unsigned int chnsshfront);
 
 /*
@@ -385,7 +385,7 @@ conv_finish:
 static int pci9118_insn_write_ao(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)
 {
        int n,chanreg,ch;
-       
+
        ch=CR_CHAN(insn->chanspec);
        if (ch) { chanreg=PCI9118_DA2;} 
            else { chanreg=PCI9118_DA1; } 
@@ -437,7 +437,7 @@ static int pci9118_insn_bits_do(comedi_device *dev,comedi_subdevice *s, comedi_i
        return 2;
 }
 
-/* 
+/*
 ==============================================================================
 */
 static void interrupt_pci9118_ai_mode4_switch(comedi_device *dev) 
@@ -481,14 +481,15 @@ static int skip_front_samples_16b(comedi_device *dev, comedi_subdevice *s,
        return -1;
 }
 
-/* 
+/*
 ==============================================================================
 */
 static int move_block_from_dma_12bit_16b(comedi_device *dev, comedi_subdevice *s,
-       sampl_t **dma, sampl_t *data, int *sampls, int *bufs)
+       void *dma_void, int *sampls, int *bufs)
 {
        unsigned int cc,sp,chans,chns;
        sampl_t sampl;
+       uint16_t **dma = (uint16_t **) dma_void;
 
        cc=s->async->cur_chan;
        sp=devpriv->ai_act_scanpos;
@@ -513,7 +514,7 @@ static int move_block_from_dma_12bit_16b(comedi_device *dev, comedi_subdevice *s
                for (;cc<chns;cc++) {
                        sampl=**dma; (*dma)++;
 #ifdef PCI9118_PARANOIDCHECK
-                       if ((sampl & 0x0f00)!=devpriv->chanlist[cc]) { 
+                       if ((sampl & 0x0f00)!=devpriv->chanlist[cc]) {
                                rt_printk("comedi: A/D  DMA - data dropout: received channel %04x, expected %04x!\n",(sampl & 0x0f00),devpriv->chanlist[cc]);
                                DPRINTK("comedi:  bufs=%d cc=%d sp=%d dmapos=%d chans=%d af=%d ab=%d sampls=%d (dma)=%04x dma=%04x!\n",*bufs,cc,sp,devpriv->ai_act_dmapos,chans,devpriv->ai_add_front,devpriv->ai_add_back,*sampls,*(*dma-1),(int)(*dma-1));
                                s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA;
@@ -523,15 +524,14 @@ static int move_block_from_dma_12bit_16b(comedi_device *dev, comedi_subdevice *s
                        }
 #endif
                        sampl=((sampl & 0xff)<<4)|((sampl & 0xf000)>>12); // get one sample
-                       *data=sampl; 
-                       data++;
+                       comedi_buf_put( s->async, sampl);
                }
                sp+=cc;
                if (cc>=chans) {
                        cc=0;
                        devpriv->ai_act_dmapos=0;
                        if (devpriv->ai_add_back)  // drop added one
-                               if (*bufs) { 
+                               if (*bufs) {
                                        (*bufs)--;
                                        (*dma)++;
                                }
@@ -539,8 +539,7 @@ static int move_block_from_dma_12bit_16b(comedi_device *dev, comedi_subdevice *s
                if(sp>=devpriv->ai_n_scanlen) { // is end of one scan?
                        sp=0;
                        devpriv->ai_act_scan++;
-                       s->async->events|=COMEDI_CB_EOS;
-                       if (*sampls) 
+                       if (*sampls)
                                if (devpriv->ai_flags & TRIG_WAKE_EOS) {
                                        comedi_event(dev,s,s->async->events);
                                        s->async->events=0;
@@ -549,19 +548,19 @@ static int move_block_from_dma_12bit_16b(comedi_device *dev, comedi_subdevice *s
        }
 //     DPRINTK("9 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos);
        devpriv->ai_act_scanpos=sp;
-       s->async->cur_chan=cc;
        return 0;
 
 }
 
-/* 
+/*
 ==============================================================================
 */
 static int move_block_from_dma_16bit_16b(comedi_device *dev, comedi_subdevice *s,
-       sampl_t **dma, sampl_t *data, int *sampls, int *bufs)
+       void *dma_void, int *sampls, int *bufs)
 {
        unsigned int cc,sp,chans,chns;
        sampl_t sampl;
+       uint16_t **dma = (uint16_t **) dma_void;
 
        cc=s->async->cur_chan;
        sp=devpriv->ai_act_scanpos;
@@ -586,15 +585,14 @@ static int move_block_from_dma_16bit_16b(comedi_device *dev, comedi_subdevice *s
                for (;cc<chns;cc++) {
                        sampl=**dma; (*dma)++;
                        sampl=(((sampl & 0xff)<<8)|((sampl & 0xff00)>>8))^0x8000; // get one sample
-                       *data=sampl; 
-                       data++;
+                       comedi_buf_put( s->async, sampl );
                }
                sp+=cc;
                if (cc>=chans) {
                        cc=0;
                        devpriv->ai_act_dmapos=0;
                        if (devpriv->ai_add_back)  // drop added one
-                               if (*bufs) { 
+                               if (*bufs) {
                                        (*bufs)--;
                                        (*dma)++;
                                }
@@ -602,8 +600,7 @@ static int move_block_from_dma_16bit_16b(comedi_device *dev, comedi_subdevice *s
                if(sp>=devpriv->ai_n_scanlen) { // is end of one scan?
                        sp=0;
                        devpriv->ai_act_scan++;
-                       s->async->events|=COMEDI_CB_EOS;
-                       if (*sampls) 
+                       if (*sampls)
                                if (devpriv->ai_flags & TRIG_WAKE_EOS) {
                                        comedi_event(dev,s,s->async->events);
                                        s->async->events=0;
@@ -612,12 +609,11 @@ static int move_block_from_dma_16bit_16b(comedi_device *dev, comedi_subdevice *s
        }
 //     DPRINTK("9 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos);
        devpriv->ai_act_scanpos=sp;
-       s->async->cur_chan=cc;
        return 0;
 
 }
 
-/* 
+/*
 ==============================================================================
   Skip a few samples at begin of every scan if is used software generated
   sample&hold signal
@@ -627,7 +623,7 @@ static int skip_front_samples_32b(comedi_device *dev, comedi_subdevice *s,
 {
        unsigned int n;
 
-       n=(devpriv->ai_add_front-devpriv->ai_act_dmapos)>>1; 
+       n=(devpriv->ai_add_front-devpriv->ai_act_dmapos)>>1;
 //     DPRINTK("n=%d bufs=%d *dma=0x%08x dmapos=%d %d\n",n,*bufs,*dma,devpriv->ai_act_dmapos,x);
        if (*bufs>n) {
                (*bufs)-=n;
@@ -645,17 +641,18 @@ static int skip_front_samples_32b(comedi_device *dev, comedi_subdevice *s,
        return -1;
 }
 
-/* 
+/*
 ==============================================================================
 */
 static int move_block_from_dma_12bit_32b(comedi_device *dev, comedi_subdevice *s,
-       lsampl_t **dma, lsampl_t *data, int *sampls, int *bufs)
+       void *dma_void, int *sampls, int *bufs)
 {
        int cc,sp,chans,chns,xx,yy;
        lsampl_t sampl;
 #ifdef PCI9118_PARANOIDCHECK
        lsampl_t *chanlist=(lsampl_t *)devpriv->chanlist;
 #endif
+       uint32_t ** dma = ( uint32_t ** ) dma_void;
 
        cc=s->async->cur_chan;
        sp=devpriv->ai_act_scanpos;
@@ -674,7 +671,7 @@ static int move_block_from_dma_12bit_32b(comedi_device *dev, comedi_subdevice *s
                for (;cc<chns;cc++) {
                        sampl=**dma; (*dma)++;
 #ifdef PCI9118_PARANOIDCHECK
-                       if ((sampl & 0x000f000f)!=chanlist[cc]) { 
+                       if ((sampl & 0x000f000f)!=chanlist[cc]) {
                                rt_printk("comedi: A/D  DMA - data dropout: received channel %08x, expected %08x!\n",(sampl & 0x000f000f),chanlist[cc]);
                                DPRINTK("comedi:  bufs=%d cc=%d sp=%d dmapos=%d chns=%d chans=%d af=%d ab=%d sampls=%d (dma)=%08x dma=%08x!\n",*bufs,cc,sp,devpriv->ai_act_dmapos,chns,chans,devpriv->ai_add_front,devpriv->ai_add_back,*sampls,*(*dma-1),(int)(*dma-1));
                                s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA;
@@ -684,8 +681,7 @@ static int move_block_from_dma_12bit_32b(comedi_device *dev, comedi_subdevice *s
                        }
 #endif
                        sampl=((sampl & 0xfff0)<<12)|((sampl & 0xfff00000)>>20);
-                       *data=sampl; 
-                       data++;
+                       comedi_buf_put_long( s->async, sampl );
                }
                sp+=cc<<1;
                if (cc>=chans) {
@@ -695,8 +691,7 @@ static int move_block_from_dma_12bit_32b(comedi_device *dev, comedi_subdevice *s
                if(sp>=devpriv->ai_n_scanlen) { // is end of one scan?
                        sp=0;
                        devpriv->ai_act_scan++;
-                       s->async->events|=COMEDI_CB_EOS;
-                       if (*sampls) 
+                       if (*sampls)
                                if (devpriv->ai_flags & TRIG_WAKE_EOS) {
                                        comedi_event(dev,s,s->async->events);
                                        s->async->events=0;
@@ -706,18 +701,18 @@ static int move_block_from_dma_12bit_32b(comedi_device *dev, comedi_subdevice *s
        *bufs-=*bufs-(xx<<1);
        *sampls-=*sampls-(yy<<1);
        devpriv->ai_act_scanpos=sp;
-       s->async->cur_chan=cc;
        return 0;
 }
 
-/* 
+/*
 ==============================================================================
 */
 static int move_block_from_dma_16bit_32b(comedi_device *dev, comedi_subdevice *s,
-       lsampl_t **dma, lsampl_t *data, int *sampls, int *bufs)
+       void *dma_void, int *sampls, int *bufs)
 {
        int cc,sp,chans,chns,xx,yy;
        lsampl_t sampl;
+       uint32_t **dma = ( uint32_t ** ) dma_void;
 
        cc=s->async->cur_chan;
        sp=devpriv->ai_act_scanpos;
@@ -736,8 +731,7 @@ 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;
-                       *data=sampl; 
-                       data++;
+                       comedi_buf_put_long( s->async, sampl );
                }
                sp+=cc<<1;
                if (cc>=chans) {
@@ -747,8 +741,7 @@ static int move_block_from_dma_16bit_32b(comedi_device *dev, comedi_subdevice *s
                if(sp>=devpriv->ai_n_scanlen) { // is end of one scan?
                        sp=0;
                        devpriv->ai_act_scan++;
-                       s->async->events|=COMEDI_CB_EOS;
-                       if (*sampls) 
+                       if (*sampls)
                                if (devpriv->ai_flags & TRIG_WAKE_EOS) {
                                        comedi_event(dev,s,s->async->events);
                                        s->async->events=0;
@@ -758,7 +751,6 @@ static int move_block_from_dma_16bit_32b(comedi_device *dev, comedi_subdevice *s
        *bufs-=*bufs-(xx<<1);
        *sampls-=*sampls-(yy<<1);
        devpriv->ai_act_scanpos=sp;
-       s->async->cur_chan=cc;
        return 0;
 }
 
@@ -810,7 +802,7 @@ static void interrupt_pci9118_ai_onesample(comedi_device *dev,comedi_subdevice *
        sampl=inw(dev->iobase+PCI9118_AD_DATA);
 
        if (devpriv->ai16bits) {
-               *(sampl_t *)(s->async->data+s->async->buf_int_ptr)=sampl^0x8000;
+               comedi_buf_put( s->async, sampl ^ 0x8000 );
        } else {
 #ifdef PCI9118_PARANOIDCHECK
                if ((sampl & 0x000f)!=devpriv->chanlist[s->async->cur_chan]) { // data dropout!
@@ -821,42 +813,31 @@ static void interrupt_pci9118_ai_onesample(comedi_device *dev,comedi_subdevice *
                        return;
                }
 #endif
-               *(sampl_t *)(s->async->data+s->async->buf_int_ptr)=(sampl>>4) & 0x0fff;
+               comedi_buf_put( s->async, ( sampl >> 4 ) & 0x0fff );
        }
 
-       s->async->buf_int_ptr+=sizeof(sampl_t);
-       s->async->buf_int_count+=sizeof(sampl_t);
-
-       s->async->cur_chan++;
-       if (s->async->cur_chan >= devpriv->ai_n_scanlen) {      /* one scan done */
-               s->async->cur_chan=0;
+       if (s->async->cur_chan == 0) {  /* one scan done */
                devpriv->ai_act_scan++;
-               s->async->events |= COMEDI_CB_EOS;
                if (!(devpriv->ai_neverending))
                        if (devpriv->ai_act_scan>=devpriv->ai_scans) {  /* all data sampled */
                                pci9118_ai_cancel(dev,s);
                                s->async->events |= COMEDI_CB_EOA;
                        }
        }
-       
-       if (s->async->buf_int_ptr >= s->async->data_len) {      /* buffer rollover */
-               s->async->buf_int_ptr = 0;
-               s->async->events |= COMEDI_CB_EOBUF;
-       }
 
-       if (s->async->events) 
+       if (s->async->events)
                comedi_event(dev,s,s->async->events);
 }
 
-/* 
+/*
 ==============================================================================
 */
-static void interrupt_pci9118_ai_dma(comedi_device *dev,comedi_subdevice *s, 
-       unsigned short int_adstat, unsigned int int_amcc, unsigned short int_daq) 
+static void interrupt_pci9118_ai_dma(comedi_device *dev,comedi_subdevice *s,
+       unsigned short int_adstat, unsigned int int_amcc, unsigned short int_daq)
 {
         lsampl_t       *ptr;
        unsigned int    next_dma_buf, samplesinbuf, sampls, m;
-       
+
        s->async->events=0;
 
        if (int_amcc&MASTER_ABORT_INT) {
@@ -877,54 +858,43 @@ static void interrupt_pci9118_ai_dma(comedi_device *dev,comedi_subdevice *s,
 
        if (int_adstat & devpriv->ai_maskerr)
 //     if (int_adstat & 0x106)
-               if (pci9118_decode_error_status(dev,s,int_adstat)) 
+               if (pci9118_decode_error_status(dev,s,int_adstat))
                        return;
 
        samplesinbuf=devpriv->dmabuf_use_size[devpriv->dma_actbuf]>>1; // number of received real samples
 //     DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf);
-               
+
        if (devpriv->dma_doublebuf) {   // switch DMA buffers if is used double buffering
                next_dma_buf=1-devpriv->dma_actbuf;
                outl(devpriv->dmabuf_hw[next_dma_buf], devpriv->iobase_a+AMCC_OP_REG_MWAR);
                outl(devpriv->dmabuf_use_size[next_dma_buf], devpriv->iobase_a+AMCC_OP_REG_MWTC);
                devpriv->dmabuf_used_size[next_dma_buf]=devpriv->dmabuf_use_size[next_dma_buf];
-               if (devpriv->ai_do==4) 
-                       interrupt_pci9118_ai_mode4_switch(dev); 
+               if (devpriv->ai_do==4)
+                       interrupt_pci9118_ai_mode4_switch(dev);
        }
 
         ptr=(lsampl_t *)devpriv->dmabuf_virt[devpriv->dma_actbuf];
 
        while (samplesinbuf) {
-               m=(devpriv->ai_data_len-s->async->buf_int_ptr)>>1; // how many samples is to end of buffer
+               m = devpriv->ai_data_len >> 1; // how many samples is to end of buffer
 //             DPRINTK("samps=%d m=%d %d %d\n",samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr);
                sampls=m;
-               if (devpriv->dma_ai_read_block(dev, s, &ptr, 
-                   ((void *)(devpriv->ai_data))+s->async->buf_int_ptr,
+               if (devpriv->dma_ai_read_block(dev, s, &ptr,
                    &sampls, &samplesinbuf))
                        return; // Uiii, error
                m=m-sampls; // m= how many samples was transfered
-               s->async->buf_int_count+=m<<1;
-               s->async->buf_int_ptr+=m<<1;
-               s->async->events|=COMEDI_CB_BLOCK;
-               if (s->async->buf_int_ptr>=devpriv->ai_data_len) { // output buffer filled
-//                     DPRINTK("EOBUF scans=%d\n",devpriv->ai_act_scan);
-                       s->async->events|=COMEDI_CB_EOBUF;
-                       s->async->buf_int_ptr=0;
-                       comedi_event(dev,s,s->async->events);
-                       s->async->events=0;
-               }
        }
 //     DPRINTK("YYY\n");
-       
+
        if (!devpriv->ai_neverending)
                if ( devpriv->ai_act_scan>=devpriv->ai_scans ) { /* all data sampled */
                        pci9118_ai_cancel(dev,s);
                        s->async->events|=COMEDI_CB_EOA;
                }
-       
+
 
        if (devpriv->dma_doublebuf) { // switch dma buffers
-               devpriv->dma_actbuf=1-devpriv->dma_actbuf; 
+               devpriv->dma_actbuf=1-devpriv->dma_actbuf;
        } else { // restart DMA if is not used double buffering
                outl(devpriv->dmabuf_hw[0], devpriv->iobase_a+AMCC_OP_REG_MWAR);
                outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a+AMCC_OP_REG_MWTC);
@@ -1450,17 +1420,17 @@ static int pci9118_ai_docmd_dma(comedi_device * dev, comedi_subdevice * s)
        switch (devpriv->usedma) { 
        case 2: // 32 bit DMA mode
                if (devpriv->ai16bits) { // select interrupt function
-                       devpriv->dma_ai_read_block=(void *)move_block_from_dma_16bit_32b;
+                       devpriv->dma_ai_read_block=move_block_from_dma_16bit_32b;
                } else {
-                       devpriv->dma_ai_read_block=(void *)move_block_from_dma_12bit_32b;
+                       devpriv->dma_ai_read_block=move_block_from_dma_12bit_32b;
                }
                outl(0x00000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR);
                break;
        case 1: // 16 bit DMA mode
                if (devpriv->ai16bits) { // select interrupt function
-                       devpriv->dma_ai_read_block=(void *)move_block_from_dma_16bit_16b;
+                       devpriv->dma_ai_read_block=move_block_from_dma_16bit_16b;
                } else {
-                       devpriv->dma_ai_read_block=(void *)move_block_from_dma_12bit_16b;
+                       devpriv->dma_ai_read_block=move_block_from_dma_12bit_16b;
                }
                outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR);
                break;
index 5c9fd93ece76ab743f66f66faaa2bba4f3961dff..3d31117a686a16e7043564616244e540c7a9edda 100644 (file)
@@ -283,14 +283,7 @@ static void parport_interrupt(int irq,void *d,struct pt_regs *regs)
                return;
        }
 
-       *(sampl_t *)(s->async->data+s->async->buf_int_ptr)=0;
-       s->async->buf_int_ptr+=sizeof(sampl_t);
-       s->async->buf_int_count+=sizeof(sampl_t);
-       if(s->async->buf_int_ptr>=s->async->data_len){
-               s->async->buf_int_ptr=0;
-               s->async->events |= COMEDI_CB_EOBUF;
-       }
-       s->async->events |= COMEDI_CB_EOS;
+       comedi_buf_put( s->async, 0 );
        
        comedi_event(dev,s,s->async->events);
 }
index 0e9a4aaf73fc0971e969be262f8dab3625c3ef9c..fad54005c1605a87f4751941f783fefeb71637d1 100644 (file)
@@ -460,7 +460,7 @@ static int das16m1_poll(comedi_device *dev, comedi_subdevice *s)
        das16m1_handler(dev, status);
        comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
 
-       return s->async->buf_int_count - s->async->buf_user_count;
+       return s->async->buf_write_count - s->async->buf_read_count;
 }
 
 static void das16m1_interrupt(int irq, void *d, struct pt_regs *regs)
index 49126da67fd67d7fd43ee705fd89b130804dbd11..dfdef7fb03172a9773174b7aeaf395b102875cf4 100644 (file)
@@ -879,7 +879,7 @@ static int das1800_ai_poll(comedi_device *dev,comedi_subdevice *s)
        das1800_ai_handler(dev);
        comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
 
-       return s->async->buf_int_count - s->async->buf_user_count;
+       return s->async->buf_write_count - s->async->buf_read_count;
 }
 
 static void das1800_interrupt(int irq, void *d, struct pt_regs *regs)
index 855c5a95d591990f03bda79dcadbc5df5f5a6022..1ae87e24aaf0931c4121e0743c955f834f795493 100644 (file)
@@ -173,7 +173,7 @@ static void intr_handler(int irq,void *d,struct pt_regs *regs)
 
        das6402_ai_fifo_dregs(dev,s);
 
-       if(s->async->buf_int_count >= devpriv->ai_bytes_to_read){
+       if(s->async->buf_write_count >= devpriv->ai_bytes_to_read){
                outw_p(SCANL,dev->iobase+2);  /* clears the fifo */
                outb(0x07,dev->iobase+8);  /* clears all flip-flops */
 #ifdef DEBUG
index 6a2723d39a08885ca43e053e2e2ab619e634295e..3b4ddaa08a6604ade6f1101481817247ee3c3f15 100644 (file)
@@ -409,53 +409,6 @@ static void dt282x_cleanup_buffer(comedi_device *dev,unsigned short *buf,unsigne
        }
 }
 
-static void copy_to_buf(comedi_device *dev,comedi_subdevice *s,void *buf,unsigned int n_bytes)
-{
-       unsigned int n;
-
-       n=n_bytes;
-       if(s->async->buf_int_ptr+n >= s->async->data_len){
-               n=s->async->data_len-s->async->buf_int_ptr;
-               memcpy(s->async->data+s->async->buf_int_ptr,buf,n);
-               buf+=n;
-               s->async->buf_int_count+=n;
-               s->async->buf_int_ptr=0;
-
-               n=n_bytes-n;
-       }
-       memcpy(s->async->data+s->async->buf_int_ptr,buf,n);
-       buf+=n;
-       s->async->buf_int_count+=n;
-       s->async->buf_int_ptr+=n;
-}
-
-static int copy_from_buf(comedi_device *dev,comedi_subdevice *s,void *buf,unsigned int n_bytes)
-{
-       unsigned int n,m;
-
-       n=s->async->buf_int_count-s->async->buf_user_count;
-       if(n==0)return 0;
-       if(n>n_bytes)
-               n=n_bytes;
-
-       n_bytes=n;
-       if(s->async->buf_int_ptr+n >= s->async->data_len){
-               m=s->async->data_len-s->async->buf_int_ptr;
-               memcpy(buf,s->async->data+s->async->buf_int_ptr,m);
-               buf+=m;
-               s->async->buf_int_count+=m;
-               s->async->buf_int_ptr=0;
-
-               n-=m;
-       }
-       memcpy(buf,s->async->data+s->async->buf_int_ptr,n);
-       s->async->buf_int_count+=n;
-       s->async->buf_int_ptr+=n;
-
-       return n_bytes;
-}
-
-
 static void dt282x_ao_dma_interrupt(comedi_device * dev)
 {
        void *ptr;
@@ -477,19 +430,18 @@ static void dt282x_ao_dma_interrupt(comedi_device * dev)
 
        devpriv->current_dma_chan=1-i;
 
-       size=copy_from_buf(dev,s,ptr,devpriv->dma_maxsize*2);
-       if(!size){
+       size = comedi_buf_get_array( s->async, ptr, devpriv->dma_maxsize );
+       if( size < 0){
                printk("dt282x: AO underrun\n");
                dt282x_ao_cancel(dev,s);
                s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
                comedi_event(dev,s,s->async->events);
                return;
        }
-       prep_ao_dma(dev,i,size/2);
+       prep_ao_dma(dev,i,size);
 
        enable_dma(devpriv->dma[i].chan);
 
-       s->async->events |= COMEDI_CB_BLOCK;
        comedi_event(dev,s,s->async->events);
        return;
 }
@@ -516,7 +468,7 @@ static void dt282x_ai_dma_interrupt(comedi_device * dev)
 
        devpriv->current_dma_chan=1-i;
        dt282x_cleanup_buffer(dev,ptr,size);
-       copy_to_buf(dev,s,ptr,size*2);
+       comedi_buf_put_array( s->async, ptr, size );
        devpriv->nread-=size;
 
        if(devpriv->nread<0){
@@ -535,8 +487,6 @@ static void dt282x_ai_dma_interrupt(comedi_device * dev)
                comedi_event(dev,s,s->async->events);
 
                return;
-       }else{
-               s->async->events |= COMEDI_CB_BLOCK;
        }
 
 #if 1
@@ -646,13 +596,7 @@ static void dt282x_interrupt(int irq, void *d, struct pt_regs *regs)
                if(devpriv->ad_2scomp){
                        data^=1<<(boardtype.adbits-1);
                }
-               *(sampl_t *)(s->async->data+s->async->buf_int_ptr)=data;
-               s->async->buf_int_ptr+=sizeof(sampl_t);
-               s->async->buf_int_count+=sizeof(sampl_t);
-               if(s->async->buf_int_ptr>=s->async->data_len){
-                       s->async->buf_int_ptr = 0;
-                       s->async->events |= COMEDI_CB_EOBUF;
-               }
+               comedi_buf_put( s->async, data );
 
                devpriv->nread--;
                if(!devpriv->nread){
@@ -1049,12 +993,14 @@ static int dt282x_ao_inttrig(comedi_device *dev,comedi_subdevice *s,
 
        if(x!=0)return -EINVAL;
 
-       size=copy_from_buf(dev,s,devpriv->dma[0].buf,devpriv->dma_maxsize*2);
-       prep_ao_dma(dev,0,size/2);
+       size=comedi_buf_get_array( s->async, devpriv->dma[0].buf, devpriv->dma_maxsize);
+       if( size < 0 ) return size;
+
+       prep_ao_dma(dev,0,size);
        enable_dma(devpriv->dma[0].chan);
 
-       size=copy_from_buf(dev,s,devpriv->dma[1].buf,devpriv->dma_maxsize*2);
-       prep_ao_dma(dev,1,size/2);
+       size=comedi_buf_get_array( s->async, devpriv->dma[1].buf, devpriv->dma_maxsize);
+       prep_ao_dma(dev,1,size);
        enable_dma(devpriv->dma[1].chan);
        
        update_supcsr(DT2821_STRIG);
index 7057b6894751c5a792475794a40db7a6543e312b..4e101b6f74488ce9625fc015c38c7881cbefa9f8 100644 (file)
@@ -339,7 +339,7 @@ static void ni_E_interrupt(int irq,void *d,struct pt_regs * regs)
                handle_a_interrupt(dev,a_status,m0_status);
        }
        if(b_status&Interrupt_B_St)handle_b_interrupt(dev,b_status);
-       
+
        win_restore(wsave);
 }
 
@@ -352,41 +352,41 @@ static void mite_handle_a_linkc(struct mite_struct *mite, comedi_device *dev)
 
        writel(CHOR_CLRLC, mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(mite->chan));
 
-       count = mite_bytes_transferred(mite, 0) - async->buf_int_count;
+       count = mite_bytes_transferred(mite, 0) - async->buf_write_count;
        if(count < 0 || count > 100000){
                printk("BUG: too many samples in interrupt (%d)\n",count);
                return;
        }
-       async->buf_int_count += count;
+       async->buf_write_count += count;
 
        if(async->cmd.flags & CMDF_RAWDATA){
                /*
                 * Don't munge the data, just update the user's status
                 * variables
                 */
-               async->buf_int_ptr += count;
-               if(async->buf_int_ptr >= async->prealloc_bufsz)
-                       async->buf_int_ptr -= async->prealloc_bufsz;
+               async->buf_write_ptr += count;
+               if(async->buf_write_ptr >= async->prealloc_bufsz)
+                       async->buf_write_ptr -= async->prealloc_bufsz;
        }else{
                /*
                 * Munge the ADC data to change its format from two's
                 * complement to unsigned int.  This is slow but makes
                 * it more compatible with other cards.
                 */
-               if(async->buf_int_ptr + count >= async->prealloc_bufsz){
+               if(async->buf_write_ptr + count >= async->prealloc_bufsz){
                        ni_munge(dev,s,
-                               async->prealloc_buf + async->buf_int_ptr,
+                               async->prealloc_buf + async->buf_write_ptr,
                                async->prealloc_buf + async->prealloc_bufsz);
-                       async->buf_int_ptr += count;
-                       async->buf_int_ptr -= async->prealloc_bufsz;
+                       async->buf_write_ptr += count;
+                       async->buf_write_ptr -= async->prealloc_bufsz;
                        ni_munge(dev,s,
                                async->prealloc_buf,
-                               async->prealloc_buf + async->buf_int_ptr);
+                               async->prealloc_buf + async->buf_write_ptr);
                }else{
                        ni_munge(dev,s,
-                               async->prealloc_buf + async->buf_int_ptr,
-                               async->prealloc_buf + async->buf_int_ptr + count);
-                       async->buf_int_ptr += count;
+                               async->prealloc_buf + async->buf_write_ptr,
+                               async->prealloc_buf + async->buf_write_ptr + count);
+                       async->buf_write_ptr += count;
                }
        }
        s->async->events |= COMEDI_CB_BLOCK;
@@ -399,7 +399,7 @@ static void mite_handle_interrupt(comedi_device *dev,unsigned int m_status)
        comedi_subdevice *s = dev->subdevices+0;
        comedi_async *async = s->async;
        struct mite_struct *mite = devpriv->mite;
-       
+
        async->events |= COMEDI_CB_BLOCK;
 
        MDPRINTK("mite_handle_interrupt: m_status=%08x\n",m_status);
@@ -852,7 +852,7 @@ static int ni_ai_poll(comedi_device *dev,comedi_subdevice *s)
 
        //comedi_event(dev,s,s->async->events);
 
-       return s->async->buf_int_count-s->async->buf_user_count;
+       return s->async->buf_write_count - s->async->buf_read_count;
 #else
        /* XXX we don't support this yet. */
        return -EINVAL;
@@ -1647,14 +1647,14 @@ static void ni_ao_fifo_load(comedi_device *dev,comedi_subdevice *s,
        // increment channel index
        async->cur_chan = (async->cur_chan + n) % async->cmd.chanlist_len;
        // increment async buf_int_count and buf_int_ptr
-       async->buf_int_count += n * sizeof(sampl_t);
-       async->buf_int_ptr += n * sizeof(sampl_t);
+       async->buf_read_count += n * sizeof(sampl_t);
+       async->buf_read_ptr += n * sizeof(sampl_t);
        // check if we have reached end of buffer
-       if(async->buf_int_ptr >= async->data_len)
+       if(async->buf_read_ptr >= async->data_len)
        {
-               async->buf_int_ptr -= async->data_len;
+               async->buf_read_ptr -= async->data_len;
                // this shouldn't ever happen
-               if(async->buf_int_ptr >= async->data_len)
+               if(async->buf_read_ptr >= async->data_len)
                        comedi_error(dev, "ao bug!");
        }
 }
@@ -1680,17 +1680,17 @@ static int ni_ao_fifo_half_empty(comedi_device *dev,comedi_subdevice *s)
 {
        int n,m;
 
-       n=(s->async->buf_int_count-s->async->buf_user_count)/sizeof(sampl_t);
+       n=(s->async->buf_read_count - s->async->buf_write_count) / sizeof(sampl_t);
        if(n==0)return 0;
        if(n>boardtype.ao_fifo_depth/2)
                n=boardtype.ao_fifo_depth/2;
 
-       if(s->async->buf_int_ptr+n*sizeof(sampl_t)>s->async->data_len){
-               m=(s->async->data_len-s->async->buf_int_ptr)/sizeof(sampl_t);
-               ni_ao_fifo_load(dev,s,s->async->data+s->async->buf_int_ptr,m);
+       if(s->async->buf_read_ptr+n*sizeof(sampl_t)>s->async->data_len){
+               m=(s->async->data_len-s->async->buf_read_ptr)/sizeof(sampl_t);
+               ni_ao_fifo_load(dev,s,s->async->data+s->async->buf_read_ptr,m);
                n-=m;
        }
-       ni_ao_fifo_load(dev,s,s->async->data+s->async->buf_int_ptr,n);
+       ni_ao_fifo_load(dev,s,s->async->data+s->async->buf_read_ptr,n);
 
        s->async->events |= COMEDI_CB_BLOCK;
 
@@ -1705,12 +1705,12 @@ static int ni_ao_prep_fifo(comedi_device *dev,comedi_subdevice *s)
        win_out(0,DAC_FIFO_Clear);
 
        /* load some data */
-       n=(s->async->buf_user_count-s->async->buf_int_count)/sizeof(sampl_t);
+       n=(s->async->buf_write_count-s->async->buf_read_count)/sizeof(sampl_t);
        if(n<0)return 0;
        if(n>boardtype.ao_fifo_depth)
                n=boardtype.ao_fifo_depth;
 
-       ni_ao_fifo_load(dev,s,s->async->data+s->async->buf_int_ptr,n);
+       ni_ao_fifo_load(dev,s,s->async->data+s->async->buf_read_ptr,n);
 
        return n;
 }
index 36679af25f1bea3c0f4910ee9dbf18d16c9a8869..ca0e3ee82da7a8142e8caf93b2982d3719945291 100644 (file)
@@ -403,13 +403,13 @@ static void nidio_interrupt(int irq, void *d, struct pt_regs *regs)
        status = readb(dev->iobase+Interrupt_And_Window_Status);
        flags = readb(dev->iobase+Group_1_Flags);
        m_status = readl(mite->mite_io_addr + MITE_CHSR + CHAN_OFFSET(1));
-       
+
        //interrupcions parasites
        if(dev->attached == 0){
                comedi_error(dev,"premature interrupt");
-               async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA; 
+               async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA;
        }
-        
+
        DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x,m_status=0x%08x\n",
                status,flags,m_status);
        ni_pcidio_print_flags(flags);
@@ -432,10 +432,10 @@ static void nidio_interrupt(int irq, void *d, struct pt_regs *regs)
 
                        /* XXX need to byteswap */
 
-                       async->buf_int_count += count;
-                       async->buf_int_ptr += count;
-                       if(async->buf_int_ptr >= async->data_len){
-                               async->buf_int_ptr -= async->data_len;
+                       async->buf_write_count += count;
+                       async->buf_write_ptr += count;
+                       if(async->buf_write_ptr >= async->data_len){
+                               async->buf_write_ptr -= async->data_len;
                        }
                        mite->current_link++;
                        if(mite->current_link >= mite->n_links){
@@ -454,7 +454,7 @@ static void nidio_interrupt(int irq, void *d, struct pt_regs *regs)
                }
                async->events |= COMEDI_CB_BLOCK;
        }
-        
+
        while(status&DataLeft){
                work++;
                if(work>20){
@@ -464,7 +464,7 @@ static void nidio_interrupt(int irq, void *d, struct pt_regs *regs)
                }
 
                flags &= IntEn;
-  
+
                if(flags & TransferReady){
                        //DPRINTK("TransferReady\n");
                        while(flags & TransferReady){
@@ -493,7 +493,7 @@ static void nidio_interrupt(int irq, void *d, struct pt_regs *regs)
                        DPRINTK("CountExpired\n");
                        writeb(ClearExpired,dev->iobase+Group_1_Second_Clear);
                        async->events |= COMEDI_CB_EOA;
-                       
+
                        writeb(0x00,dev->iobase+OpMode);
                        writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);
 #ifdef USE_DMA
@@ -838,7 +838,7 @@ static int ni_pcidio_cmd(comedi_device *dev,comedi_subdevice *s)
        }else{
                /* XXX */
        }
-  
+
 #ifdef USE_DMA
        writeb(0x05,dev->iobase+DMA_Line_Control);
        writeb(0x30,dev->iobase+Group_1_First_Clear);
index d4f337d76b27bb46b5dd5f18018c1b6e8b689372..136d17c6292c922f23b950b752db6b13a751f1e4 100644 (file)
@@ -1029,7 +1029,7 @@ static int pcl812_ai_poll(comedi_device *dev,comedi_subdevice *s)
 
        comedi_spin_unlock_irqrestore(&dev->spinlock,flags);
 
-       return s->async->buf_int_count-s->async->buf_user_count;
+       return s->async->buf_write_count-s->async->buf_read_count;
 }
 
 /*
index ca95723960c9bac981ee2efd19f9dd15d7841723..f629db361c2ac640b592fd5cb3ba1390b295f4f0 100644 (file)
@@ -700,7 +700,7 @@ static int pcl816_ai_poll(comedi_device *dev,comedi_subdevice *s)
     unsigned int top1,top2,i;
 
        if (!devpriv->dma) return 0; // poll is valid only for DMA transfer
-       
+
        comedi_spin_lock_irqsave(&dev->spinlock, flags);
 
        for (i=0; i<20; i++) {
@@ -723,11 +723,11 @@ static int pcl816_ai_poll(comedi_device *dev,comedi_subdevice *s)
 
        transfer_from_dma_buf(dev, s, (sampl_t*)devpriv->dmabuf[devpriv->next_dma_buf],
                                devpriv->ai_poll_ptr, top2);
-       
+
        devpriv->ai_poll_ptr = top1; // new buffer position
        comedi_spin_unlock_irqrestore(&dev->spinlock,flags);
 
-       return s->async->buf_int_count - s->async->buf_user_count;
+       return s->async->buf_write_count - s->async->buf_read_count;
 }
 
 
index a369bfc6831516f5a72208d7f3d1159b8dcf1c77..e792bf0e373fde7631aa6e4b943894c72ee4034b 100644 (file)
@@ -1187,7 +1187,7 @@ transferDone:
 static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s)
 {
     /* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
-    return s->async->buf_int_count - s->async->buf_user_count;
+    return s->async->buf_write_count - s->async->buf_read_count;
 }
 
 /*
index 04aa33b4e6cfde87297eb2c7019e615cfd1ce102..62f2b00050e53463faff87ae1145c0d5a886944f 100644 (file)
@@ -178,7 +178,7 @@ unsigned int comedi_get_buf_head_pos(comedi_t *d,unsigned int subdevice)
        async = s->async;
        if(async == NULL) return 0;
 
-       return async->buf_int_count;
+       return async->buf_write_count;
 }
 
 /*
@@ -191,7 +191,7 @@ int comedi_set_user_int_count(comedi_t *d,unsigned int subdevice,unsigned int bu
        comedi_async *async;
 
        async = s->async;
-       async->buf_user_count = buf_user_count;
+       async->buf_read_count = buf_user_count;
 
        return 0;
 }
index b4615886848985b21649b42c2791cbcfa7f256a1..676d63b43a56604d4ca2f1130e437ec51cecbeab 100644 (file)
@@ -105,7 +105,7 @@ void comedi_perror(const char *message)
 char *comedi_strerror(int err)
 {
        return "unknown error";
-} 
+}
 
 int comedi_fileno(comedi_t *d)
 {
@@ -115,6 +115,15 @@ 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_dirty_count = 0;
+       async->buf_read_ptr = 0;
+       async->buf_write_ptr = 0;
+}
+
 int comedi_command(comedi_t *d,comedi_cmd *cmd)
 {
        comedi_device *dev = (comedi_device *)d;
@@ -145,10 +154,7 @@ int comedi_command(comedi_t *d,comedi_cmd *cmd)
 
        s->subdev_flags |= SDF_RUNNING;
 
-       async->buf_user_ptr=0;
-       async->buf_user_count=0;
-       async->buf_int_ptr=0;
-       async->buf_int_count=0;
+       init_async_buf( async );
 
        async->data = cmd->data;
        async->data_len = cmd->data_len;
index 9d9945997b12eaf436f8dcecb5bd08e819830eb9..2e1311a1ee8c0625f3dc591a474bfd74eaea7939 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <asm/uaccess.h>
 
 #include <linux/comedi.h>
 
@@ -131,23 +132,26 @@ struct comedi_async_struct{
        unsigned int    mmap_count;     /* current number of mmaps of prealloc_buf */
 
        /* To avoid races and provide reliable overrun detection, read / writes
-        * to buffer should proceed as follows:
+        * 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 either 'count' or 'ptr' members
-        *      ('count' members are more convenient).
-        *   2) increment write count
-        *   3) write data to buffer
-        *   4) increment write ptr
+        *   1) if appropriate, check space in buffer, using read/write count members
+        *   2) call write_to_async_buffer()
         * Reading:
-        *   1) read data from buffer, using 'ptr' members to determine how much
-        *   2) update the read ptr
-        *   3) if appropriate, check for overrun using 'count' members
-        *   4) increment read count
+        *   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
         */
-       volatile unsigned int buf_int_ptr;      /* buffer marker for interrupt */
-       unsigned int buf_user_ptr;              /* buffer marker for read() and write() */
-       volatile unsigned int buf_int_count;    /* byte count for interrupt */
-       unsigned int buf_user_count;            /* byte count for read() and write() */
+       unsigned int buf_write_ptr;     /* buffer marker for writer */
+       unsigned int buf_read_ptr;              /* buffer marker for reader */
+       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 */
        unsigned int cur_chan;          /* useless channel marker for interrupt */
 
        void            *data;
@@ -321,77 +325,179 @@ static inline int alloc_private(comedi_device *dev,int size)
        return 0;
 }
 
-// writes a data point to comedi's buffer, used for input
-static inline void comedi_buf_put(comedi_async *async, sampl_t x)
+/* 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_int_count += sizeof(sampl_t);
-       *(sampl_t *)(async->data + async->buf_int_ptr) = x;
-       async->buf_int_ptr += sizeof(sampl_t);
-       if(async->buf_int_ptr >= async->data_len){
-               async->buf_int_ptr = 0;
-               async->events |= COMEDI_CB_EOBUF;
-       }
-       if(++async->cur_chan >= async->cmd.chanlist_len){
-               async->cur_chan = 0;
-               async->events |= COMEDI_CB_EOS;
+       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;
+               }
        }
-       async->events |= COMEDI_CB_BLOCK;
+
+       return 0;
 }
 
-/* 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, sampl_t* array, unsigned int length)
+static inline int read_from_async_buffer( comedi_async *async, void *destination,
+       unsigned int num_bytes, unsigned int from_user_space )
 {
-       unsigned int num_bytes;
-       unsigned int xfer_count = 0;
+       unsigned int bytes_available = async->buf_write_count - async->buf_read_count;
+       unsigned int remaining = bytes_available;
+
+       if( bytes_available == 0 ) return -EAGAIN;
 
-       while((num_bytes = length * sizeof(sampl_t) - xfer_count))
+       while( remaining )
        {
-               async->buf_int_count += num_bytes;
-               if( async->buf_int_ptr + num_bytes > async->data_len)
-                       num_bytes = async->data_len - async->buf_int_ptr;
+               unsigned int block_size;
 
-               memcpy(async->data + async->buf_int_ptr + xfer_count, array, num_bytes);
+               block_size = remaining;
+               if( async->buf_read_ptr + block_size > async->data_len )
+                       block_size = async->data_len - async->buf_read_ptr;
 
-               async->buf_int_ptr += num_bytes;
-               if(async->buf_int_ptr >= async->data_len)
+               if( from_user_space )
                {
-                       async->buf_int_ptr %= async->data_len;
-                       async->events |= COMEDI_CB_EOBUF;
-               }
-               async->cur_chan += num_bytes / sizeof(sampl_t);
-               if(async->cur_chan >= async->cmd.chanlist_len)
+                       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->cur_chan %= async->cmd.chanlist_len;
-                       async->events |= COMEDI_CB_EOS;
+                       async->buf_read_ptr = 0;
                }
-               xfer_count += num_bytes;
+       }
+       // 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(comedi_async *async, sampl_t *x)
+static inline int comedi_buf_get_array(comedi_async *async, sampl_t *array, unsigned int num_samples)
 {
-       if(async->buf_int_count == async->buf_user_count)
-               return -EAGAIN;
+       unsigned int num_bytes = num_samples * sizeof( sampl_t );
+       int retval;
+       unsigned int read_ptr = async->buf_read_ptr;
 
-       *x = *(sampl_t *)(async->data + async->buf_int_ptr);
-       async->buf_int_ptr += sizeof(sampl_t);
-       if(async->buf_int_ptr >= async->data_len){
-               async->buf_int_ptr = 0;
+       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;
        }
-       if(++async->cur_chan >= async->cmd.chanlist_len){
-               async->cur_chan = 0;
+
+       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->buf_int_count += sizeof(sampl_t);
 
        async->events |= COMEDI_CB_BLOCK;
 
-       return 0;
+       return retval / sizeof( sampl_t );
+}
+
+/* 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);
 }