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