Change Comedi buffer allocator to use a virtual function in the
authorDavid Schleef <ds@schleef.org>
Mon, 4 Feb 2002 00:28:19 +0000 (00:28 +0000)
committerDavid Schleef <ds@schleef.org>
Mon, 4 Feb 2002 00:28:19 +0000 (00:28 +0000)
subdevice structure.  Added a default allocator.  Added an override
in ni_pcimio, to use dma_alloc_consistent.  Changed the number of
maximum caldac in ni_pcimio -- mostly bogus, but is used for testing.

comedi/comedi_fops.c
comedi/drivers.c
comedi/drivers/ni_pcimio.c

index 4060f2e07f42897b7e760a49d99f77bc99d20784..01c8b89e6778d73f2c042d49624858d3ac3bf7af 100644 (file)
@@ -70,7 +70,6 @@ static int do_insn_ioctl(comedi_device *dev,void *arg,void *file);
 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);
@@ -217,7 +216,11 @@ static int do_bufconfig_ioctl(comedi_device *dev,void *arg)
                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;
@@ -236,37 +239,6 @@ copyback:
        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
index fc098c1e26007562bc0ed93dcaf985fe8cd0ef3c..1456a4c37fa5629e6348e89796a1cf2a0ac1d192 100644 (file)
@@ -45,6 +45,8 @@ static int insn_inval(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,l
 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;
 
@@ -70,7 +72,7 @@ int comedi_device_detach(comedi_device *dev)
        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);
                }
        }
@@ -241,12 +243,17 @@ static int postconfig(comedi_device *dev)
                        }
                        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;
                        }
                }
@@ -350,3 +357,37 @@ static int insn_rw_emulate_bits(comedi_device *dev,comedi_subdevice *s,
        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;
+}
+
index 799a39bb61e69709c3893c7810c37f00a49fc9ae..3220bd935711c763edc2dd7b346eb465c1412777 100644 (file)
@@ -52,8 +52,7 @@ DMA is halfway completed, but not yet operational.
 
        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:
@@ -115,7 +114,7 @@ static struct caldac_struct *type2[]={&caldac_dac8800,&caldac_dac8043,&caldac_ad
 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 */
@@ -570,6 +569,8 @@ typedef struct{
        struct mite_struct *mite;
 
        NI_PRIVATE_COMMON
+       
+       dma_addr_t ai_dma_handle;
 }ni_private;
 #define devpriv ((ni_private *)dev->private)
 
@@ -578,6 +579,8 @@ typedef struct{
 
 
 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 */
@@ -629,7 +632,13 @@ static int pcimio_attach(comedi_device *dev,comedi_devconfig *it)
                        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;
 }
 
 
@@ -666,3 +675,36 @@ static int pcimio_find_device(comedi_device *dev,int bus,int slot)
        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;
+}
+
+