drivers/char/ds1286.c: use time_before, time_before_eq, etc
[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>
0ee9cbb3 24#include <linux/smp_lock.h>
1da177e4
LT
25
26#include <asm/io.h>
27#include <asm/uaccess.h>
28#include <asm/system.h>
29
30#undef TTY_DEBUG_WAIT_UNTIL_SENT
31
32#undef DEBUG
33
34/*
35 * Internal flag options for termios setting behavior
36 */
37#define TERMIOS_FLUSH 1
38#define TERMIOS_WAIT 2
39#define TERMIOS_TERMIO 4
edc6afc5 40#define TERMIOS_OLD 8
1da177e4 41
af9b897e
AC
42
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
47 *
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)
50 *
51 * Locking: none
52 */
53
355d95a1 54void tty_wait_until_sent(struct tty_struct *tty, long timeout)
1da177e4 55{
1da177e4
LT
56#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
57 char buf[64];
355d95a1 58
1da177e4
LT
59 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
60#endif
61 if (!tty->driver->chars_in_buffer)
62 return;
1da177e4
LT
63 if (!timeout)
64 timeout = MAX_SCHEDULE_TIMEOUT;
0ee9cbb3 65 lock_kernel();
5a52bd4a 66 if (wait_event_interruptible_timeout(tty->write_wait,
0ee9cbb3
AC
67 !tty->driver->chars_in_buffer(tty), timeout) >= 0) {
68 if (tty->driver->wait_until_sent)
69 tty->driver->wait_until_sent(tty, timeout);
70 }
71 unlock_kernel();
1da177e4 72}
1da177e4
LT
73EXPORT_SYMBOL(tty_wait_until_sent);
74
edc6afc5
AC
75static void unset_locked_termios(struct ktermios *termios,
76 struct ktermios *old,
77 struct ktermios *locked)
1da177e4
LT
78{
79 int i;
355d95a1
AC
80
81#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
1da177e4
LT
82
83 if (!locked) {
84 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
85 return;
86 }
87
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;
355d95a1 93 for (i = 0; i < NCCS; i++)
1da177e4
LT
94 termios->c_cc[i] = locked->c_cc[i] ?
95 old->c_cc[i] : termios->c_cc[i];
edc6afc5 96 /* FIXME: What should we do for i/ospeed */
1da177e4
LT
97}
98
edc6afc5
AC
99/*
100 * Routine which returns the baud rate of the tty
101 *
102 * Note that the baud_table needs to be kept in sync with the
103 * include/asm/termbits.h file.
104 */
105static 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
114};
115
116#ifndef __sparc__
117static 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
123};
124#else
125static 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
130};
131#endif
132
133static int n_baud_table = ARRAY_SIZE(baud_table);
134
135/**
136 * tty_termios_baud_rate
137 * @termios: termios structure
138 *
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.
143 *
144 * Locking: none
145 */
146
147speed_t tty_termios_baud_rate(struct ktermios *termios)
148{
149 unsigned int cbaud;
150
151 cbaud = termios->c_cflag & CBAUD;
152
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;
160
161 if (cbaud < 1 || cbaud + 15 > n_baud_table)
162 termios->c_cflag &= ~CBAUDEX;
163 else
164 cbaud += 15;
165 }
166 return baud_table[cbaud];
167}
edc6afc5
AC
168EXPORT_SYMBOL(tty_termios_baud_rate);
169
170/**
171 * tty_termios_input_baud_rate
172 * @termios: termios structure
173 *
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.
178 *
179 * Locking: none
180 */
181
182speed_t tty_termios_input_baud_rate(struct ktermios *termios)
183{
184#ifdef IBSHIFT
185 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
186
187 if (cbaud == B0)
188 return tty_termios_baud_rate(termios);
189
190 /* Magic token for arbitary speed via c_ispeed*/
191 if (cbaud == BOTHER)
192 return termios->c_ispeed;
193
194 if (cbaud & CBAUDEX) {
195 cbaud &= ~CBAUDEX;
196
197 if (cbaud < 1 || cbaud + 15 > n_baud_table)
198 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
199 else
200 cbaud += 15;
201 }
202 return baud_table[cbaud];
203#else
204 return tty_termios_baud_rate(termios);
205#endif
206}
edc6afc5
AC
207EXPORT_SYMBOL(tty_termios_input_baud_rate);
208
edc6afc5
AC
209/**
210 * tty_termios_encode_baud_rate
78137e3b 211 * @termios: ktermios structure holding user requested state
edc6afc5
AC
212 * @ispeed: input speed
213 * @ospeed: output speed
214 *
215 * Encode the speeds set into the passed termios structure. This is
216 * used as a library helper for drivers os that they can report back
217 * the actual speed selected when it differs from the speed requested
218 *
78137e3b
AC
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.
edc6afc5
AC
223 *
224 * Locking: Caller should hold termios lock. This is already held
225 * when calling this function from the driver termios handler.
5f519d72
AC
226 *
227 * The ifdefs deal with platforms whose owners have yet to update them
228 * and will all go away once this is done.
edc6afc5
AC
229 */
230
75e8b71d
MR
231void tty_termios_encode_baud_rate(struct ktermios *termios,
232 speed_t ibaud, speed_t obaud)
edc6afc5
AC
233{
234 int i = 0;
78137e3b
AC
235 int ifound = -1, ofound = -1;
236 int iclose = ibaud/50, oclose = obaud/50;
237 int ibinput = 0;
edc6afc5 238
5f519d72
AC
239 if (obaud == 0) /* CD dropped */
240 ibaud = 0; /* Clear ibaud to be sure */
241
edc6afc5
AC
242 termios->c_ispeed = ibaud;
243 termios->c_ospeed = obaud;
244
5f519d72 245#ifdef BOTHER
78137e3b
AC
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 */
249
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 */
5f519d72 256#endif
edc6afc5 257 termios->c_cflag &= ~CBAUD;
edc6afc5 258
5f519d72
AC
259 /*
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
264 */
265
edc6afc5 266 do {
75e8b71d
MR
267 if (obaud - oclose <= baud_table[i] &&
268 obaud + oclose >= baud_table[i]) {
edc6afc5 269 termios->c_cflag |= baud_bits[i];
78137e3b 270 ofound = i;
edc6afc5 271 }
75e8b71d
MR
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 */
5f519d72
AC
276 if (ofound == i && !ibinput)
277 ifound = i;
278#ifdef IBSHIFT
279 else {
280 ifound = i;
78137e3b 281 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
5f519d72
AC
282 }
283#endif
edc6afc5 284 }
6804396f 285 } while (++i < n_baud_table);
5f519d72
AC
286
287 /*
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.
290 */
291#ifdef BOTHER
78137e3b 292 if (ofound == -1)
edc6afc5 293 termios->c_cflag |= BOTHER;
78137e3b
AC
294 /* Set exact input bits only if the input and output differ or the
295 user already did */
6804396f 296 if (ifound == -1 && (ibaud != obaud || ibinput))
edc6afc5 297 termios->c_cflag |= (BOTHER << IBSHIFT);
5f519d72
AC
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");
304 }
305#endif
edc6afc5 306}
edc6afc5
AC
307EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
308
5f519d72
AC
309void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
310{
311 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
312}
313EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
edc6afc5
AC
314
315/**
316 * tty_get_baud_rate - get tty bit rates
317 * @tty: tty to query
318 *
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.
322 *
323 * Locking: none
324 */
325
326speed_t tty_get_baud_rate(struct tty_struct *tty)
327{
328 speed_t baud = tty_termios_baud_rate(tty->termios);
329
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;
335 }
336 baud = tty->alt_speed;
337 }
338
339 return baud;
340}
edc6afc5
AC
341EXPORT_SYMBOL(tty_get_baud_rate);
342
5f519d72
AC
343/**
344 * tty_termios_copy_hw - copy hardware settings
345 * @new: New termios
346 * @old: Old termios
347 *
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
352 */
353
354void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
355{
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;
362}
5f519d72
AC
363EXPORT_SYMBOL(tty_termios_copy_hw);
364
bf5e5834
AC
365/**
366 * tty_termios_hw_change - check for setting change
367 * @a: termios
368 * @b: termios to compare
369 *
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.
372 */
373
374int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
375{
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;
381}
382EXPORT_SYMBOL(tty_termios_hw_change);
383
af9b897e
AC
384/**
385 * change_termios - update termios values
386 * @tty: tty to update
387 * @new_termios: desired new value
388 *
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.
392 *
393 * Locking: termios_sem
394 */
395
355d95a1 396static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
1da177e4
LT
397{
398 int canon_change;
edc6afc5 399 struct ktermios old_termios = *tty->termios;
1da177e4 400 struct tty_ldisc *ld;
04f378b1 401 unsigned long flags;
355d95a1 402
1da177e4
LT
403 /*
404 * Perform the actual termios internal changes under lock.
405 */
355d95a1 406
1da177e4
LT
407
408 /* FIXME: we need to decide on some locking/ordering semantics
409 for the set_termios notification eventually */
5785c95b 410 mutex_lock(&tty->termios_mutex);
1da177e4
LT
411
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;
420 }
355d95a1 421
5f519d72 422 /* This bit should be in the ldisc code */
1da177e4
LT
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);
426
427 /* See if packet mode change of state. */
1da177e4
LT
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) {
04f378b1 436 spin_lock_irqsave(&tty->ctrl_lock, flags);
1da177e4
LT
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;
04f378b1 442 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1da177e4
LT
443 wake_up_interruptible(&tty->link->read_wait);
444 }
445 }
355d95a1 446
1da177e4
LT
447 if (tty->driver->set_termios)
448 (*tty->driver->set_termios)(tty, &old_termios);
5f519d72
AC
449 else
450 tty_termios_copy_hw(tty->termios, &old_termios);
1da177e4
LT
451
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);
457 }
5785c95b 458 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
459}
460
af9b897e
AC
461/**
462 * set_termios - set termios values for a tty
463 * @tty: terminal device
464 * @arg: user data
465 * @opt: option information
466 *
3a4fa0a2 467 * Helper function to prepare termios data and run necessary other
af9b897e
AC
468 * functions before using change_termios to do the actual changes.
469 *
470 * Locking:
471 * Called functions take ldisc and termios_sem locks
472 */
473
355d95a1 474static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
1da177e4 475{
edc6afc5 476 struct ktermios tmp_termios;
1da177e4
LT
477 struct tty_ldisc *ld;
478 int retval = tty_check_change(tty);
479
480 if (retval)
481 return retval;
482
64bb6c5e
AC
483 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
484
1da177e4 485 if (opt & TERMIOS_TERMIO) {
1da177e4
LT
486 if (user_termio_to_kernel_termios(&tmp_termios,
487 (struct termio __user *)arg))
488 return -EFAULT;
edc6afc5
AC
489#ifdef TCGETS2
490 } else if (opt & TERMIOS_OLD) {
edc6afc5 491 if (user_termios_to_kernel_termios_1(&tmp_termios,
64bb6c5e 492 (struct termios __user *)arg))
edc6afc5 493 return -EFAULT;
1da177e4
LT
494 } else {
495 if (user_termios_to_kernel_termios(&tmp_termios,
64bb6c5e 496 (struct termios2 __user *)arg))
1da177e4
LT
497 return -EFAULT;
498 }
64bb6c5e
AC
499#else
500 } else if (user_termios_to_kernel_termios(&tmp_termios,
501 (struct termios __user *)arg))
502 return -EFAULT;
503#endif
1da177e4 504
355d95a1
AC
505 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
506 * with the real speed so its unconditionally usable */
edc6afc5
AC
507 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
508 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
509
1da177e4 510 ld = tty_ldisc_ref(tty);
355d95a1 511
1da177e4
LT
512 if (ld != NULL) {
513 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
514 ld->flush_buffer(tty);
515 tty_ldisc_deref(ld);
516 }
355d95a1 517
1da177e4
LT
518 if (opt & TERMIOS_WAIT) {
519 tty_wait_until_sent(tty, 0);
520 if (signal_pending(current))
521 return -EINTR;
522 }
523
524 change_termios(tty, &tmp_termios);
5f519d72
AC
525
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 */
1da177e4
LT
530 return 0;
531}
532
355d95a1 533static int get_termio(struct tty_struct *tty, struct termio __user *termio)
1da177e4
LT
534{
535 if (kernel_termios_to_user_termio(termio, tty->termios))
536 return -EFAULT;
537 return 0;
538}
539
355d95a1 540static unsigned long inq_canon(struct tty_struct *tty)
1da177e4
LT
541{
542 int nr, head, tail;
543
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);
555 }
556 return nr;
557}
558
559#ifdef TIOCGETP
560/*
561 * These are deprecated, but there is limited support..
562 *
563 * The "sg_flags" translation is a joke..
564 */
355d95a1 565static int get_sgflags(struct tty_struct *tty)
1da177e4
LT
566{
567 int flags = 0;
568
569 if (!(tty->termios->c_lflag & ICANON)) {
570 if (tty->termios->c_lflag & ISIG)
571 flags |= 0x02; /* cbreak */
572 else
573 flags |= 0x20; /* raw */
574 }
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;
581}
582
355d95a1 583static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
584{
585 struct sgttyb tmp;
586
5785c95b 587 mutex_lock(&tty->termios_mutex);
606d099c
AC
588 tmp.sg_ispeed = tty->termios->c_ispeed;
589 tmp.sg_ospeed = tty->termios->c_ospeed;
1da177e4
LT
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);
5785c95b 593 mutex_unlock(&tty->termios_mutex);
355d95a1 594
1da177e4
LT
595 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
596}
597
355d95a1 598static void set_sgflags(struct ktermios *termios, int flags)
1da177e4
LT
599{
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;
606 }
607 if (flags & 0x08) { /* echo */
608 termios->c_lflag |= ECHO | ECHOE | ECHOK |
609 ECHOCTL | ECHOKE | IEXTEN;
610 }
611 if (flags & 0x10) { /* crmod */
612 termios->c_oflag |= OPOST | ONLCR;
613 }
614 if (flags & 0x20) { /* raw */
615 termios->c_iflag = 0;
616 termios->c_lflag &= ~(ISIG | ICANON);
617 }
618 if (!(termios->c_lflag & ICANON)) {
619 termios->c_cc[VMIN] = 1;
620 termios->c_cc[VTIME] = 0;
621 }
622}
623
af9b897e
AC
624/**
625 * set_sgttyb - set legacy terminal values
626 * @tty: tty structure
627 * @sgttyb: pointer to old style terminal structure
628 *
629 * Updates a terminal from the legacy BSD style terminal information
630 * structure.
631 *
632 * Locking: termios_sem
633 */
634
355d95a1 635static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
636{
637 int retval;
638 struct sgttyb tmp;
edc6afc5 639 struct ktermios termios;
1da177e4
LT
640
641 retval = tty_check_change(tty);
642 if (retval)
643 return retval;
355d95a1 644
1da177e4
LT
645 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
646 return -EFAULT;
647
5785c95b 648 mutex_lock(&tty->termios_mutex);
6804396f 649 termios = *tty->termios;
1da177e4
LT
650 termios.c_cc[VERASE] = tmp.sg_erase;
651 termios.c_cc[VKILL] = tmp.sg_kill;
652 set_sgflags(&termios, tmp.sg_flags);
edc6afc5
AC
653 /* Try and encode into Bfoo format */
654#ifdef BOTHER
355d95a1
AC
655 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
656 termios.c_ospeed);
edc6afc5 657#endif
5785c95b 658 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
659 change_termios(tty, &termios);
660 return 0;
661}
662#endif
663
664#ifdef TIOCGETC
355d95a1 665static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
666{
667 struct tchars tmp;
668
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;
676}
677
355d95a1 678static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
679{
680 struct tchars tmp;
681
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;
691}
692#endif
693
694#ifdef TIOCGLTC
355d95a1 695static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
696{
697 struct ltchars tmp;
698
699 tmp.t_suspc = tty->termios->c_cc[VSUSP];
355d95a1
AC
700 /* what is dsuspc anyway? */
701 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
1da177e4 702 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
355d95a1
AC
703 /* what is flushc anyway? */
704 tmp.t_flushc = tty->termios->c_cc[VEOL2];
1da177e4
LT
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;
708}
709
355d95a1 710static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
711{
712 struct ltchars tmp;
713
714 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
715 return -EFAULT;
716
717 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
355d95a1
AC
718 /* what is dsuspc anyway? */
719 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
1da177e4 720 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
355d95a1
AC
721 /* what is flushc anyway? */
722 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
1da177e4
LT
723 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
724 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
725 return 0;
726}
727#endif
728
af9b897e
AC
729/**
730 * send_prio_char - send priority character
731 *
732 * Send a high priority character to the tty even if stopped
733 *
5f412b24 734 * Locking: none for xchar method, write ordering for write method.
1da177e4 735 */
af9b897e 736
5f412b24 737static int send_prio_char(struct tty_struct *tty, char ch)
1da177e4
LT
738{
739 int was_stopped = tty->stopped;
740
741 if (tty->driver->send_xchar) {
742 tty->driver->send_xchar(tty, ch);
5f412b24 743 return 0;
1da177e4 744 }
5f412b24 745
9c1729db 746 if (tty_write_lock(tty, 0) < 0)
5f412b24
AC
747 return -ERESTARTSYS;
748
1da177e4
LT
749 if (was_stopped)
750 start_tty(tty);
751 tty->driver->write(tty, &ch, 1);
752 if (was_stopped)
753 stop_tty(tty);
9c1729db 754 tty_write_unlock(tty);
5f412b24 755 return 0;
1da177e4
LT
756}
757
1c2630cc
AC
758/**
759 * tty_change_softcar - carrier change ioctl helper
760 * @tty: tty to update
761 * @arg: enable/disable CLOCAL
762 *
763 * Perform a change to the CLOCAL state and call into the driver
764 * layer to make it visible. All done with the termios mutex
765 */
766
767static int tty_change_softcar(struct tty_struct *tty, int arg)
768{
769 int ret = 0;
770 int bit = arg ? CLOCAL : 0;
771 struct ktermios old = *tty->termios;
772
773 mutex_lock(&tty->termios_mutex);
774 tty->termios->c_cflag &= ~CLOCAL;
775 tty->termios->c_cflag |= bit;
776 if (tty->driver->set_termios)
777 tty->driver->set_termios(tty, &old);
778 if ((tty->termios->c_cflag & CLOCAL) != bit)
779 ret = -EINVAL;
780 mutex_unlock(&tty->termios_mutex);
781 return ret;
782}
783
0fc00e24
AC
784/**
785 * tty_mode_ioctl - mode related ioctls
786 * @tty: tty for the ioctl
787 * @file: file pointer for the tty
788 * @cmd: command
789 * @arg: ioctl argument
790 *
791 * Perform non line discipline specific mode control ioctls. This
792 * is designed to be called by line disciplines to ensure they provide
793 * consistent mode setting.
794 */
795
355d95a1 796int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24 797 unsigned int cmd, unsigned long arg)
1da177e4 798{
355d95a1 799 struct tty_struct *real_tty;
1da177e4 800 void __user *p = (void __user *)arg;
1da177e4
LT
801
802 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
803 tty->driver->subtype == PTY_TYPE_MASTER)
804 real_tty = tty->link;
805 else
806 real_tty = tty;
807
808 switch (cmd) {
809#ifdef TIOCGETP
355d95a1
AC
810 case TIOCGETP:
811 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
812 case TIOCSETP:
813 case TIOCSETN:
814 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
1da177e4
LT
815#endif
816#ifdef TIOCGETC
355d95a1
AC
817 case TIOCGETC:
818 return get_tchars(real_tty, p);
819 case TIOCSETC:
820 return set_tchars(real_tty, p);
1da177e4
LT
821#endif
822#ifdef TIOCGLTC
355d95a1
AC
823 case TIOCGLTC:
824 return get_ltchars(real_tty, p);
825 case TIOCSLTC:
826 return set_ltchars(real_tty, p);
1da177e4 827#endif
355d95a1
AC
828 case TCSETSF:
829 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
830 case TCSETSW:
831 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
832 case TCSETS:
833 return set_termios(real_tty, p, TERMIOS_OLD);
edc6afc5 834#ifndef TCGETS2
355d95a1
AC
835 case TCGETS:
836 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
837 return -EFAULT;
838 return 0;
edc6afc5 839#else
355d95a1
AC
840 case TCGETS:
841 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
842 return -EFAULT;
843 return 0;
844 case TCGETS2:
845 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
846 return -EFAULT;
847 return 0;
848 case TCSETSF2:
849 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
850 case TCSETSW2:
851 return set_termios(real_tty, p, TERMIOS_WAIT);
852 case TCSETS2:
853 return set_termios(real_tty, p, 0);
edc6afc5 854#endif
355d95a1
AC
855 case TCGETA:
856 return get_termio(real_tty, p);
857 case TCSETAF:
858 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
859 case TCSETAW:
860 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
861 case TCSETA:
862 return set_termios(real_tty, p, TERMIOS_TERMIO);
0fc00e24 863#ifndef TCGETS2
355d95a1
AC
864 case TIOCGLCKTRMIOS:
865 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
866 return -EFAULT;
867 return 0;
868 case TIOCSLCKTRMIOS:
869 if (!capable(CAP_SYS_ADMIN))
870 return -EPERM;
871 if (user_termios_to_kernel_termios(real_tty->termios_locked,
872 (struct termios __user *) arg))
873 return -EFAULT;
874 return 0;
0fc00e24 875#else
355d95a1
AC
876 case TIOCGLCKTRMIOS:
877 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
878 return -EFAULT;
879 return 0;
880 case TIOCSLCKTRMIOS:
881 if (!capable(CAP_SYS_ADMIN))
882 return -EPERM;
883 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
884 (struct termios __user *) arg))
885 return -EFAULT;
0fc00e24
AC
886 return 0;
887#endif
355d95a1
AC
888 case TIOCGSOFTCAR:
889 return put_user(C_CLOCAL(tty) ? 1 : 0,
890 (int __user *)arg);
891 case TIOCSSOFTCAR:
892 if (get_user(arg, (unsigned int __user *) arg))
893 return -EFAULT;
1c2630cc 894 return tty_change_softcar(tty, arg);
355d95a1
AC
895 default:
896 return -ENOIOCTLCMD;
0fc00e24
AC
897 }
898}
0fc00e24
AC
899EXPORT_SYMBOL_GPL(tty_mode_ioctl);
900
901int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
902{
903 struct tty_ldisc *ld;
904 int retval = tty_check_change(tty);
905 if (retval)
906 return retval;
907
908 ld = tty_ldisc_ref(tty);
909 switch (arg) {
910 case TCIFLUSH:
911 if (ld && ld->flush_buffer)
912 ld->flush_buffer(tty);
913 break;
914 case TCIOFLUSH:
915 if (ld && ld->flush_buffer)
916 ld->flush_buffer(tty);
917 /* fall through */
918 case TCOFLUSH:
919 if (tty->driver->flush_buffer)
920 tty->driver->flush_buffer(tty);
921 break;
922 default:
923 tty_ldisc_deref(ld);
924 return -EINVAL;
925 }
926 tty_ldisc_deref(ld);
927 return 0;
928}
0fc00e24
AC
929EXPORT_SYMBOL_GPL(tty_perform_flush);
930
355d95a1 931int n_tty_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24
AC
932 unsigned int cmd, unsigned long arg)
933{
355d95a1 934 struct tty_struct *real_tty;
04f378b1 935 unsigned long flags;
0fc00e24
AC
936 int retval;
937
938 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
939 tty->driver->subtype == PTY_TYPE_MASTER)
940 real_tty = tty->link;
941 else
942 real_tty = tty;
943
944 switch (cmd) {
355d95a1
AC
945 case TCXONC:
946 retval = tty_check_change(tty);
947 if (retval)
948 return retval;
949 switch (arg) {
950 case TCOOFF:
951 if (!tty->flow_stopped) {
952 tty->flow_stopped = 1;
953 stop_tty(tty);
1da177e4 954 }
355d95a1
AC
955 break;
956 case TCOON:
957 if (tty->flow_stopped) {
958 tty->flow_stopped = 0;
959 start_tty(tty);
960 }
961 break;
962 case TCIOFF:
963 if (STOP_CHAR(tty) != __DISABLED_CHAR)
964 return send_prio_char(tty, STOP_CHAR(tty));
965 break;
966 case TCION:
967 if (START_CHAR(tty) != __DISABLED_CHAR)
968 return send_prio_char(tty, START_CHAR(tty));
969 break;
1da177e4 970 default:
355d95a1 971 return -EINVAL;
1da177e4 972 }
355d95a1
AC
973 return 0;
974 case TCFLSH:
975 return tty_perform_flush(tty, arg);
976 case TIOCOUTQ:
977 return put_user(tty->driver->chars_in_buffer ?
978 tty->driver->chars_in_buffer(tty) : 0,
979 (int __user *) arg);
980 case TIOCINQ:
981 retval = tty->read_cnt;
982 if (L_ICANON(tty))
983 retval = inq_canon(tty);
984 return put_user(retval, (unsigned int __user *) arg);
985 case TIOCPKT:
986 {
987 int pktmode;
988
989 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
990 tty->driver->subtype != PTY_TYPE_MASTER)
991 return -ENOTTY;
992 if (get_user(pktmode, (int __user *) arg))
993 return -EFAULT;
04f378b1 994 spin_lock_irqsave(&tty->ctrl_lock, flags);
355d95a1
AC
995 if (pktmode) {
996 if (!tty->packet) {
997 tty->packet = 1;
998 tty->link->ctrl_status = 0;
999 }
1000 } else
1001 tty->packet = 0;
04f378b1 1002 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
355d95a1
AC
1003 return 0;
1004 }
1005 default:
1006 /* Try the mode commands */
1007 return tty_mode_ioctl(tty, file, cmd, arg);
1008 }
1da177e4 1009}
1da177e4 1010EXPORT_SYMBOL(n_tty_ioctl);