Staging: comedi: Convert C99 style comments to traditional style comments
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / rt.c
CommitLineData
ed9eccbe
DS
1/*
2 comedi/rt.c
3 comedi kernel module
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
7
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.
12
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.
17
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.
21
22*/
23
24#undef DEBUG
25
26#define __NO_VERSION__
27#include <linux/comedidev.h>
28
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>
35#include <linux/mm.h>
36#include <linux/slab.h>
37#include <asm/io.h>
38
39#include "rt_pend_tq.h"
40
41#ifdef CONFIG_COMEDI_RTAI
42#include <rtai.h>
43#endif
44
45#ifdef CONFIG_COMEDI_FUSION
46#include <nucleus/asm/hal.h>
47#endif
48
49#ifdef CONFIG_COMEDI_RTL
50#include <rtl_core.h>
51#include <rtl_sync.h>
52#endif
53
54struct comedi_irq_struct {
55 int rt;
56 int irq;
57 irqreturn_t(*handler) (int irq, void *dev_id PT_REGS_ARG);
58 unsigned long flags;
59 const char *device;
60 comedi_device *dev_id;
61};
62
63static int comedi_rt_get_irq(struct comedi_irq_struct *it);
64static int comedi_rt_release_irq(struct comedi_irq_struct *it);
65
66static struct comedi_irq_struct *comedi_irqs[NR_IRQS];
67
68int 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)
71{
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;
78
79 ret = request_irq(irq, handler, unshared_flags, device, dev_id);
80 if (ret < 0) {
b6c77757 81 /* we failed, so fall back on allowing shared interrupt (which we won't ever make RT) */
ed9eccbe
DS
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);
86 }
87 if (ret < 0) {
88 return ret;
89 }
90 } else {
91 it = kzalloc(sizeof(struct comedi_irq_struct), GFP_KERNEL);
92 if (!it)
93 return -ENOMEM;
94
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;
101 }
102 return 0;
103}
104
105void comedi_free_irq(unsigned int irq, comedi_device * dev_id)
106{
107 struct comedi_irq_struct *it;
108
109 free_irq(irq, dev_id);
110
111 it = comedi_irqs[irq];
112 if (it == NULL)
113 return;
114
115 if (it->rt) {
116 printk("real-time IRQ allocated at board removal (ignore)\n");
117 comedi_rt_release_irq(it);
118 }
119
120 kfree(it);
121 comedi_irqs[irq] = NULL;
122}
123
124int comedi_switch_to_rt(comedi_device * dev)
125{
126 struct comedi_irq_struct *it;
127 unsigned long flags;
128
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;
134
135 comedi_spin_lock_irqsave(&dev->spinlock, flags);
136
137 if (!dev->rt)
138 comedi_rt_get_irq(it);
139
140 dev->rt++;
141 it->rt = 1;
142
143 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
144
145 return 0;
146}
147
148void comedi_switch_to_non_rt(comedi_device * dev)
149{
150 struct comedi_irq_struct *it;
151 unsigned long flags;
152
153 it = comedi_irqs[dev->irq];
154 if (it == NULL)
155 return;
156
157 comedi_spin_lock_irqsave(&dev->spinlock, flags);
158
159 dev->rt--;
160 if (!dev->rt)
161 comedi_rt_release_irq(it);
162
163 it->rt = 0;
164
165 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
166}
167
168void wake_up_int_handler(int arg1, void *arg2)
169{
170 wake_up_interruptible((wait_queue_head_t *) arg2);
171}
172
173void comedi_rt_pend_wakeup(wait_queue_head_t * q)
174{
175 rt_pend_call(wake_up_int_handler, 0, q);
176}
177
178/* RTAI section */
179#ifdef CONFIG_COMEDI_RTAI
180
181#ifndef HAVE_RT_REQUEST_IRQ_WITH_ARG
182#define DECLARE_VOID_IRQ(irq) \
183static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);}
184
185static void handle_void_irq(int irq)
186{
187 struct comedi_irq_struct *it;
188
189 it = comedi_irqs[irq];
190 if (it == NULL) {
191 rt_printk("comedi: null irq struct?\n");
192 return;
193 }
194 it->handler(irq, it->dev_id PT_REGS_NULL);
b6c77757 195 rt_enable_irq(irq); /* needed by rtai-adeos, seems like it shouldn't hurt earlier versions */
ed9eccbe
DS
196}
197
198DECLARE_VOID_IRQ(0);
199DECLARE_VOID_IRQ(1);
200DECLARE_VOID_IRQ(2);
201DECLARE_VOID_IRQ(3);
202DECLARE_VOID_IRQ(4);
203DECLARE_VOID_IRQ(5);
204DECLARE_VOID_IRQ(6);
205DECLARE_VOID_IRQ(7);
206DECLARE_VOID_IRQ(8);
207DECLARE_VOID_IRQ(9);
208DECLARE_VOID_IRQ(10);
209DECLARE_VOID_IRQ(11);
210DECLARE_VOID_IRQ(12);
211DECLARE_VOID_IRQ(13);
212DECLARE_VOID_IRQ(14);
213DECLARE_VOID_IRQ(15);
214DECLARE_VOID_IRQ(16);
215DECLARE_VOID_IRQ(17);
216DECLARE_VOID_IRQ(18);
217DECLARE_VOID_IRQ(19);
218DECLARE_VOID_IRQ(20);
219DECLARE_VOID_IRQ(21);
220DECLARE_VOID_IRQ(22);
221DECLARE_VOID_IRQ(23);
222
223typedef void (*V_FP_V) (void);
224static V_FP_V handle_void_irq_ptrs[] = {
225 handle_void_irq_0,
226 handle_void_irq_1,
227 handle_void_irq_2,
228 handle_void_irq_3,
229 handle_void_irq_4,
230 handle_void_irq_5,
231 handle_void_irq_6,
232 handle_void_irq_7,
233 handle_void_irq_8,
234 handle_void_irq_9,
235 handle_void_irq_10,
236 handle_void_irq_11,
237 handle_void_irq_12,
238 handle_void_irq_13,
239 handle_void_irq_14,
240 handle_void_irq_15,
241 handle_void_irq_16,
242 handle_void_irq_17,
243 handle_void_irq_18,
244 handle_void_irq_19,
245 handle_void_irq_20,
246 handle_void_irq_21,
247 handle_void_irq_22,
248 handle_void_irq_23,
249};
250
251static int comedi_rt_get_irq(struct comedi_irq_struct *it)
252{
253 rt_request_global_irq(it->irq, handle_void_irq_ptrs[it->irq]);
254 rt_startup_irq(it->irq);
255
256 return 0;
257}
258
259static int comedi_rt_release_irq(struct comedi_irq_struct *it)
260{
261 rt_shutdown_irq(it->irq);
262 rt_free_global_irq(it->irq);
263 return 0;
264}
265#else
266
267static int comedi_rt_get_irq(struct comedi_irq_struct *it)
268{
269 int ret;
270
271 ret = rt_request_global_irq_arg(it->irq, it->handler, it->flags,
272 it->device, it->dev_id);
273 if (ret < 0) {
274 rt_printk("rt_request_global_irq_arg() returned %d\n", ret);
275 return ret;
276 }
277 rt_startup_irq(it->irq);
278
279 return 0;
280}
281
282static int comedi_rt_release_irq(struct comedi_irq_struct *it)
283{
284 rt_shutdown_irq(it->irq);
285 rt_free_global_irq(it->irq);
286 return 0;
287}
288#endif
289
290void comedi_rt_init(void)
291{
292 rt_mount_rtai();
293 rt_pend_tq_init();
294}
295
296void comedi_rt_cleanup(void)
297{
298 rt_umount_rtai();
299 rt_pend_tq_cleanup();
300}
301
302#endif
303
304/* Fusion section */
305#ifdef CONFIG_COMEDI_FUSION
306
307static void fusion_handle_irq(unsigned int irq, void *cookie)
308{
309 struct comedi_irq_struct *it = cookie;
310
311 it->handler(irq, it->dev_id PT_REGS_NULL);
312 rthal_irq_enable(irq);
313}
314
315static int comedi_rt_get_irq(struct comedi_irq_struct *it)
316{
317 rthal_irq_request(it->irq, fusion_handle_irq, it);
318 rthal_irq_enable(it->irq);
319 return 0;
320}
321
322static int comedi_rt_release_irq(struct comedi_irq_struct *it)
323{
324 rthal_irq_disable(it->irq);
325 rthal_irq_release(it->irq);
326 return 0;
327}
328
329void comedi_rt_init(void)
330{
331 rt_pend_tq_init();
332}
333
334void comedi_rt_cleanup(void)
335{
336 rt_pend_tq_cleanup();
337}
338
339#endif /*CONFIG_COMEDI_FUSION */
340
341/* RTLinux section */
342#ifdef CONFIG_COMEDI_RTL
343
344static unsigned int handle_rtl_irq(unsigned int irq PT_REGS_ARG)
345{
346 struct comedi_irq_struct *it;
347
348 it = comedi_irqs[irq];
349 if (it == NULL)
350 return 0;
351 it->handler(irq, it->dev_id PT_REGS_NULL);
352 rtl_hard_enable_irq(irq);
353 return 0;
354}
355
356static int comedi_rt_get_irq(struct comedi_irq_struct *it)
357{
358 rtl_request_global_irq(it->irq, handle_rtl_irq);
359 return 0;
360}
361
362static int comedi_rt_release_irq(struct comedi_irq_struct *it)
363{
364 rtl_free_global_irq(it->irq);
365 return 0;
366}
367
368void comedi_rt_init(void)
369{
370 rt_pend_tq_init();
371}
372
373void comedi_rt_cleanup(void)
374{
375 rt_pend_tq_cleanup();
376}
377
378#endif
379
380#ifdef CONFIG_COMEDI_PIRQ
381static int comedi_rt_get_irq(struct comedi_irq_struct *it)
382{
383 int ret;
384
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);
388
389 return ret;
390}
391
392static int comedi_rt_release_irq(struct comedi_irq_struct *it)
393{
394 int ret;
395
396 free_irq(it->irq, it->dev_id);
397 ret = request_irq(it->irq, it->handler, it->flags,
398 it->device, it->dev_id);
399
400 return ret;
401}
402
403void comedi_rt_init(void)
404{
b6c77757 405 /* rt_pend_tq_init(); */
ed9eccbe
DS
406}
407
408void comedi_rt_cleanup(void)
409{
b6c77757 410 /* rt_pend_tq_cleanup(); */
ed9eccbe
DS
411}
412#endif