irixioctl.c 5.1 KB

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