TM added rt interrupt for user space support
authorDavid Schleef <ds@schleef.org>
Wed, 14 Jun 2000 07:26:47 +0000 (07:26 +0000)
committerDavid Schleef <ds@schleef.org>
Wed, 14 Jun 2000 07:26:47 +0000 (07:26 +0000)
comedi/comedi_module.h
comedi/comedi_rt.h [new file with mode: 0644]
comedi/rt.c
comedi/rt_pend_tq.h [new file with mode: 0644]
comedi/rtai.c
comedi/rtl.c

index a5fc04092b79058baa67d03c4d0411712907cdb1..ed3a175aa5d4c154c6ee68ead3353ee6ca0ef999 100644 (file)
@@ -3,7 +3,7 @@
     header file for kernel-only structures, variables, and constants
 
     COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1997-8 David A. Schleef <ds@stm.lbl.gov>
+    Copyright (C) 1997-2000 David A. Schleef <ds@stm.lbl.gov>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include <kern_compat.h>
 
 #ifdef CONFIG_COMEDI_RT
-
-struct comedi_irq_struct{
-       struct comedi_irq_struct *next;
-
-       int irq;
-       void *dev_id;
-       unsigned long flags;
-       void (*handler)(int,void *,struct pt_regs *);
-       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);
-
-#include <rtl_printf.h>
-#endif
-
-#ifdef CONFIG_COMEDI_RTAI
-void comedi_rtai_init(void);
-void comedi_rtai_cleanup(void);
-#define rt_printk(format,args...)      printk(format,##args)
-#define rt_printk_init()               
-#define rt_printk_cleanup()            
-#endif
-
-#ifdef CONFIG_COMEDI_RTL_V1
-void comedi_rtl_v1_init(void);
-void comedi_rtl_v1_cleanup(void);
-#define rt_printk(format,args...)      printk(format,##args)
-#define rt_printk_init()               
-#define rt_printk_cleanup()            
-#endif
-
-#else /* !CONFIG_COMEDI_RT */
-
-#define rt_printk(format,args...)      printk(format,##args)
-#define rt_printk_init()               
-#define rt_printk_cleanup()            
-
+#include <comedi_rt.h>
 #endif
 
 #ifdef CONFIG_COMEDI_DEBUG
@@ -228,15 +181,16 @@ void comedi_proc_cleanup(void);
 int di_unpack(unsigned int bits,comedi_trig *it);
 int do_pack(unsigned int *bits,comedi_trig *it);
 
