tty_ioctl: locking for tty_wait_until_sent
[linux-2.6/verdex.git] / drivers / char / tty_ioctl.c
blob851cfcd2702a6ff19e85ed68e3fc50e1a07a4951
1 /*
2 * linux/drivers/char/tty_ioctl.c
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
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 */
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>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include <asm/system.h>
30 #undef TTY_DEBUG_WAIT_UNTIL_SENT
32 #undef DEBUG
35 * Internal flag options for termios setting behavior
37 #define TERMIOS_FLUSH 1
38 #define TERMIOS_WAIT 2
39 #define TERMIOS_TERMIO 4
40 #define TERMIOS_OLD 8
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
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)
51 * Locking: none
54 void tty_wait_until_sent(struct tty_struct *tty, long timeout)
56 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
57 char buf[64];
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);
71 unlock_kernel();
73 EXPORT_SYMBOL(tty_wait_until_sent);
75 static void unset_locked_termios(struct ktermios *termios,
76 struct ktermios *old,
77 struct ktermios *locked)
79 int i;
81 #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
83 if (!locked) {
84 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
85 return;
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 */
100 * Routine which returns the baud rate of the tty
102 * Note that the baud_table needs to be kept in sync with the
103 * include/asm/termbits.h file.
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
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
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
131 #endif
133 static int n_baud_table = ARRAY_SIZE(baud_table);
136 * tty_termios_baud_rate
137 * @termios: termios structure
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.
144 * Locking: none
147 speed_t tty_termios_baud_rate(struct ktermios *termios)
149 unsigned int cbaud;
151 cbaud = termios->c_cflag & CBAUD;
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;
161 if (cbaud < 1 || cbaud + 15 > n_baud_table)
162 termios->c_cflag &= ~CBAUDEX;
163 else
164 cbaud += 15;
166 return baud_table[cbaud];
168 EXPORT_SYMBOL(tty_termios_baud_rate);
171 * tty_termios_input_baud_rate
172 * @termios: termios structure
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.
179 * Locking: none
182 speed_t tty_termios_input_baud_rate(struct ktermios *termios)
184 #ifdef IBSHIFT
185 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
187 if (cbaud == B0)
188 return tty_termios_baud_rate(termios);
190 /* Magic token for arbitary speed via c_ispeed*/
191 if (cbaud == BOTHER)
192 return termios->c_ispeed;
194 if (cbaud & CBAUDEX) {
195 cbaud &= ~CBAUDEX;
197 if (cbaud < 1 || cbaud + 15 > n_baud_table)
198 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
199 else
200 cbaud += 15;
202 return baud_table[cbaud];
203 #else
204 return tty_termios_baud_rate(termios);
205 #endif
207 EXPORT_SYMBOL(tty_termios_input_baud_rate);
210 * tty_termios_encode_baud_rate
211 * @termios: ktermios structure holding user requested state
212 * @ispeed: input speed
213 * @ospeed: output speed
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
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.
224 * Locking: Caller should hold termios lock. This is already held
225 * when calling this function from the driver termios handler.
227 * The ifdefs deal with platforms whose owners have yet to update them
228 * and will all go away once this is done.
231 void tty_termios_encode_baud_rate(struct ktermios *termios,
232 speed_t ibaud, speed_t obaud)
234 int i = 0;
235 int ifound = -1, ofound = -1;
236 int iclose = ibaud/50, oclose = obaud/50;
237 int ibinput = 0;
239 if (obaud == 0) /* CD dropped */
240 ibaud = 0; /* Clear ibaud to be sure */
242 termios->c_ispeed = ibaud;
243 termios->c_ospeed = obaud;
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 */
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;
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
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;
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);
283 #endif
285 } while (++i < n_baud_table);
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.
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");
305 #endif
307 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
309 void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
311 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
313 EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
316 * tty_get_baud_rate - get tty bit rates
317 * @tty: tty to query
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.
323 * Locking: none
326 speed_t tty_get_baud_rate(struct tty_struct *tty)
328 speed_t baud = tty_termios_baud_rate(tty->termios);
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;
336 baud = tty->alt_speed;
339 return baud;
341 EXPORT_SYMBOL(tty_get_baud_rate);
344 * tty_termios_copy_hw - copy hardware settings
345 * @new: New termios
346 * @old: Old termios
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
354 void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
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;
363 EXPORT_SYMBOL(tty_termios_copy_hw);
366 * tty_termios_hw_change - check for setting change
367 * @a: termios
368 * @b: termios to compare
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.
374 int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
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;
382 EXPORT_SYMBOL(tty_termios_hw_change);
385 * change_termios - update termios values
386 * @tty: tty to update
387 * @new_termios: desired new value
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.
393 * Locking: termios_sem
396 static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
398 int canon_change;
399 struct ktermios old_termios = *tty->termios;
400 struct tty_ldisc *ld;
401 unsigned long flags;
404 * Perform the actual termios internal changes under lock.
408 /* FIXME: we need to decide on some locking/ordering semantics
409 for the set_termios notification eventually */
410 mutex_lock(&tty->termios_mutex);
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;
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);
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);
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);
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);
458 mutex_unlock(&tty->termios_mutex);
462 * set_termios - set termios values for a tty
463 * @tty: terminal device
464 * @arg: user data
465 * @opt: option information
467 * Helper function to prepare termios data and run necessary other
468 * functions before using change_termios to do the actual changes.
470 * Locking:
471 * Called functions take ldisc and termios_sem locks
474 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
476 struct ktermios tmp_termios;
477 struct tty_ldisc *ld;
478 int retval = tty_check_change(tty);
480 if (retval)
481 return retval;
483 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
485 if (opt & TERMIOS_TERMIO) {
486 if (user_termio_to_kernel_termios(&tmp_termios,
487 (struct termio __user *)arg))
488 return -EFAULT;
489 #ifdef TCGETS2
490 } else if (opt & TERMIOS_OLD) {
491 if (user_termios_to_kernel_termios_1(&tmp_termios,
492 (struct termios __user *)arg))
493 return -EFAULT;
494 } else {
495 if (user_termios_to_kernel_termios(&tmp_termios,
496 (struct termios2 __user *)arg))
497 return -EFAULT;
499 #else
500 } else if (user_termios_to_kernel_termios(&tmp_termios,
501 (struct termios __user *)arg))
502 return -EFAULT;
503 #endif
505 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
506 * with the real speed so its unconditionally usable */
507 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
508 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
510 ld = tty_ldisc_ref(tty);
512 if (ld != NULL) {
513 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
514 ld->flush_buffer(tty);
515 tty_ldisc_deref(ld);
518 if (opt & TERMIOS_WAIT) {
519 tty_wait_until_sent(tty, 0);
520 if (signal_pending(current))
521 return -EINTR;
524 change_termios(tty, &tmp_termios);
526 /* FIXME: Arguably if tmp_termios == tty->termios AND the
527 actual requested termios was not tmp_termios then we may
528 want to return an error as no user requested change has
529 succeeded */
530 return 0;
533 static int get_termio(struct tty_struct *tty, struct termio __user *termio)
535 if (kernel_termios_to_user_termio(termio, tty->termios))
536 return -EFAULT;
537 return 0;
540 static unsigned long inq_canon(struct tty_struct *tty)
542 int nr, head, tail;
544 if (!tty->canon_data || !tty->read_buf)
545 return 0;
546 head = tty->canon_head;
547 tail = tty->read_tail;
548 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
549 /* Skip EOF-chars.. */
550 while (head != tail) {
551 if (test_bit(tail, tty->read_flags) &&
552 tty->read_buf[tail] == __DISABLED_CHAR)
553 nr--;
554 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
556 return nr;
559 #ifdef TIOCGETP
561 * These are deprecated, but there is limited support..
563 * The "sg_flags" translation is a joke..
565 static int get_sgflags(struct tty_struct *tty)
567 int flags = 0;
569 if (!(tty->termios->c_lflag & ICANON)) {
570 if (tty->termios->c_lflag & ISIG)
571 flags |= 0x02; /* cbreak */
572 else
573 flags |= 0x20; /* raw */
575 if (tty->termios->c_lflag & ECHO)
576 flags |= 0x08; /* echo */
577 if (tty->termios->c_oflag & OPOST)
578 if (tty->termios->c_oflag & ONLCR)
579 flags |= 0x10; /* crmod */
580 return flags;
583 static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
585 struct sgttyb tmp;
587 mutex_lock(&tty->termios_mutex);
588 tmp.sg_ispeed = tty->termios->c_ispeed;
589 tmp.sg_ospeed = tty->termios->c_ospeed;
590 tmp.sg_erase = tty->termios->c_cc[VERASE];
591 tmp.sg_kill = tty->termios->c_cc[VKILL];
592 tmp.sg_flags = get_sgflags(tty);
593 mutex_unlock(&tty->termios_mutex);
595 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
598 static void set_sgflags(struct ktermios *termios, int flags)
600 termios->c_iflag = ICRNL | IXON;
601 termios->c_oflag = 0;
602 termios->c_lflag = ISIG | ICANON;
603 if (flags & 0x02) { /* cbreak */
604 termios->c_iflag = 0;
605 termios->c_lflag &= ~ICANON;
607 if (flags & 0x08) { /* echo */
608 termios->c_lflag |= ECHO | ECHOE | ECHOK |
609 ECHOCTL | ECHOKE | IEXTEN;
611 if (flags & 0x10) { /* crmod */
612 termios->c_oflag |= OPOST | ONLCR;
614 if (flags & 0x20) { /* raw */
615 termios->c_iflag = 0;
616 termios->c_lflag &= ~(ISIG | ICANON);
618 if (!(termios->c_lflag & ICANON)) {
619 termios->c_cc[VMIN] = 1;
620 termios->c_cc[VTIME] = 0;
625 * set_sgttyb - set legacy terminal values
626 * @tty: tty structure
627 * @sgttyb: pointer to old style terminal structure
629 * Updates a terminal from the legacy BSD style terminal information
630 * structure.
632 * Locking: termios_sem
635 static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
637 int retval;
638 struct sgttyb tmp;
639 struct ktermios termios;
641 retval = tty_check_change(tty);
642 if (retval)
643 return retval;
645 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
646 return -EFAULT;
648 mutex_lock(&tty->termios_mutex);
649 termios = *tty->termios;
650 termios.c_cc[VERASE] = tmp.sg_erase;
651 termios.c_cc[VKILL] = tmp.sg_kill;
652 set_sgflags(&termios, tmp.sg_flags);
653 /* Try and encode into Bfoo format */
654 #ifdef BOTHER
655 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
656 termios.c_ospeed);
657 #endif
658 mutex_unlock(&tty->termios_mutex);
659 change_termios(tty, &termios);
660 return 0;
662 #endif
664 #ifdef TIOCGETC
665 static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
667 struct tchars tmp;
669 tmp.t_intrc = tty->termios->c_cc[VINTR];
670 tmp.t_quitc = tty->termios->c_cc[VQUIT];
671 tmp.t_startc = tty->termios->c_cc[VSTART];
672 tmp.t_stopc = tty->termios->c_cc[VSTOP];
673 tmp.t_eofc = tty->termios->c_cc[VEOF];
674 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
675 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
678 static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
680 struct tchars tmp;
682 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
683 return -EFAULT;
684 tty->termios->c_cc[VINTR] = tmp.t_intrc;
685 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
686 tty->termios->c_cc[VSTART] = tmp.t_startc;
687 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
688 tty->termios->c_cc[VEOF] = tmp.t_eofc;
689 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
690 return 0;
692 #endif
694 #ifdef TIOCGLTC
695 static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
697 struct ltchars tmp;
699 tmp.t_suspc = tty->termios->c_cc[VSUSP];
700 /* what is dsuspc anyway? */
701 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
702 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
703 /* what is flushc anyway? */
704 tmp.t_flushc = tty->termios->c_cc[VEOL2];
705 tmp.t_werasc = tty->termios->c_cc[VWERASE];
706 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
707 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
710 static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
712 struct ltchars tmp;
714 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
715 return -EFAULT;
717 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
718 /* what is dsuspc anyway? */
719 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
720 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
721 /* what is flushc anyway? */
722 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
723 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
724 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
725 return 0;
727 #endif
730 * send_prio_char - send priority character
732 * Send a high priority character to the tty even if stopped
734 * Locking: none for xchar method, write ordering for write method.
737 static int send_prio_char(struct tty_struct *tty, char ch)
739 int was_stopped = tty->stopped;
741 if (tty->driver->send_xchar) {
742 tty->driver->send_xchar(tty, ch);
743 return 0;
746 if (tty_write_lock(tty, 0) < 0)
747 return -ERESTARTSYS;
749 if (was_stopped)
750 start_tty(tty);
751 tty->driver->write(tty, &ch, 1);
752 if (was_stopped)
753 stop_tty(tty);
754 tty_write_unlock(tty);
755 return 0;
759 * tty_mode_ioctl - mode related ioctls
760 * @tty: tty for the ioctl
761 * @file: file pointer for the tty
762 * @cmd: command
763 * @arg: ioctl argument
765 * Perform non line discipline specific mode control ioctls. This
766 * is designed to be called by line disciplines to ensure they provide
767 * consistent mode setting.
770 int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
771 unsigned int cmd, unsigned long arg)
773 struct tty_struct *real_tty;
774 void __user *p = (void __user *)arg;
776 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
777 tty->driver->subtype == PTY_TYPE_MASTER)
778 real_tty = tty->link;
779 else
780 real_tty = tty;
782 switch (cmd) {
783 #ifdef TIOCGETP
784 case TIOCGETP:
785 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
786 case TIOCSETP:
787 case TIOCSETN:
788 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
789 #endif
790 #ifdef TIOCGETC
791 case TIOCGETC:
792 return get_tchars(real_tty, p);
793 case TIOCSETC:
794 return set_tchars(real_tty, p);
795 #endif
796 #ifdef TIOCGLTC
797 case TIOCGLTC:
798 return get_ltchars(real_tty, p);
799 case TIOCSLTC:
800 return set_ltchars(real_tty, p);
801 #endif
802 case TCSETSF:
803 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
804 case TCSETSW:
805 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
806 case TCSETS:
807 return set_termios(real_tty, p, TERMIOS_OLD);
808 #ifndef TCGETS2
809 case TCGETS:
810 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
811 return -EFAULT;
812 return 0;
813 #else
814 case TCGETS:
815 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
816 return -EFAULT;
817 return 0;
818 case TCGETS2:
819 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
820 return -EFAULT;
821 return 0;
822 case TCSETSF2:
823 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
824 case TCSETSW2:
825 return set_termios(real_tty, p, TERMIOS_WAIT);
826 case TCSETS2:
827 return set_termios(real_tty, p, 0);
828 #endif
829 case TCGETA:
830 return get_termio(real_tty, p);
831 case TCSETAF:
832 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
833 case TCSETAW:
834 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
835 case TCSETA:
836 return set_termios(real_tty, p, TERMIOS_TERMIO);
837 #ifndef TCGETS2
838 case TIOCGLCKTRMIOS:
839 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
840 return -EFAULT;
841 return 0;
842 case TIOCSLCKTRMIOS:
843 if (!capable(CAP_SYS_ADMIN))
844 return -EPERM;
845 if (user_termios_to_kernel_termios(real_tty->termios_locked,
846 (struct termios __user *) arg))
847 return -EFAULT;
848 return 0;
849 #else
850 case TIOCGLCKTRMIOS:
851 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
852 return -EFAULT;
853 return 0;
854 case TIOCSLCKTRMIOS:
855 if (!capable(CAP_SYS_ADMIN))
856 return -EPERM;
857 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
858 (struct termios __user *) arg))
859 return -EFAULT;
860 return 0;
861 #endif
862 case TIOCGSOFTCAR:
863 return put_user(C_CLOCAL(tty) ? 1 : 0,
864 (int __user *)arg);
865 case TIOCSSOFTCAR:
866 if (get_user(arg, (unsigned int __user *) arg))
867 return -EFAULT;
868 mutex_lock(&tty->termios_mutex);
869 tty->termios->c_cflag =
870 ((tty->termios->c_cflag & ~CLOCAL) |
871 (arg ? CLOCAL : 0));
872 mutex_unlock(&tty->termios_mutex);
873 return 0;
874 default:
875 return -ENOIOCTLCMD;
878 EXPORT_SYMBOL_GPL(tty_mode_ioctl);
880 int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
882 struct tty_ldisc *ld;
883 int retval = tty_check_change(tty);
884 if (retval)
885 return retval;
887 ld = tty_ldisc_ref(tty);
888 switch (arg) {
889 case TCIFLUSH:
890 if (ld && ld->flush_buffer)
891 ld->flush_buffer(tty);
892 break;
893 case TCIOFLUSH:
894 if (ld && ld->flush_buffer)
895 ld->flush_buffer(tty);
896 /* fall through */
897 case TCOFLUSH:
898 if (tty->driver->flush_buffer)
899 tty->driver->flush_buffer(tty);
900 break;
901 default:
902 tty_ldisc_deref(ld);
903 return -EINVAL;
905 tty_ldisc_deref(ld);
906 return 0;
908 EXPORT_SYMBOL_GPL(tty_perform_flush);
910 int n_tty_ioctl(struct tty_struct *tty, struct file *file,
911 unsigned int cmd, unsigned long arg)
913 struct tty_struct *real_tty;
914 unsigned long flags;
915 int retval;
917 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
918 tty->driver->subtype == PTY_TYPE_MASTER)
919 real_tty = tty->link;
920 else
921 real_tty = tty;
923 switch (cmd) {
924 case TCXONC:
925 retval = tty_check_change(tty);
926 if (retval)
927 return retval;
928 switch (arg) {
929 case TCOOFF:
930 if (!tty->flow_stopped) {
931 tty->flow_stopped = 1;
932 stop_tty(tty);
934 break;
935 case TCOON:
936 if (tty->flow_stopped) {
937 tty->flow_stopped = 0;
938 start_tty(tty);
940 break;
941 case TCIOFF:
942 if (STOP_CHAR(tty) != __DISABLED_CHAR)
943 return send_prio_char(tty, STOP_CHAR(tty));
944 break;
945 case TCION:
946 if (START_CHAR(tty) != __DISABLED_CHAR)
947 return send_prio_char(tty, START_CHAR(tty));
948 break;
949 default:
950 return -EINVAL;
952 return 0;
953 case TCFLSH:
954 return tty_perform_flush(tty, arg);
955 case TIOCOUTQ:
956 return put_user(tty->driver->chars_in_buffer ?
957 tty->driver->chars_in_buffer(tty) : 0,
958 (int __user *) arg);
959 case TIOCINQ:
960 retval = tty->read_cnt;
961 if (L_ICANON(tty))
962 retval = inq_canon(tty);
963 return put_user(retval, (unsigned int __user *) arg);
964 case TIOCPKT:
966 int pktmode;
968 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
969 tty->driver->subtype != PTY_TYPE_MASTER)
970 return -ENOTTY;
971 if (get_user(pktmode, (int __user *) arg))
972 return -EFAULT;
973 spin_lock_irqsave(&tty->ctrl_lock, flags);
974 if (pktmode) {
975 if (!tty->packet) {
976 tty->packet = 1;
977 tty->link->ctrl_status = 0;
979 } else
980 tty->packet = 0;
981 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
982 return 0;
984 default:
985 /* Try the mode commands */
986 return tty_mode_ioctl(tty, file, cmd, arg);
989 EXPORT_SYMBOL(n_tty_ioctl);