Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux...
[sfrench/cifs-2.6.git] / drivers / staging / comedi / comedi_compat32.c
1 /*
2     comedi/comedi_compat32.c
3     32-bit ioctl compatibility for 64-bit comedi kernel module.
4
5     Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk>
6     Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/>
7
8     COMEDI - Linux Control and Measurement Device Interface
9     Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org>
10
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     You should have received a copy of the GNU General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25 */
26
27 #define __NO_VERSION__
28 #include "comedi.h"
29 #include <linux/smp_lock.h>
30 #include <asm/uaccess.h>
31
32 #include "comedi_compat32.h"
33
34 #ifdef CONFIG_COMPAT
35
36 #ifndef HAVE_COMPAT_IOCTL
37 #include <linux/ioctl32.h>      /* for (un)register_ioctl32_conversion */
38 #endif
39
40 #define COMEDI32_CHANINFO _IOR(CIO,3,comedi32_chaninfo)
41 #define COMEDI32_RANGEINFO _IOR(CIO,8,comedi32_rangeinfo)
42 /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
43  * It's too late to change it now, but it only affects the command number. */
44 #define COMEDI32_CMD _IOR(CIO,9,comedi32_cmd)
45 /* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR.
46  * It's too late to change it now, but it only affects the command number. */
47 #define COMEDI32_CMDTEST _IOR(CIO,10,comedi32_cmd)
48 #define COMEDI32_INSNLIST _IOR(CIO,11,comedi32_insnlist)
49 #define COMEDI32_INSN _IOR(CIO,12,comedi32_insn)
50
51 typedef struct comedi32_chaninfo_struct {
52         unsigned int subdev;
53         compat_uptr_t maxdata_list;     /* 32-bit 'lsampl_t *' */
54         compat_uptr_t flaglist;         /* 32-bit 'unsigned int *' */
55         compat_uptr_t rangelist;        /* 32-bit 'unsigned int *' */
56         unsigned int unused[4];
57 } comedi32_chaninfo;
58
59 typedef struct comedi32_rangeinfo_struct {
60         unsigned int range_type;
61         compat_uptr_t range_ptr;        /* 32-bit 'void *' */
62 } comedi32_rangeinfo;
63
64 typedef struct comedi32_cmd_struct {
65         unsigned int subdev;
66         unsigned int flags;
67         unsigned int start_src;
68         unsigned int start_arg;
69         unsigned int scan_begin_src;
70         unsigned int scan_begin_arg;
71         unsigned int convert_src;
72         unsigned int convert_arg;
73         unsigned int scan_end_src;
74         unsigned int scan_end_arg;
75         unsigned int stop_src;
76         unsigned int stop_arg;
77         compat_uptr_t chanlist;         /* 32-bit 'unsigned int *' */
78         unsigned int chanlist_len;
79         compat_uptr_t data;             /* 32-bit 'sampl_t *' */
80         unsigned int data_len;
81 } comedi32_cmd;
82
83 typedef struct comedi32_insn_struct {
84         unsigned int insn;
85         unsigned int n;
86         compat_uptr_t data;             /* 32-bit 'lsampl_t *' */
87         unsigned int subdev;
88         unsigned int chanspec;
89         unsigned int unused[3];
90 } comedi32_insn;
91
92 typedef struct comedi32_insnlist_struct {
93         unsigned int n_insns;
94         compat_uptr_t insns;            /* 32-bit 'comedi_insn *' */
95 } comedi32_insnlist;
96
97 /* Handle translated ioctl. */
98 static int translated_ioctl(struct file *file, unsigned int cmd,
99                 unsigned long arg)
100 {
101         if (!file->f_op) {
102                 return -ENOTTY;
103         }
104 #ifdef HAVE_UNLOCKED_IOCTL
105         if (file->f_op->unlocked_ioctl) {
106                 int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
107                 if (rc == -ENOIOCTLCMD) {
108                         rc = -ENOTTY;
109                 }
110                 return rc;
111         }
112 #endif
113         if (file->f_op->ioctl) {
114                 int rc;
115                 lock_kernel();
116                 rc = (*file->f_op->ioctl)(file->f_dentry->d_inode,
117                                 file, cmd, arg);
118                 unlock_kernel();
119                 return rc;
120         }
121         return -ENOTTY;
122 }
123
124 /* Handle 32-bit COMEDI_CHANINFO ioctl. */
125 static int compat_chaninfo(struct file *file, unsigned long arg)
126 {
127         comedi_chaninfo __user *chaninfo;
128         comedi32_chaninfo __user *chaninfo32;
129         int err;
130         union {
131                 unsigned int uint;
132                 compat_uptr_t uptr;
133         } temp;
134
135         chaninfo32 = compat_ptr(arg);
136         chaninfo = compat_alloc_user_space(sizeof(*chaninfo));
137
138         /* Copy chaninfo structure.  Ignore unused members. */
139         if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32))
140                         || !access_ok(VERIFY_WRITE, chaninfo,
141                                 sizeof(*chaninfo))) {
142                 return -EFAULT;
143         }
144         err = 0;
145         err |= __get_user(temp.uint, &chaninfo32->subdev);
146         err |= __put_user(temp.uint, &chaninfo->subdev);
147         err |= __get_user(temp.uptr, &chaninfo32->maxdata_list);
148         err |= __put_user(compat_ptr(temp.uptr), &chaninfo->maxdata_list);
149         err |= __get_user(temp.uptr, &chaninfo32->flaglist);
150         err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist);
151         err |= __get_user(temp.uptr, &chaninfo32->rangelist);
152         err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
153         if (err) {
154                 return -EFAULT;
155         }
156
157         return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
158 }
159
160 /* Handle 32-bit COMEDI_RANGEINFO ioctl. */
161 static int compat_rangeinfo(struct file *file, unsigned long arg)
162 {
163         comedi_rangeinfo __user *rangeinfo;
164         comedi32_rangeinfo __user *rangeinfo32;
165         int err;
166         union {
167                 unsigned int uint;
168                 compat_uptr_t uptr;
169         } temp;
170
171         rangeinfo32 = compat_ptr(arg);
172         rangeinfo = compat_alloc_user_space(sizeof(*rangeinfo));
173
174         /* Copy rangeinfo structure. */
175         if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32))
176                         || !access_ok(VERIFY_WRITE, rangeinfo,
177                                 sizeof(*rangeinfo))) {
178                 return -EFAULT;
179         }
180         err = 0;
181         err |= __get_user(temp.uint, &rangeinfo32->range_type);
182         err |= __put_user(temp.uint, &rangeinfo->range_type);
183         err |= __get_user(temp.uptr, &rangeinfo32->range_ptr);
184         err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr);
185         if (err) {
186                 return -EFAULT;
187         }
188
189         return translated_ioctl(file, COMEDI_RANGEINFO,
190                         (unsigned long)rangeinfo);
191 }
192
193 /* Copy 32-bit cmd structure to native cmd structure. */
194 static int get_compat_cmd(comedi_cmd __user *cmd,
195                 comedi32_cmd __user *cmd32)
196 {
197         int err;
198         union {
199                 unsigned int uint;
200                 compat_uptr_t uptr;
201         } temp;
202
203         /* Copy cmd structure. */
204         if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32))
205                         || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) {
206                 return -EFAULT;
207         }
208         err = 0;
209         err |= __get_user(temp.uint, &cmd32->subdev);
210         err |= __put_user(temp.uint, &cmd->subdev);
211         err |= __get_user(temp.uint, &cmd32->flags);
212         err |= __put_user(temp.uint, &cmd->flags);
213         err |= __get_user(temp.uint, &cmd32->start_src);
214         err |= __put_user(temp.uint, &cmd->start_src);
215         err |= __get_user(temp.uint, &cmd32->start_arg);
216         err |= __put_user(temp.uint, &cmd->start_arg);
217         err |= __get_user(temp.uint, &cmd32->scan_begin_src);
218         err |= __put_user(temp.uint, &cmd->scan_begin_src);
219         err |= __get_user(temp.uint, &cmd32->scan_begin_arg);
220         err |= __put_user(temp.uint, &cmd->scan_begin_arg);
221         err |= __get_user(temp.uint, &cmd32->convert_src);
222         err |= __put_user(temp.uint, &cmd->convert_src);
223         err |= __get_user(temp.uint, &cmd32->convert_arg);
224         err |= __put_user(temp.uint, &cmd->convert_arg);
225         err |= __get_user(temp.uint, &cmd32->scan_end_src);
226         err |= __put_user(temp.uint, &cmd->scan_end_src);
227         err |= __get_user(temp.uint, &cmd32->scan_end_arg);
228         err |= __put_user(temp.uint, &cmd->scan_end_arg);
229         err |= __get_user(temp.uint, &cmd32->stop_src);
230         err |= __put_user(temp.uint, &cmd->stop_src);
231         err |= __get_user(temp.uint, &cmd32->stop_arg);
232         err |= __put_user(temp.uint, &cmd->stop_arg);
233         err |= __get_user(temp.uptr, &cmd32->chanlist);
234         err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist);
235         err |= __get_user(temp.uint, &cmd32->chanlist_len);
236         err |= __put_user(temp.uint, &cmd->chanlist_len);
237         err |= __get_user(temp.uptr, &cmd32->data);
238         err |= __put_user(compat_ptr(temp.uptr), &cmd->data);
239         err |= __get_user(temp.uint, &cmd32->data_len);
240         err |= __put_user(temp.uint, &cmd->data_len);
241         return err ? -EFAULT : 0;
242 }
243
244 /* Copy native cmd structure to 32-bit cmd structure. */
245 static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd)
246 {
247         int err;
248         unsigned int temp;
249
250         /* Copy back most of cmd structure. */
251         /* Assume the pointer values are already valid. */
252         /* (Could use ptr_to_compat() to set them, but that wasn't implemented
253          * until kernel version 2.6.11.) */
254         if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd))
255                         || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) {
256                 return -EFAULT;
257         }
258         err = 0;
259         err |= __get_user(temp, &cmd->subdev);
260         err |= __put_user(temp, &cmd32->subdev);
261         err |= __get_user(temp, &cmd->flags);
262         err |= __put_user(temp, &cmd32->flags);
263         err |= __get_user(temp, &cmd->start_src);
264         err |= __put_user(temp, &cmd32->start_src);
265         err |= __get_user(temp, &cmd->start_arg);
266         err |= __put_user(temp, &cmd32->start_arg);
267         err |= __get_user(temp, &cmd->scan_begin_src);
268         err |= __put_user(temp, &cmd32->scan_begin_src);
269         err |= __get_user(temp, &cmd->scan_begin_arg);
270         err |= __put_user(temp, &cmd32->scan_begin_arg);
271         err |= __get_user(temp, &cmd->convert_src);
272         err |= __put_user(temp, &cmd32->convert_src);
273         err |= __get_user(temp, &cmd->convert_arg);
274         err |= __put_user(temp, &cmd32->convert_arg);
275         err |= __get_user(temp, &cmd->scan_end_src);
276         err |= __put_user(temp, &cmd32->scan_end_src);
277         err |= __get_user(temp, &cmd->scan_end_arg);
278         err |= __put_user(temp, &cmd32->scan_end_arg);
279         err |= __get_user(temp, &cmd->stop_src);
280         err |= __put_user(temp, &cmd32->stop_src);
281         err |= __get_user(temp, &cmd->stop_arg);
282         err |= __put_user(temp, &cmd32->stop_arg);
283         /* Assume chanlist pointer is unchanged. */
284         err |= __get_user(temp, &cmd->chanlist_len);
285         err |= __put_user(temp, &cmd32->chanlist_len);
286         /* Assume data pointer is unchanged. */
287         err |= __get_user(temp, &cmd->data_len);
288         err |= __put_user(temp, &cmd32->data_len);
289         return err ? -EFAULT : 0;
290 }
291
292 /* Handle 32-bit COMEDI_CMD ioctl. */
293 static int compat_cmd(struct file *file, unsigned long arg)
294 {
295         comedi_cmd __user *cmd;
296         comedi32_cmd __user *cmd32;
297         int rc;
298
299         cmd32 = compat_ptr(arg);
300         cmd = compat_alloc_user_space(sizeof(*cmd));
301
302         rc = get_compat_cmd(cmd, cmd32);
303         if (rc) {
304                 return rc;
305         }
306
307         return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
308 }
309
310 /* Handle 32-bit COMEDI_CMDTEST ioctl. */
311 static int compat_cmdtest(struct file *file, unsigned long arg)
312 {
313         comedi_cmd __user *cmd;
314         comedi32_cmd __user *cmd32;
315         int rc, err;
316
317         cmd32 = compat_ptr(arg);
318         cmd = compat_alloc_user_space(sizeof(*cmd));
319
320         rc = get_compat_cmd(cmd, cmd32);
321         if (rc) {
322                 return rc;
323         }
324
325         rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
326         if (rc < 0) {
327                 return rc;
328         }
329
330         err = put_compat_cmd(cmd32, cmd);
331         if (err) {
332                 rc = err;
333         }
334         return rc;
335 }
336
337 /* Copy 32-bit insn structure to native insn structure. */
338 static int get_compat_insn(comedi_insn __user *insn,
339                 comedi32_insn __user *insn32)
340 {
341         int err;
342         union {
343                 unsigned int uint;
344                 compat_uptr_t uptr;
345         } temp;
346
347         /* Copy insn structure.  Ignore the unused members. */
348         err = 0;
349         if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
350                         || !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) {
351                 return -EFAULT;
352         }
353         err |= __get_user(temp.uint, &insn32->insn);
354         err |= __put_user(temp.uint, &insn->insn);
355         err |= __get_user(temp.uint, &insn32->n);
356         err |= __put_user(temp.uint, &insn->n);
357         err |= __get_user(temp.uptr, &insn32->data);
358         err |= __put_user(compat_ptr(temp.uptr), &insn->data);
359         err |= __get_user(temp.uint, &insn32->subdev);
360         err |= __put_user(temp.uint, &insn->subdev);
361         err |= __get_user(temp.uint, &insn32->chanspec);
362         err |= __put_user(temp.uint, &insn->chanspec);
363         return err ? -EFAULT : 0;
364 }
365
366 /* Handle 32-bit COMEDI_INSNLIST ioctl. */
367 static int compat_insnlist(struct file *file, unsigned long arg)
368 {
369         struct combined_insnlist {
370                 comedi_insnlist insnlist;
371                 comedi_insn insn[1];
372         } __user *s;
373         comedi32_insnlist __user *insnlist32;
374         comedi32_insn __user *insn32;
375         compat_uptr_t uptr;
376         unsigned int n_insns, n;
377         int err, rc;
378
379         insnlist32 = compat_ptr(arg);
380
381         /* Get 32-bit insnlist structure.  */
382         if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) {
383                 return -EFAULT;
384         }
385         err = 0;
386         err |= __get_user(n_insns, &insnlist32->n_insns);
387         err |= __get_user(uptr, &insnlist32->insns);
388         insn32 = compat_ptr(uptr);
389         if (err) {
390                 return -EFAULT;
391         }
392
393         /* Allocate user memory to copy insnlist and insns into. */
394         s = compat_alloc_user_space(offsetof(struct combined_insnlist,
395                                 insn[n_insns]));
396
397         /* Set native insnlist structure. */
398         if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) {
399                 return -EFAULT;
400         }
401         err |= __put_user(n_insns, &s->insnlist.n_insns);
402         err |= __put_user(&s->insn[0], &s->insnlist.insns);
403         if (err) {
404                 return -EFAULT;
405         }
406
407         /* Copy insn structures. */
408         for (n = 0; n < n_insns; n++) {
409                 rc = get_compat_insn(&s->insn[n], &insn32[n]);
410                 if (rc) {
411                         return rc;
412                 }
413         }
414
415         return translated_ioctl(file, COMEDI_INSNLIST,
416                         (unsigned long)&s->insnlist);
417 }
418
419 /* Handle 32-bit COMEDI_INSN ioctl. */
420 static int compat_insn(struct file *file, unsigned long arg)
421 {
422         comedi_insn __user *insn;
423         comedi32_insn __user *insn32;
424         int rc;
425
426         insn32 = compat_ptr(arg);
427         insn = compat_alloc_user_space(sizeof(*insn));
428
429         rc = get_compat_insn(insn, insn32);
430         if (rc) {
431                 return rc;
432         }
433
434         return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn);
435 }
436
437 /* Process untranslated ioctl. */
438 /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
439 static inline int raw_ioctl(struct file *file, unsigned int cmd,
440                 unsigned long arg)
441 {
442         int rc;
443
444         switch (cmd) {
445         case COMEDI_DEVCONFIG:
446         case COMEDI_DEVINFO:
447         case COMEDI_SUBDINFO:
448         case COMEDI_BUFCONFIG:
449         case COMEDI_BUFINFO:
450                 /* Just need to translate the pointer argument. */
451                 arg = (unsigned long)compat_ptr(arg);
452                 rc = translated_ioctl(file, cmd, arg);
453                 break;
454         case COMEDI_LOCK:
455         case COMEDI_UNLOCK:
456         case COMEDI_CANCEL:
457         case COMEDI_POLL:
458                 /* No translation needed. */
459                 rc = translated_ioctl(file, cmd, arg);
460                 break;
461         case COMEDI32_CHANINFO:
462                 rc = compat_chaninfo(file, arg);
463                 break;
464         case COMEDI32_RANGEINFO:
465                 rc = compat_rangeinfo(file, arg);
466                 break;
467         case COMEDI32_CMD:
468                 rc = compat_cmd(file, arg);
469                 break;
470         case COMEDI32_CMDTEST:
471                 rc = compat_cmdtest(file, arg);
472                 break;
473         case COMEDI32_INSNLIST:
474                 rc = compat_insnlist(file, arg);
475                 break;
476         case COMEDI32_INSN:
477                 rc = compat_insn(file, arg);
478                 break;
479         default:
480                 rc = -ENOIOCTLCMD;
481                 break;
482         }
483         return rc;
484 }
485
486 #ifdef HAVE_COMPAT_IOCTL        /* defined in <linux/fs.h> 2.6.11 onwards */
487
488 /* compat_ioctl file operation. */
489 /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
490 long comedi_compat_ioctl(struct file *file, unsigned int cmd,
491                 unsigned long arg)
492 {
493         return raw_ioctl(file, cmd, arg);
494 }
495
496 #else /* HAVE_COMPAT_IOCTL */
497
498 /*
499  * Brain-dead ioctl compatibility for 2.6.10 and earlier.
500  *
501  * It's brain-dead because cmd numbers need to be unique system-wide!
502  * The comedi driver could end up attempting to execute ioctls for non-Comedi
503  * devices because it registered the system-wide cmd code first.  Similarly,
504  * another driver could end up attempting to execute ioctls for a Comedi
505  * device because it registered the cmd code first.  Chaos ensues.
506  */
507
508 /* Handler for all 32-bit ioctl codes registered by this driver. */
509 static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
510                 struct file *file)
511 {
512         int rc;
513
514         /* Make sure we are dealing with a Comedi device. */
515         if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR) {
516                 return -ENOTTY;
517         }
518         rc = raw_ioctl(file, cmd, arg);
519         /* Do not return -ENOIOCTLCMD. */
520         if (rc == -ENOIOCTLCMD) {
521                 rc = -ENOTTY;
522         }
523         return rc;
524 }
525
526 struct ioctl32_map {
527         unsigned int cmd;
528         int (*handler)(unsigned int, unsigned int, unsigned long,
529                         struct file *);
530         int registered;
531 };
532
533 static struct ioctl32_map comedi_ioctl32_map[] = {
534         { COMEDI_DEVCONFIG, mapped_ioctl, 0 },
535         { COMEDI_DEVINFO, mapped_ioctl, 0 },
536         { COMEDI_SUBDINFO, mapped_ioctl, 0 },
537         { COMEDI_BUFCONFIG, mapped_ioctl, 0 },
538         { COMEDI_BUFINFO, mapped_ioctl, 0 },
539         { COMEDI_LOCK, mapped_ioctl, 0 },
540         { COMEDI_UNLOCK, mapped_ioctl, 0 },
541         { COMEDI_CANCEL, mapped_ioctl, 0 },
542         { COMEDI_POLL, mapped_ioctl, 0 },
543         { COMEDI32_CHANINFO, mapped_ioctl, 0 },
544         { COMEDI32_RANGEINFO, mapped_ioctl, 0 },
545         { COMEDI32_CMD, mapped_ioctl, 0 },
546         { COMEDI32_CMDTEST, mapped_ioctl, 0 },
547         { COMEDI32_INSNLIST, mapped_ioctl, 0 },
548         { COMEDI32_INSN, mapped_ioctl, 0 },
549 };
550
551 #define NUM_IOCTL32_MAPS ARRAY_SIZE(comedi_ioctl32_map)
552
553 /* Register system-wide 32-bit ioctl handlers. */
554 void comedi_register_ioctl32(void)
555 {
556         int n, rc;
557
558         for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
559                 rc = register_ioctl32_conversion(comedi_ioctl32_map[n].cmd,
560                                 comedi_ioctl32_map[n].handler);
561                 if (rc) {
562                         printk(KERN_WARNING
563                                         "comedi: failed to register 32-bit "
564                                         "compatible ioctl handler for 0x%X - "
565                                         "expect bad things to happen!\n",
566                                         comedi_ioctl32_map[n].cmd);
567                 }
568                 comedi_ioctl32_map[n].registered = !rc;
569         }
570 }
571
572 /* Unregister system-wide 32-bit ioctl translations. */
573 void comedi_unregister_ioctl32(void)
574 {
575         int n, rc;
576
577         for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
578                 if (comedi_ioctl32_map[n].registered) {
579                         rc = unregister_ioctl32_conversion(
580                                         comedi_ioctl32_map[n].cmd,
581                                         comedi_ioctl32_map[n].handler);
582                         if (rc) {
583                                 printk(KERN_ERR
584                                         "comedi: failed to unregister 32-bit "
585                                         "compatible ioctl handler for 0x%X - "
586                                         "expect kernel Oops!\n",
587                                         comedi_ioctl32_map[n].cmd);
588                         } else {
589                                 comedi_ioctl32_map[n].registered = 0;
590                         }
591                 }
592         }
593 }
594
595 #endif  /* HAVE_COMPAT_IOCTL */
596
597 #endif  /* CONFIG_COMPAT */