-#ifdef CONFIG_COMEDI_RT
-int comedi_request_irq(unsigned int irq,void (*handler)(int,void *,struct pt_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);
-#else
+#ifndef CONFIG_COMEDI_RT
+
+#define rt_printk(format,args...)      printk(format,##args)
+#define rt_printk_init()
+#define rt_printk_cleanup()
+
 #define comedi_request_irq             request_irq
 #define comedi_change_irq_flags(a,b,c) /* */
 #define comedi_free_irq                        free_irq
+
 #endif
 
 
@@ -248,7 +202,7 @@ void comedi_free_irq(unsigned int irq,void *dev_id);
 int do_rangeinfo_ioctl(comedi_device *dev,comedi_rangeinfo *arg);
 int check_chanlist(comedi_subdevice *s,int n,unsigned int *chanlist);
 
-extern int rtcomedi_lock_semaphore;
+extern volatile int rtcomedi_lock_semaphore;
 
 /* range stuff */
 
diff --git a/comedi/comedi_rt.h b/comedi/comedi_rt.h
new file mode 100644 (file)
index 0000000..b7803a0
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+    module/comedi_rt.h
+    header file for real-time structures, variables, and constants
+
+    COMEDI - Linux Control and Measurement Device Interface
+    Copyright (C) 1997-2000 David A. Schleef <ds@stm.lbl.gov>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _COMEDI_RT_H
+#define _COMEDI_RT_H
+
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/kdev_t.h>
+#include <config.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <comedi.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 *);
+       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_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()            
+#endif
+
+int comedi_request_irq(unsigned int irq,void (*handler)(int,void *,struct pt_reg
+       unsigned long flags,const char *device,void *dev_id);
+int comedi_change_irq_flags(unsigned int irq,void *dev_id,unsigned long new_flag
+void comedi_free_irq(unsigned int irq,void *dev_id);
+
+
+#endif
+
index 9be02eb839cd5692b20f355823184f2395e009dc..fcc5900887ffb634e2a974f25684f640c896fd3b 100644 (file)
@@ -53,6 +53,7 @@ int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *
        it->irq=irq;
        it->dev_id=dev_id;
        it->flags=flags;
+       it->device=device;
 
        ret=request_irq(irq,handler,flags&~SA_PRIORITY,device,dev_id);
        if(ret<0){
@@ -73,6 +74,7 @@ int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *
 int comedi_change_irq_flags(unsigned int irq,void *dev_id,unsigned long flags)
 {
        struct comedi_irq_struct *it;
+       int ret;
 
        it=get_irq_struct(irq);
        if(it){
@@ -84,9 +86,12 @@ int comedi_change_irq_flags(unsigned int irq,void *dev_id,unsigned long flags)
 
                it->flags=flags;
                if(flags&SA_PRIORITY){
+                       free_irq(it->irq,it->dev_id);
                        return get_priority_irq(it);
                }else{
-                       return free_priority_irq(it);
+                       ret=free_priority_irq(it);
+                       request_irq(it->irq,it->handler,it->flags,it->device,it->dev_id);
+                       return ret;
                }
        }
 
@@ -127,3 +132,9 @@ struct comedi_irq_struct *get_irq_struct(unsigned int irq)
        return NULL;
 }
 
+#ifdef HAVE_RT_PEND_TQ
+void wake_up_int_handler(int arg1, void * arg2)
+{
+       wake_up_interruptible((wait_queue_head_t*)arg2);
+}
+#endif
diff --git a/comedi/rt_pend_tq.h b/comedi/rt_pend_tq.h
new file mode 100644 (file)
index 0000000..67820e8
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __RT_PEND_TQ_H
+#define __RT_PEND_TQ_H
+#define RT_PEND_TQ_SIZE 16
+struct rt_pend_tq {
+       void (*func)(int arg1, void * arg2);
+       int arg1;
+       void *arg2;
+} ;
+extern int rt_pend_call(void (*func)(int arg1, void * arg2), int arg1, void * arg2);
+extern int rt_pend_tq_init(void);
+extern void rt_pend_tq_cleanup(void);
+#define HAVE_RT_PEND_TQ
+#endif
index b510e91673e19b41a98d48c0c4cc3682f502a158..e3dbe2d6e6ebe4820ca414f2026d91586d919738 100644 (file)
@@ -8,10 +8,12 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/sched.h>
-#include <asm/irq.h>
-#include <asm/ptrace.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/stddef.h>
+
+#include <asm/irq.h>
+#include <asm/ptrace.h>
 
 #include <rtai.h>
 
@@ -24,6 +26,8 @@ static void handle_rtai_irq(void)
 {
        struct comedi_irq_struct *it=rtai_irq;
 
+       printk("handle_rtai_irq printk, %p\n",it);
+       rt_printk("handle_rtai_irq, %p\n",it);
        if(it)
                it->handler(it->irq,it->dev_id,NULL);
 
@@ -36,7 +40,8 @@ int get_priority_irq(struct comedi_irq_struct *it)
 
        //free_irq(it->irq,it->dev_id);
        rt_request_global_irq(it->irq,handle_rtai_irq);
-       rt_enable_irq(it->irq);
+       rt_startup_irq(it->irq); // rtai 1.3
+//     rt_enable_irq(it->irq);  // did it ever work ?
 
        return 0;
 }
@@ -49,14 +54,64 @@ int free_priority_irq(struct comedi_irq_struct *it)
        return 0;
 }
 
+#ifdef NEED_RT_PEND_TQ
 
-void comedi_rtai_init(void)
+volatile static struct rt_pend_tq rt_pend_tq[RT_PEND_TQ_SIZE]; 
+volatile static struct rt_pend_tq * volatile rt_pend_head= rt_pend_tq,
+       * volatile rt_pend_tail = rt_pend_tq;
+int rt_pend_tq_irq=0;
+
+// WARNING: following code not checked against race conditions yet.
+#define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
+#define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
+
+int rt_pend_call(void (*func)(int arg1, void * arg2), int arg1, void * arg2)
 {
+       if(func==NULL)
+               return -EINVAL;
+       if(rt_pend_tq_irq<=0)
+               return -ENODEV;
+       INC_CIRCULAR_PTR(rt_pend_head,rt_pend_tq,RT_PEND_TQ_SIZE);
+       if(rt_pend_head==rt_pend_tail) {
+               // overflow, we just refuse to take this request
+               DEC_CIRCULAR_PTR(rt_pend_head,rt_pend_tq,RT_PEND_TQ_SIZE);
+               return -EAGAIN;
+       }
+       rt_pend_head->func=func;
+       rt_pend_head->arg1=arg1;
+       rt_pend_head->arg2=arg2;
+       rt_pend_linux_srq(rt_pend_tq_irq);
+       return 0;
+}
 
+void rt_pend_irq_handler(void)
+{
+       while(rt_pend_head!=rt_pend_tail) {
+               INC_CIRCULAR_PTR(rt_pend_tail,rt_pend_tq,RT_PEND_TQ_SIZE);
+               rt_pend_tail->func(rt_pend_tail->arg1,rt_pend_tail->arg2);
+       }
 }
 
-void comedi_rtai_cleanup(void)
+int rt_pend_tq_init(void)
 {
+       rt_pend_head=rt_pend_tail=rt_pend_tq;
+       return rt_pend_tq_irq=rt_request_srq(0,rt_pend_irq_handler,NULL);
+}
+
+void rt_pend_tq_cleanup(void)
+{
+       free_irq(rt_pend_tq_irq,NULL);
+}
+#endif
+
 
+void comedi_rtai_init(void)
+{
+       rt_pend_tq_init();
+}
+
+void comedi_rtai_cleanup(void)
+{
+       rt_pend_tq_cleanup();
 }
 
index 554da70ca333f8ab70226e7c97574a12ccfeea5e..33b5bae0e57221de2bffc0cb970d646845a42cae 100644 (file)
@@ -8,12 +8,13 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/sched.h>
-#include <asm/irq.h>
-#include <asm/ptrace.h>
 #include <linux/rtl.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+
 #include <rtl_core.h>
 #if 0
 #include <rtlinux/rtl_posixio.h>
@@ -210,16 +211,67 @@ int free_priority_irq(struct comedi_irq_struct *it)
        return 0;
 }
 
+#ifdef NEED_RT_PEND_TQ
+
+volatile static struct rt_pend_tq rt_pend_tq[RT_PEND_TQ_SIZE]; 
+volatile static struct rt_pend_tq * volatile rt_pend_head= rt_pend_tq,
+       * volatile rt_pend_tail = rt_pend_tq;
+int rt_pend_tq_irq=0;
+
+// WARNING: following code not checked against race conditions yet.
+#define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
+#define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
+
+int rt_pend_call(void (*func)(int arg1, void * arg2), int arg1, void * arg2)
+{
+       if(func==NULL)
+               return -EINVAL;
+       if(rt_pend_tq_irq<=0)
+               return -ENODEV;
+       INC_CIRCULAR_PTR(rt_pend_head,rt_pend_tq,RT_PEND_TQ_SIZE);
+       if(rt_pend_head==rt_pend_tail) {
+               // overflow, we just refuse to take this request
+               DEC_CIRCULAR_PTR(rt_pend_head,rt_pend_tq,RT_PEND_TQ_SIZE);
+               return -EAGAIN;
+       }
+       rt_pend_head->func=func;
+       rt_pend_head->arg1=arg1;
+       rt_pend_head->arg2=arg2;
+       rtl_global_pend_irq(rt_pend_tq_irq);
+       return 0;
+}
+
+void rt_pend_irq_handler(int irq, void *dev, struct pt_regs * regs)
+{
+       while(rt_pend_head!=rt_pend_tail) {
+               INC_CIRCULAR_PTR(rt_pend_tail,rt_pend_tq,RT_PEND_TQ_SIZE);
+               rt_pend_tail->func(rt_pend_tail->arg1,rt_pend_tail->arg2);
+       }
+}
+
+int rt_pend_tq_init()
+{
+       rt_pend_head=rt_pend_tail=rt_pend_tq;
+       return rt_pend_tq_irq=rtl_get_soft_irq(rt_pend_irq_handler,"rt_pend_irq");
+}
+
+void rt_pend_tq_cleanup()
+{
+       free_irq(rt_pend_tq_irq,NULL);
+}
+#endif
 
 void comedi_rtl_init(void)
 {
        //rt_printk_init();
        //rtl_register_chardev(COMEDI_MAJOR,"comedi",&comedi_rtl_fops);
+       rt_pend_tq_init();
 }
 
 void comedi_rtl_cleanup(void)
 {
        //rt_printk_cleanup();
        //rtl_unregister_chardev(COMEDI_MAJOR);
+       rt_pend_tq_cleanup();
 }