MITE DMA works with any size acquisition and any size buffer, although
authorTim Ousley <tim.ousley@ni.com>
Sat, 28 Jul 2001 19:48:01 +0000 (19:48 +0000)
committerTim Ousley <tim.ousley@ni.com>
Sat, 28 Jul 2001 19:48:01 +0000 (19:48 +0000)
large buffers are still best.

comedi/drivers/mite.c
comedi/drivers/mite.h
comedi/drivers/ni_mio_common.c

index 86abb68cb3ef4af41bacd19408f9c042d7f61fa1..6a259f6e8f222f4fadd754962115cc49c10640d5 100644 (file)
@@ -150,7 +150,7 @@ int mite_setup(struct mite_struct *mite)
 #if LINUX_VERSION_CODE < 0x020300
        addr=mite->pcidev->base_address[0];
 #else
-       pci_enable_device(mite->pcidev);
+       //pci_enable_device(mite->pcidev);  This is causing a hang when used with PCIDMA -- 7/27/01 Tim
        addr=mite->pcidev->resource[0].start;
 #endif
 #endif
@@ -293,9 +293,9 @@ void mite_dma_prep(struct mite_struct *mite,comedi_subdevice *s)
  * Create the short linkchaining MITE linked list using kernel memory
  * a drop in replacement for mite_ll_from_user( ) 
  */
-unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,int len)
+unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,int reqlen)
 {
-       int i,size_so_far, continuous_aq;
+       int i,size_so_far, continuous_aq, len;
        unsigned long nup;
        unsigned long prealloc_buf,prealloc_bufsz; 
        //comedi_subdevice *s;
@@ -312,11 +312,14 @@ unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,in
        continuous_aq = (async->cmd.stop_src == TRIG_NONE? 1:0);
        if(continuous_aq) {
                len = prealloc_bufsz;
+       }else{
+               len = (reqlen>prealloc_bufsz?prealloc_bufsz:reqlen);
        }
        
-       if(async->data_len<len) {
-               printk("<1>Comedi Error: preallocated DMA buffer is too small to hold the samples.");
-       }
+       //if(async->data_len<len) {
+       //      printk("<1>Comedi Error: preallocated DMA buffer is too small to hold the samples.");
+       //}
+       
        //find the kernel's memory pages.
        nup = (unsigned long)async->data;
        i=0;
@@ -340,9 +343,15 @@ unsigned long mite_ll_from_kvmem(struct mite_struct *mite,comedi_async *async,in
        //mite->ring[i].count=0;
        
        if (continuous_aq&&(i>0)) {
-               mite->ring[i-1].next = virt_to_bus(mite->ring+0); 
-       }else {
+               mite->ring[i-1].next = virt_to_bus(mite->ring+0);
+               mite->DMA_CheckNearEnd = 0;
+       }else if (prealloc_bufsz < reqlen) {
+               mite->ring[i-1].next = virt_to_bus(mite->ring+0);
+               mite->DMA_CheckNearEnd = 1;
+       }       
+       else {
                mite->ring[i].count=0;
+               mite->DMA_CheckNearEnd = 0;
        }
 
        
index 61a06f8cd3660690e93afabd43951b6140d16b33..6fefaea51d38da269c2a7e28ee77bf44b071b3fb 100644 (file)
@@ -64,6 +64,8 @@ struct mite_struct{
        void *mite_io_addr;
        unsigned long daq_phys_addr;
        void *daq_io_addr;
+       
+       int DMA_CheckNearEnd;
 
        struct mite_dma_chain ring[MITE_RING_SIZE];
 };
index c41b0bc17bf66a61724095da2d2db34f219ecfe1..63fd009ed9fcd9b85e181f3fc0bd8fca17cd1120 100644 (file)
@@ -328,17 +328,19 @@ void ni_E_interrupt(int irq,void *d,struct pt_regs * regs)
 #ifdef PCIDMA
 static void mite_handle_interrupt(comedi_device *dev,unsigned long m_status)
 {
+       int len;
+       
        comedi_subdevice *s=dev->subdevices+0;
        
        comedi_event(dev,s,COMEDI_CB_BLOCK);
 
        MDPRINTK("mite_handle_interrupt\n");
        writel(CHOR_CLRLC, devpriv->mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(0));
-#if 0
+/*
        //Don't munge the data, just update the user's status variables
        s->async->buf_int_count=mite_bytes_transferred(devpriv->mite, 0);
        s->async->buf_int_ptr= s->async->buf_int_count % s->async->prealloc_bufsz;     
-#else
+*/
        //Munge the ADC data to change its format from twos complement to unsigned int
        //This is slow but makes it more compatible with other cards
        { 
@@ -354,7 +356,27 @@ static void mite_handle_interrupt(comedi_device *dev,unsigned long m_status)
                raw_ptr+s->async->prealloc_buf);
        s->async->buf_int_ptr = raw_ptr;
        }
-#endif
+
+
+       len = sizeof(sampl_t)*s->async->cmd.stop_arg*s->async->cmd.scan_end_arg;
+       if((devpriv->mite->DMA_CheckNearEnd)&&
+                       (s->async->buf_int_count > (len - s->async->prealloc_bufsz))) {
+               long offset;
+               int i;
+               
+               offset = len % s->async->prealloc_bufsz;
+               if(offset < devpriv->mite->ring[0].count) {
+                       devpriv->mite->ring[0].count = offset;
+                       devpriv->mite->ring[1].count = 0;
+               }else{
+                       offset -= devpriv->mite->ring[0].count;
+                       i = offset / PAGE_SIZE;
+                       devpriv->mite->ring[i].count = offset % PAGE_SIZE;
+                       devpriv->mite->ring[(i+1)%MITE_RING_SIZE].count = 0;                    
+               }
+               devpriv->mite->DMA_CheckNearEnd = 0;            
+       }
+
        MDPRINTK("CHSR is 0x%08lx, count is %d\n",m_status,s->async->buf_int_count);
        if(m_status&CHSR_DONE){
                writel(CHOR_CLRDONE, devpriv->mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(0));
@@ -735,10 +757,7 @@ int ni_ai_setup_block_dma(comedi_device *dev,int frob,int mode1)
                
        MDPRINTK("ni_ai_setup_block_dma\n");
                
-       /*Build MITE linked list and configure the MITE
-        * ******WARNING******
-        * There is no error handling here, 
-        * the memory buffer *Must* be mlock'ed by the user*/
+       /*Build MITE linked list and configure the MITE*/
 
        len = sizeof(sampl_t)*cmd->stop_arg*cmd->scan_end_arg;