3 functions for manipulating drivers
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define __NO_VERSION__
27 #include "comedi_fops.h"
28 #include <linux/device.h>
29 #include <linux/module.h>
30 #include <linux/errno.h>
31 #include <linux/kernel.h>
32 #include <linux/sched.h>
33 #include <linux/fcntl.h>
34 #include <linux/delay.h>
35 #include <linux/ioport.h>
37 #include <linux/slab.h>
38 #include <linux/comedidev.h>
39 #include <linux/wrapper.h>
40 #include <linux/highmem.h> /* for SuSE brokenness */
41 #include <linux/vmalloc.h>
42 #include <linux/cdev.h>
43 #include <linux/dma-mapping.h>
46 #include <asm/system.h>
48 static int postconfig(comedi_device *dev);
49 static int insn_rw_emulate_bits(comedi_device *dev,comedi_subdevice *s,
50 comedi_insn *insn,lsampl_t *data);
51 static int insn_inval(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
52 static void *comedi_recognize(comedi_driver *driv, const char *name);
53 static void comedi_report_boards(comedi_driver *driv);
54 static int poll_invalid(comedi_device *dev,comedi_subdevice *s);
55 int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s,
56 unsigned long new_size);
58 comedi_driver *comedi_drivers;
60 int comedi_modprobe(int minor)
65 static void cleanup_device(comedi_device *dev)
72 for(i = 0; i < dev->n_subdevices; i++)
74 s = dev->subdevices + i;
77 unsigned minor = comedi_construct_minor_for_subdevice(dev, i);
78 dev_t devt = MKDEV(COMEDI_MAJOR, minor);
79 class_device_destroy(comedi_class, devt);
83 comedi_buf_alloc(dev, s, 0);
87 kfree(dev->subdevices);
88 dev->subdevices = NULL;
89 dev->n_subdevices = 0;
96 module_put(dev->driver->module);
98 dev->board_name = NULL;
99 dev->board_ptr = NULL;
102 dev->read_subdev = NULL;
103 dev->write_subdev = NULL;
106 comedi_set_hw_dev(dev, NULL);
109 static int __comedi_device_detach(comedi_device *dev)
113 dev->driver->detach(dev);
115 printk("BUG: dev->driver=NULL in comedi_device_detach()\n");
121 int comedi_device_detach(comedi_device *dev)
125 return __comedi_device_detach(dev);
128 int comedi_device_attach(comedi_device *dev,comedi_devconfig *it)
136 for(driv=comedi_drivers;driv;driv=driv->next){
137 if(!try_module_get( driv->module ))
139 printk( "comedi: failed to increment module count, skipping\n" );
143 dev->board_ptr = comedi_recognize(driv, it->board_name);
144 if(dev->board_ptr==NULL){
145 module_put( driv->module );
149 if(strcmp(driv->driver_name,it->board_name)){
150 module_put( driv->module );
154 //initialize dev->driver here so comedi_error() can be called from attach
156 ret=driv->attach(dev,it);
158 __comedi_device_detach(dev);
164 // recognize has failed if we get here
165 // report valid board names before returning error
166 for(driv=comedi_drivers;driv;driv=driv->next){
167 if(!try_module_get( driv->module ))
169 printk( "comedi: failed to increment module count\n" );
172 comedi_report_boards(driv);
173 module_put( driv->module );
178 /* do a little post-config cleanup */
179 ret = postconfig(dev);
182 __comedi_device_detach(dev);
186 init_waitqueue_head(&dev->read_wait);
187 init_waitqueue_head(&dev->write_wait);
189 if(!dev->board_name){
190 printk("BUG: dev->board_name=<%p>\n",dev->board_name);
191 dev->board_name="BUG";
199 int comedi_driver_register(comedi_driver *driver)
201 driver->next=comedi_drivers;
202 comedi_drivers=driver;
207 int comedi_driver_unregister(comedi_driver *driver)
212 /* check for devices using this driver */
213 for(i=0;i<COMEDI_NDEVICES;i++){
216 dev = comedi_devices + i;
217 if(dev->attached && dev->driver==driver){
219 printk("BUG! detaching device with use_count=%d\n",dev->use_count);
220 comedi_device_detach(dev);
224 if(comedi_drivers==driver){
225 comedi_drivers=driver->next;
229 for(prev=comedi_drivers;prev->next;prev=prev->next){
230 if(prev->next==driver){
231 prev->next=driver->next;
238 comedi_device *comedi_allocate_dev(comedi_driver *driver)
243 void comedi_deallocate_dev(comedi_device *dev)
248 static int postconfig(comedi_device *dev)
252 comedi_async *async = NULL;
255 for(i=0;i<dev->n_subdevices;i++){
258 if(s->type==COMEDI_SUBD_UNUSED)
261 if(s->len_chanlist==0)
268 BUG_ON((s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) == 0);
270 async = kmalloc(sizeof(comedi_async), GFP_KERNEL);
273 printk("failed to allocate async struct\n");
276 memset(async, 0, sizeof(comedi_async));
277 async->subdevice = s;
280 #define DEFAULT_BUF_MAXSIZE (64*1024)
281 #define DEFAULT_BUF_SIZE (64*1024)
283 async->max_bufsize = DEFAULT_BUF_MAXSIZE;
285 async->prealloc_buf = NULL;
286 async->prealloc_bufsz = 0;
287 if(comedi_buf_alloc(dev,s,DEFAULT_BUF_SIZE) < 0){
288 printk("Buffer allocation failed\n");
292 ret = s->buf_change(dev,s,DEFAULT_BUF_SIZE);
293 if(ret < 0)return ret;
295 minor = comedi_construct_minor_for_subdevice(dev, i);
296 devt = MKDEV(COMEDI_MAJOR, minor);
297 s->class_dev = COMEDI_CLASS_DEVICE_CREATE(comedi_class, dev->class_dev,
298 devt, NULL, "comedi%i_sub%i", dev->minor, i);
301 if(!s->range_table && !s->range_table_list)
302 s->range_table=&range_unknown;
304 if(!s->insn_read && s->insn_bits)
305 s->insn_read = insn_rw_emulate_bits;
306 if(!s->insn_write && s->insn_bits)
307 s->insn_write = insn_rw_emulate_bits;
309 if(!s->insn_read)s->insn_read = insn_inval;
310 if(!s->insn_write)s->insn_write = insn_inval;
311 if(!s->insn_bits)s->insn_bits = insn_inval;
312 if(!s->insn_config)s->insn_config = insn_inval;
314 if(!s->poll)s->poll=poll_invalid;
320 // generic recognize function for drivers that register their supported board names
321 void *comedi_recognize(comedi_driver *driv, const char *name)
324 const char * const *name_ptr = driv->board_name;
325 for(i = 0; i < driv->num_names; i++)
327 if(strcmp(*name_ptr, name) == 0)
328 return (void*)name_ptr;
329 name_ptr = (const char * const *)((const char *)name_ptr + driv->offset);
335 void comedi_report_boards(comedi_driver *driv)
338 const char * const *name_ptr;
340 printk("comedi: valid board names for %s driver are:\n", driv->driver_name);
342 name_ptr = driv->board_name;
343 for(i = 0; i < driv->num_names; i++)
345 printk(" %s\n", *name_ptr);
346 name_ptr = (const char **)((char *)name_ptr + driv->offset);
349 if(driv->num_names == 0)
350 printk(" %s\n", driv->driver_name);
353 static int poll_invalid(comedi_device *dev,comedi_subdevice *s)
358 static int insn_inval(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
363 static int insn_rw_emulate_bits(comedi_device *dev,comedi_subdevice *s,
364 comedi_insn *insn,lsampl_t *data)
366 comedi_insn new_insn;
368 static const unsigned channels_per_bitfield = 32;
370 unsigned chan = CR_CHAN(insn->chanspec);
371 const unsigned base_bitfield_channel = (chan < channels_per_bitfield) ? 0 : chan;
372 lsampl_t new_data[2];
373 memset(new_data, 0, sizeof(new_data));
374 memset(&new_insn, 0, sizeof(new_insn));
375 new_insn.insn = INSN_BITS;
376 new_insn.chanspec = base_bitfield_channel;
378 new_insn.data = new_data;
379 new_insn.subdev = insn->subdev;
381 if(insn->insn == INSN_WRITE)
383 if(!(s->subdev_flags & SDF_WRITABLE))
385 new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */
386 new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel)) : 0; /* bits */
389 ret = s->insn_bits(dev,s,&new_insn,new_data);
390 if(ret < 0) return ret;
392 if(insn->insn == INSN_READ){
393 data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1;
400 static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
402 unsigned long ret = 0UL;
408 pud = pud_offset(pgd, adr);
409 pmd = pmd_offset(pud, adr);
411 ptep = pte_offset_kernel(pmd, adr);
413 if(pte_present(pte)){
414 ret = (unsigned long) page_address(pte_page(pte));
415 ret |= (adr & (PAGE_SIZE - 1));
422 static inline unsigned long kvirt_to_kva(unsigned long adr)
424 unsigned long va, kva;
427 kva = uvirt_to_kva(pgd_offset_k(va), va);
433 int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s,
434 unsigned long new_size)
436 comedi_async *async = s->async;
438 /* if no change is required, do nothing */
439 if(async->prealloc_buf && async->prealloc_bufsz == new_size){
442 // deallocate old buffer
443 if(async->prealloc_buf && s->async_dma_dir != DMA_NONE)
445 vunmap(async->prealloc_buf);
446 async->prealloc_buf = NULL;
447 async->prealloc_bufsz = 0;
449 if(async->buf_page_list)
452 for(i = 0; i < async->n_buf_pages; ++i)
454 if(async->buf_page_list[i].virt_addr)
455 mem_map_unreserve(virt_to_page(async->buf_page_list[i].virt_addr));
456 if(async->buf_page_list[i].dma_addr)
458 dma_free_coherent(dev->hw_dev, PAGE_SIZE,
459 async->buf_page_list[i].virt_addr, async->buf_page_list[i].dma_addr);
462 vfree(async->buf_page_list);
463 async->buf_page_list = NULL;
464 async->n_buf_pages = 0;
466 if(async->prealloc_buf && s->async_dma_dir == DMA_NONE)
468 vfree(async->prealloc_buf);
469 async->prealloc_buf = NULL;
470 async->prealloc_bufsz = 0;
472 // allocate new buffer
475 unsigned n_pages = (new_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
477 // size is rounded up to nearest multiple of PAGE_SIZE
478 new_size = n_pages << PAGE_SHIFT;
480 async->buf_page_list = vmalloc(sizeof(struct comedi_buf_page) * n_pages);
481 if(async->buf_page_list == NULL)
485 memset(async->buf_page_list, 0, sizeof(struct comedi_buf_page) * n_pages);
486 async->n_buf_pages = n_pages;
488 if(s->async_dma_dir != DMA_NONE)
490 struct page** pages = NULL;
492 pages = vmalloc(sizeof(struct page*) * n_pages);
497 for(i = 0; i < n_pages; i++)
499 async->buf_page_list[i].virt_addr = dma_alloc_coherent(dev->hw_dev,
500 PAGE_SIZE, &async->buf_page_list[i].dma_addr, GFP_KERNEL | __GFP_COMP);
501 if(async->buf_page_list[i].virt_addr == NULL)
506 mem_map_reserve(virt_to_page(async->buf_page_list[i].virt_addr));
507 pages[i] = virt_to_page(async->buf_page_list[i].virt_addr);
509 async->prealloc_buf = vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NOCACHE);
511 if(async->prealloc_buf == NULL) return -ENOMEM;
514 async->prealloc_buf = vmalloc(new_size);
515 if(async->prealloc_buf == NULL)
519 for(i = 0; i < n_pages; i++)
521 async->buf_page_list[i].virt_addr = async->prealloc_buf + PAGE_SIZE * i;
522 mem_map_reserve(virt_to_page(async->buf_page_list[i].virt_addr));
526 async->prealloc_bufsz = new_size;
531 /* munging is applied to data by core as it passes between user
532 * and kernel space */
533 unsigned int comedi_buf_munge(comedi_async *async,
534 unsigned int num_bytes)
536 comedi_subdevice *s = async->subdevice;
537 unsigned int count = 0;
538 const unsigned num_sample_bytes = bytes_per_sample(s);
540 if( s->munge == NULL || ( async->cmd.flags & CMDF_RAWDATA ) )
542 async->munge_count += num_bytes;
543 if((int)(async->munge_count - async->buf_write_count) > 0) BUG();
546 /* don't munge partial samples */
547 num_bytes -= num_bytes % num_sample_bytes;
548 while( count < num_bytes )
552 block_size = num_bytes - count;
555 rt_printk("%s: %s: bug! block_size is negative\n", __FILE__, __FUNCTION__);
558 if( (int)(async->munge_ptr + block_size - async->prealloc_bufsz) > 0 )
559 block_size = async->prealloc_bufsz - async->munge_ptr;
561 s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
562 block_size, async->munge_chan );
564 smp_wmb(); //barrier insures data is munged in buffer before munge_count is incremented
566 async->munge_chan += block_size / num_sample_bytes;
567 async->munge_chan %= async->cmd.chanlist_len;
568 async->munge_count += block_size;
569 async->munge_ptr += block_size;
570 async->munge_ptr %= async->prealloc_bufsz;
573 if((int)(async->munge_count - async->buf_write_count) > 0) BUG();
577 unsigned int comedi_buf_write_n_available(comedi_async *async)
579 unsigned int free_end;
582 if(async == NULL) return 0;
584 free_end = async->buf_read_count + async->prealloc_bufsz;
585 nbytes = free_end - async->buf_write_alloc_count;
586 nbytes -= nbytes % bytes_per_sample(async->subdevice);
587 /* barrier insures the read of buf_read_count in this
588 query occurs before any following writes to the buffer which
589 might be based on the return value from this query.
595 /* allocates chunk for the writer from free buffer space */
596 unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes)
598 unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
600 if((int)(async->buf_write_alloc_count + nbytes - free_end) > 0){
601 nbytes = free_end - async->buf_write_alloc_count;
603 async->buf_write_alloc_count += nbytes;
604 /* barrier insures the read of buf_read_count above occurs before
605 we write data to the write-alloc'ed buffer space */
610 /* allocates nothing unless it can completely fulfill the request */
611 unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
614 unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
616 if((int)(async->buf_write_alloc_count + nbytes - free_end) > 0){
619 async->buf_write_alloc_count += nbytes;
620 /* barrier insures the read of buf_read_count above occurs before
621 we write data to the write-alloc'ed buffer space */
626 /* transfers a chunk from writer to filled buffer space */
627 unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes)
629 if((int)(async->buf_write_count + nbytes - async->buf_write_alloc_count) > 0)
631 rt_printk("comedi: attempted to write-free more bytes than have been write-allocated.\n");
632 nbytes = async->buf_write_alloc_count - async->buf_write_count;
634 async->buf_write_count += nbytes;
635 async->buf_write_ptr += nbytes;
636 comedi_buf_munge(async, async->buf_write_count - async->munge_count);
637 if(async->buf_write_ptr >= async->prealloc_bufsz){
638 async->buf_write_ptr %= async->prealloc_bufsz;
643 /* allocates a chunk for the reader from filled (and munged) buffer space */
644 unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes)
646 if((int)(async->buf_read_alloc_count + nbytes - async->munge_count) > 0)
648 nbytes = async->munge_count - async->buf_read_alloc_count;
650 async->buf_read_alloc_count += nbytes;
651 /* barrier insures read of munge_count occurs before we actually read
652 data out of buffer */
657 /* transfers control of a chunk from reader to free buffer space */
658 unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes)
660 // barrier insures data has been read out of buffer before read count is incremented
662 if((int)(async->buf_read_count + nbytes - async->buf_read_alloc_count) > 0)
664 rt_printk("comedi: attempted to read-free more bytes than have been read-allocated.\n");
665 nbytes = async->buf_read_alloc_count - async->buf_read_count;
667 async->buf_read_count += nbytes;
668 async->buf_read_ptr += nbytes;
669 async->buf_read_ptr %= async->prealloc_bufsz;
673 void comedi_buf_memcpy_to( comedi_async *async, unsigned int offset, const void *data,
674 unsigned int num_bytes )
676 unsigned int write_ptr = async->buf_write_ptr + offset;
678 if( write_ptr >= async->prealloc_bufsz )
679 write_ptr %= async->prealloc_bufsz;
683 unsigned int block_size;
685 if( write_ptr + num_bytes > async->prealloc_bufsz)
686 block_size = async->prealloc_bufsz - write_ptr;
688 block_size = num_bytes;
690 memcpy( async->prealloc_buf + write_ptr, data, block_size );
693 num_bytes -= block_size;
699 void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset,
700 void *dest, unsigned int nbytes)
703 unsigned int read_ptr = async->buf_read_ptr + offset;
705 if( read_ptr >= async->prealloc_bufsz )
706 read_ptr %= async->prealloc_bufsz;
710 unsigned int block_size;
712 src = async->prealloc_buf + read_ptr;
714 if( nbytes >= async->prealloc_bufsz - read_ptr )
715 block_size = async->prealloc_bufsz - read_ptr;
719 memcpy(dest, src, block_size );
720 nbytes -= block_size;
726 unsigned int comedi_buf_read_n_available(comedi_async *async)
732 num_bytes = async->munge_count - async->buf_read_count;
733 /* barrier insures the read of munge_count in this
734 query occurs before any following reads of the buffer which
735 might be based on the return value from this query.
741 int comedi_buf_get(comedi_async *async, sampl_t *x)
743 unsigned int n = comedi_buf_read_n_available(async);
745 if(n < sizeof(sampl_t)) return 0;
746 comedi_buf_read_alloc(async, sizeof(sampl_t));
747 *x = *(sampl_t *)(async->prealloc_buf + async->buf_read_ptr);
748 comedi_buf_read_free(async, sizeof(sampl_t));
752 int comedi_buf_put(comedi_async *async, sampl_t x)
754 unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t));
756 if(n<sizeof(sampl_t)){
757 async->events |= COMEDI_CB_ERROR;
760 *(sampl_t *)(async->prealloc_buf + async->buf_write_ptr) = x;
761 comedi_buf_write_free(async, sizeof(sampl_t));
765 void comedi_reset_async_buf(comedi_async *async)
767 async->buf_write_alloc_count = 0;
768 async->buf_write_count = 0;
769 async->buf_read_alloc_count = 0;
770 async->buf_read_count = 0;
772 async->buf_write_ptr = 0;
773 async->buf_read_ptr = 0;
776 async->scan_progress = 0;
777 async->munge_chan = 0;
778 async->munge_count = 0;
779 async->munge_ptr = 0;