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/interrupt.h>
31 #include <linux/kernel.h>
32 #include <linux/sched.h>
33 #include <linux/fcntl.h>
34 #include <linux/delay.h>
35 #include <linux/ioport.h>
37 #include <linux/slab.h>
40 #include "rt_pend_tq.h"
42 #ifdef CONFIG_COMEDI_RTAI
46 #ifdef CONFIG_COMEDI_FUSION
47 #include <nucleus/asm/hal.h>
50 #ifdef CONFIG_COMEDI_RTL
55 struct comedi_irq_struct
{
58 irq_handler_t handler
;
61 struct comedi_device
*dev_id
;
64 static int comedi_rt_get_irq(struct comedi_irq_struct
*it
);
65 static int comedi_rt_release_irq(struct comedi_irq_struct
*it
);
67 static struct comedi_irq_struct
*comedi_irqs
[NR_IRQS
];
69 int comedi_request_irq(unsigned irq
, irq_handler_t handler
, unsigned long flags
,
70 const char *device
, struct 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
, struct 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(struct 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(struct 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
);
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 static void handle_void_irq_ptrs
[] = {
250 static int comedi_rt_get_irq(struct comedi_irq_struct
*it
)
252 rt_request_global_irq(it
->irq
, handle_void_irq_ptrs
[it
->irq
]);
253 rt_startup_irq(it
->irq
);
258 static int comedi_rt_release_irq(struct comedi_irq_struct
*it
)
260 rt_shutdown_irq(it
->irq
);
261 rt_free_global_irq(it
->irq
);
266 static int comedi_rt_get_irq(struct comedi_irq_struct
*it
)
270 ret
= rt_request_global_irq_arg(it
->irq
, it
->handler
, it
->flags
,
271 it
->device
, it
->dev_id
);
273 rt_printk("rt_request_global_irq_arg() returned %d\n", ret
);
276 rt_startup_irq(it
->irq
);
281 static int comedi_rt_release_irq(struct comedi_irq_struct
*it
)
283 rt_shutdown_irq(it
->irq
);
284 rt_free_global_irq(it
->irq
);
289 void comedi_rt_init(void)
295 void comedi_rt_cleanup(void)
298 rt_pend_tq_cleanup();
304 #ifdef CONFIG_COMEDI_FUSION
306 static void fusion_handle_irq(unsigned int irq
, void *cookie
)
308 struct comedi_irq_struct
*it
= cookie
;
310 it
->handler(irq
, it
->dev_id
);
311 rthal_irq_enable(irq
);
314 static int comedi_rt_get_irq(struct comedi_irq_struct
*it
)
316 rthal_irq_request(it
->irq
, fusion_handle_irq
, it
);
317 rthal_irq_enable(it
->irq
);
321 static int comedi_rt_release_irq(struct comedi_irq_struct
*it
)
323 rthal_irq_disable(it
->irq
);
324 rthal_irq_release(it
->irq
);
328 void comedi_rt_init(void)
333 void comedi_rt_cleanup(void)
335 rt_pend_tq_cleanup();
338 #endif /*CONFIG_COMEDI_FUSION */
340 /* RTLinux section */
341 #ifdef CONFIG_COMEDI_RTL
343 static unsigned int handle_rtl_irq(unsigned int irq
)
345 struct comedi_irq_struct
*it
;
347 it
= comedi_irqs
[irq
];
350 it
->handler(irq
, it
->dev_id
);
351 rtl_hard_enable_irq(irq
);
355 static int comedi_rt_get_irq(struct comedi_irq_struct
*it
)
357 rtl_request_global_irq(it
->irq
, handle_rtl_irq
);
361 static int comedi_rt_release_irq(struct comedi_irq_struct
*it
)
363 rtl_free_global_irq(it
->irq
);
367 void comedi_rt_init(void)
372 void comedi_rt_cleanup(void)
374 rt_pend_tq_cleanup();
379 #ifdef CONFIG_COMEDI_PIRQ
380 static int comedi_rt_get_irq(struct comedi_irq_struct
*it
)
384 free_irq(it
->irq
, it
->dev_id
);
385 ret
= request_irq(it
->irq
, it
->handler
, it
->flags
| SA_PRIORITY
,
386 it
->device
, it
->dev_id
);
391 static int comedi_rt_release_irq(struct comedi_irq_struct
*it
)
395 free_irq(it
->irq
, it
->dev_id
);
396 ret
= request_irq(it
->irq
, it
->handler
, it
->flags
,
397 it
->device
, it
->dev_id
);
402 void comedi_rt_init(void)
404 /* rt_pend_tq_init(); */
407 void comedi_rt_cleanup(void)
409 /* rt_pend_tq_cleanup(); */