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 * Copyright (C) 2002  Maciej W. Rozycki
8 *
9 * Mostly stolen from the sparc64 ioctl32 implementation.
10 */
11#include <linux/config.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/if.h>
16#include <linux/mm.h>
17#include <linux/mtio.h>
18#include <linux/init.h>
19#include <linux/file.h>
20#include <linux/fs.h>
21#include <linux/ppp_defs.h>
22#include <linux/if_ppp.h>
23#include <linux/if_pppox.h>
24#include <linux/cdrom.h>
25#include <linux/loop.h>
26#include <linux/fb.h>
27#include <linux/vt.h>
28#include <linux/kd.h>
29#include <linux/netdevice.h>
30#include <linux/kernprof.h>
31#include <linux/route.h>
32#include <linux/hdreg.h>
33#include <linux/blkpg.h>
34#include <linux/blkdev.h>
35#include <linux/elevator.h>
36#include <linux/auto_fs.h>
37#include <linux/auto_fs4.h>
38#include <linux/ext2_fs.h>
39#include <linux/raid/md_u.h>
40
41#include <scsi/scsi.h>
42#undef __KERNEL__		/* This file was born to be ugly ...  */
43#include <scsi/scsi_ioctl.h>
44#define __KERNEL__
45#include <scsi/sg.h>
46
47#include <asm/types.h>
48#include <asm/uaccess.h>
49
50#include <linux/rtc.h>
51
52long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
53
54static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
55{
56	mm_segment_t old_fs = get_fs();
57	int err;
58	unsigned long val;
59
60	set_fs (KERNEL_DS);
61	err = sys_ioctl(fd, cmd, (unsigned long)&val);
62	set_fs (old_fs);
63	if (!err && put_user((unsigned int) val, (u32 *)arg))
64		return -EFAULT;
65	return err;
66}
67
68static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
69{
70	mm_segment_t old_fs = get_fs();
71	int err;
72	unsigned long val;
73
74	if (get_user(val, (u32 *)arg))
75		return -EFAULT;
76	set_fs(KERNEL_DS);
77	err = sys_ioctl(fd, cmd, (unsigned long)&val);
78	set_fs (old_fs);
79	if (!err && put_user(val, (u32 *)arg))
80		return -EFAULT;
81	return err;
82}
83
84#define A(__x) ((unsigned long)(__x))
85
86
87#ifdef CONFIG_FB
88
89struct fb_fix_screeninfo32 {
90	char id[16];			/* identification string eg "TT Builtin" */
91	__u32 smem_start;		/* Start of frame buffer mem */
92					/* (physical address) */
93	__u32 smem_len;			/* Length of frame buffer mem */
94	__u32 type;			/* see FB_TYPE_*		*/
95	__u32 type_aux;			/* Interleave for interleaved Planes */
96	__u32 visual;			/* see FB_VISUAL_*		*/
97	__u16 xpanstep;			/* zero if no hardware panning  */
98	__u16 ypanstep;			/* zero if no hardware panning  */
99	__u16 ywrapstep;		/* zero if no hardware ywrap    */
100	__u32 line_length;		/* length of a line in bytes    */
101	__u32 mmio_start;		/* Start of Memory Mapped I/O   */
102					/* (physical address) */
103	__u32 mmio_len;			/* Length of Memory Mapped I/O  */
104	__u32 accel;			/* Type of acceleration available */
105	__u16 reserved[3];		/* Reserved for future compatibility */
106};
107
108static int do_fbioget_fscreeninfo_ioctl(unsigned int fd, unsigned int cmd,
109					unsigned long arg)
110{
111	mm_segment_t old_fs = get_fs();
112	struct fb_fix_screeninfo fix;
113	struct fb_fix_screeninfo32 *fix32 = (struct fb_fix_screeninfo32 *)arg;
114	int err;
115
116	set_fs(KERNEL_DS);
117	err = sys_ioctl(fd, cmd, (unsigned long)&fix);
118	set_fs(old_fs);
119
120	if (err == 0) {
121		err = __copy_to_user((char *)fix32->id, (char *)fix.id,
122				     sizeof(fix.id));
123		err |= __put_user((__u32)(unsigned long)fix.smem_start,
124				  &fix32->smem_start);
125		err |= __put_user(fix.smem_len, &fix32->smem_len);
126		err |= __put_user(fix.type, &fix32->type);
127		err |= __put_user(fix.type_aux, &fix32->type_aux);
128		err |= __put_user(fix.visual, &fix32->visual);
129		err |= __put_user(fix.xpanstep, &fix32->xpanstep);
130		err |= __put_user(fix.ypanstep, &fix32->ypanstep);
131		err |= __put_user(fix.ywrapstep, &fix32->ywrapstep);
132		err |= __put_user(fix.line_length, &fix32->line_length);
133		err |= __put_user((__u32)(unsigned long)fix.mmio_start,
134				  &fix32->mmio_start);
135		err |= __put_user(fix.mmio_len, &fix32->mmio_len);
136		err |= __put_user(fix.accel, &fix32->accel);
137		err |= __copy_to_user((char *)fix32->reserved,
138				      (char *)fix.reserved,
139				      sizeof(fix.reserved));
140		if (err)
141			err = -EFAULT;
142	}
143
144	return err;
145}
146
147struct fb_cmap32 {
148	__u32 start;			/* First entry  */
149	__u32 len;			/* Number of entries */
150	__u32 red;			/* Red values   */
151	__u32 green;
152	__u32 blue;
153	__u32 transp;			/* transparency, can be NULL */
154};
155
156static int do_fbiocmap_ioctl(unsigned int fd, unsigned int cmd,
157			     unsigned long arg)
158{
159	mm_segment_t old_fs = get_fs();
160	u32 red = 0, green = 0, blue = 0, transp = 0;
161	struct fb_cmap cmap;
162	struct fb_cmap32 *cmap32 = (struct fb_cmap32 *)arg;
163	int err;
164
165	memset(&cmap, 0, sizeof(cmap));
166
167	err = __get_user(cmap.start, &cmap32->start);
168	err |= __get_user(cmap.len, &cmap32->len);
169	err |= __get_user(red, &cmap32->red);
170	err |= __get_user(green, &cmap32->green);
171	err |= __get_user(blue, &cmap32->blue);
172	err |= __get_user(transp, &cmap32->transp);
173	if (err)
174		return -EFAULT;
175
176	err = -ENOMEM;
177	cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
178	if (!cmap.red)
179		goto out;
180	cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
181	if (!cmap.green)
182		goto out;
183	cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
184	if (!cmap.blue)
185		goto out;
186	if (transp) {
187		cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
188		if (!cmap.transp)
189			goto out;
190	}
191
192	if (cmd == FBIOPUTCMAP) {
193		err = __copy_from_user(cmap.red, (char *)A(red),
194				       cmap.len * sizeof(__u16));
195		err |= __copy_from_user(cmap.green, (char *)A(green),
196					cmap.len * sizeof(__u16));
197		err |= __copy_from_user(cmap.blue, (char *)A(blue),
198					cmap.len * sizeof(__u16));
199		if (cmap.transp)
200			err |= __copy_from_user(cmap.transp, (char *)A(transp),
201						cmap.len * sizeof(__u16));
202		if (err) {
203			err = -EFAULT;
204			goto out;
205		}
206	}
207
208	set_fs(KERNEL_DS);
209	err = sys_ioctl(fd, cmd, (unsigned long)&cmap);
210	set_fs(old_fs);
211	if (err)
212		goto out;
213
214	if (cmd == FBIOGETCMAP) {
215		err = __copy_to_user((char *)A(red), cmap.red,
216				     cmap.len * sizeof(__u16));
217		err |= __copy_to_user((char *)A(green), cmap.blue,
218				      cmap.len * sizeof(__u16));
219		err |= __copy_to_user((char *)A(blue), cmap.blue,
220				      cmap.len * sizeof(__u16));
221		if (cmap.transp)
222			err |= __copy_to_user((char *)A(transp), cmap.transp,
223					      cmap.len * sizeof(__u16));
224		if (err) {
225			err = -EFAULT;
226			goto out;
227		}
228	}
229
230out:
231	if (cmap.red)
232		kfree(cmap.red);
233	if (cmap.green)
234		kfree(cmap.green);
235	if (cmap.blue)
236		kfree(cmap.blue);
237	if (cmap.transp)
238		kfree(cmap.transp);
239
240	return err;
241}
242
243#endif /* CONFIG_FB */
244
245
246struct timeval32 {
247	int tv_sec;
248	int tv_usec;
249};
250
251static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
252{
253	struct timeval32 *up = (struct timeval32 *)arg;
254	struct timeval ktv;
255	mm_segment_t old_fs = get_fs();
256	int err;
257
258	set_fs(KERNEL_DS);
259	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
260	set_fs(old_fs);
261	if (!err) {
262		err = put_user(ktv.tv_sec, &up->tv_sec);
263		err |= __put_user(ktv.tv_usec, &up->tv_usec);
264	}
265
266	return err;
267}
268
269#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
270#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
271#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
272#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
273
274struct ifmap32 {
275	unsigned int mem_start;
276	unsigned int mem_end;
277	unsigned short base_addr;
278	unsigned char irq;
279	unsigned char dma;
280	unsigned char port;
281};
282
283struct ifreq32 {
284#define IFHWADDRLEN     6
285#define IFNAMSIZ        16
286        union {
287                char    ifrn_name[IFNAMSIZ];	/* if name, e.g. "en0" */
288        } ifr_ifrn;
289        union {
290                struct  sockaddr ifru_addr;
291                struct  sockaddr ifru_dstaddr;
292                struct  sockaddr ifru_broadaddr;
293                struct  sockaddr ifru_netmask;
294                struct  sockaddr ifru_hwaddr;
295                short   ifru_flags;
296                int     ifru_ivalue;
297                int     ifru_mtu;
298                struct  ifmap32 ifru_map;
299                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
300		char	ifru_newname[IFNAMSIZ];
301                __kernel_caddr_t32 ifru_data;
302        } ifr_ifru;
303};
304
305struct ifconf32 {
306        int     ifc_len;                        /* size of buffer       */
307        __kernel_caddr_t32  ifcbuf;
308};
309
310#ifdef CONFIG_NET
311
312static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
313{
314	struct ireq32 *uir32 = (struct ireq32 *)arg;
315	struct net_device *dev;
316	struct ifreq32 ifr32;
317
318	if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32)))
319		return -EFAULT;
320
321	read_lock(&dev_base_lock);
322	dev = __dev_get_by_index(ifr32.ifr_ifindex);
323	if (!dev) {
324		read_unlock(&dev_base_lock);
325		return -ENODEV;
326	}
327
328	strcpy(ifr32.ifr_name, dev->name);
329	read_unlock(&dev_base_lock);
330
331	if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32)))
332	    return -EFAULT;
333
334	return 0;
335}
336
337static inline int dev_ifconf(unsigned int fd, unsigned int cmd,
338			     unsigned long arg)
339{
340	struct ioconf32 *uifc32 = (struct ioconf32 *)arg;
341	struct ifconf32 ifc32;
342	struct ifconf ifc;
343	struct ifreq32 *ifr32;
344	struct ifreq *ifr;
345	mm_segment_t old_fs;
346	int len;
347	int err;
348
349	if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
350		return -EFAULT;
351
352	if(ifc32.ifcbuf == 0) {
353		ifc32.ifc_len = 0;
354		ifc.ifc_len = 0;
355		ifc.ifc_buf = NULL;
356	} else {
357		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) *
358			sizeof (struct ifreq);
359		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
360		if (!ifc.ifc_buf)
361			return -ENOMEM;
362	}
363	ifr = ifc.ifc_req;
364	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
365	len = ifc32.ifc_len / sizeof (struct ifreq32);
366	while (len--) {
367		if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
368			err = -EFAULT;
369			goto out;
370		}
371	}
372
373	old_fs = get_fs();
374	set_fs (KERNEL_DS);
375	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);
376	set_fs (old_fs);
377	if (err)
378		goto out;
379
380	ifr = ifc.ifc_req;
381	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
382	len = ifc.ifc_len / sizeof (struct ifreq);
383	ifc32.ifc_len = len * sizeof (struct ifreq32);
384
385	while (len--) {
386		if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
387			err = -EFAULT;
388			goto out;
389		}
390	}
391
392	if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
393		err = -EFAULT;
394		goto out;
395	}
396out:
397	if(ifc.ifc_buf != NULL)
398		kfree (ifc.ifc_buf);
399	return err;
400}
401
402static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
403{
404	struct ifreq ifr;
405	mm_segment_t old_fs;
406	int err;
407
408	switch (cmd) {
409	case SIOCSIFMAP:
410		err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name));
411		err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
412		err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
413		err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
414		err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
415		err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
416		err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
417		if (err)
418			return -EFAULT;
419		break;
420	default:
421		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
422			return -EFAULT;
423		break;
424	}
425	old_fs = get_fs();
426	set_fs (KERNEL_DS);
427	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
428	set_fs (old_fs);
429	if (!err) {
430		switch (cmd) {
431		case SIOCGIFFLAGS:
432		case SIOCGIFMETRIC:
433		case SIOCGIFMTU:
434		case SIOCGIFMEM:
435		case SIOCGIFHWADDR:
436		case SIOCGIFINDEX:
437		case SIOCGIFADDR:
438		case SIOCGIFBRDADDR:
439		case SIOCGIFDSTADDR:
440		case SIOCGIFNETMASK:
441		case SIOCGIFTXQLEN:
442			if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
443				return -EFAULT;
444			break;
445		case SIOCGIFMAP:
446			err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name));
447			err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
448			err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
449			err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
450			err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
451			err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
452			err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
453			if (err)
454				err = -EFAULT;
455			break;
456		}
457	}
458	return err;
459}
460
461struct rtentry32
462{
463	unsigned int	rt_pad1;
464	struct sockaddr	rt_dst;		/* target address		*/
465	struct sockaddr	rt_gateway;	/* gateway addr (RTF_GATEWAY)	*/
466	struct sockaddr	rt_genmask;	/* target network mask (IP)	*/
467	unsigned short	rt_flags;
468	short		rt_pad2;
469	unsigned int	rt_pad3;
470	unsigned int	rt_pad4;
471	short		rt_metric;	/* +1 for binary compatibility!	*/
472	unsigned int	rt_dev;		/* forcing the device at add	*/
473	unsigned int	rt_mtu;		/* per route MTU/Window 	*/
474#ifndef __KERNEL__
475#define rt_mss	rt_mtu			/* Compatibility :-(            */
476#endif
477	unsigned int	rt_window;	/* Window clamping 		*/
478	unsigned short	rt_irtt;	/* Initial RTT			*/
479};
480
481static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
482{
483	struct rtentry32 *ur = (struct rtentry32 *)arg;
484	struct rtentry r;
485	char devname[16];
486	u32 rtdev;
487	int ret;
488	mm_segment_t old_fs = get_fs();
489
490	ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr));
491	ret |= __get_user (r.rt_flags, &(ur->rt_flags));
492	ret |= __get_user (r.rt_metric, &(ur->rt_metric));
493	ret |= __get_user (r.rt_mtu, &(ur->rt_mtu));
494	ret |= __get_user (r.rt_window, &(ur->rt_window));
495	ret |= __get_user (r.rt_irtt, &(ur->rt_irtt));
496	ret |= __get_user (rtdev, &(ur->rt_dev));
497	if (rtdev) {
498		ret |= copy_from_user (devname, (char *)A(rtdev), 15);
499		r.rt_dev = devname; devname[15] = 0;
500	} else
501		r.rt_dev = 0;
502	if (ret)
503		return -EFAULT;
504	set_fs (KERNEL_DS);
505	ret = sys_ioctl (fd, cmd, (long)&r);
506	set_fs (old_fs);
507	return ret;
508}
509
510#endif /* CONFIG_NET */
511
512static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
513{
514	/* These are just misnamed, they actually get/put from/to user an int */
515	switch (cmd) {
516	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
517	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
518	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
519	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
520	}
521	return sys_ioctl(fd, cmd, arg);
522}
523
524struct hd_geometry32 {
525	unsigned char heads;
526	unsigned char sectors;
527	unsigned short cylinders;
528	u32 start;
529};
530
531static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
532{
533	mm_segment_t old_fs = get_fs();
534	struct hd_geometry geo;
535	int err;
536
537	set_fs (KERNEL_DS);
538	err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
539	set_fs (old_fs);
540	if (!err) {
541		err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
542		err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
543	}
544
545	return err ? -EFAULT : 0;
546}
547
548static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
549{
550	mm_segment_t old_fs = get_fs();
551	unsigned long kval;
552	unsigned int *uvp;
553	int error;
554
555	set_fs(KERNEL_DS);
556	error = sys_ioctl(fd, cmd, (long)&kval);
557	set_fs(old_fs);
558
559	if (error == 0) {
560		uvp = (unsigned int *)arg;
561		if (put_user(kval, uvp))
562			error = -EFAULT;
563	}
564
565	return error;
566}
567
568static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
569{
570	return -EINVAL;
571}
572
573struct blkpg_ioctl_arg32 {
574	int op;
575	int flags;
576	int datalen;
577	u32 data;
578};
579
580static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd,
581                             struct blkpg_ioctl_arg32 *arg)
582{
583	struct blkpg_ioctl_arg a;
584	struct blkpg_partition p;
585	int err;
586	mm_segment_t old_fs = get_fs();
587
588	err = get_user(a.op, &arg->op);
589	err |= __get_user(a.flags, &arg->flags);
590	err |= __get_user(a.datalen, &arg->datalen);
591	err |= __get_user((long)a.data, &arg->data);
592	if (err) return err;
593	switch (a.op) {
594	case BLKPG_ADD_PARTITION:
595	case BLKPG_DEL_PARTITION:
596		if (a.datalen < sizeof(struct blkpg_partition))
597			return -EINVAL;
598                if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
599			return -EFAULT;
600		a.data = &p;
601		set_fs (KERNEL_DS);
602		err = sys_ioctl(fd, cmd, (unsigned long)&a);
603		set_fs (old_fs);
604	default:
605		return -EINVAL;
606	}
607	return err;
608}
609
610struct mtget32 {
611	__u32	mt_type;
612	__u32	mt_resid;
613	__u32	mt_dsreg;
614	__u32	mt_gstat;
615	__u32	mt_erreg;
616	__kernel_daddr_t32	mt_fileno;
617	__kernel_daddr_t32	mt_blkno;
618};
619#define MTIOCGET32	_IOR('m', 2, struct mtget32)
620
621struct mtpos32 {
622	__u32	mt_blkno;
623};
624#define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
625
626struct mtconfiginfo32 {
627	__u32	mt_type;
628	__u32	ifc_type;
629	__u16	irqnr;
630	__u16	dmanr;
631	__u16	port;
632	__u32	debug;
633	__u32	have_dens:1;
634	__u32	have_bsf:1;
635	__u32	have_fsr:1;
636	__u32	have_bsr:1;
637	__u32	have_eod:1;
638	__u32	have_seek:1;
639	__u32	have_tell:1;
640	__u32	have_ras1:1;
641	__u32	have_ras2:1;
642	__u32	have_ras3:1;
643	__u32	have_qfa:1;
644	__u32	pad1:5;
645	char	reserved[10];
646};
647#define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
648#define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
649
650static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
651{
652	mm_segment_t old_fs = get_fs();
653	struct mtconfiginfo info;
654	struct mtget get;
655	struct mtpos pos;
656	unsigned long kcmd;
657	void *karg;
658	int err = 0;
659
660	switch(cmd) {
661	case MTIOCPOS32:
662		kcmd = MTIOCPOS;
663		karg = &pos;
664		break;
665	case MTIOCGET32:
666		kcmd = MTIOCGET;
667		karg = &get;
668		break;
669	case MTIOCGETCONFIG32:
670		kcmd = MTIOCGETCONFIG;
671		karg = &info;
672		break;
673	case MTIOCSETCONFIG32:
674		kcmd = MTIOCSETCONFIG;
675		karg = &info;
676		err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
677		err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
678		err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
679		err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
680		err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
681		err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
682		err |= __copy_from_user((char *)&info.debug + sizeof(info.debug),
683				     (char *)&((struct mtconfiginfo32 *)arg)->debug
684				     + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32));
685		if (err)
686			return -EFAULT;
687		break;
688	default:
689		do {
690			static int count = 0;
691			if (++count <= 20)
692				printk("mt_ioctl: Unknown cmd fd(%d) "
693				       "cmd(%08x) arg(%08x)\n",
694				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
695		} while(0);
696		return -EINVAL;
697	}
698	set_fs (KERNEL_DS);
699	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
700	set_fs (old_fs);
701	if (err)
702		return err;
703	switch (cmd) {
704	case MTIOCPOS32:
705		err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno);
706		break;
707	case MTIOCGET32:
708		err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
709		err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid);
710		err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg);
711		err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat);
712		err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg);
713		err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno);
714		err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno);
715		break;
716	case MTIOCGETCONFIG32:
717		err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
718		err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
719		err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
720		err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
721		err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
722		err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
723		err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug
724			    		   + sizeof(((struct mtconfiginfo32 *)arg)->debug),
725					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
726		break;
727	case MTIOCSETCONFIG32:
728		break;
729	}
730	return err ? -EFAULT: 0;
731}
732
733#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
734
735static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
736{
737	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
738}
739
740struct ioctl32_handler {
741	unsigned int cmd;
742	int (*function)(unsigned int, unsigned int, unsigned long);
743};
744
745struct ioctl32_list {
746	struct ioctl32_handler handler;
747	struct ioctl32_list *next;
748};
749
750#define IOCTL32_DEFAULT(cmd)		{ { cmd, (void *) sys_ioctl }, 0 }
751#define IOCTL32_HANDLER(cmd, handler)	{ { cmd, (void *) handler }, 0 }
752
753static struct ioctl32_list ioctl32_handler_table[] = {
754	IOCTL32_DEFAULT(TCGETA),
755	IOCTL32_DEFAULT(TCSETA),
756	IOCTL32_DEFAULT(TCSETAW),
757	IOCTL32_DEFAULT(TCSETAF),
758	IOCTL32_DEFAULT(TCSBRK),
759	IOCTL32_DEFAULT(TCXONC),
760	IOCTL32_DEFAULT(TCFLSH),
761	IOCTL32_DEFAULT(TCGETS),
762	IOCTL32_DEFAULT(TCSETS),
763	IOCTL32_DEFAULT(TCSETSW),
764	IOCTL32_DEFAULT(TCSETSF),
765	IOCTL32_DEFAULT(TIOCLINUX),
766
767	IOCTL32_DEFAULT(TIOCGETD),
768	IOCTL32_DEFAULT(TIOCSETD),
769	IOCTL32_DEFAULT(TIOCEXCL),
770	IOCTL32_DEFAULT(TIOCNXCL),
771	IOCTL32_DEFAULT(TIOCCONS),
772	IOCTL32_DEFAULT(TIOCGSOFTCAR),
773	IOCTL32_DEFAULT(TIOCSSOFTCAR),
774	IOCTL32_DEFAULT(TIOCSWINSZ),
775	IOCTL32_DEFAULT(TIOCGWINSZ),
776	IOCTL32_DEFAULT(TIOCMGET),
777	IOCTL32_DEFAULT(TIOCMBIC),
778	IOCTL32_DEFAULT(TIOCMBIS),
779	IOCTL32_DEFAULT(TIOCMSET),
780	IOCTL32_DEFAULT(TIOCPKT),
781	IOCTL32_DEFAULT(TIOCNOTTY),
782	IOCTL32_DEFAULT(TIOCSTI),
783	IOCTL32_DEFAULT(TIOCOUTQ),
784	IOCTL32_DEFAULT(TIOCSPGRP),
785	IOCTL32_DEFAULT(TIOCGPGRP),
786	IOCTL32_DEFAULT(TIOCSCTTY),
787	IOCTL32_DEFAULT(TIOCGPTN),
788	IOCTL32_DEFAULT(TIOCSPTLCK),
789	IOCTL32_DEFAULT(TIOCGSERIAL),
790	IOCTL32_DEFAULT(TIOCSSERIAL),
791	IOCTL32_DEFAULT(TIOCSERGETLSR),
792
793	IOCTL32_DEFAULT(FIOCLEX),
794	IOCTL32_DEFAULT(FIONCLEX),
795	IOCTL32_DEFAULT(FIOASYNC),
796	IOCTL32_DEFAULT(FIONBIO),
797	IOCTL32_DEFAULT(FIONREAD),
798
799#ifdef CONFIG_FB
800	/* Big F */
801	IOCTL32_DEFAULT(FBIOGET_VSCREENINFO),
802	IOCTL32_DEFAULT(FBIOPUT_VSCREENINFO),
803	IOCTL32_HANDLER(FBIOGET_FSCREENINFO, do_fbioget_fscreeninfo_ioctl),
804	IOCTL32_HANDLER(FBIOGETCMAP, do_fbiocmap_ioctl),
805	IOCTL32_HANDLER(FBIOPUTCMAP, do_fbiocmap_ioctl),
806	IOCTL32_DEFAULT(FBIOPAN_DISPLAY),
807#endif /* CONFIG_FB */
808
809	/* Big K */
810	IOCTL32_DEFAULT(PIO_FONT),
811	IOCTL32_DEFAULT(GIO_FONT),
812	IOCTL32_DEFAULT(KDSIGACCEPT),
813	IOCTL32_DEFAULT(KDGETKEYCODE),
814	IOCTL32_DEFAULT(KDSETKEYCODE),
815	IOCTL32_DEFAULT(KIOCSOUND),
816	IOCTL32_DEFAULT(KDMKTONE),
817	IOCTL32_DEFAULT(KDGKBTYPE),
818	IOCTL32_DEFAULT(KDSETMODE),
819	IOCTL32_DEFAULT(KDGETMODE),
820	IOCTL32_DEFAULT(KDSKBMODE),
821	IOCTL32_DEFAULT(KDGKBMODE),
822	IOCTL32_DEFAULT(KDSKBMETA),
823	IOCTL32_DEFAULT(KDGKBMETA),
824	IOCTL32_DEFAULT(KDGKBENT),
825	IOCTL32_DEFAULT(KDSKBENT),
826	IOCTL32_DEFAULT(KDGKBSENT),
827	IOCTL32_DEFAULT(KDSKBSENT),
828	IOCTL32_DEFAULT(KDGKBDIACR),
829	IOCTL32_DEFAULT(KDSKBDIACR),
830	IOCTL32_DEFAULT(KDKBDREP),
831	IOCTL32_DEFAULT(KDGKBLED),
832	IOCTL32_DEFAULT(KDSKBLED),
833	IOCTL32_DEFAULT(KDGETLED),
834	IOCTL32_DEFAULT(KDSETLED),
835	IOCTL32_DEFAULT(GIO_SCRNMAP),
836	IOCTL32_DEFAULT(PIO_SCRNMAP),
837	IOCTL32_DEFAULT(GIO_UNISCRNMAP),
838	IOCTL32_DEFAULT(PIO_UNISCRNMAP),
839	IOCTL32_DEFAULT(PIO_FONTRESET),
840	IOCTL32_DEFAULT(PIO_UNIMAPCLR),
841
842	/* Big S */
843	IOCTL32_DEFAULT(SCSI_IOCTL_GET_IDLUN),
844	IOCTL32_DEFAULT(SCSI_IOCTL_DOORLOCK),
845	IOCTL32_DEFAULT(SCSI_IOCTL_DOORUNLOCK),
846	IOCTL32_DEFAULT(SCSI_IOCTL_TEST_UNIT_READY),
847	IOCTL32_DEFAULT(SCSI_IOCTL_TAGGED_ENABLE),
848	IOCTL32_DEFAULT(SCSI_IOCTL_TAGGED_DISABLE),
849	IOCTL32_DEFAULT(SCSI_IOCTL_GET_BUS_NUMBER),
850	IOCTL32_DEFAULT(SCSI_IOCTL_SEND_COMMAND),
851
852	/* Big V */
853	IOCTL32_DEFAULT(VT_SETMODE),
854	IOCTL32_DEFAULT(VT_GETMODE),
855	IOCTL32_DEFAULT(VT_GETSTATE),
856	IOCTL32_DEFAULT(VT_OPENQRY),
857	IOCTL32_DEFAULT(VT_ACTIVATE),
858	IOCTL32_DEFAULT(VT_WAITACTIVE),
859	IOCTL32_DEFAULT(VT_RELDISP),
860	IOCTL32_DEFAULT(VT_DISALLOCATE),
861	IOCTL32_DEFAULT(VT_RESIZE),
862	IOCTL32_DEFAULT(VT_RESIZEX),
863	IOCTL32_DEFAULT(VT_LOCKSWITCH),
864	IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
865
866#ifdef CONFIG_NET
867	/* Socket level stuff */
868	IOCTL32_DEFAULT(FIOSETOWN),
869	IOCTL32_DEFAULT(SIOCSPGRP),
870	IOCTL32_DEFAULT(FIOGETOWN),
871	IOCTL32_DEFAULT(SIOCGPGRP),
872	IOCTL32_DEFAULT(SIOCATMARK),
873	IOCTL32_DEFAULT(SIOCSIFLINK),
874	IOCTL32_DEFAULT(SIOCSIFENCAP),
875	IOCTL32_DEFAULT(SIOCGIFENCAP),
876	IOCTL32_DEFAULT(SIOCSIFBR),
877	IOCTL32_DEFAULT(SIOCGIFBR),
878	IOCTL32_DEFAULT(SIOCSARP),
879	IOCTL32_DEFAULT(SIOCGARP),
880	IOCTL32_DEFAULT(SIOCDARP),
881	IOCTL32_DEFAULT(SIOCSRARP),
882	IOCTL32_DEFAULT(SIOCGRARP),
883	IOCTL32_DEFAULT(SIOCDRARP),
884	IOCTL32_DEFAULT(SIOCADDDLCI),
885	IOCTL32_DEFAULT(SIOCDELDLCI),
886	/* SG stuff */
887	IOCTL32_DEFAULT(SG_SET_TIMEOUT),
888	IOCTL32_DEFAULT(SG_GET_TIMEOUT),
889	IOCTL32_DEFAULT(SG_EMULATED_HOST),
890	IOCTL32_DEFAULT(SG_SET_TRANSFORM),
891	IOCTL32_DEFAULT(SG_GET_TRANSFORM),
892	IOCTL32_DEFAULT(SG_SET_RESERVED_SIZE),
893	IOCTL32_DEFAULT(SG_GET_RESERVED_SIZE),
894	IOCTL32_DEFAULT(SG_GET_SCSI_ID),
895	IOCTL32_DEFAULT(SG_SET_FORCE_LOW_DMA),
896	IOCTL32_DEFAULT(SG_GET_LOW_DMA),
897	IOCTL32_DEFAULT(SG_SET_FORCE_PACK_ID),
898	IOCTL32_DEFAULT(SG_GET_PACK_ID),
899	IOCTL32_DEFAULT(SG_GET_NUM_WAITING),
900	IOCTL32_DEFAULT(SG_SET_DEBUG),
901	IOCTL32_DEFAULT(SG_GET_SG_TABLESIZE),
902	IOCTL32_DEFAULT(SG_GET_COMMAND_Q),
903	IOCTL32_DEFAULT(SG_SET_COMMAND_Q),
904	IOCTL32_DEFAULT(SG_GET_VERSION_NUM),
905	IOCTL32_DEFAULT(SG_NEXT_CMD_LEN),
906	IOCTL32_DEFAULT(SG_SCSI_RESET),
907	IOCTL32_DEFAULT(SG_IO),
908	IOCTL32_DEFAULT(SG_GET_REQUEST_TABLE),
909	IOCTL32_DEFAULT(SG_SET_KEEP_ORPHAN),
910	IOCTL32_DEFAULT(SG_GET_KEEP_ORPHAN),
911	/* PPP stuff */
912	IOCTL32_DEFAULT(PPPIOCGFLAGS),
913	IOCTL32_DEFAULT(PPPIOCSFLAGS),
914	IOCTL32_DEFAULT(PPPIOCGASYNCMAP),
915	IOCTL32_DEFAULT(PPPIOCSASYNCMAP),
916	IOCTL32_DEFAULT(PPPIOCGUNIT),
917	IOCTL32_DEFAULT(PPPIOCGRASYNCMAP),
918	IOCTL32_DEFAULT(PPPIOCSRASYNCMAP),
919	IOCTL32_DEFAULT(PPPIOCGMRU),
920	IOCTL32_DEFAULT(PPPIOCSMRU),
921	IOCTL32_DEFAULT(PPPIOCSMAXCID),
922	IOCTL32_DEFAULT(PPPIOCGXASYNCMAP),
923	IOCTL32_DEFAULT(PPPIOCSXASYNCMAP),
924	IOCTL32_DEFAULT(PPPIOCXFERUNIT),
925	IOCTL32_DEFAULT(PPPIOCGNPMODE),
926	IOCTL32_DEFAULT(PPPIOCSNPMODE),
927	IOCTL32_DEFAULT(PPPIOCGDEBUG),
928	IOCTL32_DEFAULT(PPPIOCSDEBUG),
929	IOCTL32_DEFAULT(PPPIOCNEWUNIT),
930	IOCTL32_DEFAULT(PPPIOCATTACH),
931	IOCTL32_DEFAULT(PPPIOCGCHAN),
932	/* PPPOX */
933	IOCTL32_DEFAULT(PPPOEIOCSFWD),
934	IOCTL32_DEFAULT(PPPOEIOCDFWD),
935	/* CDROM stuff */
936	IOCTL32_DEFAULT(CDROMPAUSE),
937	IOCTL32_DEFAULT(CDROMRESUME),
938	IOCTL32_DEFAULT(CDROMPLAYMSF),
939	IOCTL32_DEFAULT(CDROMPLAYTRKIND),
940	IOCTL32_DEFAULT(CDROMREADTOCHDR),
941	IOCTL32_DEFAULT(CDROMREADTOCENTRY),
942	IOCTL32_DEFAULT(CDROMSTOP),
943	IOCTL32_DEFAULT(CDROMSTART),
944	IOCTL32_DEFAULT(CDROMEJECT),
945	IOCTL32_DEFAULT(CDROMVOLCTRL),
946	IOCTL32_DEFAULT(CDROMSUBCHNL),
947	IOCTL32_DEFAULT(CDROMEJECT_SW),
948	IOCTL32_DEFAULT(CDROMMULTISESSION),
949	IOCTL32_DEFAULT(CDROM_GET_MCN),
950	IOCTL32_DEFAULT(CDROMRESET),
951	IOCTL32_DEFAULT(CDROMVOLREAD),
952	IOCTL32_DEFAULT(CDROMSEEK),
953	IOCTL32_DEFAULT(CDROMPLAYBLK),
954	IOCTL32_DEFAULT(CDROMCLOSETRAY),
955	IOCTL32_DEFAULT(CDROM_SET_OPTIONS),
956	IOCTL32_DEFAULT(CDROM_CLEAR_OPTIONS),
957	IOCTL32_DEFAULT(CDROM_SELECT_SPEED),
958	IOCTL32_DEFAULT(CDROM_SELECT_DISC),
959	IOCTL32_DEFAULT(CDROM_MEDIA_CHANGED),
960	IOCTL32_DEFAULT(CDROM_DRIVE_STATUS),
961	IOCTL32_DEFAULT(CDROM_DISC_STATUS),
962	IOCTL32_DEFAULT(CDROM_CHANGER_NSLOTS),
963	IOCTL32_DEFAULT(CDROM_LOCKDOOR),
964	IOCTL32_DEFAULT(CDROM_DEBUG),
965	IOCTL32_DEFAULT(CDROM_GET_CAPABILITY),
966	/* DVD ioctls */
967	IOCTL32_DEFAULT(DVD_READ_STRUCT),
968	IOCTL32_DEFAULT(DVD_WRITE_STRUCT),
969	IOCTL32_DEFAULT(DVD_AUTH),
970	/* Big L */
971	IOCTL32_DEFAULT(LOOP_SET_FD),
972	IOCTL32_DEFAULT(LOOP_CLR_FD),
973
974	/* And these ioctls need translation */
975	IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
976	IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
977	IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
978	IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc),
979	IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc),
980	IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc),
981	IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc),
982	IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc),
983	IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc),
984	IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc),
985	IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc),
986	IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc),
987	IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc),
988	IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc),
989	IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc),
990	IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc),
991	IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc),
992	IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc),
993	IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc),
994	IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc),
995	IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc),
996	IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc),
997	IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc),
998	IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc),
999	IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc),
1000	IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc),
1001	IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc),
1002	IOCTL32_HANDLER(SIOCGPPPSTATS, dev_ifsioc),
1003	IOCTL32_HANDLER(SIOCGPPPCSTATS, dev_ifsioc),
1004	IOCTL32_HANDLER(SIOCGPPPVER, dev_ifsioc),
1005	IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc),
1006	IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc),
1007	IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
1008	IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
1009	/*
1010	 * Note SIOCRTMSG is no longer, so this is safe and * the user would
1011	 * have seen just an -EINVAL anyways.
1012	 */
1013	IOCTL32_HANDLER(SIOCRTMSG, ret_einval),
1014	IOCTL32_HANDLER(SIOCGSTAMP, do_siocgstamp),
1015
1016#endif /* CONFIG_NET */
1017
1018	IOCTL32_DEFAULT(PROF_START),
1019	IOCTL32_DEFAULT(PROF_STOP),
1020	IOCTL32_DEFAULT(PROF_RESET),
1021	IOCTL32_DEFAULT(PROF_SET_SAMPLE_FREQ),
1022	IOCTL32_DEFAULT(PROF_GET_SAMPLE_FREQ),
1023	IOCTL32_DEFAULT(PROF_GET_PC_RES),
1024	IOCTL32_DEFAULT(PROF_GET_ON_OFF_STATE),
1025	IOCTL32_DEFAULT(PROF_SET_DOMAIN),
1026	IOCTL32_DEFAULT(PROF_GET_DOMAIN),
1027	IOCTL32_DEFAULT(PROF_SET_MODE),
1028	IOCTL32_DEFAULT(PROF_GET_MODE),
1029	IOCTL32_DEFAULT(PROF_SET_PERFCTR_EVENT),
1030	IOCTL32_DEFAULT(PROF_GET_PERFCTR_EVENT),
1031	IOCTL32_DEFAULT(PROF_SET_ENABLE_MAP),
1032	IOCTL32_DEFAULT(PROF_GET_ENABLE_MAP),
1033	IOCTL32_DEFAULT(PROF_SET_PID),
1034	IOCTL32_DEFAULT(PROF_GET_PID),
1035
1036	IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
1037	IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
1038	IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
1039	IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
1040
1041	IOCTL32_HANDLER(HDIO_GETGEO, hdio_getgeo),	/* hdreg.h ioctls  */
1042	IOCTL32_HANDLER(HDIO_GET_UNMASKINTR, hdio_ioctl_trans),
1043	IOCTL32_HANDLER(HDIO_GET_MULTCOUNT, hdio_ioctl_trans),
1044	// HDIO_OBSOLETE_IDENTITY
1045	IOCTL32_HANDLER(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans),
1046	IOCTL32_HANDLER(HDIO_GET_32BIT, hdio_ioctl_trans),
1047	IOCTL32_HANDLER(HDIO_GET_NOWERR, hdio_ioctl_trans),
1048	IOCTL32_HANDLER(HDIO_GET_DMA, hdio_ioctl_trans),
1049	IOCTL32_HANDLER(HDIO_GET_NICE, hdio_ioctl_trans),
1050	IOCTL32_DEFAULT(HDIO_GET_IDENTITY),
1051	IOCTL32_DEFAULT(HDIO_DRIVE_RESET),
1052	// HDIO_TRISTATE_HWIF				/* not implemented */
1053	// HDIO_DRIVE_TASK				/* To do, need specs */
1054	IOCTL32_DEFAULT(HDIO_DRIVE_CMD),
1055	IOCTL32_DEFAULT(HDIO_SET_MULTCOUNT),
1056	IOCTL32_DEFAULT(HDIO_SET_UNMASKINTR),
1057	IOCTL32_DEFAULT(HDIO_SET_KEEPSETTINGS),
1058	IOCTL32_DEFAULT(HDIO_SET_32BIT),
1059	IOCTL32_DEFAULT(HDIO_SET_NOWERR),
1060	IOCTL32_DEFAULT(HDIO_SET_DMA),
1061	IOCTL32_DEFAULT(HDIO_SET_PIO_MODE),
1062	IOCTL32_DEFAULT(HDIO_SCAN_HWIF),
1063	IOCTL32_DEFAULT(HDIO_SET_NICE),
1064	//HDIO_UNREGISTER_HWIF
1065
1066	IOCTL32_DEFAULT(BLKROSET),			/* fs.h ioctls  */
1067	IOCTL32_DEFAULT(BLKROGET),
1068	IOCTL32_DEFAULT(BLKRRPART),
1069	IOCTL32_HANDLER(BLKGETSIZE, w_long),
1070
1071	IOCTL32_DEFAULT(BLKFLSBUF),
1072	IOCTL32_DEFAULT(BLKRASET),
1073	IOCTL32_HANDLER(BLKRAGET, w_long),
1074	IOCTL32_DEFAULT(BLKFRASET),
1075	IOCTL32_HANDLER(BLKFRAGET, w_long),
1076	IOCTL32_DEFAULT(BLKSECTSET),
1077	IOCTL32_HANDLER(BLKSECTGET, w_long),
1078	IOCTL32_DEFAULT(BLKSSZGET),
1079	IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans),
1080	IOCTL32_DEFAULT(BLKELVGET),
1081	IOCTL32_DEFAULT(BLKELVSET),
1082	IOCTL32_DEFAULT(BLKBSZGET),
1083	IOCTL32_DEFAULT(BLKBSZSET),
1084
1085#ifdef CONFIG_MD
1086	/* status */
1087	IOCTL32_DEFAULT(RAID_VERSION),
1088	IOCTL32_DEFAULT(GET_ARRAY_INFO),
1089	IOCTL32_DEFAULT(GET_DISK_INFO),
1090	IOCTL32_DEFAULT(PRINT_RAID_DEBUG),
1091	IOCTL32_DEFAULT(RAID_AUTORUN),
1092
1093	/* configuration */
1094	IOCTL32_DEFAULT(CLEAR_ARRAY),
1095	IOCTL32_DEFAULT(ADD_NEW_DISK),
1096	IOCTL32_DEFAULT(HOT_REMOVE_DISK),
1097	IOCTL32_DEFAULT(SET_ARRAY_INFO),
1098	IOCTL32_DEFAULT(SET_DISK_INFO),
1099	IOCTL32_DEFAULT(WRITE_RAID_INFO),
1100	IOCTL32_DEFAULT(UNPROTECT_ARRAY),
1101	IOCTL32_DEFAULT(PROTECT_ARRAY),
1102	IOCTL32_DEFAULT(HOT_ADD_DISK),
1103	IOCTL32_DEFAULT(SET_DISK_FAULTY),
1104
1105	/* usage */
1106	IOCTL32_DEFAULT(RUN_ARRAY),
1107	IOCTL32_DEFAULT(START_ARRAY),
1108	IOCTL32_DEFAULT(STOP_ARRAY),
1109	IOCTL32_DEFAULT(STOP_ARRAY_RO),
1110	IOCTL32_DEFAULT(RESTART_ARRAY_RW),
1111#endif /* CONFIG_MD */
1112
1113	IOCTL32_DEFAULT(MTIOCTOP),			/* mtio.h ioctls  */
1114	IOCTL32_HANDLER(MTIOCGET32, mt_ioctl_trans),
1115	IOCTL32_HANDLER(MTIOCPOS32, mt_ioctl_trans),
1116	IOCTL32_HANDLER(MTIOCGETCONFIG32, mt_ioctl_trans),
1117	IOCTL32_HANDLER(MTIOCSETCONFIG32, mt_ioctl_trans),
1118	// MTIOCRDFTSEG
1119	// MTIOCWRFTSEG
1120	// MTIOCVOLINFO
1121	// MTIOCGETSIZE
1122	// MTIOCFTFORMAT
1123	// MTIOCFTCMD
1124
1125	IOCTL32_DEFAULT(AUTOFS_IOC_READY),		/* auto_fs.h ioctls */
1126	IOCTL32_DEFAULT(AUTOFS_IOC_FAIL),
1127	IOCTL32_DEFAULT(AUTOFS_IOC_CATATONIC),
1128	IOCTL32_DEFAULT(AUTOFS_IOC_PROTOVER),
1129	IOCTL32_HANDLER(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout),
1130	IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE),
1131	IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE_MULTI),
1132
1133	/* Little p (/dev/rtc, /dev/envctrl, etc.) */
1134	IOCTL32_DEFAULT(_IOR('p', 20, int[7])), /* RTCGET */
1135	IOCTL32_DEFAULT(_IOW('p', 21, int[7])), /* RTCSET */
1136	IOCTL32_DEFAULT(RTC_AIE_ON),
1137	IOCTL32_DEFAULT(RTC_AIE_OFF),
1138	IOCTL32_DEFAULT(RTC_UIE_ON),
1139	IOCTL32_DEFAULT(RTC_UIE_OFF),
1140	IOCTL32_DEFAULT(RTC_PIE_ON),
1141	IOCTL32_DEFAULT(RTC_PIE_OFF),
1142	IOCTL32_DEFAULT(RTC_WIE_ON),
1143	IOCTL32_DEFAULT(RTC_WIE_OFF),
1144	IOCTL32_DEFAULT(RTC_ALM_SET),
1145	IOCTL32_DEFAULT(RTC_ALM_READ),
1146	IOCTL32_DEFAULT(RTC_RD_TIME),
1147	IOCTL32_DEFAULT(RTC_SET_TIME),
1148	IOCTL32_DEFAULT(RTC_WKALM_SET),
1149	IOCTL32_DEFAULT(RTC_WKALM_RD)
1150};
1151
1152#define NR_IOCTL32_HANDLERS	(sizeof(ioctl32_handler_table) /	\
1153				 sizeof(ioctl32_handler_table[0]))
1154
1155static struct ioctl32_list *ioctl32_hash_table[1024];
1156
1157static inline int ioctl32_hash(unsigned int cmd)
1158{
1159	return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
1160}
1161
1162int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg)
1163{
1164	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
1165	struct file *filp;
1166	struct ioctl32_list *l;
1167	int error;
1168
1169	l = ioctl32_hash_table[ioctl32_hash(cmd)];
1170
1171	error = -EBADF;
1172
1173	filp = fget(fd);
1174	if (!filp)
1175		return error;
1176
1177	if (!filp->f_op || !filp->f_op->ioctl) {
1178		error = sys_ioctl (fd, cmd, arg);
1179		goto out;
1180	}
1181
1182	while (l && l->handler.cmd != cmd)
1183		l = l->next;
1184
1185	if (l) {
1186		handler = (void *)l->handler.function;
1187		error = handler(fd, cmd, arg, filp);
1188	} else {
1189		error = -EINVAL;
1190		printk("unknown ioctl: %08x\n", cmd);
1191	}
1192out:
1193	fput(filp);
1194	return error;
1195}
1196
1197static void ioctl32_insert(struct ioctl32_list *entry)
1198{
1199	int hash = ioctl32_hash(entry->handler.cmd);
1200	if (!ioctl32_hash_table[hash])
1201		ioctl32_hash_table[hash] = entry;
1202	else {
1203		struct ioctl32_list *l;
1204		l = ioctl32_hash_table[hash];
1205		while (l->next)
1206			l = l->next;
1207		l->next = entry;
1208		entry->next = 0;
1209	}
1210}
1211
1212static int __init init_ioctl32(void)
1213{
1214	int i;
1215	for (i = 0; i < NR_IOCTL32_HANDLERS; i++)
1216		ioctl32_insert(&ioctl32_handler_table[i]);
1217	return 0;
1218}
1219
1220__initcall(init_ioctl32);
1221