b29c1adb8f3ac35cbb081aa30e6688d05008053b
[openafs.git] / src / afs / LINUX24 / osi_ioctl.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Linux module support routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17
18 #include <linux/module.h> /* early to avoid printf->printk mapping */
19 #include "afs/sysincludes.h"
20 #include "afsincludes.h"
21 #include "h/unistd.h"           /* For syscall numbers. */
22 #include "h/mm.h"
23
24 #ifdef AFS_AMD64_LINUX20_ENV
25 #include <asm/ia32_unistd.h>
26 #endif
27 #ifdef AFS_SPARC64_LINUX20_ENV
28 #include <linux/ioctl32.h>
29 #endif
30
31 #include <linux/proc_fs.h>
32 #include <linux/slab.h>
33 #include <linux/init.h>
34 #include <linux/sched.h>
35 #include <linux/kernel.h>
36
37 extern struct proc_dir_entry *openafs_procfs;
38 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
39 static int ioctl32_done;
40 #endif
41
42 extern asmlinkage long
43 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
44
45 static int
46 afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
47           unsigned long arg)
48 {
49
50     struct afsprocdata sysargs;
51 #ifdef NEED_IOCTL32
52     struct afsprocdata32 sysargs32;
53 #endif
54
55     if (cmd != VIOC_SYSCALL && cmd != VIOC_SYSCALL32) return -EINVAL;
56
57 #ifdef NEED_IOCTL32
58 #ifdef AFS_SPARC64_LINUX24_ENV
59     if (current->thread.flags & SPARC_FLAG_32BIT)
60 #elif defined(AFS_SPARC64_LINUX20_ENV)
61     if (current->tss.flags & SPARC_FLAG_32BIT)
62 #elif defined(AFS_AMD64_LINUX20_ENV)
63     if (current->thread.flags & THREAD_IA32)
64 #elif defined(AFS_PPC64_LINUX20_ENV)
65     if (current->thread.flags & PPC_FLAG_32BIT)
66 #elif defined(AFS_S390X_LINUX20_ENV)
67     if (current->thread.flags & S390_FLAG_31BIT)
68 #else
69 #error Not done for this linux type
70 #endif 
71 #endif /* NEED_IOCTL32 */
72     {
73         if (copy_from_user(&sysargs32, (void *)arg,
74                            sizeof(struct afsprocdata32)))
75             return -EFAULT;
76
77         return afs_syscall((unsigned long)sysargs32.syscall,
78                            (unsigned long)sysargs32.param1,
79                            (unsigned long)sysargs32.param2,
80                            (unsigned long)sysargs32.param3,
81                            (unsigned long)sysargs32.param4);
82     } else {
83         if (copy_from_user(&sysargs, (void *)arg, sizeof(struct afsprocdata)))
84             return -EFAULT;
85
86         return afs_syscall(sysargs.syscall, sysargs.param1,
87                            sysargs.param2, sysargs.param3, sysargs.param4);
88     }
89 }
90
91 #if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
92 static long afs_unlocked_ioctl(struct file *file, unsigned int cmd,
93                                unsigned long arg) {
94     return afs_ioctl(FILE_INODE(file), file, cmd, arg);
95 }
96 #endif
97
98 static struct file_operations afs_syscall_fops = {
99 #ifdef HAVE_UNLOCKED_IOCTL
100     .unlocked_ioctl = afs_unlocked_ioctl,
101 #else
102     .ioctl = afs_ioctl,
103 #endif
104 #ifdef HAVE_COMPAT_IOCTL
105     .compat_ioctl = afs_unlocked_ioctl,
106 #endif
107 };
108
109 void
110 osi_ioctl_init(void)
111 {
112     struct proc_dir_entry *entry;
113
114     entry = create_proc_entry(PROC_SYSCALL_NAME, 0666, openafs_procfs);
115     entry->proc_fops = &afs_syscall_fops;
116 #if defined(STRUCT_PROC_DIR_ENTRY_HAS_OWNER)
117     entry->owner = THIS_MODULE;
118 #endif
119
120 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
121     if (register_ioctl32_conversion(VIOC_SYSCALL32, NULL) == 0) 
122         ioctl32_done = 1;
123 #endif
124 }
125
126 void
127 osi_ioctl_clean(void)
128 {
129     remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs);
130 #if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
131     if (ioctl32_done)
132             unregister_ioctl32_conversion(VIOC_SYSCALL32);
133 #endif
134 }