5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define __NO_VERSION__
27 #include <linux/comedidev.h>
29 #include <linux/errno.h>
30 #include <linux/kernel.h>
31 #include <linux/sched.h>
32 #include <linux/fcntl.h>
33 #include <linux/delay.h>
34 #include <linux/ioport.h>
36 #include <linux/slab.h>
39 #include "rt_pend_tq.h"
41 #ifdef CONFIG_COMEDI_RTAI
45 #ifdef CONFIG_COMEDI_FUSION
46 #include <nucleus/asm/hal.h>
49 #ifdef CONFIG_COMEDI_RTL
54 struct comedi_irq_struct {
57 irqreturn_t(*handler) (int irq, void *dev_id PT_REGS_ARG);
60 comedi_device *dev_id;
63 static int comedi_rt_get_irq(struct comedi_irq_struct *it);
64 static int comedi_rt_release_irq(struct comedi_irq_struct *it);
66 static struct comedi_irq_struct *comedi_irqs[NR_IRQS];
68 int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
69 void *PT_REGS_ARG), unsigned long flags, const char *device,
70 comedi_device * dev_id)
72 struct comedi_irq_struct *it;
74 /* null shared interrupt flag, since rt interrupt handlers do not
75 * support it, and this version of comedi_request_irq() is only
76 * called for kernels with rt support */
77 unsigned long unshared_flags = flags & ~IRQF_SHARED;
79 ret = request_irq(irq, handler, unshared_flags, device, dev_id);
81 // we failed, so fall back on allowing shared interrupt (which we won't ever make RT)
82 if (flags & IRQF_SHARED) {
84 ("comedi: cannot get unshared interrupt, will not use RT interrupts.\n");
85 ret = request_irq(irq, handler, flags, device, dev_id);
91 it = kzalloc(sizeof(struct comedi_irq_struct), GFP_KERNEL);
95 it->handler = handler;
99 it->flags = unshared_flags;
100 comedi_irqs[irq] = it;
105 void comedi_free_irq(unsigned int irq, comedi_device * dev_id)
107 struct comedi_irq_struct *it;
109 free_irq(irq, dev_id);
111 it = comedi_irqs[irq];
116 printk("real-time IRQ allocated at board removal (ignore)\n");
117 comedi_rt_release_irq(it);
121 comedi_irqs[irq] = NULL;
124 int comedi_switch_to_rt(comedi_device * dev)
126 struct comedi_irq_struct *it;
129 it = comedi_irqs[dev->irq];
130 /* drivers might not be using an interrupt for commands,
131 or we might not have been able to get an unshared irq */
135 comedi_spin_lock_irqsave(&dev->spinlock, flags);
138 comedi_rt_get_irq(it);
143 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
148 void comedi_switch_to_non_rt(comedi_device * dev)
150 struct comedi_irq_struct *it;
153 it = comedi_irqs[dev->irq];
157 comedi_spin_lock_irqsave(&dev->spinlock, flags);
161 comedi_rt_release_irq(it);
165 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
168 void wake_up_int_handler(int arg1, void *arg2)
170 wake_up_interruptible((wait_queue_head_t *) arg2);
173 void comedi_rt_pend_wakeup(wait_queue_head_t * q)
175 rt_pend_call(wake_up_int_handler, 0, q);
179 #ifdef CONFIG_COMEDI_RTAI
181 #ifndef HAVE_RT_REQUEST_IRQ_WITH_ARG
182 #define DECLARE_VOID_IRQ(irq) \
183 static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);}
185 static void handle_void_irq(int irq)
187 struct comedi_irq_struct *it;
189 it = comedi_irqs[irq];
191 rt_printk("comedi: null irq struct?\n");
194 it->handler(irq, it->dev_id PT_REGS_NULL);
195 rt_enable_irq(irq); //needed by rtai-adeos, seems like it shouldn't hurt earlier versions
208 DECLARE_VOID_IRQ(10);
209 DECLARE_VOID_IRQ(11);
210 DECLARE_VOID_IRQ(12);
211 DECLARE_VOID_IRQ(13);
212 DECLARE_VOID_IRQ(14);
213 DECLARE_VOID_IRQ(15);
214 DECLARE_VOID_IRQ(16);
215 DECLARE_VOID_IRQ(17);
216 DECLARE_VOID_IRQ(18);
217 DECLARE_VOID_IRQ(19);
218 DECLARE_VOID_IRQ(20);
219 DECLARE_VOID_IRQ(21);
220 DECLARE_VOID_IRQ(22);
221 DECLARE_VOID_IRQ(23);
223 typedef void (*V_FP_V) (void);
224 static V_FP_V handle_void_irq_ptrs[] = {
251 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
253 rt_request_global_irq(it->irq, handle_void_irq_ptrs[it->irq]);
254 rt_startup_irq(it->irq);
259 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
261 rt_shutdown_irq(it->irq);
262 rt_free_global_irq(it->irq);
267 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
271 ret = rt_request_global_irq_arg(it->irq, it->handler, it->flags,
272 it->device, it->dev_id);
274 rt_printk("rt_request_global_irq_arg() returned %d\n", ret);
277 rt_startup_irq(it->irq);
282 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
284 rt_shutdown_irq(it->irq);
285 rt_free_global_irq(it->irq);
290 void comedi_rt_init(void)
296 void comedi_rt_cleanup(void)
299 rt_pend_tq_cleanup();
305 #ifdef CONFIG_COMEDI_FUSION
307 static void fusion_handle_irq(unsigned int irq, void *cookie)
309 struct comedi_irq_struct *it = cookie;
311 it->handler(irq, it->dev_id PT_REGS_NULL);
312 rthal_irq_enable(irq);
315 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
317 rthal_irq_request(it->irq, fusion_handle_irq, it);
318 rthal_irq_enable(it->irq);
322 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
324 rthal_irq_disable(it->irq);
325 rthal_irq_release(it->irq);
329 void comedi_rt_init(void)
334 void comedi_rt_cleanup(void)
336 rt_pend_tq_cleanup();
339 #endif /*CONFIG_COMEDI_FUSION */
341 /* RTLinux section */
342 #ifdef CONFIG_COMEDI_RTL
344 static unsigned int handle_rtl_irq(unsigned int irq PT_REGS_ARG)
346 struct comedi_irq_struct *it;
348 it = comedi_irqs[irq];
351 it->handler(irq, it->dev_id PT_REGS_NULL);
352 rtl_hard_enable_irq(irq);
356 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
358 rtl_request_global_irq(it->irq, handle_rtl_irq);
362 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
364 rtl_free_global_irq(it->irq);
368 void comedi_rt_init(void)
373 void comedi_rt_cleanup(void)
375 rt_pend_tq_cleanup();
380 #ifdef CONFIG_COMEDI_PIRQ
381 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
385 free_irq(it->irq, it->dev_id);
386 ret = request_irq(it->irq, it->handler, it->flags | SA_PRIORITY,
387 it->device, it->dev_id);
392 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
396 free_irq(it->irq, it->dev_id);
397 ret = request_irq(it->irq, it->handler, it->flags,
398 it->device, it->dev_id);
403 void comedi_rt_init(void)
408 void comedi_rt_cleanup(void)
410 //rt_pend_tq_cleanup();