ide-cd is unmaintained
[linux-2.6-block.git] / drivers / char / tty_ioctl.c
CommitLineData
1da177e4
LT
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>
5785c95b 23#include <linux/mutex.h>
1da177e4
LT
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
edc6afc5 39#define TERMIOS_OLD 8
1da177e4 40
af9b897e
AC
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
1da177e4
LT
53void tty_wait_until_sent(struct tty_struct * tty, long timeout)
54{
1da177e4
LT
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;
1da177e4
LT
62 if (!timeout)
63 timeout = MAX_SCHEDULE_TIMEOUT;
5a52bd4a
JS
64 if (wait_event_interruptible_timeout(tty->write_wait,
65 !tty->driver->chars_in_buffer(tty), timeout))
66 return;
1da177e4
LT
67 if (tty->driver->wait_until_sent)
68 tty->driver->wait_until_sent(tty, timeout);
1da177e4
LT
69}
70
71EXPORT_SYMBOL(tty_wait_until_sent);
72
edc6afc5
AC
73static void unset_locked_termios(struct ktermios *termios,
74 struct ktermios *old,
75 struct ktermios *locked)
1da177e4
LT
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];
edc6afc5 94 /* FIXME: What should we do for i/ospeed */
1da177e4
LT
95}
96
edc6afc5
AC
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 */
103static 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__
115static 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
123static 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
131static 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
145speed_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
167EXPORT_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
181speed_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
207EXPORT_SYMBOL(tty_termios_input_baud_rate);
208
209#ifdef BOTHER
210
211/**
212 * tty_termios_encode_baud_rate
78137e3b 213 * @termios: ktermios structure holding user requested state
edc6afc5
AC
214 * @ispeed: input speed
215 * @ospeed: output speed
216 *
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
220 *
78137e3b
AC
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.
edc6afc5
AC
225 *
226 * Locking: Caller should hold termios lock. This is already held
227 * when calling this function from the driver termios handler.
228 */
229
230void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
231{
232 int i = 0;
78137e3b
AC
233 int ifound = -1, ofound = -1;
234 int iclose = ibaud/50, oclose = obaud/50;
235 int ibinput = 0;
edc6afc5
AC
236
237 termios->c_ispeed = ibaud;
238 termios->c_ospeed = obaud;
239
78137e3b
AC
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 */
243
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 */
250
edc6afc5 251 termios->c_cflag &= ~CBAUD;
edc6afc5
AC
252
253 do {
78137e3b 254 if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
edc6afc5 255 termios->c_cflag |= baud_bits[i];
78137e3b 256 ofound = i;
edc6afc5 257 }
78137e3b
AC
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;
edc6afc5 263 }
6804396f 264 } while (++i < n_baud_table);
78137e3b 265 if (ofound == -1)
edc6afc5 266 termios->c_cflag |= BOTHER;
78137e3b
AC
267 /* Set exact input bits only if the input and output differ or the
268 user already did */
6804396f 269 if (ifound == -1 && (ibaud != obaud || ibinput))
edc6afc5
AC
270 termios->c_cflag |= (BOTHER << IBSHIFT);
271}
272
273EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
274
275#endif
276
277/**
278 * tty_get_baud_rate - get tty bit rates
279 * @tty: tty to query
280 *
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.
284 *
285 * Locking: none
286 */
287
288speed_t tty_get_baud_rate(struct tty_struct *tty)
289{
290 speed_t baud = tty_termios_baud_rate(tty->termios);
291
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;
297 }
298 baud = tty->alt_speed;
299 }
300
301 return baud;
302}
303
304EXPORT_SYMBOL(tty_get_baud_rate);
305
af9b897e
AC
306/**
307 * change_termios - update termios values
308 * @tty: tty to update
309 * @new_termios: desired new value
310 *
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.
314 *
315 * Locking: termios_sem
316 */
317
edc6afc5 318static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
1da177e4
LT
319{
320 int canon_change;
edc6afc5 321 struct ktermios old_termios = *tty->termios;
1da177e4
LT
322 struct tty_ldisc *ld;
323
324 /*
325 * Perform the actual termios internal changes under lock.
326 */
327
328
329 /* FIXME: we need to decide on some locking/ordering semantics
330 for the set_termios notification eventually */
5785c95b 331 mutex_lock(&tty->termios_mutex);
1da177e4
LT
332
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;
341 }
342
343
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);
347
348 /* See if packet mode change of state. */
349
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);
364 }
365 }
366
367 if (tty->driver->set_termios)
368 (*tty->driver->set_termios)(tty, &old_termios);
369
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);
375 }
5785c95b 376 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
377}
378
af9b897e
AC
379/**
380 * set_termios - set termios values for a tty
381 * @tty: terminal device
382 * @arg: user data
383 * @opt: option information
384 *
385 * Helper function to prepare termios data and run neccessary other
386 * functions before using change_termios to do the actual changes.
387 *
388 * Locking:
389 * Called functions take ldisc and termios_sem locks
390 */
391
1da177e4
LT
392static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
393{
edc6afc5 394 struct ktermios tmp_termios;
1da177e4
LT
395 struct tty_ldisc *ld;
396 int retval = tty_check_change(tty);
397
398 if (retval)
399 return retval;
400
64bb6c5e
AC
401 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
402
1da177e4 403 if (opt & TERMIOS_TERMIO) {
1da177e4
LT
404 if (user_termio_to_kernel_termios(&tmp_termios,
405 (struct termio __user *)arg))
406 return -EFAULT;
edc6afc5
AC
407#ifdef TCGETS2
408 } else if (opt & TERMIOS_OLD) {
edc6afc5 409 if (user_termios_to_kernel_termios_1(&tmp_termios,
64bb6c5e 410 (struct termios __user *)arg))
edc6afc5 411 return -EFAULT;
1da177e4
LT
412 } else {
413 if (user_termios_to_kernel_termios(&tmp_termios,
64bb6c5e 414 (struct termios2 __user *)arg))
1da177e4
LT
415 return -EFAULT;
416 }
64bb6c5e
AC
417#else
418 } else if (user_termios_to_kernel_termios(&tmp_termios,
419 (struct termios __user *)arg))
420 return -EFAULT;
421#endif
1da177e4 422
edc6afc5
AC
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);
427
1da177e4
LT
428 ld = tty_ldisc_ref(tty);
429
430 if (ld != NULL) {
431 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
432 ld->flush_buffer(tty);
433 tty_ldisc_deref(ld);
434 }
435
436 if (opt & TERMIOS_WAIT) {
437 tty_wait_until_sent(tty, 0);
438 if (signal_pending(current))
439 return -EINTR;
440 }
441
442 change_termios(tty, &tmp_termios);
443 return 0;
444}
445
446static int get_termio(struct tty_struct * tty, struct termio __user * termio)
447{
448 if (kernel_termios_to_user_termio(termio, tty->termios))
449 return -EFAULT;
450 return 0;
451}
452
453static unsigned long inq_canon(struct tty_struct * tty)
454{
455 int nr, head, tail;
456
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);
468 }
469 return nr;
470}
471
472#ifdef TIOCGETP
473/*
474 * These are deprecated, but there is limited support..
475 *
476 * The "sg_flags" translation is a joke..
477 */
478static int get_sgflags(struct tty_struct * tty)
479{
480 int flags = 0;
481
482 if (!(tty->termios->c_lflag & ICANON)) {
483 if (tty->termios->c_lflag & ISIG)
484 flags |= 0x02; /* cbreak */
485 else
486 flags |= 0x20; /* raw */
487 }
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;
494}
495
496static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
497{
498 struct sgttyb tmp;
499
5785c95b 500 mutex_lock(&tty->termios_mutex);
606d099c
AC
501 tmp.sg_ispeed = tty->termios->c_ispeed;
502 tmp.sg_ospeed = tty->termios->c_ospeed;
1da177e4
LT
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);
5785c95b 506 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
507
508 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
509}
510
edc6afc5 511static void set_sgflags(struct ktermios * termios, int flags)
1da177e4
LT
512{
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;
519 }
520 if (flags & 0x08) { /* echo */
521 termios->c_lflag |= ECHO | ECHOE | ECHOK |
522 ECHOCTL | ECHOKE | IEXTEN;
523 }
524 if (flags & 0x10) { /* crmod */
525 termios->c_oflag |= OPOST | ONLCR;
526 }
527 if (flags & 0x20) { /* raw */
528 termios->c_iflag = 0;
529 termios->c_lflag &= ~(ISIG | ICANON);
530 }
531 if (!(termios->c_lflag & ICANON)) {
532 termios->c_cc[VMIN] = 1;
533 termios->c_cc[VTIME] = 0;
534 }
535}
536
af9b897e
AC
537/**
538 * set_sgttyb - set legacy terminal values
539 * @tty: tty structure
540 * @sgttyb: pointer to old style terminal structure
541 *
542 * Updates a terminal from the legacy BSD style terminal information
543 * structure.
544 *
545 * Locking: termios_sem
546 */
547
1da177e4
LT
548static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
549{
550 int retval;
551 struct sgttyb tmp;
edc6afc5 552 struct ktermios termios;
1da177e4
LT
553
554 retval = tty_check_change(tty);
555 if (retval)
556 return retval;
557
558 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
559 return -EFAULT;
560
5785c95b 561 mutex_lock(&tty->termios_mutex);
6804396f 562 termios = *tty->termios;
1da177e4
LT
563 termios.c_cc[VERASE] = tmp.sg_erase;
564 termios.c_cc[VKILL] = tmp.sg_kill;
565 set_sgflags(&termios, tmp.sg_flags);
edc6afc5
AC
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
5785c95b 570 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
571 change_termios(tty, &termios);
572 return 0;
573}
574#endif
575
576#ifdef TIOCGETC
577static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
578{
579 struct tchars tmp;
580
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;
588}
589
590static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
591{
592 struct tchars tmp;
593
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;
603}
604#endif
605
606#ifdef TIOCGLTC
607static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
608{
609 struct ltchars tmp;
610
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;
618}
619
620static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
621{
622 struct ltchars tmp;
623
624 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
625 return -EFAULT;
626
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;
634}
635#endif
636
af9b897e
AC
637/**
638 * send_prio_char - send priority character
639 *
640 * Send a high priority character to the tty even if stopped
641 *
5f412b24 642 * Locking: none for xchar method, write ordering for write method.
1da177e4 643 */
af9b897e 644
5f412b24 645static int send_prio_char(struct tty_struct *tty, char ch)
1da177e4
LT
646{
647 int was_stopped = tty->stopped;
648
649 if (tty->driver->send_xchar) {
650 tty->driver->send_xchar(tty, ch);
5f412b24 651 return 0;
1da177e4 652 }
5f412b24 653
9c1729db 654 if (tty_write_lock(tty, 0) < 0)
5f412b24
AC
655 return -ERESTARTSYS;
656
1da177e4
LT
657 if (was_stopped)
658 start_tty(tty);
659 tty->driver->write(tty, &ch, 1);
660 if (was_stopped)
661 stop_tty(tty);
9c1729db 662 tty_write_unlock(tty);
5f412b24 663 return 0;
1da177e4
LT
664}
665
666int n_tty_ioctl(struct tty_struct * tty, struct file * file,
667 unsigned int cmd, unsigned long arg)
668{
669 struct tty_struct * real_tty;
670 void __user *p = (void __user *)arg;
671 int retval;
672 struct tty_ldisc *ld;
673
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;
679
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
edc6afc5
AC
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
1da177e4
LT
707 case TCGETS:
708 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
709 return -EFAULT;
710 return 0;
edc6afc5
AC
711#else
712 case TCGETS:
64bb6c5e 713 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
edc6afc5
AC
714 return -EFAULT;
715 return 0;
716 case TCGETS2:
64bb6c5e 717 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
edc6afc5
AC
718 return -EFAULT;
719 return 0;
720 case TCSETSF2:
1da177e4 721 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
edc6afc5 722 case TCSETSW2:
1da177e4 723 return set_termios(real_tty, p, TERMIOS_WAIT);
edc6afc5 724 case TCSETS2:
1da177e4 725 return set_termios(real_tty, p, 0);
edc6afc5 726#endif
1da177e4
LT
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);
744 }
745 break;
746 case TCOON:
747 if (tty->flow_stopped) {
748 tty->flow_stopped = 0;
749 start_tty(tty);
750 }
751 break;
752 case TCIOFF:
753 if (STOP_CHAR(tty) != __DISABLED_CHAR)
5f412b24 754 return send_prio_char(tty, STOP_CHAR(tty));
1da177e4
LT
755 break;
756 case TCION:
757 if (START_CHAR(tty) != __DISABLED_CHAR)
5f412b24 758 return send_prio_char(tty, START_CHAR(tty));
1da177e4
LT
759 break;
760 default:
761 return -EINVAL;
762 }
763 return 0;
764 case TCFLSH:
765 retval = tty_check_change(tty);
766 if (retval)
767 return retval;
768
769 ld = tty_ldisc_ref(tty);
770 switch (arg) {
771 case TCIFLUSH:
69f63c5c 772 if (ld && ld->flush_buffer)
1da177e4
LT
773 ld->flush_buffer(tty);
774 break;
775 case TCIOFLUSH:
69f63c5c 776 if (ld && ld->flush_buffer)
1da177e4
LT
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;
786 }
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);
bb8bd3a5
TB
798#ifndef TCGETS2
799 case TIOCGLCKTRMIOS:
800 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
801 return -EFAULT;
802 return 0;
803
804 case TIOCSLCKTRMIOS:
805 if (!capable(CAP_SYS_ADMIN))
806 return -EPERM;
807 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
808 return -EFAULT;
809 return 0;
810#else
1da177e4 811 case TIOCGLCKTRMIOS:
f629307c 812 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
1da177e4
LT
813 return -EFAULT;
814 return 0;
815
816 case TIOCSLCKTRMIOS:
817 if (!capable(CAP_SYS_ADMIN))
818 return -EPERM;
f629307c 819 if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
1da177e4
LT
820 return -EFAULT;
821 return 0;
bb8bd3a5 822#endif
1da177e4
LT
823
824 case TIOCPKT:
825 {
826 int pktmode;
827
828 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
829 tty->driver->subtype != PTY_TYPE_MASTER)
830 return -ENOTTY;
831 if (get_user(pktmode, (int __user *) arg))
832 return -EFAULT;
833 if (pktmode) {
834 if (!tty->packet) {
835 tty->packet = 1;
836 tty->link->ctrl_status = 0;
837 }
838 } else
839 tty->packet = 0;
840 return 0;
841 }
842 case TIOCGSOFTCAR:
843 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
844 case TIOCSSOFTCAR:
845 if (get_user(arg, (unsigned int __user *) arg))
846 return -EFAULT;
5785c95b 847 mutex_lock(&tty->termios_mutex);
1da177e4
LT
848 tty->termios->c_cflag =
849 ((tty->termios->c_cflag & ~CLOCAL) |
850 (arg ? CLOCAL : 0));
5785c95b 851 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
852 return 0;
853 default:
854 return -ENOIOCTLCMD;
855 }
856}
857
858EXPORT_SYMBOL(n_tty_ioctl);