RTXI 1.3
comedi/include/linux/comedidev.h
Go to the documentation of this file.
00001 /*
00002     include/linux/comedidev.h
00003     header file for kernel-only structures, variables, and constants
00004 
00005     COMEDI - Linux Control and Measurement Device Interface
00006     Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 
00022 */
00023 
00024 #ifndef _COMEDIDEV_H
00025 #define _COMEDIDEV_H
00026 
00027 #include <linux/kernel.h>
00028 #include <linux/module.h>
00029 #include <linux/version.h>
00030 #include <linux/config.h>
00031 #include <linux/kdev_t.h>
00032 #include <linux/slab.h>
00033 #include <linux/errno.h>
00034 #include <linux/spinlock.h>
00035 #include <linux/mutex.h>
00036 #include <linux/wait.h>
00037 #include <linux/mm.h>
00038 #include <linux/init.h>
00039 #include <linux/vmalloc.h>
00040 #include <linux/mm.h>
00041 #include <linux/interrupt.h>
00042 #include <linux/dma-mapping.h>
00043 #include <asm/uaccess.h>
00044 #include <asm/io.h>
00045 
00046 #include <linux/comedi.h>
00047 
00048 #include <config.h>
00049 
00050 #define DPRINTK(format, args...)        do{                             \
00051         if(comedi_debug)printk("comedi: " format , ## args );           \
00052 } while(0)
00053 
00054 #define COMEDI_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
00055 #define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION,COMEDI_MINORVERSION,COMEDI_MICROVERSION)
00056 #define COMEDI_RELEASE VERSION
00057 
00058 #define COMEDI_INITCLEANUP_NOMODULE(x)                                  \
00059         static int __init x ## _init_module(void)                       \
00060                 {return comedi_driver_register(&(x));}                  \
00061         static void __exit x ## _cleanup_module(void)                   \
00062                 {comedi_driver_unregister(&(x));}                       \
00063         module_init(x ## _init_module);                                 \
00064         module_exit(x ## _cleanup_module);                                      \
00065 
00066 #define COMEDI_MODULE_MACROS                                            \
00067         MODULE_AUTHOR("Comedi http://www.comedi.org");          \
00068         MODULE_DESCRIPTION("Comedi low-level driver");                  \
00069         MODULE_LICENSE("GPL");                                          \
00070 
00071 #define COMEDI_INITCLEANUP(x)                                           \
00072         COMEDI_MODULE_MACROS            \
00073         COMEDI_INITCLEANUP_NOMODULE(x)
00074 
00075 #define COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) \
00076         static int __devinit comedi_driver ## _pci_probe(struct pci_dev *dev, \
00077                 const struct pci_device_id *ent) \
00078         { \
00079                 return comedi_pci_auto_config(dev, comedi_driver.driver_name); \
00080         } \
00081         static void __devexit comedi_driver ## _pci_remove(struct pci_dev *dev) \
00082         { \
00083                 comedi_pci_auto_unconfig(dev); \
00084         } \
00085         static struct pci_driver comedi_driver ## _pci_driver = \
00086         { \
00087                 .id_table = pci_id_table, \
00088                 .probe = & comedi_driver ## _pci_probe, \
00089                 .remove = __devexit_p(& comedi_driver ## _pci_remove) \
00090         }; \
00091         static int __init comedi_driver ## _init_module(void) \
00092         { \
00093                 int retval; \
00094                 retval = comedi_driver_register(& comedi_driver); \
00095                 if(retval < 0) return retval; \
00096                 comedi_driver ## _pci_driver.name = (char*)comedi_driver.driver_name; \
00097                 return pci_register_driver(& comedi_driver ## _pci_driver); \
00098         } \
00099         static void __exit comedi_driver ## _cleanup_module(void) \
00100         { \
00101                 pci_unregister_driver(& comedi_driver ## _pci_driver); \
00102                 comedi_driver_unregister(& comedi_driver); \
00103         } \
00104         module_init(comedi_driver ## _init_module); \
00105         module_exit(comedi_driver ## _cleanup_module);
00106 
00107 #define COMEDI_PCI_INITCLEANUP(comedi_driver, pci_id_table) \
00108         COMEDI_MODULE_MACROS \
00109         COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table)
00110 
00111 #define PCI_VENDOR_ID_INOVA             0x104c
00112 #define PCI_VENDOR_ID_NATINST           0x1093
00113 #define PCI_VENDOR_ID_DATX              0x1116
00114 #define PCI_VENDOR_ID_COMPUTERBOARDS    0x1307
00115 #define PCI_VENDOR_ID_ADVANTECH         0x13fe
00116 #define PCI_VENDOR_ID_RTD               0x1435
00117 #define PCI_VENDOR_ID_AMPLICON          0x14dc
00118 #define PCI_VENDOR_ID_ADLINK            0x144a
00119 #define PCI_VENDOR_ID_ICP               0x104c
00120 #define PCI_VENDOR_ID_CONTEC            0x1221
00121 #define PCI_VENDOR_ID_MEILHAUS          0x1402
00122 
00123 #define COMEDI_NUM_MINORS 0x100
00124 #define COMEDI_NUM_BOARD_MINORS 0x30
00125 #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
00126 
00127 typedef struct comedi_device_struct comedi_device;
00128 typedef struct comedi_subdevice_struct comedi_subdevice;
00129 typedef struct comedi_async_struct comedi_async;
00130 typedef struct comedi_driver_struct comedi_driver;
00131 typedef struct comedi_lrange_struct comedi_lrange;
00132 
00133 struct comedi_subdevice_struct {
00134         comedi_device *device;
00135         int type;
00136         int n_chan;
00137         volatile int subdev_flags;
00138         int len_chanlist;       /* maximum length of channel/gain list */
00139 
00140         void *private;
00141 
00142         comedi_async *async;
00143 
00144         void *lock;
00145         void *busy;
00146         unsigned runflags;
00147         spinlock_t spin_lock;
00148 
00149         int io_bits;
00150 
00151         lsampl_t maxdata;       /* if maxdata==0, use list */
00152         const lsampl_t *maxdata_list;   /* list is channel specific */
00153 
00154         unsigned int flags;
00155         const unsigned int *flaglist;
00156 
00157         unsigned int settling_time_0;
00158 
00159         const comedi_lrange *range_table;
00160         const comedi_lrange *const *range_table_list;
00161 
00162         unsigned int *chanlist; /* driver-owned chanlist (not used) */
00163 
00164         int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *,
00165                 lsampl_t *);
00166         int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *,
00167                 lsampl_t *);
00168         int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *,
00169                 lsampl_t *);
00170         int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *,
00171                 lsampl_t *);
00172 
00173         int (*do_cmd) (comedi_device *, comedi_subdevice *);
00174         int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *);
00175         int (*poll) (comedi_device *, comedi_subdevice *);
00176         int (*cancel) (comedi_device *, comedi_subdevice *);
00177         //int (*do_lock)(comedi_device *,comedi_subdevice *);
00178         //int (*do_unlock)(comedi_device *,comedi_subdevice *);
00179 
00180         /* called when the buffer changes */
00181         int (*buf_change) (comedi_device * dev, comedi_subdevice * s,
00182                 unsigned long new_size);
00183 
00184         void (*munge) (comedi_device * dev, comedi_subdevice * s, void *data,
00185                 unsigned int num_bytes, unsigned int start_chan_index);
00186         enum dma_data_direction async_dma_dir;
00187 
00188         unsigned int state;
00189 
00190         comedi_device_create_t *class_dev;
00191         int minor;
00192 };
00193 
00194 struct comedi_buf_page {
00195         void *virt_addr;
00196         dma_addr_t dma_addr;
00197 };
00198 
00199 struct comedi_async_struct {
00200         comedi_subdevice *subdevice;
00201 
00202         void *prealloc_buf;     /* pre-allocated buffer */
00203         unsigned int prealloc_bufsz;    /* buffer size, in bytes */
00204         struct comedi_buf_page *buf_page_list;  /* virtual and dma address of each page */
00205         unsigned n_buf_pages;   /* num elements in buf_page_list */
00206 
00207         unsigned int max_bufsize;       /* maximum buffer size, bytes */
00208         unsigned int mmap_count;        /* current number of mmaps of prealloc_buf */
00209 
00210         unsigned int buf_write_count;   /* byte count for writer (write completed) */
00211         unsigned int buf_write_alloc_count;     /* byte count for writer (allocated for writing) */
00212         unsigned int buf_read_count;    /* byte count for reader (read completed) */
00213         unsigned int buf_read_alloc_count;      /* byte count for reader (allocated for reading) */
00214 
00215         unsigned int buf_write_ptr;     /* buffer marker for writer */
00216         unsigned int buf_read_ptr;      /* buffer marker for reader */
00217 
00218         unsigned int cur_chan;  /* useless channel marker for interrupt */
00219         /* number of bytes that have been received for current scan */
00220         unsigned int scan_progress;
00221         /* keeps track of where we are in chanlist as for munging */
00222         unsigned int munge_chan;
00223         /* number of bytes that have been munged */
00224         unsigned int munge_count;
00225         /* buffer marker for munging */
00226         unsigned int munge_ptr;
00227 
00228         unsigned int events;    /* events that have occurred */
00229 
00230         comedi_cmd cmd;
00231 
00232         wait_queue_head_t wait_head;
00233 
00234         // callback stuff
00235         unsigned int cb_mask;
00236         int (*cb_func) (unsigned int flags, void *);
00237         void *cb_arg;
00238 
00239         int (*inttrig) (comedi_device * dev, comedi_subdevice * s,
00240                 unsigned int x);
00241 };
00242 
00243 struct comedi_driver_struct {
00244         struct comedi_driver_struct *next;
00245 
00246         const char *driver_name;
00247         struct module *module;
00248         int (*attach) (comedi_device *, comedi_devconfig *);
00249         int (*detach) (comedi_device *);
00250 
00251         /* number of elements in board_name and board_id arrays */
00252         unsigned int num_names;
00253         const char *const *board_name;
00254         /* offset in bytes from one board name pointer to the next */
00255         int offset;
00256 };
00257 
00258 struct comedi_device_struct {
00259         int use_count;
00260         comedi_driver *driver;
00261         void *private;
00262 
00263         comedi_device_create_t *class_dev;
00264         int minor;
00265         /* hw_dev is passed to dma_alloc_coherent when allocating async buffers for subdevices
00266            that have async_dma_dir set to something other than DMA_NONE */
00267         struct device *hw_dev;
00268 
00269         const char *board_name;
00270         const void *board_ptr;
00271         int attached;
00272         int rt;
00273         spinlock_t spinlock;
00274         struct mutex mutex;
00275         int in_request_module;
00276 
00277         int n_subdevices;
00278         comedi_subdevice *subdevices;
00279 
00280         /* dumb */
00281         unsigned long iobase;
00282         unsigned int irq;
00283 
00284         comedi_subdevice *read_subdev;
00285         comedi_subdevice *write_subdev;
00286 
00287         struct fasync_struct *async_queue;
00288 
00289         void (*open) (comedi_device * dev);
00290         void (*close) (comedi_device * dev);
00291 };
00292 
00293 struct comedi_device_file_info {
00294         comedi_device *device;
00295         comedi_subdevice *read_subdevice;
00296         comedi_subdevice *write_subdevice;
00297 };
00298 
00299 #ifdef CONFIG_COMEDI_DEBUG
00300 extern int comedi_debug;
00301 #else
00302 static const int comedi_debug = 0;
00303 #endif
00304 
00305 /*
00306  * function prototypes
00307  */
00308 
00309 void comedi_event(comedi_device * dev, comedi_subdevice * s);
00310 void comedi_error(const comedi_device * dev, const char *s);
00311 
00312 /* we can expand the number of bits used to encode devices/subdevices into
00313  the minor number soon, after more distros support > 8 bit minor numbers
00314  (like after Debian Etch gets released) */
00315 enum comedi_minor_bits {
00316         COMEDI_DEVICE_MINOR_MASK = 0xf,
00317         COMEDI_SUBDEVICE_MINOR_MASK = 0xf0
00318 };
00319 static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4;
00320 static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
00321 
00322 struct comedi_device_file_info* comedi_get_device_file_info(unsigned minor);
00323 
00324 static inline comedi_subdevice* comedi_get_read_subdevice(const struct comedi_device_file_info *info)
00325 {
00326         if(info->read_subdevice) return info->read_subdevice;
00327         if(info->device == NULL) return NULL;
00328         return info->device->read_subdev;
00329 }
00330 
00331 static inline comedi_subdevice* comedi_get_write_subdevice(const struct comedi_device_file_info *info)
00332 {
00333         if(info->write_subdevice) return info->write_subdevice;
00334         if(info->device == NULL) return NULL;
00335         return info->device->write_subdev;
00336 }
00337 
00338 void comedi_device_detach(comedi_device * dev);
00339 int comedi_device_attach(comedi_device * dev, comedi_devconfig * it);
00340 int comedi_driver_register(comedi_driver *);
00341 int comedi_driver_unregister(comedi_driver *);
00342 
00343 void init_polling(void);
00344 void cleanup_polling(void);
00345 void start_polling(comedi_device *);
00346 void stop_polling(comedi_device *);
00347 
00348 int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s, unsigned long
00349         new_size);
00350 
00351 #ifdef CONFIG_PROC_FS
00352 void comedi_proc_init(void);
00353 void comedi_proc_cleanup(void);
00354 #else
00355 static inline void comedi_proc_init(void)
00356 {
00357 }
00358 static inline void comedi_proc_cleanup(void)
00359 {
00360 }
00361 #endif
00362 
00363 /* subdevice runflags */
00364 enum subdevice_runflags {
00365         SRF_USER = 0x00000001,
00366         SRF_RT = 0x00000002,
00367         /* indicates an COMEDI_CB_ERROR event has occurred since the last command was started */
00368         SRF_ERROR = 0x00000004,
00369         SRF_RUNNING = 0x08000000
00370 };
00371 
00372 /*
00373    various internal comedi functions
00374  */
00375 
00376 int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg);
00377 int check_chanlist(comedi_subdevice * s, int n, unsigned int *chanlist);
00378 void comedi_set_subdevice_runflags(comedi_subdevice * s, unsigned mask,
00379         unsigned bits);
00380 unsigned comedi_get_subdevice_runflags(comedi_subdevice * s);
00381 int insn_inval(comedi_device * dev, comedi_subdevice * s,
00382         comedi_insn * insn, lsampl_t * data);
00383 
00384 /* range stuff */
00385 
00386 #define RANGE(a,b)              {(a)*1e6,(b)*1e6,0}
00387 #define RANGE_ext(a,b)          {(a)*1e6,(b)*1e6,RF_EXTERNAL}
00388 #define RANGE_mA(a,b)           {(a)*1e6,(b)*1e6,UNIT_mA}
00389 #define RANGE_unitless(a,b)     {(a)*1e6,(b)*1e6,0}     /* XXX */
00390 #define BIP_RANGE(a)            {-(a)*1e6,(a)*1e6,0}
00391 #define UNI_RANGE(a)            {0,(a)*1e6,0}
00392 
00393 extern const comedi_lrange range_bipolar10;
00394 extern const comedi_lrange range_bipolar5;
00395 extern const comedi_lrange range_bipolar2_5;
00396 extern const comedi_lrange range_unipolar10;
00397 extern const comedi_lrange range_unipolar5;
00398 extern const comedi_lrange range_unknown;
00399 
00400 #define range_digital           range_unipolar5
00401 
00402 #if __GNUC__ >= 3
00403 #define GCC_ZERO_LENGTH_ARRAY
00404 #else
00405 #define GCC_ZERO_LENGTH_ARRAY 0
00406 #endif
00407 
00408 struct comedi_lrange_struct {
00409         int length;
00410         comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
00411 };
00412 
00413 /* some silly little inline functions */
00414 
00415 static inline int alloc_subdevices(comedi_device * dev,
00416         unsigned int num_subdevices)
00417 {
00418         unsigned i;
00419 
00420         dev->n_subdevices = num_subdevices;
00421         dev->subdevices =
00422                 kcalloc(num_subdevices, sizeof(comedi_subdevice), GFP_KERNEL);
00423         if (!dev->subdevices)
00424                 return -ENOMEM;
00425         for (i = 0; i < num_subdevices; ++i) {
00426                 dev->subdevices[i].device = dev;
00427                 dev->subdevices[i].async_dma_dir = DMA_NONE;
00428                 spin_lock_init(&dev->subdevices[i].spin_lock);
00429                 dev->subdevices[i].minor = -1;
00430         }
00431         return 0;
00432 }
00433 
00434 static inline int alloc_private(comedi_device * dev, int size)
00435 {
00436         dev->private = kzalloc(size, GFP_KERNEL);
00437         if (!dev->private)
00438                 return -ENOMEM;
00439         return 0;
00440 }
00441 
00442 static inline unsigned int bytes_per_sample(const comedi_subdevice * subd)
00443 {
00444         if (subd->subdev_flags & SDF_LSAMPL)
00445                 return sizeof(lsampl_t);
00446         else
00447                 return sizeof(sampl_t);
00448 }
00449 
00450 /* must be used in attach to set dev->hw_dev if you wish to dma directly
00451 into comedi's buffer */
00452 static inline void comedi_set_hw_dev(comedi_device * dev, struct device *hw_dev)
00453 {
00454         if (dev->hw_dev) {
00455                 put_device(dev->hw_dev);
00456         }
00457         dev->hw_dev = hw_dev;
00458         if (dev->hw_dev) {
00459                 dev->hw_dev = get_device(dev->hw_dev);
00460                 BUG_ON(dev->hw_dev == NULL);
00461         }
00462 }
00463 
00464 int comedi_buf_put(comedi_async * async, sampl_t x);
00465 int comedi_buf_get(comedi_async * async, sampl_t * x);
00466 
00467 unsigned int comedi_buf_write_n_available(comedi_async * async);
00468 unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes);
00469 unsigned int comedi_buf_write_alloc_strict(comedi_async * async,
00470         unsigned int nbytes);
00471 unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes);
00472 unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes);
00473 unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes);
00474 unsigned int comedi_buf_read_n_available(comedi_async * async);
00475 void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset,
00476         const void *source, unsigned int num_bytes);
00477 void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset,
00478         void *destination, unsigned int num_bytes);
00479 static inline unsigned comedi_buf_write_n_allocated(comedi_async * async)
00480 {
00481         return async->buf_write_alloc_count - async->buf_write_count;
00482 }
00483 static inline unsigned comedi_buf_read_n_allocated(comedi_async * async)
00484 {
00485         return async->buf_read_alloc_count - async->buf_read_count;
00486 }
00487 
00488 void comedi_reset_async_buf(comedi_async * async);
00489 
00490 static inline void *comedi_aux_data(int options[], int n)
00491 {
00492         unsigned long address;
00493         unsigned long addressLow;
00494         int bit_shift;
00495         if (sizeof(int) >= sizeof(void *))
00496                 address = options[COMEDI_DEVCONF_AUX_DATA_LO];
00497         else {
00498                 address = options[COMEDI_DEVCONF_AUX_DATA_HI];
00499                 bit_shift = sizeof(int) * 8;
00500                 address <<= bit_shift;
00501                 addressLow = options[COMEDI_DEVCONF_AUX_DATA_LO];
00502                 addressLow &= (1UL << bit_shift) - 1;
00503                 address |= addressLow;
00504         }
00505         if (n >= 1)
00506                 address += options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
00507         if (n >= 2)
00508                 address += options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
00509         if (n >= 3)
00510                 address += options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
00511         BUG_ON(n > 3);
00512         return (void *)address;
00513 }
00514 
00515 int comedi_alloc_board_minor(struct device *hardware_device);
00516 void comedi_free_board_minor(unsigned minor);
00517 int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s);
00518 void comedi_free_subdevice_minor(comedi_subdevice *s);
00519 int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
00520 void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
00521 struct usb_device;      // forward declaration
00522 int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name);
00523 void comedi_usb_auto_unconfig(struct usb_device *usbdev);
00524 
00525 //#ifdef CONFIG_COMEDI_RT
00526 #include <linux/comedi_rt.h>
00527 //#endif
00528 
00529 #endif /* _COMEDIDEV_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines