From 26796c39bed9f4b38f5017a746bd4a4ee2211fb0 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 14 Jun 2000 07:26:47 +0000 Subject: [PATCH] TM added rt interrupt for user space support --- comedi/comedi_module.h | 66 ++++--------------------- comedi/comedi_rt.h | 107 +++++++++++++++++++++++++++++++++++++++++ comedi/rt.c | 13 ++++- comedi/rt_pend_tq.h | 13 +++++ comedi/rtai.c | 65 +++++++++++++++++++++++-- comedi/rtl.c | 56 ++++++++++++++++++++- 6 files changed, 256 insertions(+), 64 deletions(-) create mode 100644 comedi/comedi_rt.h create mode 100644 comedi/rt_pend_tq.h diff --git a/comedi/comedi_module.h b/comedi/comedi_module.h index a5fc0409..ed3a175a 100644 --- a/comedi/comedi_module.h +++ b/comedi/comedi_module.h @@ -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 + Copyright (C) 1997-2000 David A. Schleef 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 @@ -36,54 +36,7 @@ #include #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 -#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 #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 index 00000000..b7803a01 --- /dev/null +++ b/comedi/comedi_rt.h @@ -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 + + 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 +#include +#include +#include +#include +#include +#include + + +#include + + +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 + +#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 +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 + diff --git a/comedi/rt.c b/comedi/rt.c index 9be02eb8..fcc59008 100644 --- a/comedi/rt.c +++ b/comedi/rt.c @@ -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 index 00000000..67820e81 --- /dev/null +++ b/comedi/rt_pend_tq.h @@ -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 diff --git a/comedi/rtai.c b/comedi/rtai.c index b510e916..e3dbe2d6 100644 --- a/comedi/rtai.c +++ b/comedi/rtai.c @@ -8,10 +8,12 @@ #include #include #include -#include -#include #include #include +#include + +#include +#include #include @@ -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(); } diff --git a/comedi/rtl.c b/comedi/rtl.c index 554da70c..33b5bae0 100644 --- a/comedi/rtl.c +++ b/comedi/rtl.c @@ -8,12 +8,13 @@ #include #include #include -#include -#include #include #include #include +#include +#include + #include #if 0 #include @@ -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(); } -- 2.26.2