ioctl32.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:24k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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