tty: expose new methods needed for drivers to get termios right
[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 #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 /**
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, speed_t ibaud, speed_t obaud)
232 {
233         int i = 0;
234         int ifound = -1, ofound = -1;
235         int iclose = ibaud/50, oclose = obaud/50;
236         int ibinput = 0;
237
238         if (obaud == 0)                 /* CD dropped             */
239                 ibaud = 0;              /* Clear ibaud to be sure */
240
241         termios->c_ispeed = ibaud;
242         termios->c_ospeed = obaud;
243
244 #ifdef BOTHER
245         /* If the user asked for a precise weird speed give a precise weird
246            answer. If they asked for a Bfoo speed they many have problems
247            digesting non-exact replies so fuzz a bit */
248
249         if ((termios->c_cflag & CBAUD) == BOTHER)
250                 oclose = 0;
251         if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
252                 iclose = 0;
253         if ((termios->c_cflag >> IBSHIFT) & CBAUD)
254                 ibinput = 1;    /* An input speed was specified */
255 #endif
256         termios->c_cflag &= ~CBAUD;
257
258         /*
259          *      Our goal is to find a close match to the standard baud rate
260          *      returned. Walk the baud rate table and if we get a very close
261          *      match then report back the speed as a POSIX Bxxxx value by
262          *      preference
263          */
264
265         do {
266                 if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
267                         termios->c_cflag |= baud_bits[i];
268                         ofound = i;
269                 }
270                 if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) {
271                         if (ofound == i && !ibinput)
272                                 ifound  = i;
273 #ifdef IBSHIFT
274                         else {
275                                 ifound = i;
276                                 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
277                         }
278 #endif
279                 }
280         } while (++i < n_baud_table);
281
282         /*
283          *      If we found no match then use BOTHER if provided or warn
284          *      the user their platform maintainer needs to wake up if not.
285          */
286 #ifdef BOTHER
287         if (ofound == -1)
288                 termios->c_cflag |= BOTHER;
289         /* Set exact input bits only if the input and output differ or the
290            user already did */
291         if (ifound == -1 && (ibaud != obaud || ibinput))
292                 termios->c_cflag |= (BOTHER << IBSHIFT);
293 #else
294         if (ifound == -1 || ofound == -1) {
295                 static int warned;
296                 if (!warned++)
297                         printk(KERN_WARNING "tty: Unable to return correct "
298                           "speed data as your architecture needs updating.\n");
299         }
300 #endif
301 }
302 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
303
304 void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
305 {
306         tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
307 }
308 EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
309
310 /**
311  *      tty_get_baud_rate       -       get tty bit rates
312  *      @tty: tty to query
313  *
314  *      Returns the baud rate as an integer for this terminal. The
315  *      termios lock must be held by the caller and the terminal bit
316  *      flags may be updated.
317  *
318  *      Locking: none
319  */
320
321 speed_t tty_get_baud_rate(struct tty_struct *tty)
322 {
323         speed_t baud = tty_termios_baud_rate(tty->termios);
324
325         if (baud == 38400 && tty->alt_speed) {
326                 if (!tty->warned) {
327                         printk(KERN_WARNING "Use of setserial/setrocket to "
328                                             "set SPD_* flags is deprecated\n");
329                         tty->warned = 1;
330                 }
331                 baud = tty->alt_speed;
332         }
333
334         return baud;
335 }
336
337 EXPORT_SYMBOL(tty_get_baud_rate);
338
339 /**
340  *      tty_termios_copy_hw     -       copy hardware settings
341  *      @new: New termios
342  *      @old: Old termios
343  *
344  *      Propogate the hardware specific terminal setting bits from
345  *      the old termios structure to the new one. This is used in cases
346  *      where the hardware does not support reconfiguration or as a helper
347  *      in some cases where only minimal reconfiguration is supported
348  */
349
350 void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
351 {
352         /* The bits a dumb device handles in software. Smart devices need
353            to always provide a set_termios method */
354         new->c_cflag &= HUPCL | CREAD | CLOCAL;
355         new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
356         new->c_ispeed = old->c_ispeed;
357         new->c_ospeed = old->c_ospeed;
358 }
359
360 EXPORT_SYMBOL(tty_termios_copy_hw);
361
362 /**
363  *      change_termios          -       update termios values
364  *      @tty: tty to update
365  *      @new_termios: desired new value
366  *
367  *      Perform updates to the termios values set on this terminal. There
368  *      is a bit of layering violation here with n_tty in terms of the
369  *      internal knowledge of this function.
370  *
371  *      Locking: termios_sem
372  */
373
374 static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
375 {
376         int canon_change;
377         struct ktermios old_termios = *tty->termios;
378         struct tty_ldisc *ld;
379         
380         /*
381          *      Perform the actual termios internal changes under lock.
382          */
383          
384
385         /* FIXME: we need to decide on some locking/ordering semantics
386            for the set_termios notification eventually */
387         mutex_lock(&tty->termios_mutex);
388
389         *tty->termios = *new_termios;
390         unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
391         canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
392         if (canon_change) {
393                 memset(&tty->read_flags, 0, sizeof tty->read_flags);
394                 tty->canon_head = tty->read_tail;
395                 tty->canon_data = 0;
396                 tty->erasing = 0;
397         }
398         
399         /* This bit should be in the ldisc code */
400         if (canon_change && !L_ICANON(tty) && tty->read_cnt)
401                 /* Get characters left over from canonical mode. */
402                 wake_up_interruptible(&tty->read_wait);
403
404         /* See if packet mode change of state. */
405         if (tty->link && tty->link->packet) {
406                 int old_flow = ((old_termios.c_iflag & IXON) &&
407                                 (old_termios.c_cc[VSTOP] == '\023') &&
408                                 (old_termios.c_cc[VSTART] == '\021'));
409                 int new_flow = (I_IXON(tty) &&
410                                 STOP_CHAR(tty) == '\023' &&
411                                 START_CHAR(tty) == '\021');
412                 if (old_flow != new_flow) {
413                         tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
414                         if (new_flow)
415                                 tty->ctrl_status |= TIOCPKT_DOSTOP;
416                         else
417                                 tty->ctrl_status |= TIOCPKT_NOSTOP;
418                         wake_up_interruptible(&tty->link->read_wait);
419                 }
420         }
421            
422         if (tty->driver->set_termios)
423                 (*tty->driver->set_termios)(tty, &old_termios);
424         else
425                 tty_termios_copy_hw(tty->termios, &old_termios);
426
427         ld = tty_ldisc_ref(tty);
428         if (ld != NULL) {
429                 if (ld->set_termios)
430                         (ld->set_termios)(tty, &old_termios);
431                 tty_ldisc_deref(ld);
432         }
433         mutex_unlock(&tty->termios_mutex);
434 }
435
436 /**
437  *      set_termios             -       set termios values for a tty
438  *      @tty: terminal device
439  *      @arg: user data
440  *      @opt: option information
441  *
442  *      Helper function to prepare termios data and run neccessary other
443  *      functions before using change_termios to do the actual changes.
444  *
445  *      Locking:
446  *              Called functions take ldisc and termios_sem locks
447  */
448
449 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
450 {
451         struct ktermios tmp_termios;
452         struct tty_ldisc *ld;
453         int retval = tty_check_change(tty);
454
455         if (retval)
456                 return retval;
457
458         memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
459
460         if (opt & TERMIOS_TERMIO) {
461                 if (user_termio_to_kernel_termios(&tmp_termios,
462                                                 (struct termio __user *)arg))
463                         return -EFAULT;
464 #ifdef TCGETS2
465         } else if (opt & TERMIOS_OLD) {
466                 if (user_termios_to_kernel_termios_1(&tmp_termios,
467                                                 (struct termios __user *)arg))
468                         return -EFAULT;
469         } else {
470                 if (user_termios_to_kernel_termios(&tmp_termios,
471                                                 (struct termios2 __user *)arg))
472                         return -EFAULT;
473         }
474 #else
475         } else if (user_termios_to_kernel_termios(&tmp_termios,
476                                         (struct termios __user *)arg))
477                 return -EFAULT;
478 #endif
479
480         /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
481            so its unconditionally usable */
482         tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
483         tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
484
485         ld = tty_ldisc_ref(tty);
486         
487         if (ld != NULL) {
488                 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
489                         ld->flush_buffer(tty);
490                 tty_ldisc_deref(ld);
491         }
492         
493         if (opt & TERMIOS_WAIT) {
494                 tty_wait_until_sent(tty, 0);
495                 if (signal_pending(current))
496                         return -EINTR;
497         }
498
499         change_termios(tty, &tmp_termios);
500
501         /* FIXME: Arguably if tmp_termios == tty->termios AND the
502            actual requested termios was not tmp_termios then we may
503            want to return an error as no user requested change has
504            succeeded */
505         return 0;
506 }
507
508 static int get_termio(struct tty_struct * tty, struct termio __user * termio)
509 {
510         if (kernel_termios_to_user_termio(termio, tty->termios))
511                 return -EFAULT;
512         return 0;
513 }
514
515 static unsigned long inq_canon(struct tty_struct * tty)
516 {
517         int nr, head, tail;
518
519         if (!tty->canon_data || !tty->read_buf)
520                 return 0;
521         head = tty->canon_head;
522         tail = tty->read_tail;
523         nr = (head - tail) & (N_TTY_BUF_SIZE-1);
524         /* Skip EOF-chars.. */
525         while (head != tail) {
526                 if (test_bit(tail, tty->read_flags) &&
527                     tty->read_buf[tail] == __DISABLED_CHAR)
528                         nr--;
529                 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
530         }
531         return nr;
532 }
533
534 #ifdef TIOCGETP
535 /*
536  * These are deprecated, but there is limited support..
537  *
538  * The "sg_flags" translation is a joke..
539  */
540 static int get_sgflags(struct tty_struct * tty)
541 {
542         int flags = 0;
543
544         if (!(tty->termios->c_lflag & ICANON)) {
545                 if (tty->termios->c_lflag & ISIG)
546                         flags |= 0x02;          /* cbreak */
547                 else
548                         flags |= 0x20;          /* raw */
549         }
550         if (tty->termios->c_lflag & ECHO)
551                 flags |= 0x08;                  /* echo */
552         if (tty->termios->c_oflag & OPOST)
553                 if (tty->termios->c_oflag & ONLCR)
554                         flags |= 0x10;          /* crmod */
555         return flags;
556 }
557
558 static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
559 {
560         struct sgttyb tmp;
561
562         mutex_lock(&tty->termios_mutex);
563         tmp.sg_ispeed = tty->termios->c_ispeed;
564         tmp.sg_ospeed = tty->termios->c_ospeed;
565         tmp.sg_erase = tty->termios->c_cc[VERASE];
566         tmp.sg_kill = tty->termios->c_cc[VKILL];
567         tmp.sg_flags = get_sgflags(tty);
568         mutex_unlock(&tty->termios_mutex);
569         
570         return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
571 }
572
573 static void set_sgflags(struct ktermios * termios, int flags)
574 {
575         termios->c_iflag = ICRNL | IXON;
576         termios->c_oflag = 0;
577         termios->c_lflag = ISIG | ICANON;
578         if (flags & 0x02) {     /* cbreak */
579                 termios->c_iflag = 0;
580                 termios->c_lflag &= ~ICANON;
581         }
582         if (flags & 0x08) {             /* echo */
583                 termios->c_lflag |= ECHO | ECHOE | ECHOK |
584                                     ECHOCTL | ECHOKE | IEXTEN;
585         }
586         if (flags & 0x10) {             /* crmod */
587                 termios->c_oflag |= OPOST | ONLCR;
588         }
589         if (flags & 0x20) {     /* raw */
590                 termios->c_iflag = 0;
591                 termios->c_lflag &= ~(ISIG | ICANON);
592         }
593         if (!(termios->c_lflag & ICANON)) {
594                 termios->c_cc[VMIN] = 1;
595                 termios->c_cc[VTIME] = 0;
596         }
597 }
598
599 /**
600  *      set_sgttyb              -       set legacy terminal values
601  *      @tty: tty structure
602  *      @sgttyb: pointer to old style terminal structure
603  *
604  *      Updates a terminal from the legacy BSD style terminal information
605  *      structure.
606  *
607  *      Locking: termios_sem
608  */
609
610 static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
611 {
612         int retval;
613         struct sgttyb tmp;
614         struct ktermios termios;
615
616         retval = tty_check_change(tty);
617         if (retval)
618                 return retval;
619         
620         if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
621                 return -EFAULT;
622
623         mutex_lock(&tty->termios_mutex);
624         termios = *tty->termios;
625         termios.c_cc[VERASE] = tmp.sg_erase;
626         termios.c_cc[VKILL] = tmp.sg_kill;
627         set_sgflags(&termios, tmp.sg_flags);
628         /* Try and encode into Bfoo format */
629 #ifdef BOTHER
630         tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
631 #endif
632         mutex_unlock(&tty->termios_mutex);
633         change_termios(tty, &termios);
634         return 0;
635 }
636 #endif
637
638 #ifdef TIOCGETC
639 static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
640 {
641         struct tchars tmp;
642
643         tmp.t_intrc = tty->termios->c_cc[VINTR];
644         tmp.t_quitc = tty->termios->c_cc[VQUIT];
645         tmp.t_startc = tty->termios->c_cc[VSTART];
646         tmp.t_stopc = tty->termios->c_cc[VSTOP];
647         tmp.t_eofc = tty->termios->c_cc[VEOF];
648         tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
649         return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
650 }
651
652 static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
653 {
654         struct tchars tmp;
655
656         if (copy_from_user(&tmp, tchars, sizeof(tmp)))
657                 return -EFAULT;
658         tty->termios->c_cc[VINTR] = tmp.t_intrc;
659         tty->termios->c_cc[VQUIT] = tmp.t_quitc;
660         tty->termios->c_cc[VSTART] = tmp.t_startc;
661         tty->termios->c_cc[VSTOP] = tmp.t_stopc;
662         tty->termios->c_cc[VEOF] = tmp.t_eofc;
663         tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
664         return 0;
665 }
666 #endif
667
668 #ifdef TIOCGLTC
669 static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
670 {
671         struct ltchars tmp;
672
673         tmp.t_suspc = tty->termios->c_cc[VSUSP];
674         tmp.t_dsuspc = tty->termios->c_cc[VSUSP];       /* what is dsuspc anyway? */
675         tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
676         tmp.t_flushc = tty->termios->c_cc[VEOL2];       /* what is flushc anyway? */
677         tmp.t_werasc = tty->termios->c_cc[VWERASE];
678         tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
679         return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
680 }
681
682 static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
683 {
684         struct ltchars tmp;
685
686         if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
687                 return -EFAULT;
688
689         tty->termios->c_cc[VSUSP] = tmp.t_suspc;
690         tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;       /* what is dsuspc anyway? */
691         tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
692         tty->termios->c_cc[VEOL2] = tmp.t_flushc;       /* what is flushc anyway? */
693         tty->termios->c_cc[VWERASE] = tmp.t_werasc;
694         tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
695         return 0;
696 }
697 #endif
698
699 /**
700  *      send_prio_char          -       send priority character
701  *
702  *      Send a high priority character to the tty even if stopped
703  *
704  *      Locking: none for xchar method, write ordering for write method.
705  */
706
707 static int send_prio_char(struct tty_struct *tty, char ch)
708 {
709         int     was_stopped = tty->stopped;
710
711         if (tty->driver->send_xchar) {
712                 tty->driver->send_xchar(tty, ch);
713                 return 0;
714         }
715
716         if (tty_write_lock(tty, 0) < 0)
717                 return -ERESTARTSYS;
718
719         if (was_stopped)
720                 start_tty(tty);
721         tty->driver->write(tty, &ch, 1);
722         if (was_stopped)
723                 stop_tty(tty);
724         tty_write_unlock(tty);
725         return 0;
726 }
727
728 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
729                        unsigned int cmd, unsigned long arg)
730 {
731         struct tty_struct * real_tty;
732         void __user *p = (void __user *)arg;
733         int retval;
734         struct tty_ldisc *ld;
735
736         if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
737             tty->driver->subtype == PTY_TYPE_MASTER)
738                 real_tty = tty->link;
739         else
740                 real_tty = tty;
741
742         switch (cmd) {
743 #ifdef TIOCGETP
744                 case TIOCGETP:
745                         return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
746                 case TIOCSETP:
747                 case TIOCSETN:
748                         return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
749 #endif
750 #ifdef TIOCGETC
751                 case TIOCGETC:
752                         return get_tchars(real_tty, p);
753                 case TIOCSETC:
754                         return set_tchars(real_tty, p);
755 #endif
756 #ifdef TIOCGLTC
757                 case TIOCGLTC:
758                         return get_ltchars(real_tty, p);
759                 case TIOCSLTC:
760                         return set_ltchars(real_tty, p);
761 #endif
762                 case TCSETSF:
763                         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
764                 case TCSETSW:
765                         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
766                 case TCSETS:
767                         return set_termios(real_tty, p, TERMIOS_OLD);
768 #ifndef TCGETS2
769                 case TCGETS:
770                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
771                                 return -EFAULT;
772                         return 0;
773 #else
774                 case TCGETS:
775                         if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
776                                 return -EFAULT;
777                         return 0;
778                 case TCGETS2:
779                         if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
780                                 return -EFAULT;
781                         return 0;
782                 case TCSETSF2:
783                         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
784                 case TCSETSW2:
785                         return set_termios(real_tty, p, TERMIOS_WAIT);
786                 case TCSETS2:
787                         return set_termios(real_tty, p, 0);
788 #endif
789                 case TCGETA:
790                         return get_termio(real_tty, p);
791                 case TCSETAF:
792                         return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
793                 case TCSETAW:
794                         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
795                 case TCSETA:
796                         return set_termios(real_tty, p, TERMIOS_TERMIO);
797                 case TCXONC:
798                         retval = tty_check_change(tty);
799                         if (retval)
800                                 return retval;
801                         switch (arg) {
802                         case TCOOFF:
803                                 if (!tty->flow_stopped) {
804                                         tty->flow_stopped = 1;
805                                         stop_tty(tty);
806                                 }
807                                 break;
808                         case TCOON:
809                                 if (tty->flow_stopped) {
810                                         tty->flow_stopped = 0;
811                                         start_tty(tty);
812                                 }
813                                 break;
814                         case TCIOFF:
815                                 if (STOP_CHAR(tty) != __DISABLED_CHAR)
816                                         return send_prio_char(tty, STOP_CHAR(tty));
817                                 break;
818                         case TCION:
819                                 if (START_CHAR(tty) != __DISABLED_CHAR)
820                                         return send_prio_char(tty, START_CHAR(tty));
821                                 break;
822                         default:
823                                 return -EINVAL;
824                         }
825                         return 0;
826                 case TCFLSH:
827                         retval = tty_check_change(tty);
828                         if (retval)
829                                 return retval;
830                                 
831                         ld = tty_ldisc_ref(tty);
832                         switch (arg) {
833                         case TCIFLUSH:
834                                 if (ld && ld->flush_buffer)
835                                         ld->flush_buffer(tty);
836                                 break;
837                         case TCIOFLUSH:
838                                 if (ld && ld->flush_buffer)
839                                         ld->flush_buffer(tty);
840                                 /* fall through */
841                         case TCOFLUSH:
842                                 if (tty->driver->flush_buffer)
843                                         tty->driver->flush_buffer(tty);
844                                 break;
845                         default:
846                                 tty_ldisc_deref(ld);
847                                 return -EINVAL;
848                         }
849                         tty_ldisc_deref(ld);
850                         return 0;
851                 case TIOCOUTQ:
852                         return put_user(tty->driver->chars_in_buffer ?
853                                         tty->driver->chars_in_buffer(tty) : 0,
854                                         (int __user *) arg);
855                 case TIOCINQ:
856                         retval = tty->read_cnt;
857                         if (L_ICANON(tty))
858                                 retval = inq_canon(tty);
859                         return put_user(retval, (unsigned int __user *) arg);
860 #ifndef TCGETS2
861                 case TIOCGLCKTRMIOS:
862                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
863                                 return -EFAULT;
864                         return 0;
865
866                 case TIOCSLCKTRMIOS:
867                         if (!capable(CAP_SYS_ADMIN))
868                                 return -EPERM;
869                         if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
870                                 return -EFAULT;
871                         return 0;
872 #else
873                 case TIOCGLCKTRMIOS:
874                         if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
875                                 return -EFAULT;
876                         return 0;
877
878                 case TIOCSLCKTRMIOS:
879                         if (!capable(CAP_SYS_ADMIN))
880                                 return -EPERM;
881                         if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
882                                 return -EFAULT;
883                         return 0;
884 #endif
885
886                 case TIOCPKT:
887                 {
888                         int pktmode;
889
890                         if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
891                             tty->driver->subtype != PTY_TYPE_MASTER)
892                                 return -ENOTTY;
893                         if (get_user(pktmode, (int __user *) arg))
894                                 return -EFAULT;
895                         if (pktmode) {
896                                 if (!tty->packet) {
897                                         tty->packet = 1;
898                                         tty->link->ctrl_status = 0;
899                                 }
900                         } else
901                                 tty->packet = 0;
902                         return 0;
903                 }
904                 case TIOCGSOFTCAR:
905                         return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
906                 case TIOCSSOFTCAR:
907                         if (get_user(arg, (unsigned int __user *) arg))
908                                 return -EFAULT;
909                         mutex_lock(&tty->termios_mutex);
910                         tty->termios->c_cflag =
911                                 ((tty->termios->c_cflag & ~CLOCAL) |
912                                  (arg ? CLOCAL : 0));
913                         mutex_unlock(&tty->termios_mutex);
914                         return 0;
915                 default:
916                         return -ENOIOCTLCMD;
917                 }
918 }
919
920 EXPORT_SYMBOL(n_tty_ioctl);