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
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
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 */
--- /dev/null
+/*
+ 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
+
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){
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){
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;
}
}
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
--- /dev/null
+#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
#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>
{
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);
//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;
}
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();
}
#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>
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();
}