fixed poll, select, mod use count for RT; many RT fixes/changes; more
authorDavid Schleef <ds@schleef.org>
Sat, 25 Nov 2000 00:10:34 +0000 (00:10 +0000)
committerDavid Schleef <ds@schleef.org>
Sat, 25 Nov 2000 00:10:34 +0000 (00:10 +0000)
support for running drivers RT from user space; pcl818: added pcm3718;
quatech_daqp_cs: fixed compilation; kcomedilib: added specific
EXPORT_SYMBOL()s

TODO
comedi/Makefile
comedi/comedi_fops.c
comedi/comedi_ksyms.c
comedi/comedi_rt.h
comedi/drivers/ni_mio_common.c
comedi/drivers/pcl818.c
comedi/drivers/quatech_daqp_cs.c
comedi/kcomedilib/kcomedilib_main.c
comedi/rt.c
include/linux/comedidev.h

diff --git a/TODO b/TODO
index 2204663e50e9769a8942b49c9391fad2761b0596..637e954800c3896789e9ffc802283706de49518f 100644 (file)
--- a/TODO
+++ b/TODO
@@ -21,16 +21,10 @@ verify 2.0.x operation
 
 develop 8253 and Am9513 code
 
-increase mod use count for RT
-
 different error code for board error vs buffer overflow
 
 change _recognize to const char *
 
-implement poll/select
-
-fix mmap
-
 ni_mio_common: gpct code broken
 
 ni_mio_common: external trigger doesn't work
index 8213c6dda4d0b60de1b2d98b92177ffea82bda92..04eeae40927f223c71c180926bdb2ff97b319bf5 100644 (file)
@@ -36,18 +36,6 @@ ifeq ($(CONFIG_COMEDI_RT),y)
 MI_OBJS += rt.o
 endif
 
-ifeq ($(CONFIG_COMEDI_RTL),y)
-MI_OBJS += rtl.o
-endif
-
-ifeq ($(CONFIG_COMEDI_RTAI),y)
-MI_OBJS += rtai.o
-endif
-
-ifeq ($(CONFIG_COMEDI_RTL_V1),y)
-MI_OBJS += rtl_v1.o
-endif
-
 
 
 include $(TOPDIR)/Rules.make
index 34e970a0c9b9cc07954ab7f132166d4115961048..9793377d800de68f39df4623d4bcceff169d2cad 100644 (file)
@@ -43,6 +43,7 @@
 #if LINUX_VERSION_CODE >= 0x020100
 #include <linux/poll.h>
 #endif
+#include <kvmem.h>
 
 comedi_device *comedi_devices;
 
@@ -550,12 +551,6 @@ static int do_trig_ioctl_modeN(comedi_device *dev,comedi_subdevice *s,comedi_tri
        }
 
        s->runflags=SRF_USER;
-#ifdef CONFIG_COMEDI_RT
-       if(s->cur_trig.flags & TRIG_RT){
-               s->runflags|=SRF_RT;
-               // FIXME: TM move device to rt
-       }
-#endif
 
        s->subdev_flags|=SDF_RUNNING;
 
@@ -848,15 +843,14 @@ if(s->subdev_flags & SDF_READABLE){
        }
 
        s->runflags=SRF_USER;
-#ifdef CONFIG_COMEDI_RT
-       if(s->cmd.flags & TRIG_RT){
-               s->runflags|=SRF_RT;
-               // move device to rt
-       }
-#endif
 
        s->subdev_flags|=SDF_RUNNING;
 
+       if(s->cmd.flags&TRIG_RT){
+               comedi_switch_to_rt(dev);
+               s->runflags |= SRF_RT;
+       }
+
        ret=s->do_cmd(dev,s);
        
        if(ret==0)return 0;
@@ -1109,75 +1103,56 @@ static int do_cancel(comedi_device *dev,comedi_subdevice *s)
 }
 
 #ifdef LINUX_V22
