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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: ioctl.c,v 1.16 2000/11/18 02:10:59 davem Exp $
  2.  * ioctl.c: Solaris ioctl emulation.
  3.  *
  4.  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  5.  * Copyright (C) 1997,1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
  6.  *
  7.  * Streams & timod emulation based on code
  8.  * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
  9.  *
  10.  * 1999-08-19 Implemented solaris 'm' (mag tape) and
  11.  *            'O' (openprom) ioctls, by Jason Rappleye
  12.  *             (rappleye@ccr.buffalo.edu)
  13.  */
  14. #include <linux/types.h>
  15. #include <linux/kernel.h>
  16. #include <linux/sched.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/ioctl.h>
  20. #include <linux/fs.h>
  21. #include <linux/file.h>
  22. #include <linux/netdevice.h>
  23. #include <linux/mtio.h>
  24. #include <linux/time.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/termios.h>
  27. #include <asm/openpromio.h>
  28. #include "conv.h"
  29. #include "socksys.h"
  30. extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, 
  31. unsigned long arg);
  32. extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
  33. u32 arg);
  34. asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
  35. extern int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len,
  36. char *data_buf, int data_len, int flags);
  37. extern int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, int *ctl_len,
  38. char *data_buf, int data_maxlen, int *data_len, int *flags);
  39. /* termio* stuff {{{ */
  40. struct solaris_termios {
  41. u32 c_iflag;
  42. u32 c_oflag;
  43. u32 c_cflag;
  44. u32 c_lflag;
  45. u8 c_cc[19];
  46. };
  47. struct solaris_termio {
  48. u16 c_iflag;
  49. u16 c_oflag;
  50. u16 c_cflag;
  51. u16 c_lflag;
  52. s8 c_line;
  53. u8 c_cc[8];
  54. };
  55. struct solaris_termiox {
  56. u16 x_hflag;
  57. u16 x_cflag;
  58. u16 x_rflag[5];
  59. u16 x_sflag;
  60. };
  61. static u32 solaris_to_linux_cflag(u32 cflag)
  62. {
  63. cflag &= 0x7fdff000;
  64. if (cflag & 0x200000) {
  65. int baud = cflag & 0xf;
  66. cflag &= ~0x20000f;
  67. switch (baud) {
  68. case 0: baud = B57600; break;
  69. case 1: baud = B76800; break;
  70. case 2: baud = B115200; break;
  71. case 3: baud = B153600; break;
  72. case 4: baud = B230400; break;
  73. case 5: baud = B307200; break;
  74. case 6: baud = B460800; break;
  75. }
  76. cflag |= CBAUDEX | baud;
  77. }
  78. return cflag;
  79. }
  80. static u32 linux_to_solaris_cflag(u32 cflag)
  81. {
  82. cflag &= ~(CMSPAR | CIBAUD);
  83. if (cflag & CBAUDEX) {
  84. int baud = cflag & CBAUD;
  85. cflag &= ~CBAUD;
  86. switch (baud) {
  87. case B57600: baud = 0; break;
  88. case B76800: baud = 1; break;
  89. case B115200: baud = 2; break;
  90. case B153600: baud = 3; break;
  91. case B230400: baud = 4; break;
  92. case B307200: baud = 5; break;
  93. case B460800: baud = 6; break;
  94. case B614400: baud = 7; break;
  95. case B921600: baud = 8; break;
  96. #if 0
  97. case B1843200: baud = 9; break;
  98. #endif
  99. }
  100. cflag |= 0x200000 | baud;
  101. }
  102. return cflag;
  103. }
  104. static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg)
  105. {
  106. int ret;
  107. ret = sys_ioctl(fd, cmd, A(arg));
  108. if (!ret) {
  109. u32 cflag;
  110. if (__get_user (cflag, &((struct solaris_termio *)A(arg))->c_cflag))
  111. return -EFAULT;
  112. cflag = linux_to_solaris_cflag(cflag);
  113. if (__put_user (cflag, &((struct solaris_termio *)A(arg))->c_cflag))
  114. return -EFAULT;
  115. }
  116. return ret;
  117. }
  118. static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg)
  119. {
  120. int ret;
  121. struct solaris_termio s;
  122. mm_segment_t old_fs = get_fs();
  123. if (copy_from_user (&s, (struct solaris_termio *)A(arg), sizeof(struct solaris_termio)))
  124. return -EFAULT;
  125. s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
  126. set_fs(KERNEL_DS);
  127. ret = sys_ioctl(fd, cmd, (unsigned long)&s);
  128. set_fs(old_fs);
  129. return ret;
  130. }
  131. static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg)
  132. {
  133. int ret;
  134. struct solaris_termios s;
  135. mm_segment_t old_fs = get_fs();
  136. set_fs(KERNEL_DS);
  137. ret = sys_ioctl(fd, cmd, (unsigned long)&s);
  138. set_fs(old_fs);
  139. if (!ret) {
  140. if (put_user (s.c_iflag, &((struct solaris_termios *)A(arg))->c_iflag) ||
  141.     __put_user (s.c_oflag, &((struct solaris_termios *)A(arg))->c_oflag) ||
  142.     __put_user (linux_to_solaris_cflag(s.c_cflag), &((struct solaris_termios *)A(arg))->c_cflag) ||
  143.     __put_user (s.c_lflag, &((struct solaris_termios *)A(arg))->c_lflag) ||
  144.     __copy_to_user (((struct solaris_termios *)A(arg))->c_cc, s.c_cc, 16) ||
  145.     __clear_user (((struct solaris_termios *)A(arg))->c_cc + 16, 2))
  146. return -EFAULT;
  147. }
  148. return ret;
  149. }
  150. static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg)
  151. {
  152. int ret;
  153. struct solaris_termios s;
  154. mm_segment_t old_fs = get_fs();
  155. set_fs(KERNEL_DS);
  156. ret = sys_ioctl(fd, TCGETS, (unsigned long)&s);
  157. set_fs(old_fs);
  158. if (ret) return ret;
  159. if (put_user (s.c_iflag, &((struct solaris_termios *)A(arg))->c_iflag) ||
  160.     __put_user (s.c_oflag, &((struct solaris_termios *)A(arg))->c_oflag) ||
  161.     __put_user (s.c_cflag, &((struct solaris_termios *)A(arg))->c_cflag) ||
  162.     __put_user (s.c_lflag, &((struct solaris_termios *)A(arg))->c_lflag) ||
  163.     __copy_from_user (s.c_cc, ((struct solaris_termios *)A(arg))->c_cc, 16))
  164. return -EFAULT;
  165. s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
  166. set_fs(KERNEL_DS);
  167. ret = sys_ioctl(fd, cmd, (unsigned long)&s);
  168. set_fs(old_fs);
  169. return ret;
  170. }
  171. static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg)
  172. {
  173. switch (cmd & 0xff) {
  174. case 1: /* TCGETA */
  175. return linux_to_solaris_termio(fd, TCGETA, arg);
  176. case 2: /* TCSETA */
  177. return solaris_to_linux_termio(fd, TCSETA, arg);
  178. case 3: /* TCSETAW */
  179. return solaris_to_linux_termio(fd, TCSETAW, arg);
  180. case 4: /* TCSETAF */
  181. return solaris_to_linux_termio(fd, TCSETAF, arg);
  182. case 5: /* TCSBRK */
  183. return sys_ioctl(fd, TCSBRK, arg);
  184. case 6: /* TCXONC */
  185. return sys_ioctl(fd, TCXONC, arg);
  186. case 7: /* TCFLSH */
  187. return sys_ioctl(fd, TCFLSH, arg);
  188. case 13: /* TCGETS */
  189. return linux_to_solaris_termios(fd, TCGETS, arg);
  190. case 14: /* TCSETS */
  191. return solaris_to_linux_termios(fd, TCSETS, arg);
  192. case 15: /* TCSETSW */
  193. return solaris_to_linux_termios(fd, TCSETSW, arg);
  194. case 16: /* TCSETSF */
  195. return solaris_to_linux_termios(fd, TCSETSF, arg);
  196. case 103: /* TIOCSWINSZ */
  197. return sys_ioctl(fd, TIOCSWINSZ, arg);
  198. case 104: /* TIOCGWINSZ */
  199. return sys_ioctl(fd, TIOCGWINSZ, arg);
  200. }
  201. return -ENOSYS;
  202. }
  203. static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg)
  204. {
  205. switch (cmd & 0xff) {
  206. case 20: /* TIOCGPGRP */
  207. return sys_ioctl(fd, TIOCGPGRP, arg);
  208. case 21: /* TIOCSPGRP */
  209. return sys_ioctl(fd, TIOCSPGRP, arg);
  210. }
  211. return -ENOSYS;
  212. }
  213. /* }}} */
  214. /* A pseudo STREAMS support {{{ */
  215. struct strioctl {
  216. int cmd, timeout, len;
  217. u32 data;
  218. };
  219. struct solaris_si_sockparams {
  220. int sp_family;
  221. int sp_type;
  222. int sp_protocol;
  223. };
  224. struct solaris_o_si_udata {
  225. int tidusize;
  226. int addrsize;
  227. int optsize;
  228. int etsdusize;
  229. int servtype;
  230. int so_state;
  231. int so_options;
  232. int tsdusize;
  233. };
  234. struct solaris_si_udata {
  235. int tidusize;
  236. int addrsize;
  237. int optsize;
  238. int etsdusize;
  239. int servtype;
  240. int so_state;
  241. int so_options;
  242. int tsdusize;
  243. struct solaris_si_sockparams sockparams;
  244. };
  245. #define SOLARIS_MODULE_TIMOD    0
  246. #define SOLARIS_MODULE_SOCKMOD  1
  247. #define SOLARIS_MODULE_MAX      2
  248. static struct module_info {
  249.         const char *name;
  250.         /* can be expanded further if needed */
  251. } module_table[ SOLARIS_MODULE_MAX + 1 ] = {
  252.         /* the ordering here must match the module numbers above! */
  253.         { "timod" },
  254.         { "sockmod" },
  255.         { NULL }
  256. };
  257. static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
  258. {
  259. struct inode *ino;
  260. /* I wonder which of these tests are superfluous... --patrik */
  261. if (! current->files->fd[fd] ||
  262.     ! current->files->fd[fd]->f_dentry ||
  263.     ! (ino = current->files->fd[fd]->f_dentry->d_inode) ||
  264.     ! ino->i_sock)
  265. return TBADF;
  266. switch (cmd & 0xff) {
  267. case 109: /* SI_SOCKPARAMS */
  268. {
  269. struct solaris_si_sockparams si;
  270. if (copy_from_user (&si, (struct solaris_si_sockparams *) A(arg), sizeof(si)))
  271. return (EFAULT << 8) | TSYSERR;
  272. /* Should we modify socket ino->socket_i.ops and type? */
  273. return 0;
  274. }
  275. case 110: /* SI_GETUDATA */
  276. {
  277. int etsdusize, servtype;
  278. switch (ino->u.socket_i.type) {
  279. case SOCK_STREAM:
  280. etsdusize = 1;
  281. servtype = 2;
  282. break;
  283. default:
  284. etsdusize = -2;
  285. servtype = 3;
  286. break;
  287. }
  288. if (put_user(16384, &((struct solaris_si_udata *)A(arg))->tidusize) ||
  289.     __put_user(sizeof(struct sockaddr), &((struct solaris_si_udata *)A(arg))->addrsize) ||
  290.     __put_user(-1, &((struct solaris_si_udata *)A(arg))->optsize) ||
  291.     __put_user(etsdusize, &((struct solaris_si_udata *)A(arg))->etsdusize) ||
  292.     __put_user(servtype, &((struct solaris_si_udata *)A(arg))->servtype) ||
  293.     __put_user(0, &((struct solaris_si_udata *)A(arg))->so_state) ||
  294.     __put_user(0, &((struct solaris_si_udata *)A(arg))->so_options) ||
  295.     __put_user(16384, &((struct solaris_si_udata *)A(arg))->tsdusize) ||
  296.     __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_family) ||
  297.     __put_user(ino->u.socket_i.type, &((struct solaris_si_udata *)A(arg))->sockparams.sp_type) ||
  298.     __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_protocol))
  299. return (EFAULT << 8) | TSYSERR;
  300. return 0;
  301. }
  302. case 101: /* O_SI_GETUDATA */
  303. {
  304. int etsdusize, servtype;
  305. switch (ino->u.socket_i.type) {
  306. case SOCK_STREAM:
  307. etsdusize = 1;
  308. servtype = 2;
  309. break;
  310. default:
  311. etsdusize = -2;
  312. servtype = 3;
  313. break;
  314. }
  315. if (put_user(16384, &((struct solaris_o_si_udata *)A(arg))->tidusize) ||
  316.     __put_user(sizeof(struct sockaddr), &((struct solaris_o_si_udata *)A(arg))->addrsize) ||
  317.     __put_user(-1, &((struct solaris_o_si_udata *)A(arg))->optsize) ||
  318.     __put_user(etsdusize, &((struct solaris_o_si_udata *)A(arg))->etsdusize) ||
  319.     __put_user(servtype, &((struct solaris_o_si_udata *)A(arg))->servtype) ||
  320.     __put_user(0, &((struct solaris_o_si_udata *)A(arg))->so_state) ||
  321.     __put_user(0, &((struct solaris_o_si_udata *)A(arg))->so_options) ||
  322.     __put_user(16384, &((struct solaris_o_si_udata *)A(arg))->tsdusize))
  323. return (EFAULT << 8) | TSYSERR;
  324. return 0;
  325. }
  326. case 102: /* SI_SHUTDOWN */
  327. case 103: /* SI_LISTEN */
  328. case 104: /* SI_SETMYNAME */
  329. case 105: /* SI_SETPEERNAME */
  330. case 106: /* SI_GETINTRANSIT */
  331. case 107: /* SI_TCL_LINK */
  332. case 108: /* SI_TCL_UNLINK */
  333. }
  334. return TNOTSUPPORT;
  335. }
  336. static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
  337.                                     int len, int *len_p)
  338. {
  339. int ret;
  340. switch (cmd & 0xff) {
  341. case 141: /* TI_OPTMGMT */
  342. {
  343. int i;
  344. u32 prim;
  345. SOLD("TI_OPMGMT entry");
  346. ret = timod_putmsg(fd, (char *)A(arg), len, NULL, -1, 0);
  347. SOLD("timod_putmsg() returned");
  348. if (ret)
  349. return (-ret << 8) | TSYSERR;
  350. i = MSG_HIPRI;
  351. SOLD("calling timod_getmsg()");
  352. ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
  353. SOLD("timod_getmsg() returned");
  354. if (ret)
  355. return (-ret << 8) | TSYSERR;
  356. SOLD("ret ok");
  357. if (get_user(prim, (u32 *)A(arg)))
  358. return (EFAULT << 8) | TSYSERR;
  359. SOLD("got prim");
  360. if (prim == T_ERROR_ACK) {
  361. u32 tmp, tmp2;
  362. SOLD("prim is T_ERROR_ACK");
  363. if (get_user(tmp, (u32 *)A(arg)+3) ||
  364.     get_user(tmp2, (u32 *)A(arg)+2))
  365. return (EFAULT << 8) | TSYSERR;
  366. return (tmp2 << 8) | tmp;
  367. }
  368. SOLD("TI_OPMGMT return 0");
  369. return 0;
  370. }
  371. case 142: /* TI_BIND */
  372. {
  373. int i;
  374. u32 prim;
  375. SOLD("TI_BIND entry");
  376. ret = timod_putmsg(fd, (char *)A(arg), len, NULL, -1, 0);
  377. SOLD("timod_putmsg() returned");
  378. if (ret)
  379. return (-ret << 8) | TSYSERR;
  380. len = 1024; /* Solaris allows arbitrary return size */
  381. i = MSG_HIPRI;
  382. SOLD("calling timod_getmsg()");
  383. ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
  384. SOLD("timod_getmsg() returned");
  385. if (ret)
  386. return (-ret << 8) | TSYSERR;
  387. SOLD("ret ok");
  388. if (get_user(prim, (u32 *)A(arg)))
  389. return (EFAULT << 8) | TSYSERR;
  390. SOLD("got prim");
  391. if (prim == T_ERROR_ACK) {
  392. u32 tmp, tmp2;
  393. SOLD("prim is T_ERROR_ACK");
  394. if (get_user(tmp, (u32 *)A(arg)+3) ||
  395.     get_user(tmp2, (u32 *)A(arg)+2))
  396. return (EFAULT << 8) | TSYSERR;
  397. return (tmp2 << 8) | tmp;
  398. }
  399. SOLD("no ERROR_ACK requested");
  400. if (prim != T_OK_ACK)
  401. return TBADSEQ;
  402. SOLD("OK_ACK requested");
  403. i = MSG_HIPRI;
  404. SOLD("calling timod_getmsg()");
  405. ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
  406. SOLD("timod_getmsg() returned");
  407. if (ret)
  408. return (-ret << 8) | TSYSERR;
  409. SOLD("TI_BIND return ok");
  410. return 0;
  411. }
  412. case 140: /* TI_GETINFO */
  413. case 143: /* TI_UNBIND */
  414. case 144: /* TI_GETMYNAME */
  415. case 145: /* TI_GETPEERNAME */
  416. case 146: /* TI_SETMYNAME */
  417. case 147: /* TI_SETPEERNAME */
  418. }
  419. return TNOTSUPPORT;
  420. }
  421. static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg)
  422. {
  423. char *p;
  424. int ret;
  425. mm_segment_t old_fs;
  426. struct strioctl si;
  427. struct inode *ino;
  428.         struct sol_socket_struct *sock;
  429.         struct module_info *mi;
  430.         ino = filp->f_dentry->d_inode;
  431.         if (! ino->i_sock)
  432. return -EBADF;
  433.         sock = filp->private_data;
  434.         if (! sock) {
  435.                 printk("solaris_S: NULL private_datan");
  436.                 return -EBADF;
  437.         }
  438.         if (sock->magic != SOLARIS_SOCKET_MAGIC) {
  439.                 printk("solaris_S: invalid magicn");
  440.                 return -EBADF;
  441.         }
  442.         
  443. switch (cmd & 0xff) {
  444. case 1: /* I_NREAD */
  445. return -ENOSYS;
  446. case 2: /* I_PUSH */
  447.         {
  448. p = getname ((char *)A(arg));
  449. if (IS_ERR (p))
  450. return PTR_ERR(p);
  451.                 ret = -EINVAL;
  452.                 for (mi = module_table; mi->name; mi++) {
  453.                         if (strcmp(mi->name, p) == 0) {
  454.                                 sol_module m;
  455.                                 if (sock->modcount >= MAX_NR_STREAM_MODULES) {
  456.                                         ret = -ENXIO;
  457.                                         break;
  458.                                 }
  459.                                 m = (sol_module) (mi - module_table);
  460.                                 sock->module[sock->modcount++] = m;
  461.                                 ret = 0;
  462.                                 break;
  463.                         }
  464.                 }
  465. putname (p);
  466. return ret;
  467.         }
  468. case 3: /* I_POP */
  469.                 if (sock->modcount <= 0) return -EINVAL;
  470.                 sock->modcount--;
  471. return 0;
  472.         case 4: /* I_LOOK */
  473.         {
  474.          const char *p;
  475.                 if (sock->modcount <= 0) return -EINVAL;
  476.                 p = module_table[(unsigned)sock->module[sock->modcount]].name;
  477.                 if (copy_to_user ((char *)A(arg), p, strlen(p)))
  478.                  return -EFAULT;
  479.                 return 0;
  480.         }
  481. case 5: /* I_FLUSH */
  482. return 0;
  483. case 8: /* I_STR */
  484. if (copy_from_user(&si, (struct strioctl *)A(arg), sizeof(struct strioctl)))
  485. return -EFAULT;
  486.                 /* We ignore what module is actually at the top of stack. */
  487. switch ((si.cmd >> 8) & 0xff) {
  488. case 'I':
  489.                         return solaris_sockmod(fd, si.cmd, si.data);
  490. case 'T':
  491.                         return solaris_timod(fd, si.cmd, si.data, si.len,
  492.                                                 &((struct strioctl*)A(arg))->len);
  493. default:
  494. return solaris_ioctl(fd, si.cmd, si.data);
  495. }
  496. case 9: /* I_SETSIG */
  497. return sys_ioctl(fd, FIOSETOWN, current->pid);
  498. case 10: /* I_GETSIG */
  499. old_fs = get_fs();
  500. set_fs(KERNEL_DS);
  501. sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret);
  502. set_fs(old_fs);
  503. if (ret == current->pid) return 0x3ff;
  504. else return -EINVAL;
  505. case 11: /* I_FIND */
  506.         {
  507.                 int i;
  508. p = getname ((char *)A(arg));
  509. if (IS_ERR (p))
  510. return PTR_ERR(p);
  511.                 ret = 0;
  512.                 for (i = 0; i < sock->modcount; i++) {
  513.                         unsigned m = sock->module[i];
  514.                         if (strcmp(module_table[m].name, p) == 0) {
  515.                                 ret = 1;
  516.                                 break;
  517.                         } 
  518.                 }
  519. putname (p);
  520. return ret;
  521.         }
  522. case 19: /* I_SWROPT */
  523. case 32: /* I_SETCLTIME */
  524. return 0; /* Lie */
  525. }
  526. return -ENOSYS;
  527. }
  528. static inline int solaris_s(unsigned int fd, unsigned int cmd, u32 arg)
  529. {
  530. switch (cmd & 0xff) {
  531. case 0: /* SIOCSHIWAT */
  532. case 2: /* SIOCSLOWAT */
  533. return 0; /* We don't support them */
  534. case 1: /* SIOCGHIWAT */
  535. case 3: /* SIOCGLOWAT */
  536. if (put_user (0, (u32 *)A(arg)))
  537. return -EFAULT;
  538. return 0; /* Lie */
  539. case 7: /* SIOCATMARK */
  540. return sys_ioctl(fd, SIOCATMARK, arg);
  541. case 8: /* SIOCSPGRP */
  542. return sys_ioctl(fd, SIOCSPGRP, arg);
  543. case 9: /* SIOCGPGRP */
  544. return sys_ioctl(fd, SIOCGPGRP, arg);
  545. }
  546. return -ENOSYS;
  547. }
  548. static inline int solaris_r(unsigned int fd, unsigned int cmd, u32 arg)
  549. {
  550. switch (cmd & 0xff) {
  551. case 10: /* SIOCADDRT */
  552. return sys32_ioctl(fd, SIOCADDRT, arg);
  553. case 11: /* SIOCDELRT */
  554. return sys32_ioctl(fd, SIOCDELRT, arg);
  555. }
  556. return -ENOSYS;
  557. }
  558. static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
  559. {
  560. switch (cmd & 0xff) {
  561. case 12: /* SIOCSIFADDR */
  562. return sys32_ioctl(fd, SIOCSIFADDR, arg);
  563. case 13: /* SIOCGIFADDR */
  564. return sys32_ioctl(fd, SIOCGIFADDR, arg);
  565. case 14: /* SIOCSIFDSTADDR */
  566. return sys32_ioctl(fd, SIOCSIFDSTADDR, arg);
  567. case 15: /* SIOCGIFDSTADDR */
  568. return sys32_ioctl(fd, SIOCGIFDSTADDR, arg);
  569. case 16: /* SIOCSIFFLAGS */
  570. return sys32_ioctl(fd, SIOCSIFFLAGS, arg);
  571. case 17: /* SIOCGIFFLAGS */
  572. return sys32_ioctl(fd, SIOCGIFFLAGS, arg);
  573. case 18: /* SIOCSIFMEM */
  574. return sys32_ioctl(fd, SIOCSIFMEM, arg);
  575. case 19: /* SIOCGIFMEM */
  576. return sys32_ioctl(fd, SIOCGIFMEM, arg);
  577. case 20: /* SIOCGIFCONF */
  578. return sys32_ioctl(fd, SIOCGIFCONF, arg);
  579. case 21: /* SIOCSIFMTU */
  580. return sys32_ioctl(fd, SIOCSIFMTU, arg);
  581. case 22: /* SIOCGIFMTU */
  582. return sys32_ioctl(fd, SIOCGIFMTU, arg);
  583. case 23: /* SIOCGIFBRDADDR */
  584. return sys32_ioctl(fd, SIOCGIFBRDADDR, arg);
  585. case 24: /* SIOCSIFBRDADDR */
  586. return sys32_ioctl(fd, SIOCSIFBRDADDR, arg);
  587. case 25: /* SIOCGIFNETMASK */
  588. return sys32_ioctl(fd, SIOCGIFNETMASK, arg);
  589. case 26: /* SIOCSIFNETMASK */
  590. return sys32_ioctl(fd, SIOCSIFNETMASK, arg);
  591. case 27: /* SIOCGIFMETRIC */
  592. return sys32_ioctl(fd, SIOCGIFMETRIC, arg);
  593. case 28: /* SIOCSIFMETRIC */
  594. return sys32_ioctl(fd, SIOCSIFMETRIC, arg);
  595. case 30: /* SIOCSARP */
  596. return sys32_ioctl(fd, SIOCSARP, arg);
  597. case 31: /* SIOCGARP */
  598. return sys32_ioctl(fd, SIOCGARP, arg);
  599. case 32: /* SIOCDARP */
  600. return sys32_ioctl(fd, SIOCDARP, arg);
  601. case 52: /* SIOCGETNAME */
  602. case 53: /* SIOCGETPEER */
  603. {
  604. struct sockaddr uaddr;
  605. int uaddr_len = sizeof(struct sockaddr), ret;
  606. long args[3];
  607. mm_segment_t old_fs = get_fs();
  608. int (*sys_socketcall)(int, unsigned long *) =
  609. (int (*)(int, unsigned long *))SYS(socketcall);
  610. args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len;
  611. set_fs(KERNEL_DS);
  612. ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME,
  613. args);
  614. set_fs(old_fs);
  615. if (ret >= 0) {
  616. if (copy_to_user((char *)A(arg), &uaddr, uaddr_len))
  617. return -EFAULT;
  618. }
  619. return ret;
  620. }
  621. #if 0
  622. case 86: /* SIOCSOCKSYS */
  623. return socksys_syscall(fd, arg);
  624. #endif
  625. case 87: /* SIOCGIFNUM */
  626. {
  627. struct net_device *d;
  628. int i = 0;
  629. read_lock_bh(&dev_base_lock);
  630. for (d = dev_base; d; d = d->next) i++;
  631. read_unlock_bh(&dev_base_lock);
  632. if (put_user (i, (int *)A(arg)))
  633. return -EFAULT;
  634. return 0;
  635. }
  636. }
  637. return -ENOSYS;
  638. }
  639. static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg)
  640. {
  641. int ret;
  642. switch (cmd & 0xff) {
  643. case 1: /* MTIOCTOP */
  644. ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg);
  645. break;
  646. case 2: /* MTIOCGET */
  647. ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg);
  648. break;
  649. case 3: /* MTIOCGETDRIVETYPE */
  650. case 4: /* MTIOCPERSISTENT */
  651. case 5: /* MTIOCPERSISTENTSTATUS */
  652. case 6: /* MTIOCLRERR */
  653. case 7: /* MTIOCGUARANTEEDORDER */
  654. case 8: /* MTIOCRESERVE */
  655. case 9: /* MTIOCRELEASE */
  656. case 10: /* MTIOCFORCERESERVE */
  657. case 13: /* MTIOCSTATE */
  658. case 14: /* MTIOCREADIGNOREILI */
  659. case 15: /* MTIOCREADIGNOREEOFS */
  660. case 16: /* MTIOCSHORTFMK */
  661. default:
  662. ret = -ENOSYS; /* linux doesn't support these */
  663. break;
  664. };
  665. return ret;
  666. }
  667. static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg)
  668. {
  669. int ret = -EINVAL;
  670. switch (cmd & 0xff) {
  671. case 1: /* OPROMGETOPT */
  672. ret = sys_ioctl(fd, OPROMGETOPT, arg);
  673. break;
  674. case 2: /* OPROMSETOPT */
  675. ret = sys_ioctl(fd, OPROMSETOPT, arg);
  676. break;
  677. case 3: /* OPROMNXTOPT */
  678. ret = sys_ioctl(fd, OPROMNXTOPT, arg);
  679. break;
  680. case 4: /* OPROMSETOPT2 */
  681. ret = sys_ioctl(fd, OPROMSETOPT2, arg);
  682. break;
  683. case 5: /* OPROMNEXT */
  684. ret = sys_ioctl(fd, OPROMNEXT, arg);
  685. break;
  686. case 6: /* OPROMCHILD */
  687. ret = sys_ioctl(fd, OPROMCHILD, arg);
  688. break;
  689. case 7: /* OPROMGETPROP */
  690. ret = sys_ioctl(fd, OPROMGETPROP, arg);
  691. break;
  692. case 8: /* OPROMNXTPROP */
  693. ret = sys_ioctl(fd, OPROMNXTPROP, arg);
  694. break;
  695. case 9: /* OPROMU2P */
  696. ret = sys_ioctl(fd, OPROMU2P, arg);
  697. break;
  698. case 10: /* OPROMGETCONS */
  699. ret = sys_ioctl(fd, OPROMGETCONS, arg);
  700. break;
  701. case 11: /* OPROMGETFBNAME */
  702. ret = sys_ioctl(fd, OPROMGETFBNAME, arg);
  703. break;
  704. case 12: /* OPROMGETBOOTARGS */
  705. ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg);
  706. break;
  707. case 13: /* OPROMGETVERSION */
  708. case 14: /* OPROMPATH2DRV */
  709. case 15: /* OPROMDEV2PROMNAME */
  710. case 16: /* OPROMPROM2DEVNAME */
  711. case 17: /* OPROMGETPROPLEN */
  712. default:
  713. ret = -EINVAL;
  714. break;
  715. };
  716. return ret;
  717. }
  718. /* }}} */
  719. asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
  720. {
  721. struct file *filp;
  722. int error = -EBADF;
  723. filp = fget(fd);
  724. if (!filp)
  725. goto out;
  726. lock_kernel();
  727. error = -EFAULT;
  728. switch ((cmd >> 8) & 0xff) {
  729. case 'S': error = solaris_S(filp, fd, cmd, arg); break;
  730. case 'T': error = solaris_T(fd, cmd, arg); break;
  731. case 'i': error = solaris_i(fd, cmd, arg); break;
  732. case 'r': error = solaris_r(fd, cmd, arg); break;
  733. case 's': error = solaris_s(fd, cmd, arg); break;
  734. case 't': error = solaris_t(fd, cmd, arg); break;
  735. case 'f': error = sys_ioctl(fd, cmd, arg); break;
  736. case 'm': error = solaris_m(fd, cmd, arg); break;
  737. case 'O': error = solaris_O(fd, cmd, arg); break;
  738. default:
  739. error = -ENOSYS;
  740. break;
  741. }
  742. unlock_kernel();
  743. fput(filp);
  744. out:
  745. if (error == -ENOSYS) {
  746. unsigned char c = cmd>>8;
  747. if (c < ' ' || c > 126) c = '.';
  748. printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)n",
  749.        (int)fd, (unsigned int)cmd, c, (unsigned int)arg);
  750. error = -EINVAL;
  751. }
  752. return error;
  753. }