From: David Schleef Date: Mon, 4 Feb 2002 00:28:19 +0000 (+0000) Subject: Change Comedi buffer allocator to use a virtual function in the X-Git-Tag: r0_7_64~157 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=67bc5306f98eb2fc6bb5be7703b4f78d59d0d93a;p=comedi.git Change Comedi buffer allocator to use a virtual function in the 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. --- diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c index 4060f2e0..01c8b89e 100644 --- a/comedi/comedi_fops.c +++ b/comedi/comedi_fops.c @@ -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 diff --git a/comedi/drivers.c b/comedi/drivers.c index fc098c1e..1456a4c3 100644 --- a/comedi/drivers.c +++ b/comedi/drivers.c @@ -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;in_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; +} + diff --git a/comedi/drivers/ni_pcimio.c b/comedi/drivers/ni_pcimio.c index 799a39bb..3220bd93 100644 --- a/comedi/drivers/ni_pcimio.c +++ b/comedi/drivers/ni_pcimio.c @@ -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; +} + +