knfsd: nfsd4: fix handling of acl errrors
[pv_ops_mirror.git] / drivers / char / tty_ioctl.c
blob3423e9ee6481c1874898e448dc7e9712b3b33195
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>
25 #include <asm/io.h>
26 #include <asm/uaccess.h>
27 #include <asm/system.h>
29 #undef TTY_DEBUG_WAIT_UNTIL_SENT
31 #undef DEBUG
34 * Internal flag options for termios setting behavior
36 #define TERMIOS_FLUSH 1
37 #define TERMIOS_WAIT 2
38 #define TERMIOS_TERMIO 4
39 #define TERMIOS_OLD 8
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
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)
50 * Locking: none
53 void tty_wait_until_sent(struct tty_struct * tty, long timeout)
55 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
56 char buf[64];
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);
71 EXPORT_SYMBOL(tty_wait_until_sent);
73 static void unset_locked_termios(struct ktermios *termios,
74 struct ktermios *old,
75 struct ktermios *locked)
77 int i;
79 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
81 if (!locked) {
82 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
83 return;
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 */
98 * Routine which returns the baud rate of the tty
100 * Note that the baud_table needs to be kept in sync with the
101 * include/asm/termbits.h file.
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
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
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
129 #endif
131 static int n_baud_table = ARRAY_SIZE(baud_table);
134 * tty_termios_baud_rate
135 * @termios: termios structure
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.
142 * Locking: none
145 speed_t tty_termios_baud_rate(struct ktermios *termios)
147 unsigned int cbaud;
149 cbaud = termios->c_cflag & CBAUD;
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;
159 if (cbaud < 1 || cbaud + 15 > n_baud_table)
160 termios->c_cflag &= ~CBAUDEX;
161 else
162 cbaud += 15;
164 return baud_table[cbaud];
167 EXPORT_SYMBOL(tty_termios_baud_rate);
170 * tty_termios_input_baud_rate
171 * @termios: termios structure
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.
178 * Locking: none
181 speed_t tty_termios_input_baud_rate(struct ktermios *termios)
183 #ifdef IBSHIFT
184 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
186 if (cbaud == B0)
187 return tty_termios_baud_rate(termios);
189 /* Magic token for arbitary speed via c_ispeed*/
190 if (cbaud == BOTHER)
191 return termios->c_ispeed;
193 if (cbaud & CBAUDEX) {
194 cbaud &= ~CBAUDEX;
196 if (cbaud < 1 || cbaud + 15 > n_baud_table)
197 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
198 else
199 cbaud += 15;
201 return baud_table[cbaud];
202 #else
203 return tty_termios_baud_rate(termios);
204 #endif
207 EXPORT_SYMBOL(tty_termios_input_baud_rate);
209 #ifdef BOTHER
212 * tty_termios_encode_baud_rate
213 * @termios: ktermios structure holding user requested state
214 * @ispeed: input speed
215 * @ospeed: output speed
217 * Encode the speeds set into the passed termios structure. This is
218 * used as a library helper for drivers os that they can report back
219 * the actual speed selected when it differs from the speed requested
221 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
222 * we need to carefully set the bits when the user does not get the
223 * desired speed. We allow small margins and preserve as much of possible
224 * of the input intent to keep compatiblity.
226 * Locking: Caller should hold termios lock. This is already held
227 * when calling this function from the driver termios handler.
230 void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
232 int i = 0;
233 int ifound = -1, ofound = -1;
234 int iclose = ibaud/50, oclose = obaud/50;
235 int ibinput = 0;
237 termios->c_ispeed = ibaud;
238 termios->c_ospeed = obaud;
240 /* If the user asked for a precise weird speed give a precise weird
241 answer. If they asked for a Bfoo speed they many have problems
242 digesting non-exact replies so fuzz a bit */
244 if ((termios->c_cflag & CBAUD) == BOTHER)
245 oclose = 0;
246 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
247 iclose = 0;
248 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
249 ibinput = 1; /* An input speed was specified */
251 termios->c_cflag &= ~CBAUD;
253 do {
254 if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
255 termios->c_cflag |= baud_bits[i];
256 ofound = i;
258 if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) {
259 /* For the case input == output don't set IBAUD bits if the user didn't do so */
260 if (ofound != i || ibinput)
261 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
262 ifound = i;
264 } while (++i < n_baud_table);
265 if (ofound == -1)
266 termios->c_cflag |= BOTHER;
267 /* Set exact input bits only if the input and output differ or the
268 user already did */
269 if (ifound == -1 && (ibaud != obaud || ibinput))
270 termios->c_cflag |= (BOTHER << IBSHIFT);
273 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
275 #endif
278 * tty_get_baud_rate - get tty bit rates
279 * @tty: tty to query
281 * Returns the baud rate as an integer for this terminal. The
282 * termios lock must be held by the caller and the terminal bit
283 * flags may be updated.
285 * Locking: none
288 speed_t tty_get_baud_rate(struct tty_struct *tty)
290 speed_t baud = tty_termios_baud_rate(tty->termios);
292 if (baud == 38400 && tty->alt_speed) {
293 if (!tty->warned) {
294 printk(KERN_WARNING "Use of setserial/setrocket to "
295 "set SPD_* flags is deprecated\n");
296 tty->warned = 1;
298 baud = tty->alt_speed;
301 return baud;
304 EXPORT_SYMBOL(tty_get_baud_rate);
307 * change_termios - update termios values
308 * @tty: tty to update
309 * @new_termios: desired new value
311 * Perform updates to the termios values set on this terminal. There
312 * is a bit of layering violation here with n_tty in terms of the
313 * internal knowledge of this function.
315 * Locking: termios_sem
318 static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
320 int canon_change;
321 struct ktermios old_termios = *tty->termios;
322 struct tty_ldisc *ld;
325 * Perform the actual termios internal changes under lock.
329 /* FIXME: we need to decide on some locking/ordering semantics
330 for the set_termios notification eventually */
331 mutex_lock(&tty->termios_mutex);
333 *tty->termios = *new_termios;
334 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
335 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
336 if (canon_change) {
337 memset(&tty->read_flags, 0, sizeof tty->read_flags);
338 tty->canon_head = tty->read_tail;
339 tty->canon_data = 0;
340 tty->erasing = 0;
344 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
345 /* Get characters left over from canonical mode. */
346 wake_up_interruptible(&tty->read_wait);
348 /* See if packet mode change of state. */
350 if (tty->link && tty->link->packet) {
351 int old_flow = ((old_termios.c_iflag & IXON) &&
352 (old_termios.c_cc[VSTOP] == '\023') &&
353 (old_termios.c_cc[VSTART] == '\021'));
354 int new_flow = (I_IXON(tty) &&
355 STOP_CHAR(tty) == '\023' &&
356 START_CHAR(tty) == '\021');
357 if (old_flow != new_flow) {
358 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
359 if (new_flow)
360 tty->ctrl_status |= TIOCPKT_DOSTOP;
361 else
362 tty->ctrl_status |= TIOCPKT_NOSTOP;
363 wake_up_interruptible(&tty->link->read_wait);
367 if (tty->driver->set_termios)
368 (*tty->driver->set_termios)(tty, &old_termios);
370 ld = tty_ldisc_ref(tty);
371 if (ld != NULL) {
372 if (ld->set_termios)
373 (ld->set_termios)(tty, &old_termios);
374 tty_ldisc_deref(ld);
376 mutex_unlock(&tty->termios_mutex);
380 * set_termios - set termios values for a tty
381 * @tty: terminal device
382 * @arg: user data
383 * @opt: option information
385 * Helper function to prepare termios data and run neccessary other
386 * functions before using change_termios to do the actual changes.
388 * Locking:
389 * Called functions take ldisc and termios_sem locks
392 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
394 struct ktermios tmp_termios;
395 struct tty_ldisc *ld;
396 int retval = tty_check_change(tty);
398 if (retval)
399 return retval;
401 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
403 if (opt & TERMIOS_TERMIO) {
404 if (user_termio_to_kernel_termios(&tmp_termios,
405 (struct termio __user *)arg))
406 return -EFAULT;
407 #ifdef TCGETS2
408 } else if (opt & TERMIOS_OLD) {
409 if (user_termios_to_kernel_termios_1(&tmp_termios,
410 (struct termios __user *)arg))
411 return -EFAULT;
412 } else {
413 if (user_termios_to_kernel_termios(&tmp_termios,
414 (struct termios2 __user *)arg))
415 return -EFAULT;
417 #else
418 } else if (user_termios_to_kernel_termios(&tmp_termios,
419 (struct termios __user *)arg))
420 return -EFAULT;
421 #endif
423 /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
424 so its unconditionally usable */
425 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
426 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
428 ld = tty_ldisc_ref(tty);
430 if (ld != NULL) {
431 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
432 ld->flush_buffer(tty);
433 tty_ldisc_deref(ld);
436 if (opt & TERMIOS_WAIT) {
437 tty_wait_until_sent(tty, 0);
438 if (signal_pending(current))
439 return -EINTR;
442 change_termios(tty, &tmp_termios);
443 return 0;
446 static int get_termio(struct tty_struct * tty, struct termio __user * termio)
448 if (kernel_termios_to_user_termio(termio, tty->termios))
449 return -EFAULT;
450 return 0;
453 static unsigned long inq_canon(struct tty_struct * tty)
455 int nr, head, tail;
457 if (!tty->canon_data || !tty->read_buf)
458 return 0;
459 head = tty->canon_head;
460 tail = tty->read_tail;
461 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
462 /* Skip EOF-chars.. */
463 while (head != tail) {
464 if (test_bit(tail, tty->read_flags) &&
465 tty->read_buf[tail] == __DISABLED_CHAR)
466 nr--;
467 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
469 return nr;
472 #ifdef TIOCGETP
474 * These are deprecated, but there is limited support..
476 * The "sg_flags" translation is a joke..
478 static int get_sgflags(struct tty_struct * tty)
480 int flags = 0;
482 if (!(tty->termios->c_lflag & ICANON)) {
483 if (tty->termios->c_lflag & ISIG)
484 flags |= 0x02; /* cbreak */
485 else
486 flags |= 0x20; /* raw */
488 if (tty->termios->c_lflag & ECHO)
489 flags |= 0x08; /* echo */
490 if (tty->termios->c_oflag & OPOST)
491 if (tty->termios->c_oflag & ONLCR)
492 flags |= 0x10; /* crmod */
493 return flags;
496 static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
498 struct sgttyb tmp;
500 mutex_lock(&tty->termios_mutex);
501 tmp.sg_ispeed = tty->termios->c_ispeed;
502 tmp.sg_ospeed = tty->termios->c_ospeed;
503 tmp.sg_erase = tty->termios->c_cc[VERASE];
504 tmp.sg_kill = tty->termios->c_cc[VKILL];
505 tmp.sg_flags = get_sgflags(tty);
506 mutex_unlock(&tty->termios_mutex);
508 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
511 static void set_sgflags(struct ktermios * termios, int flags)
513 termios->c_iflag = ICRNL | IXON;
514 termios->c_oflag = 0;
515 termios->c_lflag = ISIG | ICANON;
516 if (flags & 0x02) { /* cbreak */
517 termios->c_iflag = 0;
518 termios->c_lflag &= ~ICANON;
520 if (flags & 0x08) { /* echo */
521 termios->c_lflag |= ECHO | ECHOE | ECHOK |
522 ECHOCTL | ECHOKE | IEXTEN;
524 if (flags & 0x10) { /* crmod */
525 termios->c_oflag |= OPOST | ONLCR;
527 if (flags & 0x20) { /* raw */
528 termios->c_iflag = 0;
529 termios->c_lflag &= ~(ISIG | ICANON);
531 if (!(termios->c_lflag & ICANON)) {
532 termios->c_cc[VMIN] = 1;
533 termios->c_cc[VTIME] = 0;
538 * set_sgttyb - set legacy terminal values
539 * @tty: tty structure
540 * @sgttyb: pointer to old style terminal structure
542 * Updates a terminal from the legacy BSD style terminal information
543 * structure.
545 * Locking: termios_sem
548 static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
550 int retval;
551 struct sgttyb tmp;
552 struct ktermios termios;
554 retval = tty_check_change(tty);
555 if (retval)
556 return retval;
558 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
559 return -EFAULT;
561 mutex_lock(&tty->termios_mutex);
562 termios = *tty->termios;
563 termios.c_cc[VERASE] = tmp.sg_erase;
564 termios.c_cc[VKILL] = tmp.sg_kill;
565 set_sgflags(&termios, tmp.sg_flags);
566 /* Try and encode into Bfoo format */
567 #ifdef BOTHER
568 tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
569 #endif
570 mutex_unlock(&tty->termios_mutex);
571 change_termios(tty, &termios);
572 return 0;
574 #endif
576 #ifdef TIOCGETC
577 static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
579 struct tchars tmp;
581 tmp.t_intrc = tty->termios->c_cc[VINTR];
582 tmp.t_quitc = tty->termios->c_cc[VQUIT];
583 tmp.t_startc = tty->termios->c_cc[VSTART];
584 tmp.t_stopc = tty->termios->c_cc[VSTOP];
585 tmp.t_eofc = tty->termios->c_cc[VEOF];
586 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
587 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
590 static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
592 struct tchars tmp;
594 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
595 return -EFAULT;
596 tty->termios->c_cc[VINTR] = tmp.t_intrc;
597 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
598 tty->termios->c_cc[VSTART] = tmp.t_startc;
599 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
600 tty->termios->c_cc[VEOF] = tmp.t_eofc;
601 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
602 return 0;
604 #endif
606 #ifdef TIOCGLTC
607 static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
609 struct ltchars tmp;
611 tmp.t_suspc = tty->termios->c_cc[VSUSP];
612 tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */
613 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
614 tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */
615 tmp.t_werasc = tty->termios->c_cc[VWERASE];
616 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
617 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
620 static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
622 struct ltchars tmp;
624 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
625 return -EFAULT;
627 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
628 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */
629 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
630 tty->termios->c_cc[VEOL2] = tmp.t_flushc; /* what is flushc anyway? */
631 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
632 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
633 return 0;
635 #endif
638 * send_prio_char - send priority character
640 * Send a high priority character to the tty even if stopped
642 * Locking: none for xchar method, write ordering for write method.
645 static int send_prio_char(struct tty_struct *tty, char ch)
647 int was_stopped = tty->stopped;
649 if (tty->driver->send_xchar) {
650 tty->driver->send_xchar(tty, ch);
651 return 0;
654 if (tty_write_lock(tty, 0) < 0)
655 return -ERESTARTSYS;
657 if (was_stopped)
658 start_tty(tty);
659 tty->driver->write(tty, &ch, 1);
660 if (was_stopped)
661 stop_tty(tty);
662 tty_write_unlock(tty);
663 return 0;
666 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
667 unsigned int cmd, unsigned long arg)
669 struct tty_struct * real_tty;
670 void __user *p = (void __user *)arg;
671 int retval;
672 struct tty_ldisc *ld;
674 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
675 tty->driver->subtype == PTY_TYPE_MASTER)
676 real_tty = tty->link;
677 else
678 real_tty = tty;
680 switch (cmd) {
681 #ifdef TIOCGETP
682 case TIOCGETP:
683 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
684 case TIOCSETP:
685 case TIOCSETN:
686 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
687 #endif
688 #ifdef TIOCGETC
689 case TIOCGETC:
690 return get_tchars(real_tty, p);
691 case TIOCSETC:
692 return set_tchars(real_tty, p);
693 #endif
694 #ifdef TIOCGLTC
695 case TIOCGLTC:
696 return get_ltchars(real_tty, p);
697 case TIOCSLTC:
698 return set_ltchars(real_tty, p);
699 #endif
700 case TCSETSF:
701 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
702 case TCSETSW:
703 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
704 case TCSETS:
705 return set_termios(real_tty, p, TERMIOS_OLD);
706 #ifndef TCGETS2
707 case TCGETS:
708 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
709 return -EFAULT;
710 return 0;
711 #else
712 case TCGETS:
713 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
714 return -EFAULT;
715 return 0;
716 case TCGETS2:
717 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
718 return -EFAULT;
719 return 0;
720 case TCSETSF2:
721 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
722 case TCSETSW2:
723 return set_termios(real_tty, p, TERMIOS_WAIT);
724 case TCSETS2:
725 return set_termios(real_tty, p, 0);
726 #endif
727 case TCGETA:
728 return get_termio(real_tty, p);
729 case TCSETAF:
730 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
731 case TCSETAW:
732 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
733 case TCSETA:
734 return set_termios(real_tty, p, TERMIOS_TERMIO);
735 case TCXONC:
736 retval = tty_check_change(tty);
737 if (retval)
738 return retval;
739 switch (arg) {
740 case TCOOFF:
741 if (!tty->flow_stopped) {
742 tty->flow_stopped = 1;
743 stop_tty(tty);
745 break;
746 case TCOON:
747 if (tty->flow_stopped) {
748 tty->flow_stopped = 0;
749 start_tty(tty);
751 break;
752 case TCIOFF:
753 if (STOP_CHAR(tty) != __DISABLED_CHAR)
754 return send_prio_char(tty, STOP_CHAR(tty));
755 break;
756 case TCION:
757 if (START_CHAR(tty) != __DISABLED_CHAR)
758 return send_prio_char(tty, START_CHAR(tty));
759 break;
760 default:
761 return -EINVAL;
763 return 0;
764 case TCFLSH:
765 retval = tty_check_change(tty);
766 if (retval)
767 return retval;
769 ld = tty_ldisc_ref(tty);
770 switch (arg) {
771 case TCIFLUSH:
772 if (ld && ld->flush_buffer)
773 ld->flush_buffer(tty);
774 break;
775 case TCIOFLUSH:
776 if (ld && ld->flush_buffer)
777 ld->flush_buffer(tty);
778 /* fall through */
779 case TCOFLUSH:
780 if (tty->driver->flush_buffer)
781 tty->driver->flush_buffer(tty);
782 break;
783 default:
784 tty_ldisc_deref(ld);
785 return -EINVAL;
787 tty_ldisc_deref(ld);
788 return 0;
789 case TIOCOUTQ:
790 return put_user(tty->driver->chars_in_buffer ?
791 tty->driver->chars_in_buffer(tty) : 0,
792 (int __user *) arg);
793 case TIOCINQ:
794 retval = tty->read_cnt;
795 if (L_ICANON(tty))
796 retval = inq_canon(tty);
797 return put_user(retval, (unsigned int __user *) arg);
798 case TIOCGLCKTRMIOS:
799 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
800 return -EFAULT;
801 return 0;
803 case TIOCSLCKTRMIOS:
804 if (!capable(CAP_SYS_ADMIN))
805 return -EPERM;
806 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
807 return -EFAULT;
808 return 0;
810 case TIOCPKT:
812 int pktmode;
814 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
815 tty->driver->subtype != PTY_TYPE_MASTER)
816 return -ENOTTY;
817 if (get_user(pktmode, (int __user *) arg))
818 return -EFAULT;
819 if (pktmode) {
820 if (!tty->packet) {
821 tty->packet = 1;
822 tty->link->ctrl_status = 0;
824 } else
825 tty->packet = 0;
826 return 0;
828 case TIOCGSOFTCAR:
829 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
830 case TIOCSSOFTCAR:
831 if (get_user(arg, (unsigned int __user *) arg))
832 return -EFAULT;
833 mutex_lock(&tty->termios_mutex);
834 tty->termios->c_cflag =
835 ((tty->termios->c_cflag & ~CLOCAL) |
836 (arg ? CLOCAL : 0));
837 mutex_unlock(&tty->termios_mutex);
838 return 0;
839 default:
840 return -ENOIOCTLCMD;
844 EXPORT_SYMBOL(n_tty_ioctl);