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