staging: comedi, remove interrupt.h
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / comedi / rt.c
blobace360d4a492c4b75bda7027f1e45be83489f7aa
1 /*
2 comedi/rt.c
3 comedi kernel module
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.
24 #undef DEBUG
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>
36 #include <linux/mm.h>
37 #include <linux/slab.h>
38 #include <asm/io.h>
40 #include "rt_pend_tq.h"
42 #ifdef CONFIG_COMEDI_RTAI
43 #include <rtai.h>
44 #endif
46 #ifdef CONFIG_COMEDI_FUSION
47 #include <nucleus/asm/hal.h>
48 #endif
50 #ifdef CONFIG_COMEDI_RTL
51 #include <rtl_core.h>
52 #include <rtl_sync.h>
53 #endif
55 struct comedi_irq_struct {
56 int rt;
57 int irq;
58 irq_handler_t handler;
59 unsigned long flags;
60 const char *device;
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;
73 int ret;
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);
80 if (ret < 0) {
81 /* we failed, so fall back on allowing shared interrupt (which we won't ever make RT) */
82 if (flags & IRQF_SHARED) {
83 rt_printk
84 ("comedi: cannot get unshared interrupt, will not use RT interrupts.\n");
85 ret = request_irq(irq, handler, flags, device, dev_id);
87 if (ret < 0)
88 return ret;
90 } else {
91 it = kzalloc(sizeof(struct comedi_irq_struct), GFP_KERNEL);
92 if (!it)
93 return -ENOMEM;
95 it->handler = handler;
96 it->irq = irq;
97 it->dev_id = dev_id;
98 it->device = device;
99 it->flags = unshared_flags;
100 comedi_irqs[irq] = it;
102 return 0;
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];
112 if (it == NULL)
113 return;
115 if (it->rt) {
116 printk("real-time IRQ allocated at board removal (ignore)\n");
117 comedi_rt_release_irq(it);
120 kfree(it);
121 comedi_irqs[irq] = NULL;
124 int comedi_switch_to_rt(struct comedi_device *dev)
126 struct comedi_irq_struct *it;
127 unsigned long flags;
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 */
132 if (it == NULL)
133 return -1;
135 comedi_spin_lock_irqsave(&dev->spinlock, flags);
137 if (!dev->rt)
138 comedi_rt_get_irq(it);
140 dev->rt++;
141 it->rt = 1;
143 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
145 return 0;
148 void comedi_switch_to_non_rt(struct comedi_device *dev)
150 struct comedi_irq_struct *it;
151 unsigned long flags;
153 it = comedi_irqs[dev->irq];
154 if (it == NULL)
155 return;
157 comedi_spin_lock_irqsave(&dev->spinlock, flags);
159 dev->rt--;
160 if (!dev->rt)
161 comedi_rt_release_irq(it);
163 it->rt = 0;
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);
178 /* RTAI section */
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];
190 if (it == NULL) {
191 rt_printk("comedi: null irq struct?\n");
192 return;
194 it->handler(irq, it->dev_id);
195 rt_enable_irq(irq); /* needed by rtai-adeos, seems like it shouldn't hurt earlier versions */
198 DECLARE_VOID_IRQ(0);
199 DECLARE_VOID_IRQ(1);
200 DECLARE_VOID_IRQ(2);
201 DECLARE_VOID_IRQ(3);
202 DECLARE_VOID_IRQ(4);
203 DECLARE_VOID_IRQ(5);
204 DECLARE_VOID_IRQ(6);
205 DECLARE_VOID_IRQ(7);
206 DECLARE_VOID_IRQ(8);
207 DECLARE_VOID_IRQ(9);
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[] = {
224 handle_void_irq_0,
225 handle_void_irq_1,
226 handle_void_irq_2,
227 handle_void_irq_3,
228 handle_void_irq_4,
229 handle_void_irq_5,
230 handle_void_irq_6,
231 handle_void_irq_7,
232 handle_void_irq_8,
233 handle_void_irq_9,
234 handle_void_irq_10,
235 handle_void_irq_11,
236 handle_void_irq_12,
237 handle_void_irq_13,
238 handle_void_irq_14,
239 handle_void_irq_15,
240 handle_void_irq_16,
241 handle_void_irq_17,
242 handle_void_irq_18,
243 handle_void_irq_19,
244 handle_void_irq_20,
245 handle_void_irq_21,
246 handle_void_irq_22,
247 handle_void_irq_23,
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);
255 return 0;
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);
262 return 0;
264 #else
266 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
268 int ret;
270 ret = rt_request_global_irq_arg(it->irq, it->handler, it->flags,
271 it->device, it->dev_id);
272 if (ret < 0) {
273 rt_printk("rt_request_global_irq_arg() returned %d\n", ret);
274 return ret;
276 rt_startup_irq(it->irq);
278 return 0;
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);
285 return 0;
287 #endif
289 void comedi_rt_init(void)
291 rt_mount_rtai();
292 rt_pend_tq_init();
295 void comedi_rt_cleanup(void)
297 rt_umount_rtai();
298 rt_pend_tq_cleanup();
301 #endif
303 /* Fusion section */
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);
318 return 0;
321 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
323 rthal_irq_disable(it->irq);
324 rthal_irq_release(it->irq);
325 return 0;
328 void comedi_rt_init(void)
330 rt_pend_tq_init();
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];
348 if (it == NULL)
349 return 0;
350 it->handler(irq, it->dev_id);
351 rtl_hard_enable_irq(irq);
352 return 0;
355 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
357 rtl_request_global_irq(it->irq, handle_rtl_irq);
358 return 0;
361 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
363 rtl_free_global_irq(it->irq);
364 return 0;
367 void comedi_rt_init(void)
369 rt_pend_tq_init();
372 void comedi_rt_cleanup(void)
374 rt_pend_tq_cleanup();
377 #endif
379 #ifdef CONFIG_COMEDI_PIRQ
380 static int comedi_rt_get_irq(struct comedi_irq_struct *it)
382 int ret;
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);
388 return ret;
391 static int comedi_rt_release_irq(struct comedi_irq_struct *it)
393 int ret;
395 free_irq(it->irq, it->dev_id);
396 ret = request_irq(it->irq, it->handler, it->flags,
397 it->device, it->dev_id);
399 return ret;
402 void comedi_rt_init(void)
404 /* rt_pend_tq_init(); */
407 void comedi_rt_cleanup(void)
409 /* rt_pend_tq_cleanup(); */
411 #endif