import of upstream 2.4.34.4 from kernel.org
[linux-2.4.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 <linux/if_bonding.h>
28 #include <linux/loop.h>
29 #include <linux/blkpg.h>
30 #include <linux/blk.h>
31 #include <linux/elevator.h>
32 #include <linux/raw.h>
33 #include <asm/types.h>
34 #include <asm/uaccess.h>
35 #include <asm/dasd.h>
36 #include <asm/sockios.h>
37 #include "../../../drivers/s390/char/tubio.h"
38
39 #include "linux32.h"
40
41 long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
42
43 struct hd_geometry32 {
44         unsigned char   heads;
45         unsigned char   sectors;
46         unsigned short  cylinders;
47         __u32           start;
48 };  
49
50 static inline int hd_geometry_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
51 {
52         struct hd_geometry32 *hg32 = (struct hd_geometry32 *) A(arg);
53         struct hd_geometry hg;
54         int ret;
55         mm_segment_t old_fs = get_fs();
56         
57         set_fs (KERNEL_DS);
58         ret = sys_ioctl (fd, cmd, (long)&hg);
59         set_fs (old_fs);
60
61         if (ret)
62                 return ret;
63
64         ret = put_user (hg.heads, &(hg32->heads));
65         ret |= __put_user (hg.sectors, &(hg32->sectors));
66         ret |= __put_user (hg.cylinders, &(hg32->cylinders));
67         ret |= __put_user (hg.start, &(hg32->start));
68
69         return ret;
70 }
71
72 struct timeval32 {
73         int tv_sec;
74         int tv_usec;
75 };
76
77 #define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
78 #define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
79 #define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
80 #define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
81
82 struct ifmap32 {
83         unsigned int mem_start;
84         unsigned int mem_end;
85         unsigned short base_addr;
86         unsigned char irq;
87         unsigned char dma;
88         unsigned char port;
89 };
90
91 struct ifreq32 {
92 #define IFHWADDRLEN     6
93 #define IFNAMSIZ        16
94         union {
95                 char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "en0" */
96         } ifr_ifrn;
97         union {
98                 struct  sockaddr ifru_addr;
99                 struct  sockaddr ifru_dstaddr;
100                 struct  sockaddr ifru_broadaddr;
101                 struct  sockaddr ifru_netmask;
102                 struct  sockaddr ifru_hwaddr;
103                 short   ifru_flags;
104                 int     ifru_ivalue;
105                 int     ifru_mtu;
106                 struct  ifmap32 ifru_map;
107                 char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
108                 char    ifru_newname[IFNAMSIZ];
109                 __u32   ifru_data;
110         } ifr_ifru;
111 };
112
113 struct ifconf32 {
114         int     ifc_len;                        /* size of buffer       */
115         __u32   ifcbuf;
116 };
117
118 static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
119 {
120         struct ireq32 *uir32 = (struct ireq32 *) A(arg);
121         struct net_device *dev;
122         struct ifreq32 ifr32;
123
124         if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32)))
125                 return -EFAULT;
126
127         read_lock(&dev_base_lock);
128         dev = __dev_get_by_index(ifr32.ifr_ifindex);
129         if (!dev) {
130                 read_unlock(&dev_base_lock);
131                 return -ENODEV;
132         }
133
134         strcpy(ifr32.ifr_name, dev->name);
135         read_unlock(&dev_base_lock);
136
137         if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32)))
138             return -EFAULT;
139
140         return 0;
141 }
142
143 static inline int dev_ifconf(unsigned int fd, unsigned int cmd,
144                              unsigned long arg)
145 {
146         struct ioconf32 *uifc32 = (struct ioconf32 *) A(arg);
147         struct ifconf32 ifc32;
148         struct ifconf ifc;
149         struct ifreq32 *ifr32;
150         struct ifreq *ifr;
151         mm_segment_t old_fs;
152         int len;
153         int err;
154
155         if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
156                 return -EFAULT;
157
158         if(ifc32.ifcbuf == 0) {
159                 ifc32.ifc_len = 0;
160                 ifc.ifc_len = 0;
161                 ifc.ifc_buf = NULL;
162         } else {
163                 ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) *
164                         sizeof (struct ifreq);
165                 ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
166                 if (!ifc.ifc_buf)
167                         return -ENOMEM;
168         }
169         ifr = ifc.ifc_req;
170         ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
171         len = ifc32.ifc_len / sizeof (struct ifreq32);
172         while (len--) {
173                 if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
174                         err = -EFAULT;
175                         goto out;
176                 }
177         }
178
179         old_fs = get_fs();
180         set_fs (KERNEL_DS);
181         err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); 
182         set_fs (old_fs);
183         if (err)
184                 goto out;
185
186         ifr = ifc.ifc_req;
187         ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
188         len = ifc.ifc_len / sizeof (struct ifreq);
189         ifc32.ifc_len = len * sizeof (struct ifreq32);
190
191         while (len--) {
192                 if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
193                         err = -EFAULT;
194                         goto out;
195                 }
196         }
197
198         if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
199                 err = -EFAULT;
200                 goto out;
201         }
202 out:
203         if(ifc.ifc_buf != NULL)
204                 kfree (ifc.ifc_buf);
205         return err;
206 }
207
208 static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
209 {
210         struct ifreq ifr;
211         mm_segment_t old_fs;
212         int err, len;
213         u32 data;
214         
215         if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
216                 return -EFAULT;
217         ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
218         if (!ifr.ifr_data)
219                 return -EAGAIN;
220
221         switch (cmd) {
222         case SIOCBONDENSLAVE:
223         case SIOCBONDRELEASE:
224         case SIOCBONDSETHWADDR:
225         case SIOCBONDCHANGEACTIVE:
226                 len = IFNAMSIZ * sizeof(char);
227                 break;
228         case SIOCBONDSLAVEINFOQUERY:
229                 len = sizeof(struct ifslave);
230                 break;
231         case SIOCBONDINFOQUERY:
232                 len = sizeof(struct ifbond);
233                 break;
234         default:
235                 err = -EINVAL;
236                 goto out;
237         };
238
239         __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
240         if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
241                 err = -EFAULT;
242                 goto out;
243         }
244
245         old_fs = get_fs();
246         set_fs (KERNEL_DS);
247         err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
248         set_fs (old_fs);
249         if (!err) {
250                 len = copy_to_user((char *)A(data), ifr.ifr_data, len);
251                 if (len)
252                         err = -EFAULT;
253         }
254
255 out:
256         free_page((unsigned long)ifr.ifr_data);
257         return err;
258 }
259
260 static inline int dev_ifsioc(unsigned int fd, unsigned int cmd,
261                              unsigned long arg)
262 {
263         struct ifreq32 *uifr = (struct ifreq32 *) A(arg);
264         struct ifreq ifr;
265         mm_segment_t old_fs;
266         int err;
267         
268         switch (cmd) {
269         case SIOCSIFMAP:
270                 err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name));
271                 err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
272                 err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
273                 err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
274                 err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
275                 err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
276                 err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
277                 if (err)
278                         return -EFAULT;
279                 break;
280         default:
281                 if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32)))
282                         return -EFAULT;
283                 break;
284         }
285         old_fs = get_fs();
286         set_fs (KERNEL_DS);
287         err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
288         set_fs (old_fs);
289         if (!err) {
290                 switch (cmd) {
291                 case SIOCGIFFLAGS:
292                 case SIOCGIFMETRIC:
293                 case SIOCGIFMTU:
294                 case SIOCGIFMEM:
295                 case SIOCGIFHWADDR:
296                 case SIOCGIFINDEX:
297                 case SIOCGIFADDR:
298                 case SIOCGIFBRDADDR:
299                 case SIOCGIFDSTADDR:
300                 case SIOCGIFNETMASK:
301                 case SIOCGIFTXQLEN:
302                         if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32)))
303                                 return -EFAULT;
304                         break;
305                 case SIOCGIFMAP:
306                         err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name));
307                         err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
308                         err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
309                         err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
310                         err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
311                         err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
312                         err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
313                         if (err)
314                                 err = -EFAULT;
315                         break;
316                 }
317         }
318         return err;
319 }
320
321 struct rtentry32
322 {
323         unsigned int    rt_pad1;
324         struct sockaddr rt_dst;         /* target address               */
325         struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
326         struct sockaddr rt_genmask;     /* target network mask (IP)     */
327         unsigned short  rt_flags;
328         short           rt_pad2;
329         unsigned int    rt_pad3;
330         unsigned int    rt_pad4;
331         short           rt_metric;      /* +1 for binary compatibility! */
332         unsigned int    rt_dev;         /* forcing the device at add    */
333         unsigned int    rt_mtu;         /* per route MTU/Window         */
334 #ifndef __KERNEL__
335 #define rt_mss  rt_mtu                  /* Compatibility :-(            */
336 #endif
337         unsigned int    rt_window;      /* Window clamping              */
338         unsigned short  rt_irtt;        /* Initial RTT                  */
339 };
340
341 static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
342 {
343         struct rtentry32 *ur = (struct rtentry32 *) A(arg);
344         struct rtentry r;
345         char devname[16];
346         u32 rtdev;
347         int ret;
348         mm_segment_t old_fs = get_fs();
349         
350         ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr));
351         ret |= __get_user (r.rt_flags, &(ur->rt_flags));
352         ret |= __get_user (r.rt_metric, &(ur->rt_metric));
353         ret |= __get_user (r.rt_mtu, &(ur->rt_mtu));
354         ret |= __get_user (r.rt_window, &(ur->rt_window));
355         ret |= __get_user (r.rt_irtt, &(ur->rt_irtt));
356         ret |= __get_user (rtdev, &(ur->rt_dev));
357         if (rtdev) {
358                 ret |= copy_from_user (devname, (char *) A(rtdev), 15);
359                 r.rt_dev = devname; devname[15] = 0;
360         } else
361                 r.rt_dev = 0;
362         if (ret)
363                 return -EFAULT;
364         set_fs (KERNEL_DS);
365         ret = sys_ioctl (fd, cmd, (long)&r);
366         set_fs (old_fs);
367         return ret;
368 }
369
370 static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
371 {
372         /* These are just misnamed, they actually get/put from/to user an int */
373         switch (cmd) {
374         case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
375         case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
376         case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
377         case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
378         }
379         return sys_ioctl(fd, cmd, arg);
380 }
381
382 struct loop_info32 {
383         int                     lo_number;      /* ioctl r/o */
384         __kernel_dev_t32        lo_device;      /* ioctl r/o */
385         unsigned int            lo_inode;       /* ioctl r/o */
386         __kernel_dev_t32        lo_rdevice;     /* ioctl r/o */
387         int                     lo_offset;
388         int                     lo_encrypt_type;
389         int                     lo_encrypt_key_size;    /* ioctl w/o */
390         int                     lo_flags;       /* ioctl r/o */
391         char                    lo_name[LO_NAME_SIZE];
392         unsigned char           lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
393         unsigned int            lo_init[2];
394         char                    reserved[4];
395 };
396
397 static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
398 {
399         mm_segment_t old_fs = get_fs();
400         struct loop_info l;
401         int err = -EINVAL;
402
403         switch(cmd) {
404         case LOOP_SET_STATUS:
405                 err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
406                 err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
407                 err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
408                 err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
409                 err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset,
410                                            8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
411                 if (err) {
412                         err = -EFAULT;
413                 } else {
414                         set_fs (KERNEL_DS);
415                         err = sys_ioctl (fd, cmd, (unsigned long)&l);
416                         set_fs (old_fs);
417                 }
418                 break;
419         case LOOP_GET_STATUS:
420                 set_fs (KERNEL_DS);
421                 err = sys_ioctl (fd, cmd, (unsigned long)&l);
422                 set_fs (old_fs);
423                 if (!err) {
424                         err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
425                         err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
426                         err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
427                         err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
428                         err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset,
429                                            (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
430                         if (err)
431                                 err = -EFAULT;
432                 }
433                 break;
434         default: {
435                 static int count = 0;
436                 if (++count <= 20)
437                         printk("%s: Unknown loop ioctl cmd, fd(%d) "
438                                "cmd(%08x) arg(%08lx)\n",
439                                __FUNCTION__, fd, cmd, arg);
440         }
441         }
442         return err;
443 }
444
445
446 struct blkpg_ioctl_arg32 {
447         int op;
448         int flags;
449         int datalen;
450         u32 data;
451 };
452                                 
453 static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg)
454 {
455         struct blkpg_ioctl_arg a;
456         struct blkpg_partition p;
457         int err;
458         mm_segment_t old_fs = get_fs();
459         
460         err = get_user(a.op, &arg->op);
461         err |= __get_user(a.flags, &arg->flags);
462         err |= __get_user(a.datalen, &arg->datalen);
463         err |= __get_user((long)a.data, &arg->data);
464         if (err) return err;
465         switch (a.op) {
466         case BLKPG_ADD_PARTITION:
467         case BLKPG_DEL_PARTITION:
468                 if (a.datalen < sizeof(struct blkpg_partition))
469                         return -EINVAL;
470                 if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
471                         return -EFAULT;
472                 a.data = &p;
473                 set_fs (KERNEL_DS);
474                 err = sys_ioctl(fd, cmd, (unsigned long)&a);
475                 set_fs (old_fs);
476         default:
477                 return -EINVAL;
478         }                                        
479         return err;
480 }
481
482
483 static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
484 {
485         mm_segment_t old_fs = get_fs();
486         int err;
487         unsigned long val;
488         
489         set_fs (KERNEL_DS);
490         err = sys_ioctl(fd, cmd, (unsigned long)&val);
491         set_fs (old_fs);
492         if (!err && put_user((unsigned int) val, (u32 *)arg))
493                 return -EFAULT;
494         return err;
495 }
496
497 struct ioctl32_handler {
498         unsigned int cmd;
499         int (*function)(unsigned int, unsigned int, unsigned long);
500 };
501
502 struct ioctl32_list {
503         struct ioctl32_handler handler;
504         struct ioctl32_list *next;
505 };
506
507 #define IOCTL32_DEFAULT(cmd)            { { cmd, (void *) sys_ioctl }, 0 }
508 #define IOCTL32_HANDLER(cmd, handler)   { { cmd, (void *) handler }, 0 }
509
510 static struct ioctl32_list ioctl32_handler_table[] = {
511         IOCTL32_DEFAULT(FIBMAP),
512         IOCTL32_DEFAULT(FIGETBSZ),
513
514         IOCTL32_DEFAULT(DASDAPIVER),
515         IOCTL32_DEFAULT(BIODASDDISABLE),
516         IOCTL32_DEFAULT(BIODASDENABLE),
517         IOCTL32_DEFAULT(BIODASDRSRV),
518         IOCTL32_DEFAULT(BIODASDRLSE),
519         IOCTL32_DEFAULT(BIODASDSLCK),
520         IOCTL32_DEFAULT(BIODASDINFO),
521         IOCTL32_DEFAULT(BIODASDFMT),
522
523         IOCTL32_DEFAULT(BLKROSET),
524         IOCTL32_DEFAULT(BLKROGET),
525         IOCTL32_DEFAULT(BLKRRPART),
526         IOCTL32_DEFAULT(BLKFLSBUF),
527         IOCTL32_DEFAULT(BLKRASET),
528         IOCTL32_DEFAULT(BLKFRASET),
529         IOCTL32_DEFAULT(BLKSECTSET),
530         IOCTL32_DEFAULT(BLKSSZGET),
531         IOCTL32_DEFAULT(BLKBSZGET),
532         IOCTL32_DEFAULT(BLKGETSIZE64),
533
534         IOCTL32_DEFAULT(BLKELVGET),
535         IOCTL32_DEFAULT(BLKELVSET),
536
537         IOCTL32_HANDLER(HDIO_GETGEO, hd_geometry_ioctl),
538
539         IOCTL32_DEFAULT(TUBICMD),
540         IOCTL32_DEFAULT(TUBOCMD),
541         IOCTL32_DEFAULT(TUBGETI),
542         IOCTL32_DEFAULT(TUBGETO),
543         IOCTL32_DEFAULT(TUBSETMOD),
544         IOCTL32_DEFAULT(TUBGETMOD),
545         IOCTL32_DEFAULT(TCGETA),
546         IOCTL32_DEFAULT(TCSETA),
547         IOCTL32_DEFAULT(TCSETAW),
548         IOCTL32_DEFAULT(TCSETAF),
549         IOCTL32_DEFAULT(TCSBRK),
550         IOCTL32_DEFAULT(TCSBRKP),
551         IOCTL32_DEFAULT(TCXONC),
552         IOCTL32_DEFAULT(TCFLSH),
553         IOCTL32_DEFAULT(TCGETS),
554         IOCTL32_DEFAULT(TCSETS),
555         IOCTL32_DEFAULT(TCSETSW),
556         IOCTL32_DEFAULT(TCSETSF),
557         IOCTL32_DEFAULT(TIOCLINUX),
558
559         IOCTL32_DEFAULT(TIOCGETD),
560         IOCTL32_DEFAULT(TIOCSETD),
561         IOCTL32_DEFAULT(TIOCEXCL),
562         IOCTL32_DEFAULT(TIOCNXCL),
563         IOCTL32_DEFAULT(TIOCCONS),
564         IOCTL32_DEFAULT(TIOCGSOFTCAR),
565         IOCTL32_DEFAULT(TIOCSSOFTCAR),
566         IOCTL32_DEFAULT(TIOCSWINSZ),
567         IOCTL32_DEFAULT(TIOCGWINSZ),
568         IOCTL32_DEFAULT(TIOCMGET),
569         IOCTL32_DEFAULT(TIOCMBIC),
570         IOCTL32_DEFAULT(TIOCMBIS),
571         IOCTL32_DEFAULT(TIOCMSET),
572         IOCTL32_DEFAULT(TIOCPKT),
573         IOCTL32_DEFAULT(TIOCNOTTY),
574         IOCTL32_DEFAULT(TIOCSTI),
575         IOCTL32_DEFAULT(TIOCOUTQ),
576         IOCTL32_DEFAULT(TIOCSPGRP),
577         IOCTL32_DEFAULT(TIOCGPGRP),
578         IOCTL32_DEFAULT(TIOCSCTTY),
579         IOCTL32_DEFAULT(TIOCGPTN),
580         IOCTL32_DEFAULT(TIOCSPTLCK),
581         IOCTL32_DEFAULT(TIOCGSERIAL),
582         IOCTL32_DEFAULT(TIOCSSERIAL),
583         IOCTL32_DEFAULT(TIOCSERGETLSR),
584
585         IOCTL32_DEFAULT(FIOCLEX),
586         IOCTL32_DEFAULT(FIONCLEX),
587         IOCTL32_DEFAULT(FIOASYNC),
588         IOCTL32_DEFAULT(FIONBIO),
589         IOCTL32_DEFAULT(FIONREAD),
590
591         IOCTL32_DEFAULT(PIO_FONT),
592         IOCTL32_DEFAULT(GIO_FONT),
593         IOCTL32_DEFAULT(KDSIGACCEPT),
594         IOCTL32_DEFAULT(KDGETKEYCODE),
595         IOCTL32_DEFAULT(KDSETKEYCODE),
596         IOCTL32_DEFAULT(KIOCSOUND),
597         IOCTL32_DEFAULT(KDMKTONE),
598         IOCTL32_DEFAULT(KDGKBTYPE),
599         IOCTL32_DEFAULT(KDSETMODE),
600         IOCTL32_DEFAULT(KDGETMODE),
601         IOCTL32_DEFAULT(KDSKBMODE),
602         IOCTL32_DEFAULT(KDGKBMODE),
603         IOCTL32_DEFAULT(KDSKBMETA),
604         IOCTL32_DEFAULT(KDGKBMETA),
605         IOCTL32_DEFAULT(KDGKBENT),
606         IOCTL32_DEFAULT(KDSKBENT),
607         IOCTL32_DEFAULT(KDGKBSENT),
608         IOCTL32_DEFAULT(KDSKBSENT),
609         IOCTL32_DEFAULT(KDGKBDIACR),
610         IOCTL32_DEFAULT(KDSKBDIACR),
611         IOCTL32_DEFAULT(KDGKBLED),
612         IOCTL32_DEFAULT(KDSKBLED),
613         IOCTL32_DEFAULT(KDGETLED),
614         IOCTL32_DEFAULT(KDSETLED),
615         IOCTL32_DEFAULT(GIO_SCRNMAP),
616         IOCTL32_DEFAULT(PIO_SCRNMAP),
617         IOCTL32_DEFAULT(GIO_UNISCRNMAP),
618         IOCTL32_DEFAULT(PIO_UNISCRNMAP),
619         IOCTL32_DEFAULT(PIO_FONTRESET),
620         IOCTL32_DEFAULT(PIO_UNIMAPCLR),
621
622         IOCTL32_DEFAULT(VT_SETMODE),
623         IOCTL32_DEFAULT(VT_GETMODE),
624         IOCTL32_DEFAULT(VT_GETSTATE),
625         IOCTL32_DEFAULT(VT_OPENQRY),
626         IOCTL32_DEFAULT(VT_ACTIVATE),
627         IOCTL32_DEFAULT(VT_WAITACTIVE),
628         IOCTL32_DEFAULT(VT_RELDISP),
629         IOCTL32_DEFAULT(VT_DISALLOCATE),
630         IOCTL32_DEFAULT(VT_RESIZE),
631         IOCTL32_DEFAULT(VT_RESIZEX),
632         IOCTL32_DEFAULT(VT_LOCKSWITCH),
633         IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
634
635         IOCTL32_DEFAULT(SIOCGSTAMP),
636
637         IOCTL32_DEFAULT(LOOP_SET_FD),
638         IOCTL32_DEFAULT(LOOP_CLR_FD),
639
640         IOCTL32_DEFAULT(SIOCATMARK),
641         IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
642         IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
643         IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
644         IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc),
645         IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc),
646         IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc),
647         IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc),
648         IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc),
649         IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc),
650         IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc),
651         IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc),
652         IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc),
653         IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc),
654         IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc),
655         IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc),
656         IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc),
657         IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc),
658         IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc),
659         IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc),
660         IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc),
661         IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc),
662         IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc),
663         IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc),
664         IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc),
665         IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc),
666         IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc),
667         IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc),
668         IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc),
669         IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc),
670         IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
671         IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
672
673         IOCTL32_HANDLER(SIOCBONDENSLAVE, bond_ioctl),
674         IOCTL32_HANDLER(SIOCBONDRELEASE, bond_ioctl),
675         IOCTL32_HANDLER(SIOCBONDSETHWADDR, bond_ioctl),
676         IOCTL32_HANDLER(SIOCBONDSLAVEINFOQUERY, bond_ioctl),
677         IOCTL32_HANDLER(SIOCBONDINFOQUERY, bond_ioctl),
678         IOCTL32_HANDLER(SIOCBONDCHANGEACTIVE, bond_ioctl),
679
680         IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
681         IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
682         IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
683         IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
684
685         IOCTL32_HANDLER(LOOP_SET_STATUS, loop_status),
686         IOCTL32_HANDLER(LOOP_GET_STATUS, loop_status),
687
688 /* Raw devices */
689         IOCTL32_DEFAULT(RAW_SETBIND),
690         IOCTL32_DEFAULT(RAW_GETBIND),
691
692         IOCTL32_HANDLER(BLKRAGET, w_long),
693         IOCTL32_HANDLER(BLKGETSIZE, w_long),
694         IOCTL32_HANDLER(BLKFRAGET, w_long),
695         IOCTL32_HANDLER(BLKSECTGET, w_long),
696         IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans)
697
698 };
699
700 #define NR_IOCTL32_HANDLERS     (sizeof(ioctl32_handler_table) /        \
701                                  sizeof(ioctl32_handler_table[0]))
702
703 static struct ioctl32_list *ioctl32_hash_table[1024];
704
705 static inline int ioctl32_hash(unsigned int cmd)
706 {
707         return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
708 }
709
710 int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
711 {
712         int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
713         struct file *filp;
714         struct ioctl32_list *l;
715         int error;
716
717         l = ioctl32_hash_table[ioctl32_hash(cmd)];
718
719         error = -EBADF;
720
721         filp = fget(fd);
722         if (!filp)
723                 return error;
724
725         if (!filp->f_op || !filp->f_op->ioctl) {
726                 error = sys_ioctl (fd, cmd, arg);
727                 goto out;
728         }
729
730         while (l && l->handler.cmd != cmd)
731                 l = l->next;
732
733         if (l) {
734                 handler = (void *)l->handler.function;
735                 error = handler(fd, cmd, arg, filp);
736         } else {
737                 error = -EINVAL;
738                 printk("unknown ioctl: %08x\n", cmd);
739         }
740 out:
741         fput(filp);
742         return error;
743 }
744
745 static void ioctl32_insert(struct ioctl32_list *entry)
746 {
747         int hash = ioctl32_hash(entry->handler.cmd);
748
749         entry->next = 0;
750         if (!ioctl32_hash_table[hash])
751                 ioctl32_hash_table[hash] = entry;
752         else {
753                 struct ioctl32_list *l;
754                 l = ioctl32_hash_table[hash];
755                 while (l->next)
756                         l = l->next;
757                 l->next = entry;
758         }
759 }
760
761 int register_ioctl32_conversion(unsigned int cmd,
762                                 int (*handler)(unsigned int, unsigned int,
763                                                unsigned long, struct file *))
764 {
765         struct ioctl32_list *l, *new;
766         int hash;
767
768         hash = ioctl32_hash(cmd);
769         for (l = ioctl32_hash_table[hash]; l != NULL; l = l->next)
770                 if (l->handler.cmd == cmd)
771                         return -EBUSY;
772         new = kmalloc(sizeof(struct ioctl32_list), GFP_KERNEL);
773         if (new == NULL)
774                 return -ENOMEM;
775         new->handler.cmd = cmd;
776         new->handler.function = (void *) handler;
777         ioctl32_insert(new);
778         return 0;
779 }
780
781 int unregister_ioctl32_conversion(unsigned int cmd)
782 {
783         struct ioctl32_list *p, *l;
784         int hash;
785
786         hash = ioctl32_hash(cmd);
787         p = NULL;
788         for (l = ioctl32_hash_table[hash]; l != NULL; l = l->next) {
789                 if (l->handler.cmd == cmd)
790                         break;
791                 p = l;
792         }
793         if (l == NULL)
794                 return -ENOENT;
795         if (p == NULL)
796                 ioctl32_hash_table[hash] = l->next;
797         else
798                 p->next = l->next;
799         kfree(l);
800         return 0;
801 }
802
803 static int __init init_ioctl32(void)
804 {
805         int i;
806         for (i = 0; i < NR_IOCTL32_HANDLERS; i++)
807                 ioctl32_insert(&ioctl32_handler_table[i]);
808         return 0;
809 }
810
811 __initcall(init_ioctl32);