v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / arch / s390x / kernel / ioctl32.c
1 /*
2  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
3  *
4  *  S390 version
5  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6  *    Author(s): Gerhard Tonn (ton@de.ibm.com)
7  *
8  * Heavily inspired by the 32-bit Sparc compat code which is  
9  * Copyright (C) 2000 Silicon Graphics, Inc.
10  * Written by Ulf Carlsson (ulfc@engr.sgi.com) 
11  *
12  */
13
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/fs.h>
17 #include <linux/sched.h>
18 #include <linux/mm.h>
19 #include <linux/init.h>
20 #include <linux/file.h>
21 #include <linux/vt.h>
22 #include <linux/kd.h>
23 #include <linux/netdevice.h>
24 #include <linux/route.h>
25 #include <linux/ext2_fs.h>
26 #include <linux/hdreg.h>
27 #include <asm/types.h>
28 #include <asm/uaccess.h>
29 #include <asm/dasd.h>
30
31 #include "linux32.h"
32
33 long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
34
35 struct hd_geometry32 {
36         unsigned char   heads;
37         unsigned char   sectors;
38         unsigned short  cylinders;
39         __u32           start;
40 };  
41
42 static inline int hd_geometry_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
43 {
44         struct hd_geometry32 *hg32 = (struct hd_geometry32 *) A(arg);
45         struct hd_geometry hg;
46         int ret;
47         mm_segment_t old_fs = get_fs();
48         
49         set_fs (KERNEL_DS);
50         ret = sys_ioctl (fd, cmd, (long)&hg);
51         set_fs (old_fs);
52
53         if (ret)
54                 return ret;
55
56         ret = put_user (hg.heads, &(hg32->heads));
57         ret |= __put_user (hg.sectors, &(hg32->sectors));
58         ret |= __put_user (hg.cylinders, &(hg32->cylinders));
59         ret |= __put_user (hg.start, &(hg32->start));
60
61         return ret;
62 }
63
64 struct timeval32 {
65         int tv_sec;
66         int tv_usec;
67 };
68
69 #define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
70 #define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
71 #define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
72 #define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
73
74 struct ifmap32 {
75         unsigned int mem_start;
76         unsigned int mem_end;
77         unsigned short base_addr;
78         unsigned char irq;
79         unsigned char dma;
80         unsigned char port;
81 };
82
83 struct ifreq32 {
84 #define IFHWADDRLEN     6
85 #define IFNAMSIZ        16
86         union {
87                 char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "en0" */
88         } ifr_ifrn;
89         union {
90                 struct  sockaddr ifru_addr;
91                 struct  sockaddr ifru_dstaddr;
92                 struct  sockaddr ifru_broadaddr;
93                 struct  sockaddr ifru_netmask;
94                 struct  sockaddr ifru_hwaddr;
95                 short   ifru_flags;
96                 int     ifru_ivalue;
97                 int     ifru_mtu;
98                 struct  ifmap32 ifru_map;
99                 char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
100                 char    ifru_newname[IFNAMSIZ];
101                 __u32   ifru_data;
102         } ifr_ifru;
103 };
104
105 struct ifconf32 {
106         int     ifc_len;                        /* size of buffer       */
107         __u32   ifcbuf;
108 };
109
110 static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
111 {
112         struct ireq32 *uir32 = (struct ireq32 *) A(arg);
113         struct net_device *dev;
114         struct ifreq32 ifr32;
115
116         if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32)))
117                 return -EFAULT;
118
119         read_lock(&dev_base_lock);
120         dev = __dev_get_by_index(ifr32.ifr_ifindex);
121         if (!dev) {
122                 read_unlock(&dev_base_lock);
123                 return -ENODEV;
124         }
125
126         strcpy(ifr32.ifr_name, dev->name);
127         read_unlock(&dev_base_lock);
128
129         if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32)))
130             return -EFAULT;
131
132         return 0;
133 }
134
135 static inline int dev_ifconf(unsigned int fd, unsigned int cmd,
136                              unsigned long arg)
137 {
138         struct ioconf32 *uifc32 = (struct ioconf32 *) A(arg);
139         struct ifconf32 ifc32;
140         struct ifconf ifc;
141         struct ifreq32 *ifr32;
142         struct ifreq *ifr;
143         mm_segment_t old_fs;
144         int len;
145         int err;
146
147         if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
148                 return -EFAULT;
149
150         if(ifc32.ifcbuf == 0) {
151                 ifc32.ifc_len = 0;
152                 ifc.ifc_len = 0;
153                 ifc.ifc_buf = NULL;
154         } else {
155                 ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) *
156                         sizeof (struct ifreq);
157                 ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
158                 if (!ifc.ifc_buf)
159                         return -ENOMEM;
160         }
161         ifr = ifc.ifc_req;
162         ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
163         len = ifc32.ifc_len / sizeof (struct ifreq32);
164         while (len--) {
165                 if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
166                         err = -EFAULT;
167                         goto out;
168                 }
169         }
170
171         old_fs = get_fs();
172         set_fs (KERNEL_DS);
173         err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); 
174         set_fs (old_fs);
175         if (err)
176                 goto out;
177
178         ifr = ifc.ifc_req;
179         ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
180         len = ifc.ifc_len / sizeof (struct ifreq);
181         ifc32.ifc_len = len * sizeof (struct ifreq32);
182
183         while (len--) {
184                 if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
185                         err = -EFAULT;
186                         goto out;
187                 }
188         }
189
190         if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
191                 err = -EFAULT;
192                 goto out;
193         }
194 out:
195         if(ifc.ifc_buf != NULL)
196                 kfree (ifc.ifc_buf);
197         return err;
198 }
199
200 static inline int dev_ifsioc(unsigned int fd, unsigned int cmd,
201                              unsigned long arg)
202 {
203         struct ifreq32 *uifr = (struct ifreq32 *) A(arg);
204         struct ifreq ifr;
205         mm_segment_t old_fs;
206         int err;
207         
208         switch (cmd) {
209         case SIOCSIFMAP:
210                 err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name));
211                 err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
212                 err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
213                 err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
214                 err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
215                 err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
216                 err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
217                 if (err)
218                         return -EFAULT;
219                 break;
220         default:
221                 if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32)))
222                         return -EFAULT;
223                 break;
224         }
225         old_fs = get_fs();
226         set_fs (KERNEL_DS);
227         err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
228         set_fs (old_fs);
229         if (!err) {
230                 switch (cmd) {
231                 case SIOCGIFFLAGS:
232                 case SIOCGIFMETRIC:
233                 case SIOCGIFMTU:
234                 case SIOCGIFMEM:
235                 case SIOCGIFHWADDR:
236                 case SIOCGIFINDEX:
237                 case SIOCGIFADDR:
238                 case SIOCGIFBRDADDR:
239                 case SIOCGIFDSTADDR:
240                 case SIOCGIFNETMASK:
241                 case SIOCGIFTXQLEN:
242                         if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32)))
243                                 return -EFAULT;
244                         break;
245                 case SIOCGIFMAP:
246                         err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name));
247                         err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
248                         err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
249                         err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
250                         err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
251                         err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
252                         err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
253                         if (err)
254                                 err = -EFAULT;
255                         break;
256                 }
257         }
258         return err;
259 }
260
261 struct rtentry32
262 {
263         unsigned int    rt_pad1;
264         struct sockaddr rt_dst;         /* target address               */
265         struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
266         struct sockaddr rt_genmask;     /* target network mask (IP)     */
267         unsigned short  rt_flags;
268         short           rt_pad2;
269         unsigned int    rt_pad3;
270         unsigned int    rt_pad4;
271         short           rt_metric;      /* +1 for binary compatibility! */
272         unsigned int    rt_dev;         /* forcing the device at add    */
273         unsigned int    rt_mtu;         /* per route MTU/Window         */
274 #ifndef __KERNEL__
275 #define rt_mss  rt_mtu                  /* Compatibility :-(            */
276 #endif
277         unsigned int    rt_window;      /* Window clamping              */
278         unsigned short  rt_irtt;        /* Initial RTT                  */
279 };
280
281 static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
282 {
283         struct rtentry32 *ur = (struct rtentry32 *) A(arg);
284         struct rtentry r;
285         char devname[16];
286         u32 rtdev;
287         int ret;
288         mm_segment_t old_fs = get_fs();
289         
290         ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr));
291         ret |= __get_user (r.rt_flags, &(ur->rt_flags));
292         ret |= __get_user (r.rt_metric, &(ur->rt_metric));
293         ret |= __get_user (r.rt_mtu, &(ur->rt_mtu));
294         ret |= __get_user (r.rt_window, &(ur->rt_window));
295         ret |= __get_user (r.rt_irtt, &(ur->rt_irtt));
296         ret |= __get_user (rtdev, &(ur->rt_dev));
297         if (rtdev) {
298                 ret |= copy_from_user (devname, (char *) A(rtdev), 15);
299                 r.rt_dev = devname; devname[15] = 0;
300         } else
301                 r.rt_dev = 0;
302         if (ret)
303                 return -EFAULT;
304         set_fs (KERNEL_DS);
305         ret = sys_ioctl (fd, cmd, (long)&r);
306         set_fs (old_fs);
307         return ret;
308 }
309
310 static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
311 {
312         /* These are just misnamed, they actually get/put from/to user an int */
313         switch (cmd) {
314         case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
315         case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
316         case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
317         case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
318         }
319         return sys_ioctl(fd, cmd, arg);
320 }
321
322 static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
323 {
324         mm_segment_t old_fs = get_fs();
325         int err;
326         unsigned long val;
327         
328         set_fs (KERNEL_DS);
329         err = sys_ioctl(fd, cmd, (unsigned long)&val);
330         set_fs (old_fs);
331         if (!err && put_user((unsigned int) val, (u32 *)arg))
332                 return -EFAULT;
333         return err;
334 }
335
336 struct ioctl32_handler {
337         unsigned int cmd;
338         int (*function)(unsigned int, unsigned int, unsigned long);
339 };
340
341 struct ioctl32_list {
342         struct ioctl32_handler handler;
343         struct ioctl32_list *next;
344 };
345
346 #define IOCTL32_DEFAULT(cmd)            { { cmd, (void *) sys_ioctl }, 0 }
347 #define IOCTL32_HANDLER(cmd, handler)   { { cmd, (void *) handler }, 0 }
348
349 static struct ioctl32_list ioctl32_handler_table[] = {
350         IOCTL32_DEFAULT(FIBMAP),
351         IOCTL32_DEFAULT(FIGETBSZ),
352
353         IOCTL32_DEFAULT(DASDAPIVER),
354         IOCTL32_DEFAULT(BIODASDDISABLE),
355         IOCTL32_DEFAULT(BIODASDENABLE),
356         IOCTL32_DEFAULT(BIODASDRSRV),
357         IOCTL32_DEFAULT(BIODASDRLSE),
358         IOCTL32_DEFAULT(BIODASDSLCK),
359         IOCTL32_DEFAULT(BIODASDINFO),
360         IOCTL32_DEFAULT(BIODASDFMT),
361
362         IOCTL32_DEFAULT(BLKRRPART),
363
364         IOCTL32_HANDLER(HDIO_GETGEO, hd_geometry_ioctl),
365
366         IOCTL32_DEFAULT(TCGETA),
367         IOCTL32_DEFAULT(TCSETA),
368         IOCTL32_DEFAULT(TCSETAW),
369         IOCTL32_DEFAULT(TCSETAF),
370         IOCTL32_DEFAULT(TCSBRK),
371         IOCTL32_DEFAULT(TCXONC),
372         IOCTL32_DEFAULT(TCFLSH),
373         IOCTL32_DEFAULT(TCGETS),
374         IOCTL32_DEFAULT(TCSETS),
375         IOCTL32_DEFAULT(TCSETSW),
376         IOCTL32_DEFAULT(TCSETSF),
377         IOCTL32_DEFAULT(TIOCLINUX),
378
379         IOCTL32_DEFAULT(TIOCGETD),
380         IOCTL32_DEFAULT(TIOCSETD),
381         IOCTL32_DEFAULT(TIOCEXCL),
382         IOCTL32_DEFAULT(TIOCNXCL),
383         IOCTL32_DEFAULT(TIOCCONS),
384         IOCTL32_DEFAULT(TIOCGSOFTCAR),
385         IOCTL32_DEFAULT(TIOCSSOFTCAR),
386         IOCTL32_DEFAULT(TIOCSWINSZ),
387         IOCTL32_DEFAULT(TIOCGWINSZ),
388         IOCTL32_DEFAULT(TIOCMGET),
389         IOCTL32_DEFAULT(TIOCMBIC),
390         IOCTL32_DEFAULT(TIOCMBIS),
391         IOCTL32_DEFAULT(TIOCMSET),
392         IOCTL32_DEFAULT(TIOCPKT),
393         IOCTL32_DEFAULT(TIOCNOTTY),
394         IOCTL32_DEFAULT(TIOCSTI),
395         IOCTL32_DEFAULT(TIOCOUTQ),
396         IOCTL32_DEFAULT(TIOCSPGRP),
397         IOCTL32_DEFAULT(TIOCGPGRP),
398         IOCTL32_DEFAULT(TIOCSCTTY),
399         IOCTL32_DEFAULT(TIOCGPTN),
400         IOCTL32_DEFAULT(TIOCSPTLCK),
401         IOCTL32_DEFAULT(TIOCGSERIAL),
402         IOCTL32_DEFAULT(TIOCSSERIAL),
403         IOCTL32_DEFAULT(TIOCSERGETLSR),
404
405         IOCTL32_DEFAULT(FIOCLEX),
406         IOCTL32_DEFAULT(FIONCLEX),
407         IOCTL32_DEFAULT(FIOASYNC),
408         IOCTL32_DEFAULT(FIONBIO),
409         IOCTL32_DEFAULT(FIONREAD),
410
411         IOCTL32_DEFAULT(PIO_FONT),
412         IOCTL32_DEFAULT(GIO_FONT),
413         IOCTL32_DEFAULT(KDSIGACCEPT),
414         IOCTL32_DEFAULT(KDGETKEYCODE),
415         IOCTL32_DEFAULT(KDSETKEYCODE),
416         IOCTL32_DEFAULT(KIOCSOUND),
417         IOCTL32_DEFAULT(KDMKTONE),
418         IOCTL32_DEFAULT(KDGKBTYPE),
419         IOCTL32_DEFAULT(KDSETMODE),
420         IOCTL32_DEFAULT(KDGETMODE),
421         IOCTL32_DEFAULT(KDSKBMODE),
422         IOCTL32_DEFAULT(KDGKBMODE),
423         IOCTL32_DEFAULT(KDSKBMETA),
424         IOCTL32_DEFAULT(KDGKBMETA),
425         IOCTL32_DEFAULT(KDGKBENT),
426         IOCTL32_DEFAULT(KDSKBENT),
427         IOCTL32_DEFAULT(KDGKBSENT),
428         IOCTL32_DEFAULT(KDSKBSENT),
429         IOCTL32_DEFAULT(KDGKBDIACR),
430         IOCTL32_DEFAULT(KDSKBDIACR),
431         IOCTL32_DEFAULT(KDGKBLED),
432         IOCTL32_DEFAULT(KDSKBLED),
433         IOCTL32_DEFAULT(KDGETLED),
434         IOCTL32_DEFAULT(KDSETLED),
435         IOCTL32_DEFAULT(GIO_SCRNMAP),
436         IOCTL32_DEFAULT(PIO_SCRNMAP),
437         IOCTL32_DEFAULT(GIO_UNISCRNMAP),
438         IOCTL32_DEFAULT(PIO_UNISCRNMAP),
439         IOCTL32_DEFAULT(PIO_FONTRESET),
440         IOCTL32_DEFAULT(PIO_UNIMAPCLR),
441
442         IOCTL32_DEFAULT(VT_SETMODE),
443         IOCTL32_DEFAULT(VT_GETMODE),
444         IOCTL32_DEFAULT(VT_GETSTATE),
445         IOCTL32_DEFAULT(VT_OPENQRY),
446         IOCTL32_DEFAULT(VT_ACTIVATE),
447         IOCTL32_DEFAULT(VT_WAITACTIVE),
448         IOCTL32_DEFAULT(VT_RELDISP),
449         IOCTL32_DEFAULT(VT_DISALLOCATE),
450         IOCTL32_DEFAULT(VT_RESIZE),
451         IOCTL32_DEFAULT(VT_RESIZEX),
452         IOCTL32_DEFAULT(VT_LOCKSWITCH),
453         IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
454
455         IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
456         IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
457         IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
458         IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc),
459         IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc),
460         IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc),
461         IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc),
462         IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc),
463         IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc),
464         IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc),
465         IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc),
466         IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc),
467         IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc),
468         IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc),
469         IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc),
470         IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc),
471         IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc),
472         IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc),
473         IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc),
474         IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc),
475         IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc),
476         IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc),
477         IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc),
478         IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc),
479         IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc),
480         IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc),
481         IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc),
482         IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc),
483         IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc),
484         IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
485         IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
486
487         IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
488         IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
489         IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
490         IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
491
492         IOCTL32_HANDLER(BLKGETSIZE, w_long)
493
494 };
495
496 #define NR_IOCTL32_HANDLERS     (sizeof(ioctl32_handler_table) /        \
497                                  sizeof(ioctl32_handler_table[0]))
498
499 static struct ioctl32_list *ioctl32_hash_table[1024];
500
501 static inline int ioctl32_hash(unsigned int cmd)
502 {
503         return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
504 }
505
506 int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
507 {
508         int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
509         struct file *filp;
510         struct ioctl32_list *l;
511         int error;
512
513         l = ioctl32_hash_table[ioctl32_hash(cmd)];
514
515         error = -EBADF;
516
517         filp = fget(fd);
518         if (!filp)
519                 return error;
520
521         if (!filp->f_op || !filp->f_op->ioctl) {
522                 error = sys_ioctl (fd, cmd, arg);
523                 goto out;
524         }
525
526         while (l && l->handler.cmd != cmd)
527                 l = l->next;
528
529         if (l) {
530                 handler = (void *)l->handler.function;
531                 error = handler(fd, cmd, arg, filp);
532         } else {
533                 error = -EINVAL;
534                 printk("unknown ioctl: %08x\n", cmd);
535         }
536 out:
537         fput(filp);
538         return error;
539 }
540
541 static void ioctl32_insert(struct ioctl32_list *entry)
542 {
543         int hash = ioctl32_hash(entry->handler.cmd);
544         if (!ioctl32_hash_table[hash])
545                 ioctl32_hash_table[hash] = entry;
546         else {
547                 struct ioctl32_list *l;
548                 l = ioctl32_hash_table[hash];
549                 while (l->next)
550                         l = l->next;
551                 l->next = entry;
552                 entry->next = 0;
553         }
554 }
555
556 static int __init init_ioctl32(void)
557 {
558         int i;
559         for (i = 0; i < NR_IOCTL32_HANDLERS; i++)
560                 ioctl32_insert(&ioctl32_handler_table[i]);
561         return 0;
562 }
563
564 __initcall(init_ioctl32);