ocfs2: Create locks at initially requested level
[linux-2.6/mini2440.git] / drivers / char / tty_ioctl.c
blob7a003504c265f73ee5f99aaffb140d97d1853991
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);
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;
342 EXPORT_SYMBOL(tty_get_baud_rate);
345 * tty_termios_copy_hw - copy hardware settings
346 * @new: New termios
347 * @old: Old termios
349 * Propogate the hardware specific terminal setting bits from
350 * the old termios structure to the new one. This is used in cases
351 * where the hardware does not support reconfiguration or as a helper
352 * in some cases where only minimal reconfiguration is supported
355 void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
357 /* The bits a dumb device handles in software. Smart devices need
358 to always provide a set_termios method */
359 new->c_cflag &= HUPCL | CREAD | CLOCAL;
360 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
361 new->c_ispeed = old->c_ispeed;
362 new->c_ospeed = old->c_ospeed;
365 EXPORT_SYMBOL(tty_termios_copy_hw);
368 * change_termios - update termios values
369 * @tty: tty to update
370 * @new_termios: desired new value
372 * Perform updates to the termios values set on this terminal. There
373 * is a bit of layering violation here with n_tty in terms of the
374 * internal knowledge of this function.
376 * Locking: termios_sem
379 static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
381 int canon_change;
382 struct ktermios old_termios = *tty->termios;
383 struct tty_ldisc *ld;
386 * Perform the actual termios internal changes under lock.
390 /* FIXME: we need to decide on some locking/ordering semantics
391 for the set_termios notification eventually */
392 mutex_lock(&tty->termios_mutex);
394 *tty->termios = *new_termios;
395 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
396 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
397 if (canon_change) {
398 memset(&tty->read_flags, 0, sizeof tty->read_flags);
399 tty->canon_head = tty->read_tail;
400 tty->canon_data = 0;
401 tty->erasing = 0;
404 /* This bit should be in the ldisc code */
405 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
406 /* Get characters left over from canonical mode. */
407 wake_up_interruptible(&tty->read_wait);
409 /* See if packet mode change of state. */
410 if (tty->link && tty->link->packet) {
411 int old_flow = ((old_termios.c_iflag & IXON) &&
412 (old_termios.c_cc[VSTOP] == '\023') &&
413 (old_termios.c_cc[VSTART] == '\021'));
414 int new_flow = (I_IXON(tty) &&
415 STOP_CHAR(tty) == '\023' &&
416 START_CHAR(tty) == '\021');
417 if (old_flow != new_flow) {
418 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
419 if (new_flow)
420 tty->ctrl_status |= TIOCPKT_DOSTOP;
421 else
422 tty->ctrl_status |= TIOCPKT_NOSTOP;
423 wake_up_interruptible(&tty->link->read_wait);
427 if (tty->driver->set_termios)
428 (*tty->driver->set_termios)(tty, &old_termios);
429 else
430 tty_termios_copy_hw(tty->termios, &old_termios);
432 ld = tty_ldisc_ref(tty);
433 if (ld != NULL) {
434 if (ld->set_termios)
435 (ld->set_termios)(tty, &old_termios);
436 tty_ldisc_deref(ld);
438 mutex_unlock(&tty->termios_mutex);
442 * set_termios - set termios values for a tty
443 * @tty: terminal device
444 * @arg: user data
445 * @opt: option information
447 * Helper function to prepare termios data and run necessary other
448 * functions before using change_termios to do the actual changes.
450 * Locking:
451 * Called functions take ldisc and termios_sem locks
454 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
456 struct ktermios tmp_termios;
457 struct tty_ldisc *ld;
458 int retval = tty_check_change(tty);
460 if (retval)
461 return retval;
463 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
465 if (opt & TERMIOS_TERMIO) {
466 if (user_termio_to_kernel_termios(&tmp_termios,
467 (struct termio __user *)arg))
468 return -EFAULT;
469 #ifdef TCGETS2
470 } else if (opt & TERMIOS_OLD) {
471 if (user_termios_to_kernel_termios_1(&tmp_termios,
472 (struct termios __user *)arg))
473 return -EFAULT;
474 } else {
475 if (user_termios_to_kernel_termios(&tmp_termios,
476 (struct termios2 __user *)arg))
477 return -EFAULT;
479 #else
480 } else if (user_termios_to_kernel_termios(&tmp_termios,
481 (struct termios __user *)arg))
482 return -EFAULT;
483 #endif
485 /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
486 so its unconditionally usable */
487 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
488 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
490 ld = tty_ldisc_ref(tty);
492 if (ld != NULL) {
493 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
494 ld->flush_buffer(tty);
495 tty_ldisc_deref(ld);
498 if (opt & TERMIOS_WAIT) {
499 tty_wait_until_sent(tty, 0);
500 if (signal_pending(current))
501 return -EINTR;
504 change_termios(tty, &tmp_termios);
506 /* FIXME: Arguably if tmp_termios == tty->termios AND the
507 actual requested termios was not tmp_termios then we may
508 want to return an error as no user requested change has
509 succeeded */
510 return 0;
513 static int get_termio(struct tty_struct * tty, struct termio __user * termio)
515 if (kernel_termios_to_user_termio(termio, tty->termios))
516 return -EFAULT;
517 return 0;
520 static unsigned long inq_canon(struct tty_struct * tty)
522 int nr, head, tail;
524 if (!tty->canon_data || !tty->read_buf)
525 return 0;
526 head = tty->canon_head;
527 tail = tty->read_tail;
528 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
529 /* Skip EOF-chars.. */
530 while (head != tail) {
531 if (test_bit(tail, tty->read_flags) &&
532 tty->read_buf[tail] == __DISABLED_CHAR)
533 nr--;
534 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
536 return nr;
539 #ifdef TIOCGETP
541 * These are deprecated, but there is limited support..
543 * The "sg_flags" translation is a joke..
545 static int get_sgflags(struct tty_struct * tty)
547 int flags = 0;
549 if (!(tty->termios->c_lflag & ICANON)) {
550 if (tty->termios->c_lflag & ISIG)
551 flags |= 0x02; /* cbreak */
552 else
553 flags |= 0x20; /* raw */
555 if (tty->termios->c_lflag & ECHO)
556 flags |= 0x08; /* echo */
557 if (tty->termios->c_oflag & OPOST)
558 if (tty->termios->c_oflag & ONLCR)
559 flags |= 0x10; /* crmod */
560 return flags;
563 static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
565 struct sgttyb tmp;
567 mutex_lock(&tty->termios_mutex);
568 tmp.sg_ispeed = tty->termios->c_ispeed;
569 tmp.sg_ospeed = tty->termios->c_ospeed;
570 tmp.sg_erase = tty->termios->c_cc[VERASE];
571 tmp.sg_kill = tty->termios->c_cc[VKILL];
572 tmp.sg_flags = get_sgflags(tty);
573 mutex_unlock(&tty->termios_mutex);
575 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
578 static void set_sgflags(struct ktermios * termios, int flags)
580 termios->c_iflag = ICRNL | IXON;
581 termios->c_oflag = 0;
582 termios->c_lflag = ISIG | ICANON;
583 if (flags & 0x02) { /* cbreak */
584 termios->c_iflag = 0;
585 termios->c_lflag &= ~ICANON;
587 if (flags & 0x08) { /* echo */
588 termios->c_lflag |= ECHO | ECHOE | ECHOK |
589 ECHOCTL | ECHOKE | IEXTEN;
591 if (flags & 0x10) { /* crmod */
592 termios->c_oflag |= OPOST | ONLCR;
594 if (flags & 0x20) { /* raw */
595 termios->c_iflag = 0;
596 termios->c_lflag &= ~(ISIG | ICANON);
598 if (!(termios->c_lflag & ICANON)) {
599 termios->c_cc[VMIN] = 1;
600 termios->c_cc[VTIME] = 0;
605 * set_sgttyb - set legacy terminal values
606 * @tty: tty structure
607 * @sgttyb: pointer to old style terminal structure
609 * Updates a terminal from the legacy BSD style terminal information
610 * structure.
612 * Locking: termios_sem
615 static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
617 int retval;
618 struct sgttyb tmp;
619 struct ktermios termios;
621 retval = tty_check_change(tty);
622 if (retval)
623 return retval;
625 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
626 return -EFAULT;
628 mutex_lock(&tty->termios_mutex);
629 termios = *tty->termios;
630 termios.c_cc[VERASE] = tmp.sg_erase;
631 termios.c_cc[VKILL] = tmp.sg_kill;
632 set_sgflags(&termios, tmp.sg_flags);
633 /* Try and encode into Bfoo format */
634 #ifdef BOTHER
635 tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
636 #endif
637 mutex_unlock(&tty->termios_mutex);
638 change_termios(tty, &termios);
639 return 0;
641 #endif
643 #ifdef TIOCGETC
644 static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
646 struct tchars tmp;
648 tmp.t_intrc = tty->termios->c_cc[VINTR];
649 tmp.t_quitc = tty->termios->c_cc[VQUIT];
650 tmp.t_startc = tty->termios->c_cc[VSTART];
651 tmp.t_stopc = tty->termios->c_cc[VSTOP];
652 tmp.t_eofc = tty->termios->c_cc[VEOF];
653 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
654 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
657 static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
659 struct tchars tmp;
661 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
662 return -EFAULT;
663 tty->termios->c_cc[VINTR] = tmp.t_intrc;
664 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
665 tty->termios->c_cc[VSTART] = tmp.t_startc;
666 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
667 tty->termios->c_cc[VEOF] = tmp.t_eofc;
668 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
669 return 0;
671 #endif
673 #ifdef TIOCGLTC
674 static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
676 struct ltchars tmp;
678 tmp.t_suspc = tty->termios->c_cc[VSUSP];
679 tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */
680 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
681 tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */
682 tmp.t_werasc = tty->termios->c_cc[VWERASE];
683 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
684 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
687 static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
689 struct ltchars tmp;
691 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
692 return -EFAULT;
694 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
695 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */
696 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
697 tty->termios->c_cc[VEOL2] = tmp.t_flushc; /* what is flushc anyway? */
698 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
699 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
700 return 0;
702 #endif
705 * send_prio_char - send priority character
707 * Send a high priority character to the tty even if stopped
709 * Locking: none for xchar method, write ordering for write method.
712 static int send_prio_char(struct tty_struct *tty, char ch)
714 int was_stopped = tty->stopped;
716 if (tty->driver->send_xchar) {
717 tty->driver->send_xchar(tty, ch);
718 return 0;
721 if (tty_write_lock(tty, 0) < 0)
722 return -ERESTARTSYS;
724 if (was_stopped)
725 start_tty(tty);
726 tty->driver->write(tty, &ch, 1);
727 if (was_stopped)
728 stop_tty(tty);
729 tty_write_unlock(tty);
730 return 0;
733 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
734 unsigned int cmd, unsigned long arg)
736 struct tty_struct * real_tty;
737 void __user *p = (void __user *)arg;
738 int retval;
739 struct tty_ldisc *ld;
741 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
742 tty->driver->subtype == PTY_TYPE_MASTER)
743 real_tty = tty->link;
744 else
745 real_tty = tty;
747 switch (cmd) {
748 #ifdef TIOCGETP
749 case TIOCGETP:
750 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
751 case TIOCSETP:
752 case TIOCSETN:
753 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
754 #endif
755 #ifdef TIOCGETC
756 case TIOCGETC:
757 return get_tchars(real_tty, p);
758 case TIOCSETC:
759 return set_tchars(real_tty, p);
760 #endif
761 #ifdef TIOCGLTC
762 case TIOCGLTC:
763 return get_ltchars(real_tty, p);
764 case TIOCSLTC:
765 return set_ltchars(real_tty, p);
766 #endif
767 case TCSETSF:
768 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
769 case TCSETSW:
770 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
771 case TCSETS:
772 return set_termios(real_tty, p, TERMIOS_OLD);
773 #ifndef TCGETS2
774 case TCGETS:
775 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
776 return -EFAULT;
777 return 0;
778 #else
779 case TCGETS:
780 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
781 return -EFAULT;
782 return 0;
783 case TCGETS2:
784 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
785 return -EFAULT;
786 return 0;
787 case TCSETSF2:
788 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
789 case TCSETSW2:
790 return set_termios(real_tty, p, TERMIOS_WAIT);
791 case TCSETS2:
792 return set_termios(real_tty, p, 0);
793 #endif
794 case TCGETA:
795 return get_termio(real_tty, p);
796 case TCSETAF:
797 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
798 case TCSETAW:
799 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
800 case TCSETA:
801 return set_termios(real_tty, p, TERMIOS_TERMIO);
802 case TCXONC:
803 retval = tty_check_change(tty);
804 if (retval)
805 return retval;
806 switch (arg) {
807 case TCOOFF:
808 if (!tty->flow_stopped) {
809 tty->flow_stopped = 1;
810 stop_tty(tty);
812 break;
813 case TCOON:
814 if (tty->flow_stopped) {
815 tty->flow_stopped = 0;
816 start_tty(tty);
818 break;
819 case TCIOFF:
820 if (STOP_CHAR(tty) != __DISABLED_CHAR)
821 return send_prio_char(tty, STOP_CHAR(tty));
822 break;
823 case TCION:
824 if (START_CHAR(tty) != __DISABLED_CHAR)
825 return send_prio_char(tty, START_CHAR(tty));
826 break;
827 default:
828 return -EINVAL;
830 return 0;
831 case TCFLSH:
832 retval = tty_check_change(tty);
833 if (retval)
834 return retval;
836 ld = tty_ldisc_ref(tty);
837 switch (arg) {
838 case TCIFLUSH:
839 if (ld && ld->flush_buffer)
840 ld->flush_buffer(tty);
841 break;
842 case TCIOFLUSH:
843 if (ld && ld->flush_buffer)
844 ld->flush_buffer(tty);
845 /* fall through */
846 case TCOFLUSH:
847 if (tty->driver->flush_buffer)
848 tty->driver->flush_buffer(tty);
849 break;
850 default:
851 tty_ldisc_deref(ld);
852 return -EINVAL;
854 tty_ldisc_deref(ld);
855 return 0;
856 case TIOCOUTQ:
857 return put_user(tty->driver->chars_in_buffer ?
858 tty->driver->chars_in_buffer(tty) : 0,
859 (int __user *) arg);
860 case TIOCINQ:
861 retval = tty->read_cnt;
862 if (L_ICANON(tty))
863 retval = inq_canon(tty);
864 return put_user(retval, (unsigned int __user *) arg);
865 #ifndef TCGETS2
866 case TIOCGLCKTRMIOS:
867 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
868 return -EFAULT;
869 return 0;
871 case TIOCSLCKTRMIOS:
872 if (!capable(CAP_SYS_ADMIN))
873 return -EPERM;
874 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
875 return -EFAULT;
876 return 0;
877 #else
878 case TIOCGLCKTRMIOS:
879 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
880 return -EFAULT;
881 return 0;
883 case TIOCSLCKTRMIOS:
884 if (!capable(CAP_SYS_ADMIN))
885 return -EPERM;
886 if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
887 return -EFAULT;
888 return 0;
889 #endif
891 case TIOCPKT:
893 int pktmode;
895 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
896 tty->driver->subtype != PTY_TYPE_MASTER)
897 return -ENOTTY;
898 if (get_user(pktmode, (int __user *) arg))
899 return -EFAULT;
900 if (pktmode) {
901 if (!tty->packet) {
902 tty->packet = 1;
903 tty->link->ctrl_status = 0;
905 } else
906 tty->packet = 0;
907 return 0;
909 case TIOCGSOFTCAR:
910 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
911 case TIOCSSOFTCAR:
912 if (get_user(arg, (unsigned int __user *) arg))
913 return -EFAULT;
914 mutex_lock(&tty->termios_mutex);
915 tty->termios->c_cflag =
916 ((tty->termios->c_cflag & ~CLOCAL) |
917 (arg ? CLOCAL : 0));
918 mutex_unlock(&tty->termios_mutex);
919 return 0;
920 default:
921 return -ENOIOCTLCMD;
925 EXPORT_SYMBOL(n_tty_ioctl);