return 1;
}
+void comedi_buf_copy_from(comedi_async *async, void *dest, int nbytes)
+{
+ void *src;
+
+ src = async->prealloc_buf + async->buf_read_ptr;
+ if(async->buf_read_ptr + nbytes >= async->prealloc_bufsz){
+ memcpy(dest, src,
+ async->prealloc_bufsz - async->buf_read_ptr - nbytes);
+ nbytes -= async->prealloc_bufsz - async->buf_read_ptr;
+ src = async->prealloc_buf;
+ dest += async->prealloc_bufsz - async->buf_read_ptr;
+ }
+ memcpy(dest, src, nbytes);
+}
+
// PCI vendor number of ComputerBoards/MeasurementComputing
#define PCI_VENDOR_ID_CB 0x1307
#define TIMER_BASE 100 // 10MHz master clock
-static const int max_fifo_size = 1024; // maximum fifo size of any supported board
#define NUM_CHANNELS_8800 8
#define NUM_CHANNELS_7376 1
#define NUM_CHANNELS_8402 2
static int cb_pcidas_ao_inttrig(comedi_device *dev, comedi_subdevice *s, unsigned int trig_num)
{
unsigned int i, num_points = thisboard->fifo_size;
- sampl_t data[max_fifo_size];
+ sampl_t d;
comedi_async *async = s->async;
comedi_cmd *cmd = &s->async->cmd;
if(cmd->stop_src == TRIG_COUNT &&
devpriv->ao_count < num_points)
num_points = devpriv->ao_count;
- for(i = 0; i < num_points; i++)
- {
- if(comedi_buf_get(async, &data[i]))
- break;
+
+ // write data to board's fifo
+ for(i = 0; i < num_points; i++) {
+ /* XXX check return value */
+ comedi_buf_get(async, &d);
+ outw(devpriv->ao_registers + DACDATA, d);
}
- if(cmd->stop_src == TRIG_COUNT)
- {
+ if(cmd->stop_src == TRIG_COUNT) {
devpriv->ao_count -= i;
}
- // write data to board's fifo
- outsw(devpriv->ao_registers + DACDATA, data, i);
// enable dac half-full and empty interrupts
devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
comedi_async *async;
int status, s5933_status;
int half_fifo = thisboard->fifo_size / 2;
- static const int max_half_fifo = 512; // maximum possible half-fifo size
- sampl_t data[max_half_fifo];
unsigned int num_samples, i;
static const int timeout = 10000;
// if fifo half-full
if(status & ADHFI)
{
+ int i;
+
// read data
num_samples = half_fifo;
if(async->cmd.stop_src == TRIG_COUNT &&
{
num_samples = devpriv->count;
}
- insw(devpriv->adc_fifo + ADCDATA, data, num_samples);
- comedi_buf_put_array(async, data, num_samples);
+ for(i=0;i<num_samples;i++){
+ comedi_buf_put(async, inw(devpriv->adc_fifo + ADCDATA));
+ }
devpriv->count -= num_samples;
if(async->cmd.stop_src == TRIG_COUNT &&
devpriv->count == 0)
// break if fifo is empty
if((ADNE & inw(devpriv->control_status + INT_ADCFIFO)) == 0)
break;
- data[0] = inw(devpriv->adc_fifo);
- comedi_buf_put(async, data[0]);
+ comedi_buf_put(async, inw(devpriv->adc_fifo + ADCDATA));
if(async->cmd.stop_src == TRIG_COUNT &&
--devpriv->count == 0)
{ /* end of acquisition */
comedi_async *async = s->async;
comedi_cmd *cmd = &async->cmd;
unsigned int half_fifo = thisboard->fifo_size / 2;
- static const int max_half_fifo = max_fifo_size / 2; // maximum possible half-fifo size
- sampl_t data[max_half_fifo];
unsigned int num_points, i;
async->events = 0;
}
}else if(status & DAHFI)
{
+ sampl_t d;
+
// figure out how many points we are writing to fifo
num_points = half_fifo;
if(cmd->stop_src == TRIG_COUNT &&
devpriv->ao_count < num_points)
num_points = devpriv->ao_count;
+ // write data to board's fifo
for(i = 0; i < num_points; i++)
{
- if(comedi_buf_get(async, &data[i]))
- break;
+ comedi_buf_get(async, &d);
+ outw(devpriv->ao_registers + DACDATA, d);
}
if(async->cmd.stop_src == TRIG_COUNT)
{
devpriv->ao_count -= i;
}
- // write data to board's fifo
- outsw(devpriv->ao_registers + DACDATA, data, i);
async->events |= COMEDI_CB_BLOCK;
// clear half-full interrupt latch
outw(devpriv->adc_fifo_bits | DAHFI, devpriv->control_status + INT_ADCFIFO);
static void das16m1_handler(comedi_device *dev, unsigned int status)
{
int i;
- sampl_t data[FIFO_SIZE];
comedi_subdevice *s;
comedi_async *async;
comedi_cmd *cmd;
// make sure we dont try to get too many points if fifo has overrun
if(num_samples > FIFO_SIZE)
num_samples = FIFO_SIZE;
- insw(dev->iobase, data, num_samples);
- for(i = 0; i < num_samples; i++)
- {
- data[i] = AI_DATA(data[i]);
+ for(i = 0; i < num_samples; i++) {
+ sampl_t d;
+
+ d = inw(dev->iobase);
+ /* XXX check return value */
+ comedi_buf_put(async, AI_DATA(d));
}
- comedi_buf_put_array(async, data, num_samples);
devpriv->adc_count += num_samples;
if(cmd->stop_src == TRIG_COUNT)
short *buf; /* DMA buffer */
int size; /* size of current transfer */
}dma[2];
- int dma_maxsize; /* max size of DMA transfer */
+ int dma_maxsize; /* max size of DMA transfer (in bytes) */
int usedma; /* driver uses DMA */
int current_dma_chan;
int dma_dir;
static int dt282x_grab_dma(comedi_device *dev,int dma1,int dma2);
-static void dt282x_cleanup_buffer(comedi_device *dev,unsigned short *buf,unsigned int len)
+static void dt282x_copy_to_buffer(comedi_device *dev,sampl_t *buf,
+ unsigned int nbytes)
{
+ comedi_async *async = dev->subdevices[0].async;
unsigned int i;
unsigned short mask=(1<<boardtype.adbits)-1;
unsigned short sign=1<<(boardtype.adbits-1);
+ unsigned short *abuf;
+ int n;
if(devpriv->ad_2scomp){
- for(i=0;i<len;i++){
- buf[i]&=mask;
- buf[i]^=sign;
- }
+ sign = 1<<(boardtype.adbits-1);
}else{
- for(i=0;i<len;i++){
- buf[i]&=mask;
+ sign = 0;
+ }
+
+ abuf = async->prealloc_buf + async->buf_write_ptr;
+ if(async->buf_write_ptr + nbytes >= async->prealloc_bufsz){
+ n = (async->prealloc_bufsz - async->buf_write_ptr - nbytes)/2;
+ for(i=0;i<n;i++){
+ abuf[i] = (buf[i]&mask)^sign;
}
+ nbytes -= n;
+ abuf = async->prealloc_buf;
+ buf = buf + i;
+ }
+ n = nbytes/2;
+ for(i=0;i<n;i++){
+ abuf[i] = (buf[i]&mask)^sign;
}
}
devpriv->current_dma_chan=1-i;
- size = comedi_buf_get_array( s->async, ptr, devpriv->dma_maxsize );
- if( size < 0){
- printk("dt282x: AO underrun\n");
+ size = comedi_buf_read_n_available(s->async);
+ if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;
+ if( size == 0){
+ rt_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;
}
+ comedi_buf_copy_from(s->async, ptr, size);
+ comedi_buf_read_free(s->async, size);
prep_ao_dma(dev,i,size);
-
enable_dma(devpriv->dma[i].chan);
comedi_event(dev,s,s->async->events);
void *ptr;
int size;
int i;
+ int ret;
comedi_subdevice *s=dev->subdevices;
update_supcsr(DT2821_CLRDMADNE);
return;
}
- i=devpriv->current_dma_chan;
- ptr=devpriv->dma[i].buf;
- size=devpriv->dma[i].size;
+ i = devpriv->current_dma_chan;
+ ptr = devpriv->dma[i].buf;
+ size = devpriv->dma[i].size;
disable_dma(devpriv->dma[i].chan);
- devpriv->current_dma_chan=1-i;
- dt282x_cleanup_buffer(dev,ptr,size);
- comedi_buf_put_array( s->async, ptr, size );
- devpriv->nread-=size;
+ devpriv->current_dma_chan = 1-i;
+
+ ret = comedi_buf_write_alloc(s->async, size);
+ if(!ret){
+ rt_printk("dt282x: AI buffer overflow\n");
+ s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+ comedi_event(dev,s,s->async->events);
+ return;
+ }
+ dt282x_copy_to_buffer(dev, ptr, size);
+ comedi_buf_write_free(s->async, size);
+
+ devpriv->nread-=size/2;
if(devpriv->nread<0){
printk("dt282x: off by one\n");
if(n==0)
n = devpriv->dma_maxsize;
- if (n >= devpriv->ntrig)
- n = devpriv->ntrig;
- devpriv->ntrig -= n;
+ if (n >= devpriv->ntrig*2)
+ n = devpriv->ntrig*2;
+ devpriv->ntrig -= n/2;
devpriv->dma[chan].size = n;
dma_chan = devpriv->dma[chan].chan;
set_dma_mode(dma_chan, DMA_MODE_READ);
flags=claim_dma_lock();
set_dma_addr(dma_chan, dma_ptr);
- set_dma_count(dma_chan, n << 1);
+ set_dma_count(dma_chan, n);
release_dma_lock(flags);
return n;
set_dma_mode(dma_chan, DMA_MODE_WRITE);
flags=claim_dma_lock();
set_dma_addr(dma_chan, dma_ptr);
- set_dma_count(dma_chan, n*2 );
+ set_dma_count(dma_chan, n );
release_dma_lock(flags);
return n;
comedi_subdevice *s = dev->subdevices+0;
unsigned int supcsr, adcsr, dacsr;
sampl_t data;
+ int ret;
adcsr=inw(dev->iobase + DT2821_ADCSR);
if (adcsr & DT2821_ADERR) {
if(devpriv->ad_2scomp){
data^=1<<(boardtype.adbits-1);
}
- comedi_buf_put( s->async, data );
+ ret = comedi_buf_put( s->async, data );
+ if(ret==0){
+ s->async->events |= COMEDI_CB_ERROR;
+ }
devpriv->nread--;
if(!devpriv->nread){
if(x!=0)return -EINVAL;
- size=comedi_buf_get_array( s->async, devpriv->dma[0].buf, devpriv->dma_maxsize);
- if( size < 0 ) return size;
-
+ size = comedi_buf_read_n_available(s->async);
+ if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;
+ if( size == 0){
+ rt_printk("dt282x: AO underrun\n");
+ return -EPIPE;
+ }
+ comedi_buf_copy_from(s->async, devpriv->dma[0].buf, size);
+ comedi_buf_read_free(s->async, size);
prep_ao_dma(dev,0,size);
enable_dma(devpriv->dma[0].chan);
- size=comedi_buf_get_array( s->async, devpriv->dma[1].buf, devpriv->dma_maxsize);
+ size = comedi_buf_read_n_available(s->async);
+ if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;
+ if( size == 0){
+ rt_printk("dt282x: AO underrun\n");
+ return -EPIPE;
+ }
+ comedi_buf_copy_from(s->async, devpriv->dma[1].buf, size);
+ comedi_buf_read_free(s->async, size);
prep_ao_dma(dev,1,size);
enable_dma(devpriv->dma[1].chan);
-
+
update_supcsr(DT2821_STRIG);
s->async->inttrig=NULL;
return -EBUSY;
devpriv->dma[1].chan=dma2;
- devpriv->dma_maxsize = PAGE_SIZE >> 1;
+ devpriv->dma_maxsize = PAGE_SIZE;
devpriv->dma[0].buf = (void *) get_free_page(GFP_KERNEL | GFP_DMA);
devpriv->dma[1].buf = (void *) get_free_page(GFP_KERNEL | GFP_DMA);
if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) {
int status;
unsigned long flags;
unsigned int max_points, num_points, residue, leftover;
+ int i;
status = devpriv->status1_bits;
}
/* write data to comedi buffer */
- comedi_buf_put_array(async, devpriv->dma_buffer, num_points);
+ for(i=0;i<num_points;i++){
+ /* XXX check for errors */
+ comedi_buf_put(async, devpriv->dma_buffer[i]);
+ }
if(async->cmd.stop_src == TRIG_COUNT) devpriv->count -= num_points;
// set address and count for next transfer
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);
+void comedi_buf_copy_from(comedi_async *async, void *dest, int nbytes);
//#ifdef CONFIG_COMEDI_RT