+static void comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y);
+
+static struct vm_operations_struct comedi_vm_ops={
+       unmap:          comedi_unmap,
+};
+
 /*
    comedi_mmap_v22
 
-   mmap issues:
-       - mmap has issues with lock and busy
-       - mmap has issues with reference counting
-       - RT issues?
-
-   unmapping:
-       vm_ops->unmap()
-       - this needs to call comedi_cancel, or whatever.
+   issues:
+      what happens when the underlying buffer gets changed?
+      
  */
 static int comedi_mmap_v22(struct file * file, struct vm_area_struct *vma)
 {
        kdev_t minor=MINOR(RDEV_OF_FILE(file));
        comedi_device *dev=comedi_get_device_by_minor(minor);
        comedi_subdevice *s;
-       int size;
-       unsigned long offset;
-
-#if LINUX_VERSION_CODE < 0x020300
-       offset=vma->vm_offset;
-#else
-       offset=0;       /* XXX */
-#endif
-       if(offset >= dev->n_subdevices)
-               return -EIO;
-       s=dev->subdevices+offset;
-
-       if((vma->vm_flags & VM_WRITE) && !(s->subdev_flags & SDF_WRITEABLE))
-               return -EINVAL;
+       int subdev;
 
-       if((vma->vm_flags & VM_READ) && !(s->subdev_flags & SDF_READABLE))
+       if(vma->vm_flags & VM_WRITE){
+               subdev=dev->write_subdev;
+       }else{
+               subdev=dev->read_subdev;
+       }
+       if(subdev<0){
                return -EINVAL;
+       }
+       s=dev->subdevices+subdev;
 
-       size = vma->vm_end - vma->vm_start;
-       if(size>(1<<16))
+       if(vma->vm_pgoff != 0){
+               DPRINTK("comedi: mmap() offset must be 0.\n");
                return -EINVAL;
+       }
 
-       if(remap_page_range(vma->vm_start, virt_to_phys(s->prealloc_buf),
-               size,vma->vm_page_prot))
-               return -EAGAIN;
+       rvmmap(s->prealloc_buf,s->prealloc_bufsz,vma);
        
-       vma->vm_file=file;
-#if 0
-       file->f_count++;
-#else
+       vma->vm_file = file;
+       vma->vm_ops = &comedi_vm_ops;
        file_atomic_inc(&file->f_count);
-#endif
 
-       /* mark subdev as mapped */
+       /* XXX mark subdev as mapped */
        
-       /* call subdev about mmap, if necessary */
-printk("mmap done\n");
-
        return 0;
 }
 
-#if 0
-/*
-   I can't find a driver that notices when it gets unmapped.
- */
-static void *comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y)
+static void comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y)
 {
        printk("comedi unmap\n");
-
-       return NULL;
 }
-#endif
 
 #endif
 
@@ -1186,7 +1161,7 @@ static void *comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y)
 static unsigned int comedi_poll_v22(struct file *file, poll_table * wait)
 {
        comedi_device *dev;
-       //comedi_subdevice *s;
+       comedi_subdevice *s;
        unsigned int mask;
 
        dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file)));
@@ -1194,11 +1169,16 @@ static unsigned int comedi_poll_v22(struct file *file, poll_table * wait)
        poll_wait(file, &dev->read_wait, wait);
        poll_wait(file, &dev->write_wait, wait);
        mask = 0;
-/* XXX incomplete */
-       if(0)
-               mask |= POLLIN | POLLRDNORM;
-       if(0)
-               mask |= POLLOUT | POLLWRNORM;
+       if(dev->read_subdev>=0){
+               s=dev->subdevices+dev->read_subdev;
+               if(s->buf_user_count < s->buf_int_count)
+                       mask |= POLLIN | POLLRDNORM;
+       }
+       if(dev->write_subdev>=0){
+               s=dev->subdevices+dev->write_subdev;
+               if(s->buf_user_count < s->buf_int_count + s->prealloc_bufsz)
+                       mask |= POLLOUT | POLLWRNORM;
+       }
 
        return mask;
 }
@@ -1405,11 +1385,10 @@ static void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s)
        /* we do this because it's useful for the non-standard cases */
        s->subdev_flags &= ~SDF_RUNNING;
 
-#ifdef CONFIG_COMEDI_RT
        if(s->runflags&SRF_RT){
-               // FIXME: TM move device out of rt
+               comedi_switch_to_non_rt(dev);
+               s->runflags &= ~SRF_RT;
        }
