From 62b05e33cdd055a2d2e5c034fc373d899cfda58e Mon Sep 17 00:00:00 2001 From: Tim Ousley Date: Sat, 28 Jul 2001 19:48:01 +0000 Subject: [PATCH] MITE DMA works with any size acquisition and any size buffer, although large buffers are still best. --- comedi/drivers/mite.c | 25 +++++++++++++++++-------- comedi/drivers/mite.h | 2 ++ comedi/drivers/ni_mio_common.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/comedi/drivers/mite.c b/comedi/drivers/mite.c index 86abb68c..6a259f6e 100644 --- a/comedi/drivers/mite.c +++ b/comedi/drivers/mite.c @@ -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_lenComedi Error: preallocated DMA buffer is too small to hold the samples."); - } + //if(async->data_lenComedi 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; } diff --git a/comedi/drivers/mite.h b/comedi/drivers/mite.h index 61a06f8c..6fefaea5 100644 --- a/comedi/drivers/mite.h +++ b/comedi/drivers/mite.h @@ -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]; }; diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index c41b0bc1..63fd009e 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -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; -- 2.26.2