File: /usr/src/linux/arch/mips64/kernel/ioctl32.c

1     /*
2      * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
3      *
4      * Copyright (C) 2000 Silicon Graphics, Inc.
5      * Written by Ulf Carlsson (ulfc@engr.sgi.com)
6      * Copyright (C) 2000 Ralf Baechle
7      *
8      * Mostly stolen from the sparc64 ioctl32 implementation.
9      */
10     #include <linux/config.h>
11     #include <linux/types.h>
12     #include <linux/kernel.h>
13     #include <linux/fs.h>
14     #include <linux/sched.h>
15     #include <linux/mm.h>
16     #include <linux/mtio.h>
17     #include <linux/init.h>
18     #include <linux/file.h>
19     #include <linux/vt.h>
20     #include <linux/kd.h>
21     #include <linux/netdevice.h>
22     #include <linux/route.h>
23     #include <linux/hdreg.h>
24     #include <linux/blkpg.h>
25     #include <linux/blkdev.h>
26     #include <linux/elevator.h>
27     #include <linux/auto_fs.h>
28     #include <linux/ext2_fs.h>
29     #include <linux/raid/md_u.h>
30     #include <asm/types.h>
31     #include <asm/uaccess.h>
32     
33     long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
34     
35     static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
36     {
37     	mm_segment_t old_fs = get_fs();
38     	int err;
39     	unsigned long val;
40     	
41     	set_fs (KERNEL_DS);
42     	err = sys_ioctl(fd, cmd, (unsigned long)&val);
43     	set_fs (old_fs);
44     	if (!err && put_user((unsigned int) val, (u32 *)arg))
45     		return -EFAULT;
46     	return err;
47     }
48     
49     static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
50     {
51     	mm_segment_t old_fs = get_fs();
52     	int err;
53     	unsigned long val;
54     
55     	if (get_user(val, (u32 *)arg))
56     		return -EFAULT;
57     	set_fs(KERNEL_DS);
58     	err = sys_ioctl(fd, cmd, (unsigned long)&val);
59     	set_fs (old_fs);
60     	if (!err && put_user(val, (u32 *)arg))
61     		return -EFAULT;
62     	return err;
63     }
64     
65     #define A(__x) ((unsigned long)(__x))
66     
67     struct timeval32 {
68     	int tv_sec;
69     	int tv_usec;
70     };
71     
72     static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
73     {
74     	struct timeval32 *up = (struct timeval32 *)arg;
75     	struct timeval ktv;
76     	mm_segment_t old_fs = get_fs();
77     	int err;
78     
79     	set_fs(KERNEL_DS);
80     	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
81     	set_fs(old_fs);
82     	if (!err) {
83     		err = put_user(ktv.tv_sec, &up->tv_sec);
84     		err |= __put_user(ktv.tv_usec, &up->tv_usec);
85     	}
86     
87     	return err;
88     }
89     
90     #define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
91     #define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
92     #define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
93     #define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
94     
95     struct ifmap32 {
96     	unsigned int mem_start;
97     	unsigned int mem_end;
98     	unsigned short base_addr;
99     	unsigned char irq;
100     	unsigned char dma;
101     	unsigned char port;
102     };
103     
104     struct ifreq32 {
105     #define IFHWADDRLEN     6
106     #define IFNAMSIZ        16
107             union {
108                     char    ifrn_name[IFNAMSIZ];	/* if name, e.g. "en0" */
109             } ifr_ifrn;
110             union {
111                     struct  sockaddr ifru_addr;
112                     struct  sockaddr ifru_dstaddr;
113                     struct  sockaddr ifru_broadaddr;
114                     struct  sockaddr ifru_netmask;
115                     struct  sockaddr ifru_hwaddr;
116                     short   ifru_flags;
117                     int     ifru_ivalue;
118                     int     ifru_mtu;
119                     struct  ifmap32 ifru_map;
120                     char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
121     		char	ifru_newname[IFNAMSIZ];
122                     __kernel_caddr_t32 ifru_data;
123             } ifr_ifru;
124     };
125     
126     struct ifconf32 {
127             int     ifc_len;                        /* size of buffer       */
128             __kernel_caddr_t32  ifcbuf;
129     };
130     
131     #ifdef CONFIG_NET
132     
133     static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
134     {
135     	struct ireq32 *uir32 = (struct ireq32 *)arg;
136     	struct net_device *dev;
137     	struct ifreq32 ifr32;
138     
139     	if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32)))
140     		return -EFAULT;
141     
142     	read_lock(&dev_base_lock);
143     	dev = __dev_get_by_index(ifr32.ifr_ifindex);
144     	if (!dev) {
145     		read_unlock(&dev_base_lock);
146     		return -ENODEV;
147     	}
148     
149     	strcpy(ifr32.ifr_name, dev->name);
150     	read_unlock(&dev_base_lock);
151     
152     	if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32)))
153     	    return -EFAULT;
154     
155     	return 0;
156     }
157     
158     static inline int dev_ifconf(unsigned int fd, unsigned int cmd,
159     			     unsigned long arg)
160     {
161     	struct ioconf32 *uifc32 = (struct ioconf32 *)arg;
162     	struct ifconf32 ifc32;
163     	struct ifconf ifc;
164     	struct ifreq32 *ifr32;
165     	struct ifreq *ifr;
166     	mm_segment_t old_fs;
167     	int len;
168     	int err;
169     
170     	if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
171     		return -EFAULT;
172     
173     	if(ifc32.ifcbuf == 0) {
174     		ifc32.ifc_len = 0;
175     		ifc.ifc_len = 0;
176     		ifc.ifc_buf = NULL;
177     	} else {
178     		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) *
179     			sizeof (struct ifreq);
180     		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
181     		if (!ifc.ifc_buf)
182     			return -ENOMEM;
183     	}
184     	ifr = ifc.ifc_req;
185     	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
186     	len = ifc32.ifc_len / sizeof (struct ifreq32);
187     	while (len--) {
188     		if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
189     			err = -EFAULT;
190     			goto out;
191     		}
192     	}
193     
194     	old_fs = get_fs();
195     	set_fs (KERNEL_DS);
196     	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);	
197     	set_fs (old_fs);
198     	if (err)
199     		goto out;
200     
201     	ifr = ifc.ifc_req;
202     	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
203     	len = ifc.ifc_len / sizeof (struct ifreq);
204     	ifc32.ifc_len = len * sizeof (struct ifreq32);
205     
206     	while (len--) {
207     		if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
208     			err = -EFAULT;
209     			goto out;
210     		}
211     	}
212     
213     	if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
214     		err = -EFAULT;
215     		goto out;
216     	}
217     out:
218     	if(ifc.ifc_buf != NULL)
219     		kfree (ifc.ifc_buf);
220     	return err;
221     }
222     
223     static inline int dev_ifsioc(unsigned int fd, unsigned int cmd,
224     			     unsigned long arg)
225     {
226     	struct ifreq32 *uifr = (struct ifreq32 *)arg;
227     	struct ifreq ifr;
228     	mm_segment_t old_fs;
229     	int err;
230     	
231     	switch (cmd) {
232     	case SIOCSIFMAP:
233     		err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name));
234     		err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
235     		err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
236     		err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
237     		err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
238     		err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
239     		err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
240     		if (err)
241     			return -EFAULT;
242     		break;
243     	default:
244     		if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32)))
245     			return -EFAULT;
246     		break;
247     	}
248     	old_fs = get_fs();
249     	set_fs (KERNEL_DS);
250     	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
251     	set_fs (old_fs);
252     	if (!err) {
253     		switch (cmd) {
254     		case SIOCGIFFLAGS:
255     		case SIOCGIFMETRIC:
256     		case SIOCGIFMTU:
257     		case SIOCGIFMEM:
258     		case SIOCGIFHWADDR:
259     		case SIOCGIFINDEX:
260     		case SIOCGIFADDR:
261     		case SIOCGIFBRDADDR:
262     		case SIOCGIFDSTADDR:
263     		case SIOCGIFNETMASK:
264     		case SIOCGIFTXQLEN:
265     			if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32)))
266     				return -EFAULT;
267     			break;
268     		case SIOCGIFMAP:
269     			err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name));
270     			err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
271     			err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
272     			err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
273     			err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
274     			err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
275     			err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
276     			if (err)
277     				err = -EFAULT;
278     			break;
279     		}
280     	}
281     	return err;
282     }
283     
284     struct rtentry32
285     {
286     	unsigned int	rt_pad1;
287     	struct sockaddr	rt_dst;		/* target address		*/
288     	struct sockaddr	rt_gateway;	/* gateway addr (RTF_GATEWAY)	*/
289     	struct sockaddr	rt_genmask;	/* target network mask (IP)	*/
290     	unsigned short	rt_flags;
291     	short		rt_pad2;
292     	unsigned int	rt_pad3;
293     	unsigned int	rt_pad4;
294     	short		rt_metric;	/* +1 for binary compatibility!	*/
295     	unsigned int	rt_dev;		/* forcing the device at add	*/
296     	unsigned int	rt_mtu;		/* per route MTU/Window 	*/
297     #ifndef __KERNEL__
298     #define rt_mss	rt_mtu			/* Compatibility :-(            */
299     #endif
300     	unsigned int	rt_window;	/* Window clamping 		*/
301     	unsigned short	rt_irtt;	/* Initial RTT			*/
302     };
303     
304     static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
305     {
306     	struct rtentry32 *ur = (struct rtentry32 *)arg;
307     	struct rtentry r;
308     	char devname[16];
309     	u32 rtdev;
310     	int ret;
311     	mm_segment_t old_fs = get_fs();
312     	
313     	ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr));
314     	ret |= __get_user (r.rt_flags, &(ur->rt_flags));
315     	ret |= __get_user (r.rt_metric, &(ur->rt_metric));
316     	ret |= __get_user (r.rt_mtu, &(ur->rt_mtu));
317     	ret |= __get_user (r.rt_window, &(ur->rt_window));
318     	ret |= __get_user (r.rt_irtt, &(ur->rt_irtt));
319     	ret |= __get_user (rtdev, &(ur->rt_dev));
320     	if (rtdev) {
321     		ret |= copy_from_user (devname, (char *)A(rtdev), 15);
322     		r.rt_dev = devname; devname[15] = 0;
323     	} else
324     		r.rt_dev = 0;
325     	if (ret)
326     		return -EFAULT;
327     	set_fs (KERNEL_DS);
328     	ret = sys_ioctl (fd, cmd, (long)&r);
329     	set_fs (old_fs);
330     	return ret;
331     }
332     
333     #endif /* CONFIG_NET */
334     
335     static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
336     {
337     	/* These are just misnamed, they actually get/put from/to user an int */
338     	switch (cmd) {
339     	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
340     	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
341     	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
342     	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
343     	}
344     	return sys_ioctl(fd, cmd, arg);
345     }
346     
347     struct hd_geometry32 {
348     	unsigned char heads;
349     	unsigned char sectors;
350     	unsigned short cylinders;
351     	u32 start;
352     };
353     
354     static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
355     {
356     	mm_segment_t old_fs = get_fs();
357     	struct hd_geometry geo;
358     	int err;
359     
360     	set_fs (KERNEL_DS);
361     	err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
362     	set_fs (old_fs);
363     	if (!err) {
364     		err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
365     		err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
366     	}
367     
368     	return err ? -EFAULT : 0;
369     }
370     
371     static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
372     {
373     	mm_segment_t old_fs = get_fs();
374     	unsigned long kval;
375     	unsigned int *uvp;
376     	int error;
377     
378     	set_fs(KERNEL_DS);
379     	error = sys_ioctl(fd, cmd, (long)&kval);
380     	set_fs(old_fs);
381     
382     	if (error == 0) {
383     		uvp = (unsigned int *)arg;
384     		if (put_user(kval, uvp))
385     			error = -EFAULT;
386     	}
387     
388     	return error;
389     }
390     
391     static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
392     {
393     	return -EINVAL;
394     }
395     
396     struct blkpg_ioctl_arg32 {
397     	int op;
398     	int flags;
399     	int datalen;
400     	u32 data;
401     };
402     
403     static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd,
404                                  struct blkpg_ioctl_arg32 *arg)
405     {
406     	struct blkpg_ioctl_arg a;
407     	struct blkpg_partition p;
408     	int err;
409     	mm_segment_t old_fs = get_fs();
410     	
411     	err = get_user(a.op, &arg->op);
412     	err |= __get_user(a.flags, &arg->flags);
413     	err |= __get_user(a.datalen, &arg->datalen);
414     	err |= __get_user((long)a.data, &arg->data);
415     	if (err) return err;
416     	switch (a.op) {
417     	case BLKPG_ADD_PARTITION:
418     	case BLKPG_DEL_PARTITION:
419     		if (a.datalen < sizeof(struct blkpg_partition))
420     			return -EINVAL;
421                     if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
422     			return -EFAULT;
423     		a.data = &p;
424     		set_fs (KERNEL_DS);
425     		err = sys_ioctl(fd, cmd, (unsigned long)&a);
426     		set_fs (old_fs);
427     	default:
428     		return -EINVAL;
429     	}                                        
430     	return err;
431     }
432     
433     struct mtget32 {
434     	__u32	mt_type;
435     	__u32	mt_resid;
436     	__u32	mt_dsreg;
437     	__u32	mt_gstat;
438     	__u32	mt_erreg;
439     	__kernel_daddr_t32	mt_fileno;
440     	__kernel_daddr_t32	mt_blkno;
441     };
442     #define MTIOCGET32	_IOR('m', 2, struct mtget32)
443     
444     struct mtpos32 {
445     	__u32	mt_blkno;
446     };
447     #define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
448     
449     struct mtconfiginfo32 {
450     	__u32	mt_type;
451     	__u32	ifc_type;
452     	__u16	irqnr;
453     	__u16	dmanr;
454     	__u16	port;
455     	__u32	debug;
456     	__u32	have_dens:1;
457     	__u32	have_bsf:1;
458     	__u32	have_fsr:1;
459     	__u32	have_bsr:1;
460     	__u32	have_eod:1;
461     	__u32	have_seek:1;
462     	__u32	have_tell:1;
463     	__u32	have_ras1:1;
464     	__u32	have_ras2:1;
465     	__u32	have_ras3:1;
466     	__u32	have_qfa:1;
467     	__u32	pad1:5;
468     	char	reserved[10];
469     };
470     #define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
471     #define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
472     
473     static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
474     {
475     	mm_segment_t old_fs = get_fs();
476     	struct mtconfiginfo info;
477     	struct mtget get;
478     	struct mtpos pos;
479     	unsigned long kcmd;
480     	void *karg;
481     	int err = 0;
482     
483     	switch(cmd) {
484     	case MTIOCPOS32:
485     		kcmd = MTIOCPOS;
486     		karg = &pos;
487     		break;
488     	case MTIOCGET32:
489     		kcmd = MTIOCGET;
490     		karg = &get;
491     		break;
492     	case MTIOCGETCONFIG32:
493     		kcmd = MTIOCGETCONFIG;
494     		karg = &info;
495     		break;
496     	case MTIOCSETCONFIG32:
497     		kcmd = MTIOCSETCONFIG;
498     		karg = &info;
499     		err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
500     		err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
501     		err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
502     		err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
503     		err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
504     		err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
505     		err |= __copy_from_user((char *)&info.debug + sizeof(info.debug),
506     				     (char *)&((struct mtconfiginfo32 *)arg)->debug
507     				     + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32));
508     		if (err)
509     			return -EFAULT;
510     		break;
511     	default:
512     		do {
513     			static int count = 0;
514     			if (++count <= 20)
515     				printk("mt_ioctl: Unknown cmd fd(%d) "
516     				       "cmd(%08x) arg(%08x)\n",
517     				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
518     		} while(0);
519     		return -EINVAL;
520     	}
521     	set_fs (KERNEL_DS);
522     	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
523     	set_fs (old_fs);
524     	if (err)
525     		return err;
526     	switch (cmd) {
527     	case MTIOCPOS32:
528     		err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno);
529     		break;
530     	case MTIOCGET32:
531     		err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
532     		err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid);
533     		err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg);
534     		err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat);
535     		err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg);
536     		err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno);
537     		err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno);
538     		break;
539     	case MTIOCGETCONFIG32:
540     		err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
541     		err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
542     		err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
543     		err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
544     		err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
545     		err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
546     		err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug
547     			    		   + sizeof(((struct mtconfiginfo32 *)arg)->debug),
548     					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
549     		break;
550     	case MTIOCSETCONFIG32:
551     		break;
552     	}
553     	return err ? -EFAULT: 0;
554     }
555     
556     #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
557     
558     static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
559     {
560     	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
561     }
562     
563     struct ioctl32_handler {
564     	unsigned int cmd;
565     	int (*function)(unsigned int, unsigned int, unsigned long);
566     };
567     
568     struct ioctl32_list {
569     	struct ioctl32_handler handler;
570     	struct ioctl32_list *next;
571     };
572     
573     #define IOCTL32_DEFAULT(cmd)		{ { cmd, (void *) sys_ioctl }, 0 }
574     #define IOCTL32_HANDLER(cmd, handler)	{ { cmd, (void *) handler }, 0 }
575     
576     static struct ioctl32_list ioctl32_handler_table[] = {
577     	IOCTL32_DEFAULT(TCGETA),
578     	IOCTL32_DEFAULT(TCSETA),
579     	IOCTL32_DEFAULT(TCSETAW),
580     	IOCTL32_DEFAULT(TCSETAF),
581     	IOCTL32_DEFAULT(TCSBRK),
582     	IOCTL32_DEFAULT(TCXONC),
583     	IOCTL32_DEFAULT(TCFLSH),
584     	IOCTL32_DEFAULT(TCGETS),
585     	IOCTL32_DEFAULT(TCSETS),
586     	IOCTL32_DEFAULT(TCSETSW),
587     	IOCTL32_DEFAULT(TCSETSF),
588     	IOCTL32_DEFAULT(TIOCLINUX),
589     
590     	IOCTL32_DEFAULT(TIOCGETD),
591     	IOCTL32_DEFAULT(TIOCSETD),
592     	IOCTL32_DEFAULT(TIOCEXCL),
593     	IOCTL32_DEFAULT(TIOCNXCL),
594     	IOCTL32_DEFAULT(TIOCCONS),
595     	IOCTL32_DEFAULT(TIOCGSOFTCAR),
596     	IOCTL32_DEFAULT(TIOCSSOFTCAR),
597     	IOCTL32_DEFAULT(TIOCSWINSZ),
598     	IOCTL32_DEFAULT(TIOCGWINSZ),
599     	IOCTL32_DEFAULT(TIOCMGET),
600     	IOCTL32_DEFAULT(TIOCMBIC),
601     	IOCTL32_DEFAULT(TIOCMBIS),
602     	IOCTL32_DEFAULT(TIOCMSET),
603     	IOCTL32_DEFAULT(TIOCPKT),
604     	IOCTL32_DEFAULT(TIOCNOTTY),
605     	IOCTL32_DEFAULT(TIOCSTI),
606     	IOCTL32_DEFAULT(TIOCOUTQ),
607     	IOCTL32_DEFAULT(TIOCSPGRP),
608     	IOCTL32_DEFAULT(TIOCGPGRP),
609     	IOCTL32_DEFAULT(TIOCSCTTY),
610     	IOCTL32_DEFAULT(TIOCGPTN),
611     	IOCTL32_DEFAULT(TIOCSPTLCK),
612     	IOCTL32_DEFAULT(TIOCGSERIAL),
613     	IOCTL32_DEFAULT(TIOCSSERIAL),
614     	IOCTL32_DEFAULT(TIOCSERGETLSR),
615     
616     	IOCTL32_DEFAULT(FIOCLEX),
617     	IOCTL32_DEFAULT(FIONCLEX),
618     	IOCTL32_DEFAULT(FIOASYNC),
619     	IOCTL32_DEFAULT(FIONBIO),
620     	IOCTL32_DEFAULT(FIONREAD),
621     
622     	IOCTL32_DEFAULT(PIO_FONT),
623     	IOCTL32_DEFAULT(GIO_FONT),
624     	IOCTL32_DEFAULT(KDSIGACCEPT),
625     	IOCTL32_DEFAULT(KDGETKEYCODE),
626     	IOCTL32_DEFAULT(KDSETKEYCODE),
627     	IOCTL32_DEFAULT(KIOCSOUND),
628     	IOCTL32_DEFAULT(KDMKTONE),
629     	IOCTL32_DEFAULT(KDGKBTYPE),
630     	IOCTL32_DEFAULT(KDSETMODE),
631     	IOCTL32_DEFAULT(KDGETMODE),
632     	IOCTL32_DEFAULT(KDSKBMODE),
633     	IOCTL32_DEFAULT(KDGKBMODE),
634     	IOCTL32_DEFAULT(KDSKBMETA),
635     	IOCTL32_DEFAULT(KDGKBMETA),
636     	IOCTL32_DEFAULT(KDGKBENT),
637     	IOCTL32_DEFAULT(KDSKBENT),
638     	IOCTL32_DEFAULT(KDGKBSENT),
639     	IOCTL32_DEFAULT(KDSKBSENT),
640     	IOCTL32_DEFAULT(KDGKBDIACR),
641     	IOCTL32_DEFAULT(KDSKBDIACR),
642     	IOCTL32_DEFAULT(KDGKBLED),
643     	IOCTL32_DEFAULT(KDSKBLED),
644     	IOCTL32_DEFAULT(KDGETLED),
645     	IOCTL32_DEFAULT(KDSETLED),
646     	IOCTL32_DEFAULT(GIO_SCRNMAP),
647     	IOCTL32_DEFAULT(PIO_SCRNMAP),
648     	IOCTL32_DEFAULT(GIO_UNISCRNMAP),
649     	IOCTL32_DEFAULT(PIO_UNISCRNMAP),
650     	IOCTL32_DEFAULT(PIO_FONTRESET),
651     	IOCTL32_DEFAULT(PIO_UNIMAPCLR),
652     
653     	IOCTL32_DEFAULT(VT_SETMODE),
654     	IOCTL32_DEFAULT(VT_GETMODE),
655     	IOCTL32_DEFAULT(VT_GETSTATE),
656     	IOCTL32_DEFAULT(VT_OPENQRY),
657     	IOCTL32_DEFAULT(VT_ACTIVATE),
658     	IOCTL32_DEFAULT(VT_WAITACTIVE),
659     	IOCTL32_DEFAULT(VT_RELDISP),
660     	IOCTL32_DEFAULT(VT_DISALLOCATE),
661     	IOCTL32_DEFAULT(VT_RESIZE),
662     	IOCTL32_DEFAULT(VT_RESIZEX),
663     	IOCTL32_DEFAULT(VT_LOCKSWITCH),
664     	IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
665     
666     #ifdef CONFIG_NET
667     	/* Socket level stuff */
668     	IOCTL32_DEFAULT(FIOSETOWN),
669     	IOCTL32_DEFAULT(SIOCSPGRP),
670     	IOCTL32_DEFAULT(FIOGETOWN),
671     	IOCTL32_DEFAULT(SIOCGPGRP),
672     	IOCTL32_DEFAULT(SIOCATMARK),
673     	IOCTL32_DEFAULT(SIOCSIFLINK),
674     	IOCTL32_DEFAULT(SIOCSIFENCAP),
675     	IOCTL32_DEFAULT(SIOCGIFENCAP),
676     	IOCTL32_DEFAULT(SIOCSIFBR),
677     	IOCTL32_DEFAULT(SIOCGIFBR),
678     	IOCTL32_DEFAULT(SIOCSARP),
679     	IOCTL32_DEFAULT(SIOCGARP),
680     	IOCTL32_DEFAULT(SIOCDARP),
681     	IOCTL32_DEFAULT(SIOCSRARP),
682     	IOCTL32_DEFAULT(SIOCGRARP),
683     	IOCTL32_DEFAULT(SIOCDRARP),
684     	IOCTL32_DEFAULT(SIOCADDDLCI),
685     	IOCTL32_DEFAULT(SIOCDELDLCI),
686     
687     	IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
688     	IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
689     	IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
690     	IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc),
691     	IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc),
692     	IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc),
693     	IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc),
694     	IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc),
695     	IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc),
696     	IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc),
697     	IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc),
698     	IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc),
699     	IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc),
700     	IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc),
701     	IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc),
702     	IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc),
703     	IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc),
704     	IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc),
705     	IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc),
706     	IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc),
707     	IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc),
708     	IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc),
709     	IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc),
710     	IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc),
711     	IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc),
712     	IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc),
713     	IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc),
714     	IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc),
715     	IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc),
716     	IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
717     	IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
718     	/*
719     	 * Note SIOCRTMSG is no longer, so this is safe and * the user would
720     	 * have seen just an -EINVAL anyways.
721     	 */
722     	IOCTL32_HANDLER(SIOCRTMSG, ret_einval),
723     	IOCTL32_HANDLER(SIOCGSTAMP, do_siocgstamp),
724     
725     #endif /* CONFIG_NET */
726     
727     	IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
728     	IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
729     	IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
730     	IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
731     
732     	IOCTL32_HANDLER(HDIO_GETGEO, hdio_getgeo),	/* hdreg.h ioctls  */
733     	IOCTL32_HANDLER(HDIO_GET_UNMASKINTR, hdio_ioctl_trans),
734     	IOCTL32_HANDLER(HDIO_GET_MULTCOUNT, hdio_ioctl_trans),
735     	// HDIO_OBSOLETE_IDENTITY
736     	IOCTL32_HANDLER(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans),
737     	IOCTL32_HANDLER(HDIO_GET_32BIT, hdio_ioctl_trans),
738     	IOCTL32_HANDLER(HDIO_GET_NOWERR, hdio_ioctl_trans),
739     	IOCTL32_HANDLER(HDIO_GET_DMA, hdio_ioctl_trans),
740     	IOCTL32_HANDLER(HDIO_GET_NICE, hdio_ioctl_trans),
741     	IOCTL32_DEFAULT(HDIO_GET_IDENTITY),
742     	IOCTL32_DEFAULT(HDIO_DRIVE_RESET),
743     	// HDIO_TRISTATE_HWIF				/* not implemented */
744     	// HDIO_DRIVE_TASK				/* To do, need specs */
745     	IOCTL32_DEFAULT(HDIO_DRIVE_CMD),
746     	IOCTL32_DEFAULT(HDIO_SET_MULTCOUNT),
747     	IOCTL32_DEFAULT(HDIO_SET_UNMASKINTR),
748     	IOCTL32_DEFAULT(HDIO_SET_KEEPSETTINGS),
749     	IOCTL32_DEFAULT(HDIO_SET_32BIT),
750     	IOCTL32_DEFAULT(HDIO_SET_NOWERR),
751     	IOCTL32_DEFAULT(HDIO_SET_DMA),
752     	IOCTL32_DEFAULT(HDIO_SET_PIO_MODE),
753     	IOCTL32_DEFAULT(HDIO_SCAN_HWIF),
754     	IOCTL32_DEFAULT(HDIO_SET_NICE),
755     	//HDIO_UNREGISTER_HWIF
756     
757     	IOCTL32_DEFAULT(BLKROSET),			/* fs.h ioctls  */
758     	IOCTL32_DEFAULT(BLKROGET),
759     	IOCTL32_DEFAULT(BLKRRPART),
760     	IOCTL32_HANDLER(BLKGETSIZE, w_long),
761     
762     	IOCTL32_DEFAULT(BLKFLSBUF),
763     	IOCTL32_DEFAULT(BLKRASET),
764     	IOCTL32_HANDLER(BLKRAGET, w_long),
765     	IOCTL32_DEFAULT(BLKFRASET),
766     	IOCTL32_HANDLER(BLKFRAGET, w_long),
767     	IOCTL32_DEFAULT(BLKSECTSET),
768     	IOCTL32_HANDLER(BLKSECTGET, w_long),
769     	IOCTL32_DEFAULT(BLKSSZGET),
770     	IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans),
771     	IOCTL32_DEFAULT(BLKELVGET),
772     	IOCTL32_DEFAULT(BLKELVSET),
773     	IOCTL32_DEFAULT(BLKBSZGET),
774     	IOCTL32_DEFAULT(BLKBSZSET),
775     
776     #ifdef CONFIG_MD
777     	/* status */
778     	IOCTL32_DEFAULT(RAID_VERSION),
779     	IOCTL32_DEFAULT(GET_ARRAY_INFO),
780     	IOCTL32_DEFAULT(GET_DISK_INFO),
781     	IOCTL32_DEFAULT(PRINT_RAID_DEBUG),
782     	IOCTL32_DEFAULT(RAID_AUTORUN),
783     
784     	/* configuration */
785     	IOCTL32_DEFAULT(CLEAR_ARRAY),
786     	IOCTL32_DEFAULT(ADD_NEW_DISK),
787     	IOCTL32_DEFAULT(HOT_REMOVE_DISK),
788     	IOCTL32_DEFAULT(SET_ARRAY_INFO),
789     	IOCTL32_DEFAULT(SET_DISK_INFO),
790     	IOCTL32_DEFAULT(WRITE_RAID_INFO),
791     	IOCTL32_DEFAULT(UNPROTECT_ARRAY),
792     	IOCTL32_DEFAULT(PROTECT_ARRAY),
793     	IOCTL32_DEFAULT(HOT_ADD_DISK),
794     	IOCTL32_DEFAULT(SET_DISK_FAULTY),
795     
796     	/* usage */
797     	IOCTL32_DEFAULT(RUN_ARRAY),
798     	IOCTL32_DEFAULT(START_ARRAY),
799     	IOCTL32_DEFAULT(STOP_ARRAY),
800     	IOCTL32_DEFAULT(STOP_ARRAY_RO),
801     	IOCTL32_DEFAULT(RESTART_ARRAY_RW),
802     #endif /* CONFIG_MD */
803     
804     	IOCTL32_DEFAULT(MTIOCTOP),			/* mtio.h ioctls  */
805     	IOCTL32_HANDLER(MTIOCGET32, mt_ioctl_trans),
806     	IOCTL32_HANDLER(MTIOCPOS32, mt_ioctl_trans),
807     	IOCTL32_HANDLER(MTIOCGETCONFIG32, mt_ioctl_trans),
808     	IOCTL32_HANDLER(MTIOCSETCONFIG32, mt_ioctl_trans),
809     	// MTIOCRDFTSEG
810     	// MTIOCWRFTSEG
811     	// MTIOCVOLINFO
812     	// MTIOCGETSIZE
813     	// MTIOCFTFORMAT
814     	// MTIOCFTCMD
815     
816     	IOCTL32_DEFAULT(AUTOFS_IOC_READY),		/* auto_fs.h ioctls */
817     	IOCTL32_DEFAULT(AUTOFS_IOC_FAIL),
818     	IOCTL32_DEFAULT(AUTOFS_IOC_CATATONIC),
819     	IOCTL32_DEFAULT(AUTOFS_IOC_PROTOVER),
820     	IOCTL32_HANDLER(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout),
821     	IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE)
822     };
823     
824     #define NR_IOCTL32_HANDLERS	(sizeof(ioctl32_handler_table) /	\
825     				 sizeof(ioctl32_handler_table[0]))
826     
827     static struct ioctl32_list *ioctl32_hash_table[1024];
828     
829     static inline int ioctl32_hash(unsigned int cmd)
830     {
831     	return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
832     }
833     
834     int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg)
835     {
836     	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
837     	struct file *filp;
838     	struct ioctl32_list *l;
839     	int error;
840     
841     	l = ioctl32_hash_table[ioctl32_hash(cmd)];
842     
843     	error = -EBADF;
844     
845     	filp = fget(fd);
846     	if (!filp)
847     		return error;
848     
849     	if (!filp->f_op || !filp->f_op->ioctl) {
850     		error = sys_ioctl (fd, cmd, arg);
851     		goto out;
852     	}
853     
854     	while (l && l->handler.cmd != cmd)
855     		l = l->next;
856     
857     	if (l) {
858     		handler = (void *)l->handler.function;
859     		error = handler(fd, cmd, arg, filp);
860     	} else {
861     		error = -EINVAL;
862     		printk("unknown ioctl: %08x\n", cmd);
863     	}
864     out:
865     	fput(filp);
866     	return error;
867     }
868     
869     static void ioctl32_insert(struct ioctl32_list *entry)
870     {
871     	int hash = ioctl32_hash(entry->handler.cmd);
872     	if (!ioctl32_hash_table[hash])
873     		ioctl32_hash_table[hash] = entry;
874     	else {
875     		struct ioctl32_list *l;
876     		l = ioctl32_hash_table[hash];
877     		while (l->next)
878     			l = l->next;
879     		l->next = entry;
880     		entry->next = 0;
881     	}
882     }
883     
884     static int __init init_ioctl32(void)
885     {
886     	int i;
887     	for (i = 0; i < NR_IOCTL32_HANDLERS; i++)
888     		ioctl32_insert(&ioctl32_handler_table[i]);
889     	return 0;
890     }
891     
892     __initcall(init_ioctl32);
893