static int do_poll_ioctl(comedi_device *dev,unsigned int subd,void *file);
void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s);
-int resize_buf(comedi_device *dev,comedi_async *s, unsigned int size);
static int do_cancel(comedi_device *dev,comedi_subdevice *s);
static int comedi_fasync (int fd, struct file *file, int on);
if(!async->prealloc_buf)
return -EINVAL;
- ret = resize_buf(dev,async,bc.size);
+ /* make sure buffer is an integral number of pages
+ * (we round up) */
+ bc.size = (bc.size + 1)&PAGE_MASK;
+
+ ret = s->buf_alloc(dev,s,bc.size);
if(ret < 0)
return ret;
return 0;
}
-/* utility function that resizes the prealloc_buf for
- * a subdevice
- */
-int resize_buf(comedi_device *dev, comedi_async *async, unsigned int size)
-{
- void *old_buf;
-
- // make sure buffer is an integral number of pages (we round up)
- size = ((size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
-
- // if no change is required, do nothing
- if(async->prealloc_buf && async->prealloc_bufsz &&
- async->prealloc_bufsz == size)
- {
- return 0;
- }
-
- old_buf = async->prealloc_buf;
- async->prealloc_buf = rvmalloc(size);
- // restore old buffer on error
- if(async->prealloc_buf == NULL){
- async->prealloc_buf = old_buf;
- return -ENOMEM;
- }
-
- rvfree(old_buf, async->prealloc_bufsz);
- async->prealloc_bufsz = size;
-
- return 0;
-}
-
/*
COMEDI_DEVINFO
device info ioctl
static void *comedi_recognize(comedi_driver *driv, const char *name);
static void comedi_report_boards(comedi_driver *driv);
static int poll_invalid(comedi_device *dev,comedi_subdevice *s);
+static int buf_alloc(comedi_device *dev, comedi_subdevice *s,
+ unsigned long new_size);
comedi_driver *comedi_drivers;
for(i=0;i<dev->n_subdevices;i++){
s=dev->subdevices+i;
if(s->async){
- rvfree(s->async->prealloc_buf,s->async->prealloc_bufsz);
+ if(s->buf_alloc) s->buf_alloc(dev,s,0);
kfree(s->async);
}
}
}
memset(async, 0, sizeof(comedi_async));
s->async = async;
- async->max_bufsize=64*1024;
- async->prealloc_bufsz=16*1024;
- async->prealloc_buf=rvmalloc(async->prealloc_bufsz);
- if(!async->prealloc_buf){
- printk("ENOMEM\n");
- kfree(async);
+
+#define DEFAULT_BUF_MAXSIZE (64*1024)
+#define DEFAULT_BUF_SIZE (16*1024)
+
+ async->max_bufsize = DEFAULT_BUF_MAXSIZE;
+ if(!s->buf_alloc) s->buf_alloc = buf_alloc;
+
+ async->prealloc_buf = NULL;
+ async->prealloc_bufsz = 0;
+ if(s->buf_alloc(dev,s,DEFAULT_BUF_SIZE) < 0){
+ printk("Buffer allocation failed\n");
return -ENOMEM;
}
}
return 1;
}
+/*
+ * Default allocator for Comedi buffers
+ * Override function should allocate a new buffer of size new_size,
+ * and update async->prealloc_buf and async->prealloc_bufsz. Set
+ * NULL and 0 if the allocation fails. If new_size is 0, deallocate
+ * the old buffer and don't allocate a new one.
+ */
+static int buf_alloc(comedi_device *dev, comedi_subdevice *s,
+ unsigned long new_size)
+{
+ comedi_async *async = s->async;
+
+ /* if no change is required, do nothing */
+ if(async->prealloc_buf && async->prealloc_bufsz == new_size){
+ return 0;
+ }
+
+ if(async->prealloc_bufsz){
+ rvfree(async->prealloc_buf, async->prealloc_bufsz);
+ async->prealloc_buf = NULL;
+ }
+
+ if(new_size){
+ async->prealloc_buf = rvmalloc(new_size);
+ if(async->prealloc_buf == NULL){
+ async->prealloc_bufsz = 0;
+ return -ENOMEM;
+ }
+ }
+ async->prealloc_bufsz = new_size;
+
+ return 0;
+}
+
References for specifications:
- 321747b.pdf Register Level Programmer Manual (obsolete)
- 321747c.pdf Register Level Programmer Manual (new)
+ 340747c.pdf Register Level Programmer Manual
DAQ-STC reference manual
Other possibly relevant info:
static struct caldac_struct *type3[]={&caldac_mb88341,NULL,NULL};
static struct caldac_struct *type4[]={&caldac_mb88341,&caldac_mb88341,&caldac_ad8522};
-#define MAX_N_CALDACS (12+12+2)
+#define MAX_N_CALDACS (16+16+2)
#define NI_VENDOR_ID 0x1093
/* The following two tables must be in the same order */
struct mite_struct *mite;
NI_PRIVATE_COMMON
+
+ dma_addr_t ai_dma_handle;
}ni_private;
#define devpriv ((ni_private *)dev->private)
static int pcimio_find_device(comedi_device *dev,int bus,int slot);
+static int pcimio_ai_alloc(comedi_device *dev, comedi_subdevice *s,
+ unsigned long new_size);
/* cleans up allocated resources */
dev->irq=0;
}
}
- return ni_E_init(dev,it);
+
+ ret = ni_E_init(dev,it);
+ if(ret<0)return ret;
+
+ dev->subdevices[0].buf_alloc = pcimio_ai_alloc;
+
+ return ret;
}
return -EIO;
}
+/* This needs to be fixed before it can be used for AO, since it
+ * uses devpriv->ai_dma_handle */
+static int pcimio_ai_alloc(comedi_device *dev, comedi_subdevice *s,
+ unsigned long new_size)
+{
+ comedi_async *async = s->async;
+
+ if(async->prealloc_buf && async->prealloc_bufsz == new_size){
+ return 0;
+ }
+
+ if(async->prealloc_bufsz){
+ pci_free_consistent(devpriv->mite->pcidev,
+ async->prealloc_bufsz, async->prealloc_buf,
+ devpriv->ai_dma_handle);
+ async->prealloc_buf = NULL;
+ async->prealloc_bufsz = 0;
+ }
+
+ if(new_size){
+ async->prealloc_buf = pci_alloc_consistent(devpriv->mite->pcidev,
+ new_size, &devpriv->ai_dma_handle);
+ if(async->prealloc_buf == NULL){
+ async->prealloc_bufsz = 0;
+ return -ENOMEM;
+ }
+ }
+ async->prealloc_bufsz = new_size;
+
+ return 0;
+}
+
+