From 30bdde4ced639fb7e9a1b44175ab43a72d8d6b9e Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 25 Jul 2002 23:31:45 +0000 Subject: [PATCH] Update DMA code for recent buffer changes --- comedi/drivers/ni_mio_common.c | 106 ++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 48 deletions(-) diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index b2c98930..a37722ab 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -250,7 +250,7 @@ static void handle_a_interrupt(comedi_device *dev,unsigned short status, static void handle_b_interrupt(comedi_device *dev,unsigned short status); #ifdef PCIDMA //static void mite_handle_interrupt(comedi_device *dev,unsigned int status); -static void ni_munge(comedi_device *dev,comedi_subdevice *s,sampl_t *start, sampl_t *stop); +static void ni_munge(comedi_device *dev,comedi_subdevice *s,sampl_t *data, int nbytes); #endif /* ni_set_bits( ) allows different parts of the ni_mio_common driver to @@ -349,47 +349,40 @@ static void mite_handle_a_linkc(struct mite_struct *mite, comedi_device *dev) int count; comedi_subdevice *s = dev->subdevices + 0; comedi_async *async = s->async; + int nbytes; + int ret; writel(CHOR_CLRLC, mite->mite_io_addr+MITE_CHOR+CHAN_OFFSET(mite->chan)); - 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); + nbytes = mite_bytes_transferred(mite, 0); + if(nbytes >= async->buf_free_count){ + printk("ni_mio_common: BUG: DMA overwrite of free area\n"); + ni_ai_reset(dev,s); + async->events |= COMEDI_CB_OVERFLOW; return; } - 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_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_write_ptr + count >= async->prealloc_bufsz){ - ni_munge(dev,s, - async->prealloc_buf + async->buf_write_ptr, - async->prealloc_buf + 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_write_ptr); - }else{ + count = nbytes - async->buf_write_count; + + while(count >= PAGE_SIZE){ + if(!(async->cmd.flags & CMDF_RAWDATA)){ ni_munge(dev,s, async->prealloc_buf + async->buf_write_ptr, - async->prealloc_buf + async->buf_write_ptr + count); - async->buf_write_ptr += count; + PAGE_SIZE); } + comedi_buf_write_free(async,PAGE_SIZE); + + ret = comedi_buf_write_alloc(s->async, PAGE_SIZE); + if(retevents |= COMEDI_CB_OVERFLOW; + } + + count -= PAGE_SIZE; } - s->async->events |= COMEDI_CB_BLOCK; + + async->events |= COMEDI_CB_BLOCK; } #if 0 @@ -581,7 +574,7 @@ static void handle_b_interrupt(comedi_device *dev,unsigned short b_status) if(b_status&AO_Overrun_St){ rt_printk("ni_mio_common: AO FIFO underrun status=0x%04x status2=0x%04x\n",b_status,win_in(AO_Status_2_Register)); ni_ao_reset(dev,s); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_OVERFLOW; } if(b_status&AO_BC_TC_St){ @@ -600,7 +593,7 @@ static void handle_b_interrupt(comedi_device *dev,unsigned short b_status) rt_printk("Ack! didn't clear AO interrupt. b_status=0x%04x\n",b_status); win_out(0,Interrupt_B_Enable_Register); ni_ao_reset(dev,s); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_OVERFLOW; } comedi_event(dev,s,s->async->events); @@ -658,12 +651,16 @@ static void ni_ai_fifo_read(comedi_device *dev,comedi_subdevice *s, int i; sampl_t d; unsigned int mask; + int err = 1; mask=(1<ai_xorlist[ async->cur_chan ]; - comedi_buf_put(async, d); + err &= comedi_buf_put(async, d); + } + if(err==0){ + async->events |= COMEDI_CB_OVERFLOW; } } @@ -698,6 +695,7 @@ static void ni_handle_fifo_dregs(comedi_device *dev) int i,n; unsigned int mask; unsigned int dl; + int err = 1; mask=(1<>16) + devpriv->ai_xorlist[async->cur_chan]; - comedi_buf_put(s->async, data); + err &= comedi_buf_put(s->async, data); data = (dl&0xffff) + devpriv->ai_xorlist[async->cur_chan]; - comedi_buf_put(s->async, data); + err &= 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); + err &= comedi_buf_put(s->async, data); } }else{ while(1){ @@ -726,25 +724,26 @@ 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); + err &= comedi_buf_put(s->async, data); } } } + if(err==0){ + async->events |= COMEDI_CB_OVERFLOW; + } } #ifdef PCIDMA -static void ni_munge(comedi_device *dev,comedi_subdevice *s,sampl_t *start, - sampl_t *stop) +static void ni_munge(comedi_device *dev,comedi_subdevice *s,sampl_t *data, + int nbytes) { comedi_async *async = s->async; unsigned int j; - sampl_t *i; - unsigned int mask; - mask=(1<cur_chan; - for(i=start;iai_xorlist[j]; + for(;nbytes>0;nbytes-=2){ + *data = __le16_to_cpu(*data) + devpriv->ai_xorlist[j]; + data++; j++; if(j>=async->cmd.chanlist_len)j=0; } @@ -773,6 +772,10 @@ static void ni_handle_block_dma(comedi_device *dev) static void ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd) { struct mite_struct *mite = devpriv->mite; + comedi_subdevice *s = dev->subdevices + 0; + + /* mark 2 pages as being under DMA control */ + comedi_buf_write_alloc(s->async, 2*PAGE_SIZE); mite->current_link = 0; mite->chan = 0; @@ -1657,6 +1660,7 @@ static void ni_ao_fifo_load(comedi_device *dev,comedi_subdevice *s, int n) sampl_t d; int range; int offset; + int err = 1; if(boardtype.reg_611x){ port = DAC_FIFO_Data_611x; @@ -1667,7 +1671,7 @@ static void ni_ao_fifo_load(comedi_device *dev,comedi_subdevice *s, int n) offset = 1 << (boardtype.aobits - 1); chan = async->cur_chan; for(i=0;ichanlist[chan]); if(!boardtype.ao_unipolar || !(range & 1)){ @@ -1680,6 +1684,9 @@ static void ni_ao_fifo_load(comedi_device *dev,comedi_subdevice *s, int n) if(chan>=cmd->chanlist_len)chan=0; } async->cur_chan = chan; + if(err==0){ + async->events |= COMEDI_CB_OVERFLOW; + } } @@ -1704,7 +1711,10 @@ static int ni_ao_fifo_half_empty(comedi_device *dev,comedi_subdevice *s) int n; n = comedi_buf_read_n_available(s->async); - if(n==0)return 0; + if(n==0){ + s->async->events |= COMEDI_CB_OVERFLOW; + return 0; + } n /= sizeof(sampl_t); if(n>boardtype.ao_fifo_depth/2) -- 2.26.2