-#endif
 
        if(s->cur_trig.chanlist){               /* XXX wrong? */
                kfree(s->cur_trig.chanlist);
@@ -1574,6 +1553,9 @@ static struct file_operations comedi_fops={
 #define comedi_open_v22 comedi_fop_open
 
 static struct file_operations comedi_fops={
+#if LINUX_VERSION_CODE >= 0x020400
+       owner           : THIS_MODULE,
+#endif
        llseek          : comedi_lseek_v22,
        ioctl           : comedi_ioctl_v22,
        open            : comedi_open_v22,
@@ -1614,7 +1596,7 @@ int comedi_init(void)
        comedi_proc_init();
        
 #ifdef CONFIG_COMEDI_RT
-       comedi_rt_init();
+//     comedi_rt_init();
 #endif
        init_drivers();
 
@@ -1644,7 +1626,7 @@ void comedi_cleanup(void)
        kfree(comedi_devices);
 
 #ifdef CONFIG_COMEDI_RT
-       comedi_rt_cleanup();
+//     comedi_rt_cleanup();
 #endif
 
 }
@@ -1670,20 +1652,31 @@ void comedi_event(comedi_device *dev,comedi_subdevice *s,unsigned int mask)
 {
        if(s->cb_mask&mask){
                if(s->runflags&SRF_USER){
-                       if(s->runflags&SRF_RT){
+                       unsigned int subdev;
+
+                       subdev = s - dev->subdevices;
+                       if(dev->rt){
                                // pend wake up
+                               if(subdev==dev->read_subdev)
+                                       comedi_rt_pend_wakeup(&dev->read_wait);
+                               if(subdev==dev->write_subdev)
+                                       comedi_rt_pend_wakeup(&dev->write_wait);
                        }else{
-                               unsigned int subdev;
-
-                               subdev = s - dev->subdevices;
-
                                if(subdev==dev->read_subdev)
                                        wake_up_interruptible(&dev->read_wait);
                                if(subdev==dev->write_subdev)
                                        wake_up_interruptible(&dev->write_wait);
                        }
                }else{
-                       s->cb_func(mask,s->cb_arg);
+                       if(s->runflags&SRF_RT){
+                               s->cb_func(mask,s->cb_arg);
+                       }else{
+                       /* XXX bug here.  If subdevice A is rt, and
+                        * subdevice B tries to callback to a normal
+                        * linux kernel function, it will be at the
+                        * wrong priority.  Since this isn't very
+                        * common, I'm not going to worry about it. */
+                       }
                }
        }
        
index fb5e8686812600b664132c4fb3c1e6db4e2f7732..baac6bded01bf5d5b2a96b9e14b082a93edf3d2e 100644 (file)
@@ -42,10 +42,11 @@ EXPORT_SYMBOL(comedi_bufcheck);
 EXPORT_SYMBOL(comedi_done);
 EXPORT_SYMBOL(comedi_error_done);
 EXPORT_SYMBOL(comedi_error);
-EXPORT_SYMBOL(do_pack);
-EXPORT_SYMBOL(di_unpack);
 EXPORT_SYMBOL(comedi_eobuf);
 EXPORT_SYMBOL(comedi_eos);
+EXPORT_SYMBOL(comedi_event);
+EXPORT_SYMBOL(do_pack);
+EXPORT_SYMBOL(di_unpack);
 EXPORT_SYMBOL(range_bipolar10);
 EXPORT_SYMBOL(range_bipolar5);
 EXPORT_SYMBOL(range_bipolar2_5);
@@ -53,7 +54,6 @@ EXPORT_SYMBOL(range_unipolar10);
 EXPORT_SYMBOL(range_unipolar5);
 EXPORT_SYMBOL(range_unknown);
 #ifdef CONFIG_COMEDI_RT
-EXPORT_SYMBOL(comedi_change_irq_flags);
 EXPORT_SYMBOL(comedi_free_irq);
 EXPORT_SYMBOL(comedi_request_irq);
 #endif
index ecb27688312d6f6e114df39fd1d0812648ae28b5..09a47ee5cf006f1c6dac71bd3ddcf2059e9bfafb 100644 (file)
 #include <linux/config.h>
 #include <linux/malloc.h>
 #include <linux/errno.h>
-#include <linux/comedi.h>
+#include <linux/comedidev.h>
 
-
-#include <kern_compat.h>
-
-
-struct comedi_irq_struct{
-       struct comedi_irq_struct *next;
-
-       int irq;
-       void *dev_id;
-       unsigned long flags;
-       void (*handler)(int,void *,struct pt_regs *);
-       const char *device;
-};
-
-int get_priority_irq(struct comedi_irq_struct *);
-int free_priority_irq(struct comedi_irq_struct *);
-struct comedi_irq_struct * get_irq_struct(unsigned int);
-
-#ifndef SA_PRIORITY
-#define SA_PRIORITY 0x08000000
-#endif
-
-#ifdef CONFIG_COMEDI_RTL
-void comedi_rtl_init(void);
-void comedi_rtl_cleanup(void);
-#define comedi_rt_init         comedi_rtl_init
-#define comedi_rt_cleanup      comedi_rtl_cleanup
-
-#include <rtl_printf.h>
-
-#define NEED_RT_PEND_TQ
-#endif
+#ifdef CONFIG_COMEDI_RT
 
 #ifdef CONFIG_COMEDI_RTAI
-void comedi_rtai_init(void);
-void comedi_rtai_cleanup(void);
-#define comedi_rt_init         comedi_rtai_init
-#define comedi_rt_cleanup      comedi_rtai_cleanup
-
-#define NEED_RT_PEND_TQ
-#define NEED_RT_PRINTK
-#endif
-
-#ifdef CONFIG_COMEDI_RTL_V1
-void comedi_rtl_v1_init(void);
-void comedi_rtl_v1_cleanup(void);
-#define comedi_rt_init         comedi_rtl_v1_init
-#define comedi_rt_cleanup      comedi_rtl_v1_cleanup
-
-/* we do not have sort IRQs (unless my v1 patch is used) T.M. */
-
-#define NEED_RT_PRINTK
-#endif
-
-#ifdef NEED_RT_PEND_TQ
-#include <rt_pend_tq.h>
-extern void wake_up_int_handler(int arg1, void * arg2);
-#endif
-
-#ifdef NEED_RT_PRINTK
-#define rt_printk(format,args...)      printk(format,##args)
-#define rt_printk_init()               
-#define rt_printk_cleanup()            
+#include <rtai/rtai.h>
 #endif
 
 int comedi_request_irq(unsigned int irq,void (*handler)(int,void *,
        struct pt_regs *regs),unsigned long flags,const char *device,
        void *dev_id);
-int comedi_change_irq_flags(unsigned int irq,void *dev_id,
-       unsigned long new_flags);
 void comedi_free_irq(unsigned int irq,void *dev_id);
+void comedi_rt_init(void);
+void comedi_rt_cleanup(void);
+void comedi_switch_to_rt(comedi_device *dev);
+void comedi_switch_to_non_rt(comedi_device *dev);
+void comedi_rt_pend_wakeup(wait_queue_head_t *q);
+
+#else
+
+#define comedi_request_irq(a,b,c,d,e) request_irq(a,b,c,d,e)
+#define comedi_free_irq(a,b) free_irq(a,b)
+#define comedi_rt_init() do{}while(0)
+#define comedi_rt_cleanup() do{}while(0)
+#define comedi_swtich_to_rt(a) do{}while(0)
+#define comedi_swtich_to_non_rt(a) do{}while(0)
+#define comedi_rt_pend_wakeup(a) do{}while(0)
 
+#endif
 
 #endif
 
index a503ff775655f9ca68496b5ed3143c4fcf14ee64..22bfb4b3eb7cb7b339cee88896cbe74cdb7d51a2 100644 (file)
@@ -190,31 +190,6 @@ static int ni_gpct_insn_read(comedi_device *dev,comedi_subdevice *s,
 #define AIMODE_SCAN            2
 #define AIMODE_SAMPLE          3
 
-#ifdef CONFIG_COMEDI_RT
-
-#define RTirqmask_AI 1
-#define RTirqmask_AO 2
-
-static int ni_ai_lock(comedi_device *dev,comedi_subdevice *s)
-{
-       comedi_change_irq_flags(dev->irq,dev,NI_E_IRQ_FLAGS | SA_PRIORITY );
-
-       return 0;
-}
-
-static int ni_ai_unlock(comedi_device *dev,comedi_subdevice *s)
-{
-       comedi_change_irq_flags(dev->irq,dev,NI_E_IRQ_FLAGS );
-
-       return 0;
-}
-
-#else
-
-#define ni_ai_lock NULL
-#define ni_ai_unlock NULL
-
-#endif
 
 static void ni_E_interrupt(int irq,void *d,struct pt_regs * regs)
 {
@@ -1665,8 +1640,6 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
        s->do_cmdtest=ni_ai_cmdtest;
        s->do_cmd=ni_ai_cmd;
        s->cancel=ni_ai_reset;
-       s->do_lock=ni_ai_lock;
-       s->do_unlock=ni_ai_unlock;
        
        /* analog output subdevice */
        /* XXX what about boards without ao? */
index e604dabb5e9c650e10242c9a9c7dd7f2cb7e6f54..999f23076a199b82d3262fefa49423c96ae0d61f 100644 (file)
@@ -252,6 +252,9 @@ static boardtype boardtypes[] =
          0x0a, 0xfff, 0xfff, 1024, 2, 0 },
        {"pcl718",    1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,    &range_unipolar5, PCLx1x_RANGE, 0x00fc, 
          0x0a, 0xfff, 0xfff, 1024, 2, 0 },
+       /* pcm3718 */
+       {"pcm3718",   9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,   &range_unipolar5, PCLx1x_RANGE, 0x00fc, 
+         0x0a, 0xfff, 0xfff, 1024, 0, 0 },
 };
 
 #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
index 693269d45814a5fa168cada681b7759f317e00b0..79ae66f23548ab1899c2782b8a671f6dc50b98ab 100644 (file)
 ======================================================================*/
 
 
-#include <pcmcia/config.h>
-#include <pcmcia/k_compat.h>
+//#include <pcmcia/config.h>
+//#include <pcmcia/k_compat.h>
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
index 898c4289c15c57c8aca2ba134b384788c739360d..81d55dc7b347fd6683cabbd478095329e28370bb 100644 (file)
@@ -24,6 +24,7 @@
 
 
 #include <linux/comedidev.h>
+#include <linux/comedi.h>
 
 #include <linux/module.h>
 
@@ -669,6 +670,7 @@ int comedi_lock_ioctl(unsigned int minor,unsigned int subdev)
        if(s->lock && s->lock!=&rtcomedi_lock_semaphore){
                ret=-EACCES;
        }else{
+               __MOD_INC_USE_COUNT(dev->driver->module);
                s->lock=(void *)&rtcomedi_lock_semaphore;
 
                if(s->do_lock)
@@ -724,6 +726,8 @@ int comedi_unlock_ioctl(unsigned int minor,unsigned int subdev)
                s->cb_mask=0;
                s->cb_func=NULL;
                s->cb_arg=NULL;
+               
+               __MOD_DEC_USE_COUNT(dev->driver->module);
        }
 
        return 0;
@@ -827,4 +831,56 @@ int comedi_register_callback(unsigned int minor,unsigned int subdev,
        return 0;
 }
 
+/* XXX */
+void comedi_cancel(void);
+void comedi_lock(void);
+void comedi_unlock(void);
+void comedi_trigger(void);
+
+
+
+#ifdef LINUX_V22
+
+EXPORT_SYMBOL(comedi_open);
+EXPORT_SYMBOL(comedi_close);
+//EXPORT_SYMBOL(comedi_loglevel);
+//EXPORT_SYMBOL(comedi_perror);
+//EXPORT_SYMBOL(comedi_strerror);
+//EXPORT_SYMBOL(comedi_errno);
+//EXPORT_SYMBOL(comedi_fileno);
+EXPORT_SYMBOL(comedi_get_n_subdevices);
+EXPORT_SYMBOL(comedi_find_subdevice_by_type);
+EXPORT_SYMBOL(comedi_get_n_channels);
+EXPORT_SYMBOL(comedi_get_maxdata);
+EXPORT_SYMBOL(comedi_get_rangetype);
+//EXPORT_SYMBOL(comedi_get_range);
+//EXPORT_SYMBOL(comedi_find_range);
+EXPORT_SYMBOL(comedi_get_n_ranges);
+//EXPORT_SYMBOL(comedi_range_is_chan_specific);
+//EXPORT_SYMBOL(comedi_maxdata_is_chan_specific);
+EXPORT_SYMBOL(comedi_cancel);
+EXPORT_SYMBOL(comedi_trigger);
+//EXPORT_SYMBOL(comedi_command);
+//EXPORT_SYMBOL(comedi_command_test);
+//EXPORT_SYMBOL(comedi_do_insnlist);
+//EXPORT_SYMBOL(comedi_do_insn);
+EXPORT_SYMBOL(comedi_lock);
+EXPORT_SYMBOL(comedi_unlock);
+//EXPORT_SYMBOL(comedi_to_phys);
+//EXPORT_SYMBOL(comedi_from_phys);
+EXPORT_SYMBOL(comedi_data_read);
+EXPORT_SYMBOL(comedi_data_write);
+//EXPORT_SYMBOL(comedi_sv_init);
+//EXPORT_SYMBOL(comedi_sv_update);
+//EXPORT_SYMBOL(comedi_sv_measure);
+EXPORT_SYMBOL(comedi_dio_config);
+EXPORT_SYMBOL(comedi_dio_read);
+EXPORT_SYMBOL(comedi_dio_write);
+EXPORT_SYMBOL(comedi_dio_bitfield);
+//EXPORT_SYMBOL(comedi_get_timer);
+//EXPORT_SYMBOL(comedi_timed_1chan);
+//EXPORT_SYMBOL(comedi_set_global_oor_behavior);
+
+
+#endif
 
index a9fc05a2a50d93ea77c89f5e8e1bbbdc9c65a05c..eff38dc41a769ecee6d4b5997f68d85388381b04 100644 (file)
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/irq.h>
 #include <asm/io.h>
 
+#ifdef CONFIG_COMEDI_RTAI
+#include <rtai/rtai.h>
 
+#define RT_protect()   hard_cli()
+#define RT_unprotect() hard_sti()
+#define RT_spin_lock_irq(x)    rt_spin_lock_irq(x)
+#define RT_spin_unlock_irq(x)  rt_spin_unlock_irq(x)
+#endif
+
+#ifdef CONFIG_COMEDI_RTLINUX
+#include <rtl_core.h>
+
+#define RT_protect()   rtl_make_rt_system_active()
+#define RT_unprotect() rtl_make_rt_system_idle()
+#define RT_spin_lock_irq(x)    rt_spin_lock_irq(x)
+#define RT_spin_unlock_irq(x)  rt_spin_unlock_irq(x)
+#endif
+
+
+struct comedi_irq_struct {
+       int rt;
+       int irq;
+       void (*handler)(int irq,void *dev_id,struct pt_regs *regs);
+       unsigned long flags;
+       const char *device;
+       void *dev_id;
+};
+
+static int rt_get_irq(struct comedi_irq_struct *it);
+static int rt_release_irq(struct comedi_irq_struct *it);
+
+
+static struct comedi_irq_struct *comedi_irqs[NR_IRQS];
 
-static struct comedi_irq_struct *comedi_irqs;
 
 int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *),
                unsigned long flags,const char *device,void *dev_id)
@@ -55,81 +87,70 @@ int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *
        it->flags=flags;
        it->device=device;
 
-       ret=request_irq(irq,handler,flags&~SA_PRIORITY,device,dev_id);
+       ret=request_irq(irq,handler,flags,device,dev_id);
        if(ret<0){
                kfree(it);
                return ret;
        }
 
-       if(flags&SA_PRIORITY){
-               get_priority_irq(it);
-       }
-
-       it->next=comedi_irqs;
-       comedi_irqs=it;
+       comedi_irqs[irq]=it;
 
        return 0;
 }
 
-int comedi_change_irq_flags(unsigned int irq,void *dev_id,unsigned long flags)
+void comedi_free_irq(unsigned int irq,void *dev_id)
 {
        struct comedi_irq_struct *it;
-       int ret;
 
-       it=get_irq_struct(irq);
-       if(it){
-               if((it->flags&~SA_PRIORITY)!=(flags&~SA_PRIORITY))
-                       return -EINVAL;
-
-               if((it->flags&SA_PRIORITY)==(flags&SA_PRIORITY))
-                       return 0;
-
-               it->flags=flags;
-               if(flags&SA_PRIORITY){
-                       free_irq(it->irq,it->dev_id);
-                       return get_priority_irq(it);
-               }else{
-                       ret=free_priority_irq(it);
-                       request_irq(it->irq,it->handler,it->flags,it->device,it->dev_id);
-                       return ret;
-               }
+       it=comedi_irqs[irq];
+       if(!it)return;
+
+       comedi_irqs[irq]=NULL;
+
+       if(it->rt){
+               printk("BUG! \n");
+               rt_release_irq(it);
        }
 
-       return -EINVAL;
+       free_irq(it->irq,it->dev_id);
+
+       kfree(it);
 }
 
-void comedi_free_irq(unsigned int irq,void *dev_id)
+void comedi_switch_to_rt(comedi_device *dev)
 {
-       struct comedi_irq_struct *it,*prev;
-
-       prev=NULL;
-       for(it=comedi_irqs;it;it=it->next){
-               if(it->irq==irq){
-                       break;
-               }
-               prev=it;
-       }
-       if(it->flags&SA_PRIORITY)
-               free_priority_irq(it);
+       struct comedi_irq_struct *it=comedi_irqs[dev->irq];
 
-       free_irq(it->irq,it->dev_id);
+       spin_lock_irq(&dev->spinlock);
+       RT_protect();
+       sti();
 
-       if(prev) prev->next=it->next;
-       else comedi_irqs=it->next;
+       if(!dev->rt)
+               rt_get_irq(it);
 
-       kfree(it);
+       dev->rt++;
+       it->rt=1;
+       spin_unlock(&dev->spinlock);
+       RT_unprotect();
 }
 
-struct comedi_irq_struct *get_irq_struct(unsigned int irq)
+void comedi_switch_to_non_rt(comedi_device *dev)
+{
+       struct comedi_irq_struct *it=comedi_irqs[dev->irq];
+
+       RT_spin_lock_irq(&dev->spinlock);
+
+       dev->rt--;
+       if(!dev->rt)
+               rt_release_irq(it);
+
+       it->rt=0;
+       RT_spin_unlock_irq(&dev->spinlock);
+}
+
+void comedi_rt_pend_wakeup(wait_queue_head_t *q)
 {
-       struct comedi_irq_struct *it;
 
-       for(it=comedi_irqs;it;it=it->next){
-               if(it->irq==irq){
-                       return it;
-               }
-       }
-       return NULL;
 }
 
 #ifdef HAVE_RT_PEND_TQ
@@ -138,3 +159,115 @@ void wake_up_int_handler(int arg1, void * arg2)
        wake_up_interruptible((wait_queue_head_t*)arg2);
 }
 #endif
+
+
+/* RTAI section */
+#ifdef CONFIG_COMEDI_RTAI
+
+#define DECLARE_VOID_IRQ(irq) \
+static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);}
+
+static inline void handle_void_irq(int irq)
+{
+       struct comedi_irq_struct *it=comedi_irqs[irq];
+       it->handler(irq,it->dev_id,NULL);
+       rt_unmask_irq(irq);
+}
+
+DECLARE_VOID_IRQ(0);
+DECLARE_VOID_IRQ(1);
+DECLARE_VOID_IRQ(2);
+DECLARE_VOID_IRQ(3);
+DECLARE_VOID_IRQ(4);
+DECLARE_VOID_IRQ(5);
+DECLARE_VOID_IRQ(6);
+DECLARE_VOID_IRQ(7);
+DECLARE_VOID_IRQ(8);
+DECLARE_VOID_IRQ(9);
+DECLARE_VOID_IRQ(10);
+DECLARE_VOID_IRQ(11);
+DECLARE_VOID_IRQ(12);
+DECLARE_VOID_IRQ(13);
+DECLARE_VOID_IRQ(14);
+DECLARE_VOID_IRQ(15);
+DECLARE_VOID_IRQ(16);
+DECLARE_VOID_IRQ(17);
+DECLARE_VOID_IRQ(18);
+DECLARE_VOID_IRQ(19);
+DECLARE_VOID_IRQ(20);
+DECLARE_VOID_IRQ(21);
+DECLARE_VOID_IRQ(22);
+DECLARE_VOID_IRQ(23);
+
+typedef void (*V_FP_V)(void);
+static V_FP_V handle_void_irq_ptrs[]={
+       handle_void_irq_0,
+       handle_void_irq_1,
+       handle_void_irq_2,
+       handle_void_irq_3,
+       handle_void_irq_4,
+       handle_void_irq_5,
+       handle_void_irq_6,
+       handle_void_irq_7,
+       handle_void_irq_8,
+       handle_void_irq_9,
+       handle_void_irq_10,
+       handle_void_irq_11,
+       handle_void_irq_12,
+       handle_void_irq_13,
+       handle_void_irq_14,
+       handle_void_irq_15,
+       handle_void_irq_16,
+       handle_void_irq_17,
+       handle_void_irq_18,
+       handle_void_irq_19,
+       handle_void_irq_20,
+       handle_void_irq_21,
+       handle_void_irq_22,
+       handle_void_irq_23,
+};
+/* if you need more, fix it yourself... */
+
+static int rt_get_irq(struct comedi_irq_struct *it)
+{
+       rt_request_global_irq(it->irq,handle_void_irq_ptrs[it->irq]);
+       rt_startup_irq(it->irq);
+       
+       return 0;
+}
+
+static int rt_release_irq(struct comedi_irq_struct *it)
+{
+       rt_free_global_irq(it->irq);
+       return 0;
+}
+
+
+#endif
+
+
+/* RTLinux section */
+#ifdef CONFIG_COMEDI_RTLINUX
+
+static unsigned int handle_rtl_irq(unsigned int irq,struct pt_regs *regs)
+{
+       struct comedi_irq_struct *it=comedi_irqs[irq];
+       it->handler(irq,it->dev_id,regs);
+       rtl_hard_enable_irq(irq);
+}
+
+static int rt_get_irq(struct comedi_irq_struct *it)
+{
+       rtl_request_global_irq(it->irq,handle_rtl_irq);
+       return 0;
+}
+
+static int rt_release_irq(struct comedi_irq_struct *it)
+{
+       rtl_free_global_irq(it->irq);
+       return 0;
+}
+
+#endif
+
+
index 378af7b840c73dcf7a77288828404bd721a1162b..766fcde550e94fd0c422ccca4a801e627db1daab 100644 (file)
 
 #include "kern_compat.h"
 
-#ifdef CONFIG_COMEDI_RT
-#include <comedi_rt.h>
-#endif
-
 #ifdef CONFIG_COMEDI_DEBUG
 #define DPRINTK(format, args...)       printk("comedi: " format , ## args )
 #else
@@ -146,6 +142,8 @@ struct comedi_device_struct{
        int board;
        void *board_ptr;
        int attached;
+       int rt;
+       spinlock_t spinlock;
 
        int n_subdevices;
        comedi_subdevice *subdevices;
@@ -171,6 +169,7 @@ extern comedi_device *comedi_devices;
  * function prototypes
  */
 
+void comedi_event(comedi_device *dev,comedi_subdevice *s,unsigned int mask);
 void comedi_error(comedi_device *dev,const char *s);
 void comedi_done(comedi_device *dev,comedi_subdevice *s);
 void comedi_error_done(comedi_device *dev,comedi_subdevice *s);
@@ -284,6 +283,10 @@ static inline int alloc_private(comedi_device *dev,int size)
 extern struct symbol_table comedi_syms;
 #endif
 
+#ifdef CONFIG_COMEDI_RT
+#include <comedi_rt.h>
+#endif
+
 
 #endif /* _COMEDI_MODULE_H */