irixioctl.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * irixioctl.c: A fucking mess...
  3. *
  4. * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/sched.h>
  8. #include <linux/fs.h>
  9. #include <linux/mm.h>
  10. #include <linux/smp.h>
  11. #include <linux/sockios.h>
  12. #include <linux/syscalls.h>
  13. #include <linux/tty.h>
  14. #include <linux/file.h>
  15. #include <linux/rcupdate.h>
  16. #include <asm/uaccess.h>
  17. #include <asm/ioctl.h>
  18. #include <asm/ioctls.h>
  19. #undef DEBUG_IOCTLS
  20. #undef DEBUG_MISSING_IOCTL
  21. struct irix_termios {
  22. tcflag_t c_iflag, c_oflag, c_cflag, c_lflag;
  23. cc_t c_cc[NCCS];
  24. };
  25. extern void start_tty(struct tty_struct *tty);
  26. static struct tty_struct *get_tty(int fd)
  27. {
  28. struct file *filp;
  29. struct tty_struct *ttyp = NULL;
  30. rcu_read_lock();
  31. filp = fcheck(fd);
  32. if(filp && filp->private_data) {
  33. ttyp = (struct tty_struct *) filp->private_data;
  34. if(ttyp->magic != TTY_MAGIC)
  35. ttyp =NULL;
  36. }
  37. rcu_read_unlock();
  38. return ttyp;
  39. }
  40. static struct tty_struct *get_real_tty(struct tty_struct *tp)
  41. {
  42. if (tp->driver->type == TTY_DRIVER_TYPE_PTY &&
  43. tp->driver->subtype == PTY_TYPE_MASTER)
  44. return tp->link;
  45. else
  46. return tp;
  47. }
  48. asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
  49. {
  50. struct tty_struct *tp, *rtp;
  51. mm_segment_t old_fs;
  52. int i, error = 0;
  53. #ifdef DEBUG_IOCTLS
  54. printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
  55. #endif
  56. switch(cmd) {
  57. case 0x00005401:
  58. #ifdef DEBUG_IOCTLS
  59. printk("TCGETA, %08lx) ", arg);
  60. #endif
  61. error = sys_ioctl(fd, TCGETA, arg);
  62. break;
  63. case 0x0000540d: {
  64. struct termios kt;
  65. struct irix_termios __user *it =
  66. (struct irix_termios __user *) arg;
  67. #ifdef DEBUG_IOCTLS
  68. printk("TCGETS, %08lx) ", arg);
  69. #endif
  70. if (!access_ok(VERIFY_WRITE, it, sizeof(*it))) {
  71. error = -EFAULT;
  72. break;
  73. }
  74. old_fs = get_fs(); set_fs(get_ds());
  75. error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
  76. set_fs(old_fs);
  77. if (error)
  78. break;
  79. error = __put_user(kt.c_iflag, &it->c_iflag);
  80. error |= __put_user(kt.c_oflag, &it->c_oflag);
  81. error |= __put_user(kt.c_cflag, &it->c_cflag);
  82. error |= __put_user(kt.c_lflag, &it->c_lflag);
  83. for (i = 0; i < NCCS; i++)
  84. error |= __put_user(kt.c_cc[i], &it->c_cc[i]);
  85. break;
  86. }
  87. case 0x0000540e: {
  88. struct termios kt;
  89. struct irix_termios *it = (struct irix_termios *) arg;
  90. #ifdef DEBUG_IOCTLS
  91. printk("TCSETS, %08lx) ", arg);
  92. #endif
  93. if (!access_ok(VERIFY_READ, it, sizeof(*it))) {
  94. error = -EFAULT;
  95. break;
  96. }
  97. old_fs = get_fs(); set_fs(get_ds());
  98. error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
  99. set_fs(old_fs);
  100. if (error)
  101. break;
  102. error = __get_user(kt.c_iflag, &it->c_iflag);
  103. error |= __get_user(kt.c_oflag, &it->c_oflag);
  104. error |= __get_user(kt.c_cflag, &it->c_cflag);
  105. error |= __get_user(kt.c_lflag, &it->c_lflag);
  106. for (i = 0; i < NCCS; i++)
  107. error |= __get_user(kt.c_cc[i], &it->c_cc[i]);
  108. if (error)
  109. break;
  110. old_fs = get_fs(); set_fs(get_ds());
  111. error = sys_ioctl(fd, TCSETS, (unsigned long) &kt);
  112. set_fs(old_fs);
  113. break;
  114. }
  115. case 0x0000540f:
  116. #ifdef DEBUG_IOCTLS
  117. printk("TCSETSW, %08lx) ", arg);
  118. #endif
  119. error = sys_ioctl(fd, TCSETSW, arg);
  120. break;
  121. case 0x00005471:
  122. #ifdef DEBUG_IOCTLS
  123. printk("TIOCNOTTY, %08lx) ", arg);
  124. #endif
  125. error = sys_ioctl(fd, TIOCNOTTY, arg);
  126. break;
  127. case 0x00007416:
  128. #ifdef DEBUG_IOCTLS
  129. printk("TIOCGSID, %08lx) ", arg);
  130. #endif
  131. tp = get_tty(fd);
  132. if(!tp) {
  133. error = -EINVAL;
  134. break;
  135. }
  136. rtp = get_real_tty(tp);
  137. #ifdef DEBUG_IOCTLS
  138. printk("rtp->session=%d ", rtp->session);
  139. #endif
  140. error = put_user(rtp->session, (unsigned long __user *) arg);
  141. break;
  142. case 0x746e:
  143. /* TIOCSTART, same effect as hitting ^Q */
  144. #ifdef DEBUG_IOCTLS
  145. printk("TIOCSTART, %08lx) ", arg);
  146. #endif
  147. tp = get_tty(fd);
  148. if(!tp) {
  149. error = -EINVAL;
  150. break;
  151. }
  152. rtp = get_real_tty(tp);
  153. start_tty(rtp);
  154. break;
  155. case 0x20006968:
  156. #ifdef DEBUG_IOCTLS
  157. printk("SIOCGETLABEL, %08lx) ", arg);
  158. #endif
  159. error = -ENOPKG;
  160. break;
  161. case 0x40047477:
  162. #ifdef DEBUG_IOCTLS
  163. printk("TIOCGPGRP, %08lx) ", arg);
  164. #endif
  165. error = sys_ioctl(fd, TIOCGPGRP, arg);
  166. #ifdef DEBUG_IOCTLS
  167. printk("arg=%d ", *(int *)arg);
  168. #endif
  169. break;
  170. case 0x40087468:
  171. #ifdef DEBUG_IOCTLS
  172. printk("TIOCGWINSZ, %08lx) ", arg);
  173. #endif
  174. error = sys_ioctl(fd, TIOCGWINSZ, arg);
  175. break;
  176. case 0x8004667e:
  177. error = sys_ioctl(fd, FIONBIO, arg);
  178. break;
  179. case 0x80047476:
  180. error = sys_ioctl(fd, TIOCSPGRP, arg);
  181. break;
  182. case 0x8020690c:
  183. error = sys_ioctl(fd, SIOCSIFADDR, arg);
  184. break;
  185. case 0x80206910:
  186. error = sys_ioctl(fd, SIOCSIFFLAGS, arg);
  187. break;
  188. case 0xc0206911:
  189. error = sys_ioctl(fd, SIOCGIFFLAGS, arg);
  190. break;
  191. case 0xc020691b:
  192. error = sys_ioctl(fd, SIOCGIFMETRIC, arg);
  193. break;
  194. default: {
  195. #ifdef DEBUG_MISSING_IOCTL
  196. char *msg = "Unimplemented IOCTL cmd tell linux-mips@linux-mips.org\n";
  197. #ifdef DEBUG_IOCTLS
  198. printk("UNIMP_IOCTL, %08lx)\n", arg);
  199. #endif
  200. old_fs = get_fs(); set_fs(get_ds());
  201. sys_write(2, msg, strlen(msg));
  202. set_fs(old_fs);
  203. printk("[%s:%d] Does unimplemented IRIX ioctl cmd %08lx\n",
  204. current->comm, current->pid, cmd);
  205. do_exit(255);
  206. #else
  207. error = sys_ioctl(fd, cmd, arg);
  208. #endif
  209. }
  210. };
  211. #ifdef DEBUG_IOCTLS
  212. printk("error=%d\n", error);
  213. #endif
  214. return error;
  215. }