]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/char/tty_ioctl.c
tty/serial: lay the foundations for the next set of reworks
[linux-2.6-omap-h63xx.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 #include <linux/smp_lock.h>
25
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include <asm/system.h>
29
30 #undef TTY_DEBUG_WAIT_UNTIL_SENT
31
32 #undef  DEBUG
33
34 /*
35  * Internal flag options for termios setting behavior
36  */
37 #define TERMIOS_FLUSH   1
38 #define TERMIOS_WAIT    2
39 #define TERMIOS_TERMIO  4
40 #define TERMIOS_OLD     8
41
42
43 /**
44  *      tty_wait_until_sent     -       wait for I/O to finish
45  *      @tty: tty we are waiting for
46  *      @timeout: how long we will wait
47  *
48  *      Wait for characters pending in a tty driver to hit the wire, or
49  *      for a timeout to occur (eg due to flow control)
50  *
51  *      Locking: none
52  */
53
54 void tty_wait_until_sent(struct tty_struct *tty, long timeout)
55 {
56 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
57         char buf[64];
58
59         printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
60 #endif
61         if (!tty->driver->chars_in_buffer)
62                 return;
63         if (!timeout)
64                 timeout = MAX_SCHEDULE_TIMEOUT;
65         lock_kernel();
66         if (wait_event_interruptible_timeout(tty->write_wait,
67                         !tty->driver->chars_in_buffer(tty), timeout) >= 0) {
68                 if (tty->driver->wait_until_sent)
69                         tty->driver->wait_until_sent(tty, timeout);
70         }
71         unlock_kernel();
72 }
73 EXPORT_SYMBOL(tty_wait_until_sent);
74
75 static void unset_locked_termios(struct ktermios *termios,
76                                  struct ktermios *old,
77                                  struct ktermios *locked)
78 {
79         int     i;
80
81 #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
82
83         if (!locked) {
84                 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
85                 return;
86         }
87
88         NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
89         NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
90         NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
91         NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
92         termios->c_line = locked->c_line ? old->c_line : termios->c_line;
93         for (i = 0; i < NCCS; i++)
94                 termios->c_cc[i] = locked->c_cc[i] ?
95                         old->c_cc[i] : termios->c_cc[i];
96         /* FIXME: What should we do for i/ospeed */
97 }
98
99 /*
100  * Routine which returns the baud rate of the tty
101  *
102  * Note that the baud_table needs to be kept in sync with the
103  * include/asm/termbits.h file.
104  */
105 static const speed_t baud_table[] = {
106         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
107         9600, 19200, 38400, 57600, 115200, 230400, 460800,
108 #ifdef __sparc__
109         76800, 153600, 307200, 614400, 921600
110 #else
111         500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
112         2500000, 3000000, 3500000, 4000000
113 #endif
114 };
115
116 #ifndef __sparc__
117 static const tcflag_t baud_bits[] = {
118         B0, B50, B75, B110, B134, B150, B200, B300, B600,
119         B1200, B1800, B2400, B4800, B9600, B19200, B38400,
120         B57600, B115200, B230400, B460800, B500000, B576000,
121         B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
122         B3000000, B3500000, B4000000
123 };
124 #else
125 static const tcflag_t baud_bits[] = {
126         B0, B50, B75, B110, B134, B150, B200, B300, B600,
127         B1200, B1800, B2400, B4800, B9600, B19200, B38400,
128         B57600, B115200, B230400, B460800, B76800, B153600,
129         B307200, B614400, B921600
130 };
131 #endif
132
133 static int n_baud_table = ARRAY_SIZE(baud_table);
134
135 /**
136  *      tty_termios_baud_rate
137  *      @termios: termios structure
138  *
139  *      Convert termios baud rate data into a speed. This should be called
140  *      with the termios lock held if this termios is a terminal termios
141  *      structure. May change the termios data. Device drivers can call this
142  *      function but should use ->c_[io]speed directly as they are updated.
143  *
144  *      Locking: none
145  */
146
147 speed_t tty_termios_baud_rate(struct ktermios *termios)
148 {
149         unsigned int cbaud;
150
151         cbaud = termios->c_cflag & CBAUD;
152
153 #ifdef BOTHER
154         /* Magic token for arbitary speed via c_ispeed/c_ospeed */
155         if (cbaud == BOTHER)
156                 return termios->c_ospeed;
157 #endif
158         if (cbaud & CBAUDEX) {
159                 cbaud &= ~CBAUDEX;
160
161                 if (cbaud < 1 || cbaud + 15 > n_baud_table)
162                         termios->c_cflag &= ~CBAUDEX;
163                 else
164                         cbaud += 15;
165         }
166         return baud_table[cbaud];
167 }
168 EXPORT_SYMBOL(tty_termios_baud_rate);
169
170 /**
171  *      tty_termios_input_baud_rate
172  *      @termios: termios structure
173  *
174  *      Convert termios baud rate data into a speed. This should be called
175  *      with the termios lock held if this termios is a terminal termios
176  *      structure. May change the termios data. Device drivers can call this
177  *      function but should use ->c_[io]speed directly as they are updated.
178  *
179  *      Locking: none
180  */
181
182 speed_t tty_termios_input_baud_rate(struct ktermios *termios)
183 {
184 #ifdef IBSHIFT
185         unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
186
187         if (cbaud == B0)
188                 return tty_termios_baud_rate(termios);
189
190         /* Magic token for arbitary speed via c_ispeed*/
191         if (cbaud == BOTHER)
192                 return termios->c_ispeed;
193
194         if (cbaud & CBAUDEX) {
195                 cbaud &= ~CBAUDEX;
196
197                 if (cbaud < 1 || cbaud + 15 > n_baud_table)
198                         termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
199                 else
200                         cbaud += 15;
201         }
202         return baud_table[cbaud];
203 #else
204         return tty_termios_baud_rate(termios);
205 #endif
206 }
207 EXPORT_SYMBOL(tty_termios_input_baud_rate);
208
209 /**
210  *      tty_termios_encode_baud_rate
211  *      @termios: ktermios structure holding user requested state
212  *      @ispeed: input speed
213  *      @ospeed: output speed
214  *
215  *      Encode the speeds set into the passed termios structure. This is
216  *      used as a library helper for drivers os that they can report back
217  *      the actual speed selected when it differs from the speed requested
218  *
219  *      For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
220  *      we need to carefully set the bits when the user does not get the
221  *      desired speed. We allow small margins and preserve as much of possible
222  *      of the input intent to keep compatiblity.
223  *
224  *      Locking: Caller should hold termios lock. This is already held
225  *      when calling this function from the driver termios handler.
226  *
227  *      The ifdefs deal with platforms whose owners have yet to update them
228  *      and will all go away once this is done.
229  */
230
231 void tty_termios_encode_baud_rate(struct ktermios *termios,
232                                   speed_t ibaud, speed_t obaud)
233 {
234         int i = 0;
235         int ifound = -1, ofound = -1;
236         int iclose = ibaud/50, oclose = obaud/50;
237         int ibinput = 0;
238
239         if (obaud == 0)                 /* CD dropped             */
240                 ibaud = 0;              /* Clear ibaud to be sure */
241
242         termios->c_ispeed = ibaud;
243         termios->c_ospeed = obaud;
244
245 #ifdef BOTHER
246         /* If the user asked for a precise weird speed give a precise weird
247            answer. If they asked for a Bfoo speed they many have problems
248            digesting non-exact replies so fuzz a bit */
249
250         if ((termios->c_cflag & CBAUD) == BOTHER)
251                 oclose = 0;
252         if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
253                 iclose = 0;
254         if ((termios->c_cflag >> IBSHIFT) & CBAUD)
255                 ibinput = 1;    /* An input speed was specified */
256 #endif
257         termios->c_cflag &= ~CBAUD;
258
259         /*
260          *      Our goal is to find a close match to the standard baud rate
261          *      returned. Walk the baud rate table and if we get a very close
262          *      match then report back the speed as a POSIX Bxxxx value by
263          *      preference
264          */
265
266         do {
267                 if (obaud - oclose <= baud_table[i] &&
268                     obaud + oclose >= baud_table[i]) {
269                         termios->c_cflag |= baud_bits[i];
270                         ofound = i;
271                 }
272                 if (ibaud - iclose <= baud_table[i] &&
273                     ibaud + iclose >= baud_table[i]) {
274                         /* For the case input == output don't set IBAUD bits
275                            if the user didn't do so */
276                         if (ofound == i && !ibinput)
277                                 ifound  = i;
278 #ifdef IBSHIFT
279                         else {
280                                 ifound = i;
281                                 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
282                         }
283 #endif
284                 }
285         } while (++i < n_baud_table);
286
287         /*
288          *      If we found no match then use BOTHER if provided or warn
289          *      the user their platform maintainer needs to wake up if not.
290          */
291 #ifdef BOTHER
292         if (ofound == -1)
293                 termios->c_cflag |= BOTHER;
294         /* Set exact input bits only if the input and output differ or the
295            user already did */
296         if (ifound == -1 && (ibaud != obaud || ibinput))
297                 termios->c_cflag |= (BOTHER << IBSHIFT);
298 #else
299         if (ifound == -1 || ofound == -1) {
300                 static int warned;
301                 if (!warned++)
302                         printk(KERN_WARNING "tty: Unable to return correct "
303                           "speed data as your architecture needs updating.\n");
304         }
305 #endif
306 }
307 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
308
309 void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
310 {
311         tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
312 }
313 EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
314
315 /**
316  *      tty_get_baud_rate       -       get tty bit rates
317  *      @tty: tty to query
318  *
319  *      Returns the baud rate as an integer for this terminal. The
320  *      termios lock must be held by the caller and the terminal bit
321  *      flags may be updated.
322  *
323  *      Locking: none
324  */
325
326 speed_t tty_get_baud_rate(struct tty_struct *tty)
327 {
328         speed_t baud = tty_termios_baud_rate(tty->termios);
329
330         if (baud == 38400 && tty->alt_speed) {
331                 if (!tty->warned) {
332                         printk(KERN_WARNING "Use of setserial/setrocket to "
333                                             "set SPD_* flags is deprecated\n");
334                         tty->warned = 1;
335                 }
336                 baud = tty->alt_speed;
337         }
338
339         return baud;
340 }
341 EXPORT_SYMBOL(tty_get_baud_rate);
342
343 /**
344  *      tty_termios_copy_hw     -       copy hardware settings
345  *      @new: New termios
346  *      @old: Old termios
347  *
348  *      Propogate the hardware specific terminal setting bits from
349  *      the old termios structure to the new one. This is used in cases
350  *      where the hardware does not support reconfiguration or as a helper
351  *      in some cases where only minimal reconfiguration is supported
352  */
353
354 void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
355 {
356         /* The bits a dumb device handles in software. Smart devices need
357            to always provide a set_termios method */
358         new->c_cflag &= HUPCL | CREAD | CLOCAL;
359         new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
360         new->c_ispeed = old->c_ispeed;
361         new->c_ospeed = old->c_ospeed;
362 }
363 EXPORT_SYMBOL(tty_termios_copy_hw);
364
365 /**
366  *      tty_termios_hw_change   -       check for setting change
367  *      @a: termios
368  *      @b: termios to compare
369  *
370  *      Check if any of the bits that affect a dumb device have changed
371  *      between the two termios structures, or a speed change is needed.
372  */
373
374 int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
375 {
376         if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
377                 return 1;
378         if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
379                 return 1;
380         return 0;
381 }
382 EXPORT_SYMBOL(tty_termios_hw_change);
383
384 /**
385  *      change_termios          -       update termios values
386  *      @tty: tty to update
387  *      @new_termios: desired new value
388  *
389  *      Perform updates to the termios values set on this terminal. There
390  *      is a bit of layering violation here with n_tty in terms of the
391  *      internal knowledge of this function.
392  *
393  *      Locking: termios_sem
394  */
395
396 static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
397 {
398         int canon_change;
399         struct ktermios old_termios;
400         struct tty_ldisc *ld;
401         unsigned long flags;
402
403         /*
404          *      Perform the actual termios internal changes under lock.
405          */
406
407
408         /* FIXME: we need to decide on some locking/ordering semantics
409            for the set_termios notification eventually */
410         mutex_lock(&tty->termios_mutex);
411         old_termios = *tty->termios;
412         *tty->termios = *new_termios;
413         unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
414         canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
415         if (canon_change) {
416                 memset(&tty->read_flags, 0, sizeof tty->read_flags);
417                 tty->canon_head = tty->read_tail;
418                 tty->canon_data = 0;
419                 tty->erasing = 0;
420         }
421
422         /* This bit should be in the ldisc code */
423         if (canon_change && !L_ICANON(tty) && tty->read_cnt)
424                 /* Get characters left over from canonical mode. */
425                 wake_up_interruptible(&tty->read_wait);
426
427         /* See if packet mode change of state. */
428         if (tty->link && tty->link->packet) {
429                 int old_flow = ((old_termios.c_iflag & IXON) &&
430                                 (old_termios.c_cc[VSTOP] == '\023') &&
431                                 (old_termios.c_cc[VSTART] == '\021'));
432                 int new_flow = (I_IXON(tty) &&
433                                 STOP_CHAR(tty) == '\023' &&
434                                 START_CHAR(tty) == '\021');
435                 if (old_flow != new_flow) {
436                         spin_lock_irqsave(&tty->ctrl_lock, flags);
437                         tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
438                         if (new_flow)
439                                 tty->ctrl_status |= TIOCPKT_DOSTOP;
440                         else
441                                 tty->ctrl_status |= TIOCPKT_NOSTOP;
442                         spin_unlock_irqrestore(&tty->ctrl_lock, flags);
443                         wake_up_interruptible(&tty->link->read_wait);
444                 }
445         }
446
447         if (tty->driver->set_termios)
448                 (*tty->driver->set_termios)(tty, &old_termios);
449         else
450                 tty_termios_copy_hw(tty->termios, &old_termios);
451
452         ld = tty_ldisc_ref(tty);
453         if (ld != NULL) {
454                 if (ld->set_termios)
455                         (ld->set_termios)(tty, &old_termios);
456                 tty_ldisc_deref(ld);
457         }
458         mutex_unlock(&tty->termios_mutex);
459 }
460
461 /**
462  *      set_termios             -       set termios values for a tty
463  *      @tty: terminal device
464  *      @arg: user data
465  *      @opt: option information
466  *
467  *      Helper function to prepare termios data and run necessary other
468  *      functions before using change_termios to do the actual changes.
469  *
470  *      Locking:
471  *              Called functions take ldisc and termios_sem locks
472  */
473
474 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
475 {
476         struct ktermios tmp_termios;
477         struct tty_ldisc *ld;
478         int retval = tty_check_change(tty);
479
480         if (retval)
481                 return retval;
482
483         mutex_lock(&tty->termios_mutex);
484         memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
485         mutex_unlock(&tty->termios_mutex);
486
487         if (opt & TERMIOS_TERMIO) {
488                 if (user_termio_to_kernel_termios(&tmp_termios,
489                                                 (struct termio __user *)arg))
490                         return -EFAULT;
491 #ifdef TCGETS2
492         } else if (opt & TERMIOS_OLD) {
493                 if (user_termios_to_kernel_termios_1(&tmp_termios,
494                                                 (struct termios __user *)arg))
495                         return -EFAULT;
496         } else {
497                 if (user_termios_to_kernel_termios(&tmp_termios,
498                                                 (struct termios2 __user *)arg))
499                         return -EFAULT;
500         }
501 #else
502         } else if (user_termios_to_kernel_termios(&tmp_termios,
503                                         (struct termios __user *)arg))
504                 return -EFAULT;
505 #endif
506
507         /* If old style Bfoo values are used then load c_ispeed/c_ospeed
508          * with the real speed so its unconditionally usable */
509         tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
510         tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
511
512         ld = tty_ldisc_ref(tty);
513
514         if (ld != NULL) {
515                 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
516                         ld->flush_buffer(tty);
517                 tty_ldisc_deref(ld);
518         }
519
520         if (opt & TERMIOS_WAIT) {
521                 tty_wait_until_sent(tty, 0);
522                 if (signal_pending(current))
523                         return -EINTR;
524         }
525
526         change_termios(tty, &tmp_termios);
527
528         /* FIXME: Arguably if tmp_termios == tty->termios AND the
529            actual requested termios was not tmp_termios then we may
530            want to return an error as no user requested change has
531            succeeded */
532         return 0;
533 }
534
535 static int get_termio(struct tty_struct *tty, struct termio __user *termio)
536 {
537         if (kernel_termios_to_user_termio(termio, tty->termios))
538                 return -EFAULT;
539         return 0;
540 }
541
542 static unsigned long inq_canon(struct tty_struct *tty)
543 {
544         int nr, head, tail;
545
546         if (!tty->canon_data || !tty->read_buf)
547                 return 0;
548         head = tty->canon_head;
549         tail = tty->read_tail;
550         nr = (head - tail) & (N_TTY_BUF_SIZE-1);
551         /* Skip EOF-chars.. */
552         while (head != tail) {
553                 if (test_bit(tail, tty->read_flags) &&
554                     tty->read_buf[tail] == __DISABLED_CHAR)
555                         nr--;
556                 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
557         }
558         return nr;
559 }
560
561 #ifdef TIOCGETP
562 /*
563  * These are deprecated, but there is limited support..
564  *
565  * The "sg_flags" translation is a joke..
566  */
567 static int get_sgflags(struct tty_struct *tty)
568 {
569         int flags = 0;
570
571         if (!(tty->termios->c_lflag & ICANON)) {
572                 if (tty->termios->c_lflag & ISIG)
573                         flags |= 0x02;          /* cbreak */
574                 else
575                         flags |= 0x20;          /* raw */
576         }
577         if (tty->termios->c_lflag & ECHO)
578                 flags |= 0x08;                  /* echo */
579         if (tty->termios->c_oflag & OPOST)
580                 if (tty->termios->c_oflag & ONLCR)
581                         flags |= 0x10;          /* crmod */
582         return flags;
583 }
584
585 static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
586 {
587         struct sgttyb tmp;
588
589         mutex_lock(&tty->termios_mutex);
590         tmp.sg_ispeed = tty->termios->c_ispeed;
591         tmp.sg_ospeed = tty->termios->c_ospeed;
592         tmp.sg_erase = tty->termios->c_cc[VERASE];
593         tmp.sg_kill = tty->termios->c_cc[VKILL];
594         tmp.sg_flags = get_sgflags(tty);
595         mutex_unlock(&tty->termios_mutex);
596
597         return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
598 }
599
600 static void set_sgflags(struct ktermios *termios, int flags)
601 {
602         termios->c_iflag = ICRNL | IXON;
603         termios->c_oflag = 0;
604         termios->c_lflag = ISIG | ICANON;
605         if (flags & 0x02) {     /* cbreak */
606                 termios->c_iflag = 0;
607                 termios->c_lflag &= ~ICANON;
608         }
609         if (flags & 0x08) {             /* echo */
610                 termios->c_lflag |= ECHO | ECHOE | ECHOK |
611                                     ECHOCTL | ECHOKE | IEXTEN;
612         }
613         if (flags & 0x10) {             /* crmod */
614                 termios->c_oflag |= OPOST | ONLCR;
615         }
616         if (flags & 0x20) {     /* raw */
617                 termios->c_iflag = 0;
618                 termios->c_lflag &= ~(ISIG | ICANON);
619         }
620         if (!(termios->c_lflag & ICANON)) {
621                 termios->c_cc[VMIN] = 1;
622                 termios->c_cc[VTIME] = 0;
623         }
624 }
625
626 /**
627  *      set_sgttyb              -       set legacy terminal values
628  *      @tty: tty structure
629  *      @sgttyb: pointer to old style terminal structure
630  *
631  *      Updates a terminal from the legacy BSD style terminal information
632  *      structure.
633  *
634  *      Locking: termios_sem
635  */
636
637 static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
638 {
639         int retval;
640         struct sgttyb tmp;
641         struct ktermios termios;
642
643         retval = tty_check_change(tty);
644         if (retval)
645                 return retval;
646
647         if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
648                 return -EFAULT;
649
650         mutex_lock(&tty->termios_mutex);
651         termios = *tty->termios;
652         termios.c_cc[VERASE] = tmp.sg_erase;
653         termios.c_cc[VKILL] = tmp.sg_kill;
654         set_sgflags(&termios, tmp.sg_flags);
655         /* Try and encode into Bfoo format */
656 #ifdef BOTHER
657         tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
658                                                 termios.c_ospeed);
659 #endif
660         mutex_unlock(&tty->termios_mutex);
661         change_termios(tty, &termios);
662         return 0;
663 }
664 #endif
665
666 #ifdef TIOCGETC
667 static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
668 {
669         struct tchars tmp;
670
671         mutex_lock(&tty->termios_mutex);
672         tmp.t_intrc = tty->termios->c_cc[VINTR];
673         tmp.t_quitc = tty->termios->c_cc[VQUIT];
674         tmp.t_startc = tty->termios->c_cc[VSTART];
675         tmp.t_stopc = tty->termios->c_cc[VSTOP];
676         tmp.t_eofc = tty->termios->c_cc[VEOF];
677         tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
678         mutex_unlock(&tty->termios_mutex);
679         return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
680 }
681
682 static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
683 {
684         struct tchars tmp;
685
686         if (copy_from_user(&tmp, tchars, sizeof(tmp)))
687                 return -EFAULT;
688         mutex_lock(&tty->termios_mutex);
689         tty->termios->c_cc[VINTR] = tmp.t_intrc;
690         tty->termios->c_cc[VQUIT] = tmp.t_quitc;
691         tty->termios->c_cc[VSTART] = tmp.t_startc;
692         tty->termios->c_cc[VSTOP] = tmp.t_stopc;
693         tty->termios->c_cc[VEOF] = tmp.t_eofc;
694         tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
695         mutex_unlock(&tty->termios_mutex);
696         return 0;
697 }
698 #endif
699
700 #ifdef TIOCGLTC
701 static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
702 {
703         struct ltchars tmp;
704
705         mutex_lock(&tty->termios_mutex);
706         tmp.t_suspc = tty->termios->c_cc[VSUSP];
707         /* what is dsuspc anyway? */
708         tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
709         tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
710         /* what is flushc anyway? */
711         tmp.t_flushc = tty->termios->c_cc[VEOL2];
712         tmp.t_werasc = tty->termios->c_cc[VWERASE];
713         tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
714         mutex_unlock(&tty->termios_mutex);
715         return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
716 }
717
718 static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
719 {
720         struct ltchars tmp;
721
722         if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
723                 return -EFAULT;
724
725         mutex_lock(&tty->termios_mutex);
726         tty->termios->c_cc[VSUSP] = tmp.t_suspc;
727         /* what is dsuspc anyway? */
728         tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
729         tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
730         /* what is flushc anyway? */
731         tty->termios->c_cc[VEOL2] = tmp.t_flushc;
732         tty->termios->c_cc[VWERASE] = tmp.t_werasc;
733         tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
734         mutex_unlock(&tty->termios_mutex);
735         return 0;
736 }
737 #endif
738
739 /**
740  *      send_prio_char          -       send priority character
741  *
742  *      Send a high priority character to the tty even if stopped
743  *
744  *      Locking: none for xchar method, write ordering for write method.
745  */
746
747 static int send_prio_char(struct tty_struct *tty, char ch)
748 {
749         int     was_stopped = tty->stopped;
750
751         if (tty->driver->send_xchar) {
752                 tty->driver->send_xchar(tty, ch);
753                 return 0;
754         }
755
756         if (tty_write_lock(tty, 0) < 0)
757                 return -ERESTARTSYS;
758
759         if (was_stopped)
760                 start_tty(tty);
761         tty->driver->write(tty, &ch, 1);
762         if (was_stopped)
763                 stop_tty(tty);
764         tty_write_unlock(tty);
765         return 0;
766 }
767
768 /**
769  *      tty_change_softcar      -       carrier change ioctl helper
770  *      @tty: tty to update
771  *      @arg: enable/disable CLOCAL
772  *
773  *      Perform a change to the CLOCAL state and call into the driver
774  *      layer to make it visible. All done with the termios mutex
775  */
776
777 static int tty_change_softcar(struct tty_struct *tty, int arg)
778 {
779         int ret = 0;
780         int bit = arg ? CLOCAL : 0;
781         struct ktermios old = *tty->termios;
782
783         mutex_lock(&tty->termios_mutex);
784         tty->termios->c_cflag &= ~CLOCAL;
785         tty->termios->c_cflag |= bit;
786         if (tty->driver->set_termios)
787                 tty->driver->set_termios(tty, &old);
788         if ((tty->termios->c_cflag & CLOCAL) != bit)
789                 ret = -EINVAL;
790         mutex_unlock(&tty->termios_mutex);
791         return ret;
792 }
793
794 /**
795  *      tty_mode_ioctl          -       mode related ioctls
796  *      @tty: tty for the ioctl
797  *      @file: file pointer for the tty
798  *      @cmd: command
799  *      @arg: ioctl argument
800  *
801  *      Perform non line discipline specific mode control ioctls. This
802  *      is designed to be called by line disciplines to ensure they provide
803  *      consistent mode setting.
804  */
805
806 int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
807                         unsigned int cmd, unsigned long arg)
808 {
809         struct tty_struct *real_tty;
810         void __user *p = (void __user *)arg;
811
812         if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
813             tty->driver->subtype == PTY_TYPE_MASTER)
814                 real_tty = tty->link;
815         else
816                 real_tty = tty;
817
818         switch (cmd) {
819 #ifdef TIOCGETP
820         case TIOCGETP:
821                 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
822         case TIOCSETP:
823         case TIOCSETN:
824                 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
825 #endif
826 #ifdef TIOCGETC
827         case TIOCGETC:
828                 return get_tchars(real_tty, p);
829         case TIOCSETC:
830                 return set_tchars(real_tty, p);
831 #endif
832 #ifdef TIOCGLTC
833         case TIOCGLTC:
834                 return get_ltchars(real_tty, p);
835         case TIOCSLTC:
836                 return set_ltchars(real_tty, p);
837 #endif
838         case TCSETSF:
839                 return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
840         case TCSETSW:
841                 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
842         case TCSETS:
843                 return set_termios(real_tty, p, TERMIOS_OLD);
844 #ifndef TCGETS2
845         case TCGETS:
846                 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
847                         return -EFAULT;
848                 return 0;
849 #else
850         case TCGETS:
851                 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
852                         return -EFAULT;
853                 return 0;
854         case TCGETS2:
855                 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
856                         return -EFAULT;
857                 return 0;
858         case TCSETSF2:
859                 return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
860         case TCSETSW2:
861                 return set_termios(real_tty, p, TERMIOS_WAIT);
862         case TCSETS2:
863                 return set_termios(real_tty, p, 0);
864 #endif
865         case TCGETA:
866                 return get_termio(real_tty, p);
867         case TCSETAF:
868                 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
869         case TCSETAW:
870                 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
871         case TCSETA:
872                 return set_termios(real_tty, p, TERMIOS_TERMIO);
873 #ifndef TCGETS2
874         case TIOCGLCKTRMIOS:
875                 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
876                         return -EFAULT;
877                 return 0;
878         case TIOCSLCKTRMIOS:
879                 if (!capable(CAP_SYS_ADMIN))
880                         return -EPERM;
881                 if (user_termios_to_kernel_termios(real_tty->termios_locked,
882                                                (struct termios __user *) arg))
883                         return -EFAULT;
884                 return 0;
885 #else
886         case TIOCGLCKTRMIOS:
887                 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
888                         return -EFAULT;
889                 return 0;
890         case TIOCSLCKTRMIOS:
891                 if (!capable(CAP_SYS_ADMIN))
892                         return -EPERM;
893                 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
894                                                (struct termios __user *) arg))
895                         return -EFAULT;
896                         return 0;
897 #endif
898         case TIOCGSOFTCAR:
899                 return put_user(C_CLOCAL(tty) ? 1 : 0,
900                                                 (int __user *)arg);
901         case TIOCSSOFTCAR:
902                 if (get_user(arg, (unsigned int __user *) arg))
903                         return -EFAULT;
904                 return tty_change_softcar(tty, arg);
905         default:
906                 return -ENOIOCTLCMD;
907         }
908 }
909 EXPORT_SYMBOL_GPL(tty_mode_ioctl);
910
911 int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
912 {
913         struct tty_ldisc *ld;
914         int retval = tty_check_change(tty);
915         if (retval)
916                 return retval;
917
918         ld = tty_ldisc_ref(tty);
919         switch (arg) {
920         case TCIFLUSH:
921                 if (ld && ld->flush_buffer)
922                         ld->flush_buffer(tty);
923                 break;
924         case TCIOFLUSH:
925                 if (ld && ld->flush_buffer)
926                         ld->flush_buffer(tty);
927                 /* fall through */
928         case TCOFLUSH:
929                 if (tty->driver->flush_buffer)
930                         tty->driver->flush_buffer(tty);
931                 break;
932         default:
933                 tty_ldisc_deref(ld);
934                 return -EINVAL;
935         }
936         tty_ldisc_deref(ld);
937         return 0;
938 }
939 EXPORT_SYMBOL_GPL(tty_perform_flush);
940
941 int n_tty_ioctl(struct tty_struct *tty, struct file *file,
942                        unsigned int cmd, unsigned long arg)
943 {
944         struct tty_struct *real_tty;
945         unsigned long flags;
946         int retval;
947
948         if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
949             tty->driver->subtype == PTY_TYPE_MASTER)
950                 real_tty = tty->link;
951         else
952                 real_tty = tty;
953
954         switch (cmd) {
955         case TCXONC:
956                 retval = tty_check_change(tty);
957                 if (retval)
958                         return retval;
959                 switch (arg) {
960                 case TCOOFF:
961                         if (!tty->flow_stopped) {
962                                 tty->flow_stopped = 1;
963                                 stop_tty(tty);
964                         }
965                         break;
966                 case TCOON:
967                         if (tty->flow_stopped) {
968                                 tty->flow_stopped = 0;
969                                 start_tty(tty);
970                         }
971                         break;
972                 case TCIOFF:
973                         if (STOP_CHAR(tty) != __DISABLED_CHAR)
974                                 return send_prio_char(tty, STOP_CHAR(tty));
975                         break;
976                 case TCION:
977                         if (START_CHAR(tty) != __DISABLED_CHAR)
978                                 return send_prio_char(tty, START_CHAR(tty));
979                         break;
980                 default:
981                         return -EINVAL;
982                 }
983                 return 0;
984         case TCFLSH:
985                 return tty_perform_flush(tty, arg);
986         case TIOCOUTQ:
987                 return put_user(tty->driver->chars_in_buffer ?
988                                 tty->driver->chars_in_buffer(tty) : 0,
989                                 (int __user *) arg);
990         case TIOCINQ:
991                 retval = tty->read_cnt;
992                 if (L_ICANON(tty))
993                         retval = inq_canon(tty);
994                 return put_user(retval, (unsigned int __user *) arg);
995         case TIOCPKT:
996         {
997                 int pktmode;
998
999                 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
1000                     tty->driver->subtype != PTY_TYPE_MASTER)
1001                         return -ENOTTY;
1002                 if (get_user(pktmode, (int __user *) arg))
1003                         return -EFAULT;
1004                 spin_lock_irqsave(&tty->ctrl_lock, flags);
1005                 if (pktmode) {
1006                         if (!tty->packet) {
1007                                 tty->packet = 1;
1008                                 tty->link->ctrl_status = 0;
1009                         }
1010                 } else
1011                         tty->packet = 0;
1012                 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1013                 return 0;
1014         }
1015         default:
1016                 /* Try the mode commands */
1017                 return tty_mode_ioctl(tty, file, cmd, arg);
1018         }
1019 }
1020 EXPORT_SYMBOL(n_tty_ioctl);