[PATCH] tty: switch to ktermios
[safe/jmp/linux-2.6] / drivers / char / tty_ioctl.c
1 /*
2  *  linux/drivers/char/tty_ioctl.c
3  *
4  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
5  *
6  * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
7  * which can be dynamically activated and de-activated by the line
8  * discipline handling modules (like SLIP).
9  */
10
11 #include <linux/types.h>
12 #include <linux/termios.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/major.h>
17 #include <linux/tty.h>
18 #include <linux/fcntl.h>
19 #include <linux/string.h>
20 #include <linux/mm.h>
21 #include <linux/module.h>
22 #include <linux/bitops.h>
23 #include <linux/mutex.h>
24
25 #include <asm/io.h>
26 #include <asm/uaccess.h>
27 #include <asm/system.h>
28
29 #undef TTY_DEBUG_WAIT_UNTIL_SENT
30
31 #undef  DEBUG
32
33 /*
34  * Internal flag options for termios setting behavior
35  */
36 #define TERMIOS_FLUSH   1
37 #define TERMIOS_WAIT    2
38 #define TERMIOS_TERMIO  4
39 #define TERMIOS_OLD     8
40
41
42 /**
43  *      tty_wait_until_sent     -       wait for I/O to finish
44  *      @tty: tty we are waiting for
45  *      @timeout: how long we will wait
46  *
47  *      Wait for characters pending in a tty driver to hit the wire, or
48  *      for a timeout to occur (eg due to flow control)
49  *
50  *      Locking: none
51  */
52
53 void tty_wait_until_sent(struct tty_struct * tty, long timeout)
54 {
55         DECLARE_WAITQUEUE(wait, current);
56
57 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
58         char buf[64];
59         
60         printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
61 #endif
62         if (!tty->driver->chars_in_buffer)
63                 return;
64         add_wait_queue(&tty->write_wait, &wait);
65         if (!timeout)
66                 timeout = MAX_SCHEDULE_TIMEOUT;
67         do {
68 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
69                 printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
70                        tty->driver->chars_in_buffer(tty));
71 #endif
72                 set_current_state(TASK_INTERRUPTIBLE);
73                 if (signal_pending(current))
74                         goto stop_waiting;
75                 if (!tty->driver->chars_in_buffer(tty))
76                         break;
77                 timeout = schedule_timeout(timeout);
78         } while (timeout);
79         if (tty->driver->wait_until_sent)
80                 tty->driver->wait_until_sent(tty, timeout);
81 stop_waiting:
82         set_current_state(TASK_RUNNING);
83         remove_wait_queue(&tty->write_wait, &wait);
84 }
85
86 EXPORT_SYMBOL(tty_wait_until_sent);
87
88 static void unset_locked_termios(struct ktermios *termios,
89                                  struct ktermios *old,
90                                  struct ktermios *locked)
91 {
92         int     i;
93         
94 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
95
96         if (!locked) {
97                 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
98                 return;
99         }
100
101         NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
102         NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
103         NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
104         NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
105         termios->c_line = locked->c_line ? old->c_line : termios->c_line;
106         for (i=0; i < NCCS; i++)
107                 termios->c_cc[i] = locked->c_cc[i] ?
108                         old->c_cc[i] : termios->c_cc[i];
109         /* FIXME: What should we do for i/ospeed */
110 }
111
112 /*
113  * Routine which returns the baud rate of the tty
114  *
115  * Note that the baud_table needs to be kept in sync with the
116  * include/asm/termbits.h file.
117  */
118 static const speed_t baud_table[] = {
119         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
120         9600, 19200, 38400, 57600, 115200, 230400, 460800,
121 #ifdef __sparc__
122         76800, 153600, 307200, 614400, 921600
123 #else
124         500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
125         2500000, 3000000, 3500000, 4000000
126 #endif
127 };
128
129 #ifndef __sparc__
130 static const tcflag_t baud_bits[] = {
131         B0, B50, B75, B110, B134, B150, B200, B300, B600,
132         B1200, B1800, B2400, B4800, B9600, B19200, B38400,
133         B57600, B115200, B230400, B460800, B500000, B576000,
134         B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
135         B3000000, B3500000, B4000000
136 };
137 #else
138 static const tcflag_t baud_bits[] = {
139         B0, B50, B75, B110, B134, B150, B200, B300, B600,
140         B1200, B1800, B2400, B4800, B9600, B19200, B38400,
141         B57600, B115200, B230400, B460800, B76800, B153600,
142         B307200, B614400, B921600
143 };
144 #endif
145
146 static int n_baud_table = ARRAY_SIZE(baud_table);
147
148 /**
149  *      tty_termios_baud_rate
150  *      @termios: termios structure
151  *
152  *      Convert termios baud rate data into a speed. This should be called
153  *      with the termios lock held if this termios is a terminal termios
154  *      structure. May change the termios data. Device drivers can call this
155  *      function but should use ->c_[io]speed directly as they are updated.
156  *
157  *      Locking: none
158  */
159
160 speed_t tty_termios_baud_rate(struct ktermios *termios)
161 {
162         unsigned int cbaud;
163
164         cbaud = termios->c_cflag & CBAUD;
165
166 #ifdef BOTHER
167         /* Magic token for arbitary speed via c_ispeed/c_ospeed */
168         if (cbaud == BOTHER)
169                 return termios->c_ospeed;
170 #endif
171         if (cbaud & CBAUDEX) {
172                 cbaud &= ~CBAUDEX;
173
174                 if (cbaud < 1 || cbaud + 15 > n_baud_table)
175                         termios->c_cflag &= ~CBAUDEX;
176                 else
177                         cbaud += 15;
178         }
179         return baud_table[cbaud];
180 }
181
182 EXPORT_SYMBOL(tty_termios_baud_rate);
183
184 /**
185  *      tty_termios_input_baud_rate
186  *      @termios: termios structure
187  *
188  *      Convert termios baud rate data into a speed. This should be called
189  *      with the termios lock held if this termios is a terminal termios
190  *      structure. May change the termios data. Device drivers can call this
191  *      function but should use ->c_[io]speed directly as they are updated.
192  *
193  *      Locking: none
194  */
195
196 speed_t tty_termios_input_baud_rate(struct ktermios *termios)
197 {
198 #ifdef IBSHIFT
199         unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
200
201         if (cbaud == B0)
202                 return tty_termios_baud_rate(termios);
203
204         /* Magic token for arbitary speed via c_ispeed*/
205         if (cbaud == BOTHER)
206                 return termios->c_ispeed;
207
208         if (cbaud & CBAUDEX) {
209                 cbaud &= ~CBAUDEX;
210
211                 if (cbaud < 1 || cbaud + 15 > n_baud_table)
212                         termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
213                 else
214                         cbaud += 15;
215         }
216         return baud_table[cbaud];
217 #else
218         return tty_termios_baud_rate(termios);
219 #endif
220 }
221
222 EXPORT_SYMBOL(tty_termios_input_baud_rate);
223
224 #ifdef BOTHER
225
226 /**
227  *      tty_termios_encode_baud_rate
228  *      @termios: termios structure
229  *      @ispeed: input speed
230  *      @ospeed: output speed
231  *
232  *      Encode the speeds set into the passed termios structure. This is
233  *      used as a library helper for drivers os that they can report back
234  *      the actual speed selected when it differs from the speed requested
235  *
236  *      For now input and output speed must agree.
237  *
238  *      Locking: Caller should hold termios lock. This is already held
239  *      when calling this function from the driver termios handler.
240  */
241
242 void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
243 {
244         int i = 0;
245         int ifound = 0, ofound = 0;
246
247         termios->c_ispeed = ibaud;
248         termios->c_ospeed = obaud;
249
250         termios->c_cflag &= ~CBAUD;
251         /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/
252         if (termios->c_ispeed == termios->c_ospeed)
253                 ifound = 1;
254
255         do {
256                 if (obaud == baud_table[i]) {
257                         termios->c_cflag |= baud_bits[i];
258                         ofound = 1;
259                         /* So that if ibaud == obaud we don't set it */
260                         continue;
261                 }
262                 if (ibaud == baud_table[i]) {
263                         termios->c_cflag |= (baud_bits[i] << IBSHIFT);
264                         ifound = 1;
265                 }
266         }
267         while(++i < n_baud_table);
268         if (!ofound)
269                 termios->c_cflag |= BOTHER;
270         if (!ifound)
271                 termios->c_cflag |= (BOTHER << IBSHIFT);
272 }
273
274 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
275
276 #endif
277
278 /**
279  *      tty_get_baud_rate       -       get tty bit rates
280  *      @tty: tty to query
281  *
282  *      Returns the baud rate as an integer for this terminal. The
283  *      termios lock must be held by the caller and the terminal bit
284  *      flags may be updated.
285  *
286  *      Locking: none
287  */
288
289 speed_t tty_get_baud_rate(struct tty_struct *tty)
290 {
291         speed_t baud = tty_termios_baud_rate(tty->termios);
292
293         if (baud == 38400 && tty->alt_speed) {
294                 if (!tty->warned) {
295                         printk(KERN_WARNING "Use of setserial/setrocket to "
296                                             "set SPD_* flags is deprecated\n");
297                         tty->warned = 1;
298                 }
299                 baud = tty->alt_speed;
300         }
301
302         return baud;
303 }
304
305 EXPORT_SYMBOL(tty_get_baud_rate);
306
307 /**
308  *      change_termios          -       update termios values
309  *      @tty: tty to update
310  *      @new_termios: desired new value
311  *
312  *      Perform updates to the termios values set on this terminal. There
313  *      is a bit of layering violation here with n_tty in terms of the
314  *      internal knowledge of this function.
315  *
316  *      Locking: termios_sem
317  */
318
319 static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
320 {
321         int canon_change;
322         struct ktermios old_termios = *tty->termios;
323         struct tty_ldisc *ld;
324         
325         /*
326          *      Perform the actual termios internal changes under lock.
327          */
328          
329
330         /* FIXME: we need to decide on some locking/ordering semantics
331            for the set_termios notification eventually */
332         mutex_lock(&tty->termios_mutex);
333
334         *tty->termios = *new_termios;
335         unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
336         canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
337         if (canon_change) {
338                 memset(&tty->read_flags, 0, sizeof tty->read_flags);
339                 tty->canon_head = tty->read_tail;
340                 tty->canon_data = 0;
341                 tty->erasing = 0;
342         }
343         
344         
345         if (canon_change && !L_ICANON(tty) && tty->read_cnt)
346                 /* Get characters left over from canonical mode. */
347                 wake_up_interruptible(&tty->read_wait);
348
349         /* See if packet mode change of state. */
350
351         if (tty->link && tty->link->packet) {
352                 int old_flow = ((old_termios.c_iflag & IXON) &&
353                                 (old_termios.c_cc[VSTOP] == '\023') &&
354                                 (old_termios.c_cc[VSTART] == '\021'));
355                 int new_flow = (I_IXON(tty) &&
356                                 STOP_CHAR(tty) == '\023' &&
357                                 START_CHAR(tty) == '\021');
358                 if (old_flow != new_flow) {
359                         tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
360                         if (new_flow)
361                                 tty->ctrl_status |= TIOCPKT_DOSTOP;
362                         else
363                                 tty->ctrl_status |= TIOCPKT_NOSTOP;
364                         wake_up_interruptible(&tty->link->read_wait);
365                 }
366         }
367            
368         if (tty->driver->set_termios)
369                 (*tty->driver->set_termios)(tty, &old_termios);
370
371         ld = tty_ldisc_ref(tty);
372         if (ld != NULL) {
373                 if (ld->set_termios)
374                         (ld->set_termios)(tty, &old_termios);
375                 tty_ldisc_deref(ld);
376         }
377         mutex_unlock(&tty->termios_mutex);
378 }
379
380 /**
381  *      set_termios             -       set termios values for a tty
382  *      @tty: terminal device
383  *      @arg: user data
384  *      @opt: option information
385  *
386  *      Helper function to prepare termios data and run neccessary other
387  *      functions before using change_termios to do the actual changes.
388  *
389  *      Locking:
390  *              Called functions take ldisc and termios_sem locks
391  */
392
393 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
394 {
395         struct ktermios tmp_termios;
396         struct tty_ldisc *ld;
397         int retval = tty_check_change(tty);
398
399         if (retval)
400                 return retval;
401
402         if (opt & TERMIOS_TERMIO) {
403                 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
404                 if (user_termio_to_kernel_termios(&tmp_termios,
405                                                 (struct termio __user *)arg))
406                         return -EFAULT;
407 #ifdef TCGETS2
408         } else if (opt & TERMIOS_OLD) {
409                 memcpy(&tmp_termios, tty->termios, sizeof(struct termios));
410                 if (user_termios_to_kernel_termios_1(&tmp_termios,
411                                                 (struct termios_v1 __user *)arg))
412                         return -EFAULT;
413 #endif
414         } else {
415                 if (user_termios_to_kernel_termios(&tmp_termios,
416                                                 (struct termios __user *)arg))
417                         return -EFAULT;
418         }
419
420         /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
421            so its unconditionally usable */
422         tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
423         tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
424
425         ld = tty_ldisc_ref(tty);
426         
427         if (ld != NULL) {
428                 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
429                         ld->flush_buffer(tty);
430                 tty_ldisc_deref(ld);
431         }
432         
433         if (opt & TERMIOS_WAIT) {
434                 tty_wait_until_sent(tty, 0);
435                 if (signal_pending(current))
436                         return -EINTR;
437         }
438
439         change_termios(tty, &tmp_termios);
440         return 0;
441 }
442
443 static int get_termio(struct tty_struct * tty, struct termio __user * termio)
444 {
445         if (kernel_termios_to_user_termio(termio, tty->termios))
446                 return -EFAULT;
447         return 0;
448 }
449
450 static unsigned long inq_canon(struct tty_struct * tty)
451 {
452         int nr, head, tail;
453
454         if (!tty->canon_data || !tty->read_buf)
455                 return 0;
456         head = tty->canon_head;
457         tail = tty->read_tail;
458         nr = (head - tail) & (N_TTY_BUF_SIZE-1);
459         /* Skip EOF-chars.. */
460         while (head != tail) {
461                 if (test_bit(tail, tty->read_flags) &&
462                     tty->read_buf[tail] == __DISABLED_CHAR)
463                         nr--;
464                 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
465         }
466         return nr;
467 }
468
469 #ifdef TIOCGETP
470 /*
471  * These are deprecated, but there is limited support..
472  *
473  * The "sg_flags" translation is a joke..
474  */
475 static int get_sgflags(struct tty_struct * tty)
476 {
477         int flags = 0;
478
479         if (!(tty->termios->c_lflag & ICANON)) {
480                 if (tty->termios->c_lflag & ISIG)
481                         flags |= 0x02;          /* cbreak */
482                 else
483                         flags |= 0x20;          /* raw */
484         }
485         if (tty->termios->c_lflag & ECHO)
486                 flags |= 0x08;                  /* echo */
487         if (tty->termios->c_oflag & OPOST)
488                 if (tty->termios->c_oflag & ONLCR)
489                         flags |= 0x10;          /* crmod */
490         return flags;
491 }
492
493 static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
494 {
495         struct sgttyb tmp;
496
497         mutex_lock(&tty->termios_mutex);
498         tmp.sg_ispeed = tty->termios->c_ispeed;
499         tmp.sg_ospeed = tty->termios->c_ospeed;
500         tmp.sg_erase = tty->termios->c_cc[VERASE];
501         tmp.sg_kill = tty->termios->c_cc[VKILL];
502         tmp.sg_flags = get_sgflags(tty);
503         mutex_unlock(&tty->termios_mutex);
504         
505         return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
506 }
507
508 static void set_sgflags(struct ktermios * termios, int flags)
509 {
510         termios->c_iflag = ICRNL | IXON;
511         termios->c_oflag = 0;
512         termios->c_lflag = ISIG | ICANON;
513         if (flags & 0x02) {     /* cbreak */
514                 termios->c_iflag = 0;
515                 termios->c_lflag &= ~ICANON;
516         }
517         if (flags & 0x08) {             /* echo */
518                 termios->c_lflag |= ECHO | ECHOE | ECHOK |
519                                     ECHOCTL | ECHOKE | IEXTEN;
520         }
521         if (flags & 0x10) {             /* crmod */
522                 termios->c_oflag |= OPOST | ONLCR;
523         }
524         if (flags & 0x20) {     /* raw */
525                 termios->c_iflag = 0;
526                 termios->c_lflag &= ~(ISIG | ICANON);
527         }
528         if (!(termios->c_lflag & ICANON)) {
529                 termios->c_cc[VMIN] = 1;
530                 termios->c_cc[VTIME] = 0;
531         }
532 }
533
534 /**
535  *      set_sgttyb              -       set legacy terminal values
536  *      @tty: tty structure
537  *      @sgttyb: pointer to old style terminal structure
538  *
539  *      Updates a terminal from the legacy BSD style terminal information
540  *      structure.
541  *
542  *      Locking: termios_sem
543  */
544
545 static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
546 {
547         int retval;
548         struct sgttyb tmp;
549         struct ktermios termios;
550
551         retval = tty_check_change(tty);
552         if (retval)
553                 return retval;
554         
555         if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
556                 return -EFAULT;
557
558         mutex_lock(&tty->termios_mutex);
559         termios =  *tty->termios;
560         termios.c_cc[VERASE] = tmp.sg_erase;
561         termios.c_cc[VKILL] = tmp.sg_kill;
562         set_sgflags(&termios, tmp.sg_flags);
563         /* Try and encode into Bfoo format */
564 #ifdef BOTHER
565         tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
566 #endif
567         mutex_unlock(&tty->termios_mutex);
568         change_termios(tty, &termios);
569         return 0;
570 }
571 #endif
572
573 #ifdef TIOCGETC
574 static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
575 {
576         struct tchars tmp;
577
578         tmp.t_intrc = tty->termios->c_cc[VINTR];
579         tmp.t_quitc = tty->termios->c_cc[VQUIT];
580         tmp.t_startc = tty->termios->c_cc[VSTART];
581         tmp.t_stopc = tty->termios->c_cc[VSTOP];
582         tmp.t_eofc = tty->termios->c_cc[VEOF];
583         tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
584         return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
585 }
586
587 static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
588 {
589         struct tchars tmp;
590
591         if (copy_from_user(&tmp, tchars, sizeof(tmp)))
592                 return -EFAULT;
593         tty->termios->c_cc[VINTR] = tmp.t_intrc;
594         tty->termios->c_cc[VQUIT] = tmp.t_quitc;
595         tty->termios->c_cc[VSTART] = tmp.t_startc;
596         tty->termios->c_cc[VSTOP] = tmp.t_stopc;
597         tty->termios->c_cc[VEOF] = tmp.t_eofc;
598         tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
599         return 0;
600 }
601 #endif
602
603 #ifdef TIOCGLTC
604 static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
605 {
606         struct ltchars tmp;
607
608         tmp.t_suspc = tty->termios->c_cc[VSUSP];
609         tmp.t_dsuspc = tty->termios->c_cc[VSUSP];       /* what is dsuspc anyway? */
610         tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
611         tmp.t_flushc = tty->termios->c_cc[VEOL2];       /* what is flushc anyway? */
612         tmp.t_werasc = tty->termios->c_cc[VWERASE];
613         tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
614         return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
615 }
616
617 static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
618 {
619         struct ltchars tmp;
620
621         if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
622                 return -EFAULT;
623
624         tty->termios->c_cc[VSUSP] = tmp.t_suspc;
625         tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;       /* what is dsuspc anyway? */
626         tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
627         tty->termios->c_cc[VEOL2] = tmp.t_flushc;       /* what is flushc anyway? */
628         tty->termios->c_cc[VWERASE] = tmp.t_werasc;
629         tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
630         return 0;
631 }
632 #endif
633
634 /**
635  *      send_prio_char          -       send priority character
636  *
637  *      Send a high priority character to the tty even if stopped
638  *
639  *      Locking: none for xchar method, write ordering for write method.
640  */
641
642 static int send_prio_char(struct tty_struct *tty, char ch)
643 {
644         int     was_stopped = tty->stopped;
645
646         if (tty->driver->send_xchar) {
647                 tty->driver->send_xchar(tty, ch);
648                 return 0;
649         }
650
651         if (mutex_lock_interruptible(&tty->atomic_write_lock))
652                 return -ERESTARTSYS;
653
654         if (was_stopped)
655                 start_tty(tty);
656         tty->driver->write(tty, &ch, 1);
657         if (was_stopped)
658                 stop_tty(tty);
659         mutex_unlock(&tty->atomic_write_lock);
660         return 0;
661 }
662
663 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
664                        unsigned int cmd, unsigned long arg)
665 {
666         struct tty_struct * real_tty;
667         void __user *p = (void __user *)arg;
668         int retval;
669         struct tty_ldisc *ld;
670
671         if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
672             tty->driver->subtype == PTY_TYPE_MASTER)
673                 real_tty = tty->link;
674         else
675                 real_tty = tty;
676
677         switch (cmd) {
678 #ifdef TIOCGETP
679                 case TIOCGETP:
680                         return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
681                 case TIOCSETP:
682                 case TIOCSETN:
683                         return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
684 #endif
685 #ifdef TIOCGETC
686                 case TIOCGETC:
687                         return get_tchars(real_tty, p);
688                 case TIOCSETC:
689                         return set_tchars(real_tty, p);
690 #endif
691 #ifdef TIOCGLTC
692                 case TIOCGLTC:
693                         return get_ltchars(real_tty, p);
694                 case TIOCSLTC:
695                         return set_ltchars(real_tty, p);
696 #endif
697                 case TCSETSF:
698                         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
699                 case TCSETSW:
700                         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
701                 case TCSETS:
702                         return set_termios(real_tty, p, TERMIOS_OLD);
703 #ifndef TCGETS2
704                 case TCGETS:
705                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
706                                 return -EFAULT;
707                         return 0;
708 #else
709                 case TCGETS:
710                         if (kernel_termios_to_user_termios_1((struct termios_v1 __user *)arg, real_tty->termios))
711                                 return -EFAULT;
712                         return 0;
713                 case TCGETS2:
714                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
715                                 return -EFAULT;
716                         return 0;
717                 case TCSETSF2:
718                         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
719                 case TCSETSW2:
720                         return set_termios(real_tty, p, TERMIOS_WAIT);
721                 case TCSETS2:
722                         return set_termios(real_tty, p, 0);
723 #endif
724                 case TCGETA:
725                         return get_termio(real_tty, p);
726                 case TCSETAF:
727                         return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
728                 case TCSETAW:
729                         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
730                 case TCSETA:
731                         return set_termios(real_tty, p, TERMIOS_TERMIO);
732                 case TCXONC:
733                         retval = tty_check_change(tty);
734                         if (retval)
735                                 return retval;
736                         switch (arg) {
737                         case TCOOFF:
738                                 if (!tty->flow_stopped) {
739                                         tty->flow_stopped = 1;
740                                         stop_tty(tty);
741                                 }
742                                 break;
743                         case TCOON:
744                                 if (tty->flow_stopped) {
745                                         tty->flow_stopped = 0;
746                                         start_tty(tty);
747                                 }
748                                 break;
749                         case TCIOFF:
750                                 if (STOP_CHAR(tty) != __DISABLED_CHAR)
751                                         return send_prio_char(tty, STOP_CHAR(tty));
752                                 break;
753                         case TCION:
754                                 if (START_CHAR(tty) != __DISABLED_CHAR)
755                                         return send_prio_char(tty, START_CHAR(tty));
756                                 break;
757                         default:
758                                 return -EINVAL;
759                         }
760                         return 0;
761                 case TCFLSH:
762                         retval = tty_check_change(tty);
763                         if (retval)
764                                 return retval;
765                                 
766                         ld = tty_ldisc_ref(tty);
767                         switch (arg) {
768                         case TCIFLUSH:
769                                 if (ld && ld->flush_buffer)
770                                         ld->flush_buffer(tty);
771                                 break;
772                         case TCIOFLUSH:
773                                 if (ld && ld->flush_buffer)
774                                         ld->flush_buffer(tty);
775                                 /* fall through */
776                         case TCOFLUSH:
777                                 if (tty->driver->flush_buffer)
778                                         tty->driver->flush_buffer(tty);
779                                 break;
780                         default:
781                                 tty_ldisc_deref(ld);
782                                 return -EINVAL;
783                         }
784                         tty_ldisc_deref(ld);
785                         return 0;
786                 case TIOCOUTQ:
787                         return put_user(tty->driver->chars_in_buffer ?
788                                         tty->driver->chars_in_buffer(tty) : 0,
789                                         (int __user *) arg);
790                 case TIOCINQ:
791                         retval = tty->read_cnt;
792                         if (L_ICANON(tty))
793                                 retval = inq_canon(tty);
794                         return put_user(retval, (unsigned int __user *) arg);
795                 case TIOCGLCKTRMIOS:
796                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
797                                 return -EFAULT;
798                         return 0;
799
800                 case TIOCSLCKTRMIOS:
801                         if (!capable(CAP_SYS_ADMIN))
802                                 return -EPERM;
803                         if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
804                                 return -EFAULT;
805                         return 0;
806
807                 case TIOCPKT:
808                 {
809                         int pktmode;
810
811                         if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
812                             tty->driver->subtype != PTY_TYPE_MASTER)
813                                 return -ENOTTY;
814                         if (get_user(pktmode, (int __user *) arg))
815                                 return -EFAULT;
816                         if (pktmode) {
817                                 if (!tty->packet) {
818                                         tty->packet = 1;
819                                         tty->link->ctrl_status = 0;
820                                 }
821                         } else
822                                 tty->packet = 0;
823                         return 0;
824                 }
825                 case TIOCGSOFTCAR:
826                         return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
827                 case TIOCSSOFTCAR:
828                         if (get_user(arg, (unsigned int __user *) arg))
829                                 return -EFAULT;
830                         mutex_lock(&tty->termios_mutex);
831                         tty->termios->c_cflag =
832                                 ((tty->termios->c_cflag & ~CLOCAL) |
833                                  (arg ? CLOCAL : 0));
834                         mutex_unlock(&tty->termios_mutex);
835                         return 0;
836                 default:
837                         return -ENOIOCTLCMD;
838                 }
839 }
840
841 EXPORT_SYMBOL(n_tty_ioctl);