3 #include <linux/kernel.h>
4 #include <linux/errno.h>
5 #include <linux/sched.h>
6 #include "comedidev.h" // for rt spinlocks
7 #include "rt_pend_tq.h"
8 #ifdef CONFIG_COMEDI_RTAI
11 #ifdef CONFIG_COMEDI_FUSION
12 #include <nucleus/asm/hal.h>
14 #ifdef CONFIG_COMEDI_RTL
19 #include <linux/module.h>
20 #define rt_pend_tq_init init_module
21 #define rt_pend_tq_cleanup cleanup_module
24 volatile static struct rt_pend_tq rt_pend_tq[RT_PEND_TQ_SIZE];
25 volatile static struct rt_pend_tq *volatile rt_pend_head = rt_pend_tq,
26 *volatile rt_pend_tail = rt_pend_tq;
27 int rt_pend_tq_irq = 0;
28 DEFINE_SPINLOCK(rt_pend_tq_lock);
30 // WARNING: following code not checked against race conditions yet.
31 #define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
32 #define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
34 int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2)
40 if (rt_pend_tq_irq <= 0)
42 comedi_spin_lock_irqsave(&rt_pend_tq_lock, flags);
43 INC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE);
44 if (rt_pend_head == rt_pend_tail) {
45 // overflow, we just refuse to take this request
46 DEC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE);
47 comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags);
50 rt_pend_head->func = func;
51 rt_pend_head->arg1 = arg1;
52 rt_pend_head->arg2 = arg2;
53 comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags);
54 #ifdef CONFIG_COMEDI_RTAI
55 rt_pend_linux_srq(rt_pend_tq_irq);
57 #ifdef CONFIG_COMEDI_FUSION
58 rthal_apc_schedule(rt_pend_tq_irq);
60 #ifdef CONFIG_COMEDI_RTL
61 rtl_global_pend_irq(rt_pend_tq_irq);
67 #ifdef CONFIG_COMEDI_RTAI
68 void rt_pend_irq_handler(void)
69 #elif defined(CONFIG_COMEDI_FUSION)
70 void rt_pend_irq_handler(void *cookie)
71 #elif defined(CONFIG_COMEDI_RTL)
72 void rt_pend_irq_handler(int irq, void *dev PT_REGS_ARG)
75 while (rt_pend_head != rt_pend_tail) {
76 INC_CIRCULAR_PTR(rt_pend_tail, rt_pend_tq, RT_PEND_TQ_SIZE);
77 rt_pend_tail->func(rt_pend_tail->arg1, rt_pend_tail->arg2);
81 int rt_pend_tq_init(void)
83 rt_pend_head = rt_pend_tail = rt_pend_tq;
84 #ifdef CONFIG_COMEDI_RTAI
85 rt_pend_tq_irq = rt_request_srq(0, rt_pend_irq_handler, NULL);
87 #ifdef CONFIG_COMEDI_FUSION
89 rthal_apc_alloc("comedi APC", rt_pend_irq_handler, NULL);
91 #ifdef CONFIG_COMEDI_RTL
92 rt_pend_tq_irq = rtl_get_soft_irq(rt_pend_irq_handler, "rt_pend_irq");
94 if (rt_pend_tq_irq > 0)
95 printk("rt_pend_tq: RT bottom half scheduler initialized OK\n");
97 printk("rt_pend_tq: rtl_get_soft_irq failed\n");
101 void rt_pend_tq_cleanup(void)
103 printk("rt_pend_tq: unloading\n");
104 #ifdef CONFIG_COMEDI_RTAI
105 rt_free_srq(rt_pend_tq_irq);
107 #ifdef CONFIG_COMEDI_FUSION
108 rthal_apc_free(rt_pend_tq_irq);
110 #ifdef CONFIG_COMEDI_RTL
111 free_irq(rt_pend_tq_irq, NULL);