isicom: fix buffer allocation
[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 42
f34d7a5b
AC
43int tty_chars_in_buffer(struct tty_struct *tty)
44{
45 if (tty->ops->chars_in_buffer)
46 return tty->ops->chars_in_buffer(tty);
47 else
48 return 0;
49}
50
51EXPORT_SYMBOL(tty_chars_in_buffer);
52
53int tty_write_room(struct tty_struct *tty)
54{
55 if (tty->ops->write_room)
56 return tty->ops->write_room(tty);
57 return 2048;
58}
59
60EXPORT_SYMBOL(tty_write_room);
61
62void tty_driver_flush_buffer(struct tty_struct *tty)
63{
64 if (tty->ops->flush_buffer)
65 tty->ops->flush_buffer(tty);
66}
67
68EXPORT_SYMBOL(tty_driver_flush_buffer);
69
70
af9b897e
AC
71/**
72 * tty_wait_until_sent - wait for I/O to finish
73 * @tty: tty we are waiting for
74 * @timeout: how long we will wait
75 *
76 * Wait for characters pending in a tty driver to hit the wire, or
77 * for a timeout to occur (eg due to flow control)
78 *
79 * Locking: none
80 */
81
355d95a1 82void tty_wait_until_sent(struct tty_struct *tty, long timeout)
1da177e4 83{
1da177e4
LT
84#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
85 char buf[64];
355d95a1 86
1da177e4
LT
87 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
88#endif
1da177e4
LT
89 if (!timeout)
90 timeout = MAX_SCHEDULE_TIMEOUT;
5a52bd4a 91 if (wait_event_interruptible_timeout(tty->write_wait,
f34d7a5b
AC
92 !tty_chars_in_buffer(tty), timeout) >= 0) {
93 if (tty->ops->wait_until_sent)
94 tty->ops->wait_until_sent(tty, timeout);
0ee9cbb3 95 }
1da177e4 96}
1da177e4
LT
97EXPORT_SYMBOL(tty_wait_until_sent);
98
edc6afc5
AC
99static void unset_locked_termios(struct ktermios *termios,
100 struct ktermios *old,
101 struct ktermios *locked)
1da177e4
LT
102{
103 int i;
355d95a1
AC
104
105#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
1da177e4
LT
106
107 if (!locked) {
108 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
109 return;
110 }
111
112 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
113 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
114 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
115 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
116 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
355d95a1 117 for (i = 0; i < NCCS; i++)
1da177e4
LT
118 termios->c_cc[i] = locked->c_cc[i] ?
119 old->c_cc[i] : termios->c_cc[i];
edc6afc5 120 /* FIXME: What should we do for i/ospeed */
1da177e4
LT
121}
122
edc6afc5
AC
123/*
124 * Routine which returns the baud rate of the tty
125 *
126 * Note that the baud_table needs to be kept in sync with the
127 * include/asm/termbits.h file.
128 */
129static const speed_t baud_table[] = {
130 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
131 9600, 19200, 38400, 57600, 115200, 230400, 460800,
132#ifdef __sparc__
133 76800, 153600, 307200, 614400, 921600
134#else
135 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
136 2500000, 3000000, 3500000, 4000000
137#endif
138};
139
140#ifndef __sparc__
141static const tcflag_t baud_bits[] = {
142 B0, B50, B75, B110, B134, B150, B200, B300, B600,
143 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
144 B57600, B115200, B230400, B460800, B500000, B576000,
145 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
146 B3000000, B3500000, B4000000
147};
148#else
149static const tcflag_t baud_bits[] = {
150 B0, B50, B75, B110, B134, B150, B200, B300, B600,
151 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
152 B57600, B115200, B230400, B460800, B76800, B153600,
153 B307200, B614400, B921600
154};
155#endif
156
157static int n_baud_table = ARRAY_SIZE(baud_table);
158
159/**
160 * tty_termios_baud_rate
161 * @termios: termios structure
162 *
163 * Convert termios baud rate data into a speed. This should be called
164 * with the termios lock held if this termios is a terminal termios
165 * structure. May change the termios data. Device drivers can call this
166 * function but should use ->c_[io]speed directly as they are updated.
167 *
168 * Locking: none
169 */
170
171speed_t tty_termios_baud_rate(struct ktermios *termios)
172{
173 unsigned int cbaud;
174
175 cbaud = termios->c_cflag & CBAUD;
176
177#ifdef BOTHER
178 /* Magic token for arbitary speed via c_ispeed/c_ospeed */
179 if (cbaud == BOTHER)
180 return termios->c_ospeed;
181#endif
182 if (cbaud & CBAUDEX) {
183 cbaud &= ~CBAUDEX;
184
185 if (cbaud < 1 || cbaud + 15 > n_baud_table)
186 termios->c_cflag &= ~CBAUDEX;
187 else
188 cbaud += 15;
189 }
190 return baud_table[cbaud];
191}
edc6afc5
AC
192EXPORT_SYMBOL(tty_termios_baud_rate);
193
194/**
195 * tty_termios_input_baud_rate
196 * @termios: termios structure
197 *
198 * Convert termios baud rate data into a speed. This should be called
199 * with the termios lock held if this termios is a terminal termios
200 * structure. May change the termios data. Device drivers can call this
201 * function but should use ->c_[io]speed directly as they are updated.
202 *
203 * Locking: none
204 */
205
206speed_t tty_termios_input_baud_rate(struct ktermios *termios)
207{
208#ifdef IBSHIFT
209 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
210
211 if (cbaud == B0)
212 return tty_termios_baud_rate(termios);
213
214 /* Magic token for arbitary speed via c_ispeed*/
215 if (cbaud == BOTHER)
216 return termios->c_ispeed;
217
218 if (cbaud & CBAUDEX) {
219 cbaud &= ~CBAUDEX;
220
221 if (cbaud < 1 || cbaud + 15 > n_baud_table)
222 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
223 else
224 cbaud += 15;
225 }
226 return baud_table[cbaud];
227#else
228 return tty_termios_baud_rate(termios);
229#endif
230}
edc6afc5
AC
231EXPORT_SYMBOL(tty_termios_input_baud_rate);
232
edc6afc5
AC
233/**
234 * tty_termios_encode_baud_rate
78137e3b 235 * @termios: ktermios structure holding user requested state
edc6afc5
AC
236 * @ispeed: input speed
237 * @ospeed: output speed
238 *
239 * Encode the speeds set into the passed termios structure. This is
240 * used as a library helper for drivers os that they can report back
241 * the actual speed selected when it differs from the speed requested
242 *
78137e3b
AC
243 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
244 * we need to carefully set the bits when the user does not get the
245 * desired speed. We allow small margins and preserve as much of possible
246 * of the input intent to keep compatiblity.
edc6afc5
AC
247 *
248 * Locking: Caller should hold termios lock. This is already held
249 * when calling this function from the driver termios handler.
5f519d72
AC
250 *
251 * The ifdefs deal with platforms whose owners have yet to update them
252 * and will all go away once this is done.
edc6afc5
AC
253 */
254
75e8b71d
MR
255void tty_termios_encode_baud_rate(struct ktermios *termios,
256 speed_t ibaud, speed_t obaud)
edc6afc5
AC
257{
258 int i = 0;
78137e3b
AC
259 int ifound = -1, ofound = -1;
260 int iclose = ibaud/50, oclose = obaud/50;
261 int ibinput = 0;
edc6afc5 262
5f519d72
AC
263 if (obaud == 0) /* CD dropped */
264 ibaud = 0; /* Clear ibaud to be sure */
265
edc6afc5
AC
266 termios->c_ispeed = ibaud;
267 termios->c_ospeed = obaud;
268
5f519d72 269#ifdef BOTHER
78137e3b
AC
270 /* If the user asked for a precise weird speed give a precise weird
271 answer. If they asked for a Bfoo speed they many have problems
272 digesting non-exact replies so fuzz a bit */
273
274 if ((termios->c_cflag & CBAUD) == BOTHER)
275 oclose = 0;
276 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
277 iclose = 0;
278 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
279 ibinput = 1; /* An input speed was specified */
5f519d72 280#endif
edc6afc5 281 termios->c_cflag &= ~CBAUD;
edc6afc5 282
5f519d72
AC
283 /*
284 * Our goal is to find a close match to the standard baud rate
285 * returned. Walk the baud rate table and if we get a very close
286 * match then report back the speed as a POSIX Bxxxx value by
287 * preference
288 */
289
edc6afc5 290 do {
75e8b71d
MR
291 if (obaud - oclose <= baud_table[i] &&
292 obaud + oclose >= baud_table[i]) {
edc6afc5 293 termios->c_cflag |= baud_bits[i];
78137e3b 294 ofound = i;
edc6afc5 295 }
75e8b71d
MR
296 if (ibaud - iclose <= baud_table[i] &&
297 ibaud + iclose >= baud_table[i]) {
298 /* For the case input == output don't set IBAUD bits
299 if the user didn't do so */
5f519d72
AC
300 if (ofound == i && !ibinput)
301 ifound = i;
302#ifdef IBSHIFT
303 else {
304 ifound = i;
78137e3b 305 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
5f519d72
AC
306 }
307#endif
edc6afc5 308 }
6804396f 309 } while (++i < n_baud_table);
5f519d72
AC
310
311 /*
312 * If we found no match then use BOTHER if provided or warn
313 * the user their platform maintainer needs to wake up if not.
314 */
315#ifdef BOTHER
78137e3b 316 if (ofound == -1)
edc6afc5 317 termios->c_cflag |= BOTHER;
78137e3b
AC
318 /* Set exact input bits only if the input and output differ or the
319 user already did */
6804396f 320 if (ifound == -1 && (ibaud != obaud || ibinput))
edc6afc5 321 termios->c_cflag |= (BOTHER << IBSHIFT);
5f519d72
AC
322#else
323 if (ifound == -1 || ofound == -1) {
324 static int warned;
325 if (!warned++)
326 printk(KERN_WARNING "tty: Unable to return correct "
327 "speed data as your architecture needs updating.\n");
328 }
329#endif
edc6afc5 330}
edc6afc5
AC
331EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
332
5f519d72
AC
333void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
334{
335 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
336}
337EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
edc6afc5
AC
338
339/**
340 * tty_get_baud_rate - get tty bit rates
341 * @tty: tty to query
342 *
343 * Returns the baud rate as an integer for this terminal. The
344 * termios lock must be held by the caller and the terminal bit
345 * flags may be updated.
346 *
347 * Locking: none
348 */
349
350speed_t tty_get_baud_rate(struct tty_struct *tty)
351{
352 speed_t baud = tty_termios_baud_rate(tty->termios);
353
354 if (baud == 38400 && tty->alt_speed) {
355 if (!tty->warned) {
356 printk(KERN_WARNING "Use of setserial/setrocket to "
357 "set SPD_* flags is deprecated\n");
358 tty->warned = 1;
359 }
360 baud = tty->alt_speed;
361 }
362
363 return baud;
364}
edc6afc5
AC
365EXPORT_SYMBOL(tty_get_baud_rate);
366
5f519d72
AC
367/**
368 * tty_termios_copy_hw - copy hardware settings
369 * @new: New termios
370 * @old: Old termios
371 *
372 * Propogate the hardware specific terminal setting bits from
373 * the old termios structure to the new one. This is used in cases
374 * where the hardware does not support reconfiguration or as a helper
375 * in some cases where only minimal reconfiguration is supported
376 */
377
378void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
379{
380 /* The bits a dumb device handles in software. Smart devices need
381 to always provide a set_termios method */
382 new->c_cflag &= HUPCL | CREAD | CLOCAL;
383 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
384 new->c_ispeed = old->c_ispeed;
385 new->c_ospeed = old->c_ospeed;
386}
5f519d72
AC
387EXPORT_SYMBOL(tty_termios_copy_hw);
388
bf5e5834
AC
389/**
390 * tty_termios_hw_change - check for setting change
391 * @a: termios
392 * @b: termios to compare
393 *
394 * Check if any of the bits that affect a dumb device have changed
395 * between the two termios structures, or a speed change is needed.
396 */
397
398int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
399{
400 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
401 return 1;
402 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
403 return 1;
404 return 0;
405}
406EXPORT_SYMBOL(tty_termios_hw_change);
407
af9b897e
AC
408/**
409 * change_termios - update termios values
410 * @tty: tty to update
411 * @new_termios: desired new value
412 *
413 * Perform updates to the termios values set on this terminal. There
414 * is a bit of layering violation here with n_tty in terms of the
415 * internal knowledge of this function.
416 *
417 * Locking: termios_sem
418 */
419
355d95a1 420static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
1da177e4
LT
421{
422 int canon_change;
978e595f 423 struct ktermios old_termios;
1da177e4 424 struct tty_ldisc *ld;
04f378b1 425 unsigned long flags;
355d95a1 426
1da177e4
LT
427 /*
428 * Perform the actual termios internal changes under lock.
429 */
355d95a1 430
1da177e4
LT
431
432 /* FIXME: we need to decide on some locking/ordering semantics
433 for the set_termios notification eventually */
5785c95b 434 mutex_lock(&tty->termios_mutex);
978e595f 435 old_termios = *tty->termios;
1da177e4
LT
436 *tty->termios = *new_termios;
437 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
438 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
439 if (canon_change) {
440 memset(&tty->read_flags, 0, sizeof tty->read_flags);
441 tty->canon_head = tty->read_tail;
442 tty->canon_data = 0;
443 tty->erasing = 0;
444 }
355d95a1 445
5f519d72 446 /* This bit should be in the ldisc code */
1da177e4
LT
447 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
448 /* Get characters left over from canonical mode. */
449 wake_up_interruptible(&tty->read_wait);
450
451 /* See if packet mode change of state. */
1da177e4
LT
452 if (tty->link && tty->link->packet) {
453 int old_flow = ((old_termios.c_iflag & IXON) &&
454 (old_termios.c_cc[VSTOP] == '\023') &&
455 (old_termios.c_cc[VSTART] == '\021'));
456 int new_flow = (I_IXON(tty) &&
457 STOP_CHAR(tty) == '\023' &&
458 START_CHAR(tty) == '\021');
459 if (old_flow != new_flow) {
04f378b1 460 spin_lock_irqsave(&tty->ctrl_lock, flags);
1da177e4
LT
461 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
462 if (new_flow)
463 tty->ctrl_status |= TIOCPKT_DOSTOP;
464 else
465 tty->ctrl_status |= TIOCPKT_NOSTOP;
04f378b1 466 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1da177e4
LT
467 wake_up_interruptible(&tty->link->read_wait);
468 }
469 }
355d95a1 470
f34d7a5b
AC
471 if (tty->ops->set_termios)
472 (*tty->ops->set_termios)(tty, &old_termios);
5f519d72
AC
473 else
474 tty_termios_copy_hw(tty->termios, &old_termios);
1da177e4
LT
475
476 ld = tty_ldisc_ref(tty);
477 if (ld != NULL) {
478 if (ld->set_termios)
479 (ld->set_termios)(tty, &old_termios);
480 tty_ldisc_deref(ld);
481 }
5785c95b 482 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
483}
484
af9b897e
AC
485/**
486 * set_termios - set termios values for a tty
487 * @tty: terminal device
488 * @arg: user data
489 * @opt: option information
490 *
3a4fa0a2 491 * Helper function to prepare termios data and run necessary other
af9b897e
AC
492 * functions before using change_termios to do the actual changes.
493 *
494 * Locking:
495 * Called functions take ldisc and termios_sem locks
496 */
497
355d95a1 498static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
1da177e4 499{
edc6afc5 500 struct ktermios tmp_termios;
1da177e4
LT
501 struct tty_ldisc *ld;
502 int retval = tty_check_change(tty);
503
504 if (retval)
505 return retval;
506
978e595f 507 mutex_lock(&tty->termios_mutex);
64bb6c5e 508 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
978e595f 509 mutex_unlock(&tty->termios_mutex);
64bb6c5e 510
1da177e4 511 if (opt & TERMIOS_TERMIO) {
1da177e4
LT
512 if (user_termio_to_kernel_termios(&tmp_termios,
513 (struct termio __user *)arg))
514 return -EFAULT;
edc6afc5
AC
515#ifdef TCGETS2
516 } else if (opt & TERMIOS_OLD) {
edc6afc5 517 if (user_termios_to_kernel_termios_1(&tmp_termios,
64bb6c5e 518 (struct termios __user *)arg))
edc6afc5 519 return -EFAULT;
1da177e4
LT
520 } else {
521 if (user_termios_to_kernel_termios(&tmp_termios,
64bb6c5e 522 (struct termios2 __user *)arg))
1da177e4
LT
523 return -EFAULT;
524 }
64bb6c5e
AC
525#else
526 } else if (user_termios_to_kernel_termios(&tmp_termios,
527 (struct termios __user *)arg))
528 return -EFAULT;
529#endif
1da177e4 530
355d95a1
AC
531 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
532 * with the real speed so its unconditionally usable */
edc6afc5
AC
533 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
534 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
535
1da177e4 536 ld = tty_ldisc_ref(tty);
355d95a1 537
1da177e4
LT
538 if (ld != NULL) {
539 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
540 ld->flush_buffer(tty);
541 tty_ldisc_deref(ld);
542 }
355d95a1 543
1da177e4
LT
544 if (opt & TERMIOS_WAIT) {
545 tty_wait_until_sent(tty, 0);
546 if (signal_pending(current))
547 return -EINTR;
548 }
549
550 change_termios(tty, &tmp_termios);
5f519d72
AC
551
552 /* FIXME: Arguably if tmp_termios == tty->termios AND the
553 actual requested termios was not tmp_termios then we may
554 want to return an error as no user requested change has
555 succeeded */
1da177e4
LT
556 return 0;
557}
558
355d95a1 559static int get_termio(struct tty_struct *tty, struct termio __user *termio)
1da177e4
LT
560{
561 if (kernel_termios_to_user_termio(termio, tty->termios))
562 return -EFAULT;
563 return 0;
564}
565
355d95a1 566static unsigned long inq_canon(struct tty_struct *tty)
1da177e4
LT
567{
568 int nr, head, tail;
569
570 if (!tty->canon_data || !tty->read_buf)
571 return 0;
572 head = tty->canon_head;
573 tail = tty->read_tail;
574 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
575 /* Skip EOF-chars.. */
576 while (head != tail) {
577 if (test_bit(tail, tty->read_flags) &&
578 tty->read_buf[tail] == __DISABLED_CHAR)
579 nr--;
580 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
581 }
582 return nr;
583}
584
585#ifdef TIOCGETP
586/*
587 * These are deprecated, but there is limited support..
588 *
589 * The "sg_flags" translation is a joke..
590 */
355d95a1 591static int get_sgflags(struct tty_struct *tty)
1da177e4
LT
592{
593 int flags = 0;
594
595 if (!(tty->termios->c_lflag & ICANON)) {
596 if (tty->termios->c_lflag & ISIG)
597 flags |= 0x02; /* cbreak */
598 else
599 flags |= 0x20; /* raw */
600 }
601 if (tty->termios->c_lflag & ECHO)
602 flags |= 0x08; /* echo */
603 if (tty->termios->c_oflag & OPOST)
604 if (tty->termios->c_oflag & ONLCR)
605 flags |= 0x10; /* crmod */
606 return flags;
607}
608
355d95a1 609static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
610{
611 struct sgttyb tmp;
612
5785c95b 613 mutex_lock(&tty->termios_mutex);
606d099c
AC
614 tmp.sg_ispeed = tty->termios->c_ispeed;
615 tmp.sg_ospeed = tty->termios->c_ospeed;
1da177e4
LT
616 tmp.sg_erase = tty->termios->c_cc[VERASE];
617 tmp.sg_kill = tty->termios->c_cc[VKILL];
618 tmp.sg_flags = get_sgflags(tty);
5785c95b 619 mutex_unlock(&tty->termios_mutex);
355d95a1 620
1da177e4
LT
621 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
622}
623
355d95a1 624static void set_sgflags(struct ktermios *termios, int flags)
1da177e4
LT
625{
626 termios->c_iflag = ICRNL | IXON;
627 termios->c_oflag = 0;
628 termios->c_lflag = ISIG | ICANON;
629 if (flags & 0x02) { /* cbreak */
630 termios->c_iflag = 0;
631 termios->c_lflag &= ~ICANON;
632 }
633 if (flags & 0x08) { /* echo */
634 termios->c_lflag |= ECHO | ECHOE | ECHOK |
635 ECHOCTL | ECHOKE | IEXTEN;
636 }
637 if (flags & 0x10) { /* crmod */
638 termios->c_oflag |= OPOST | ONLCR;
639 }
640 if (flags & 0x20) { /* raw */
641 termios->c_iflag = 0;
642 termios->c_lflag &= ~(ISIG | ICANON);
643 }
644 if (!(termios->c_lflag & ICANON)) {
645 termios->c_cc[VMIN] = 1;
646 termios->c_cc[VTIME] = 0;
647 }
648}
649
af9b897e
AC
650/**
651 * set_sgttyb - set legacy terminal values
652 * @tty: tty structure
653 * @sgttyb: pointer to old style terminal structure
654 *
655 * Updates a terminal from the legacy BSD style terminal information
656 * structure.
657 *
658 * Locking: termios_sem
659 */
660
355d95a1 661static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
662{
663 int retval;
664 struct sgttyb tmp;
edc6afc5 665 struct ktermios termios;
1da177e4
LT
666
667 retval = tty_check_change(tty);
668 if (retval)
669 return retval;
355d95a1 670
1da177e4
LT
671 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
672 return -EFAULT;
673
5785c95b 674 mutex_lock(&tty->termios_mutex);
6804396f 675 termios = *tty->termios;
1da177e4
LT
676 termios.c_cc[VERASE] = tmp.sg_erase;
677 termios.c_cc[VKILL] = tmp.sg_kill;
678 set_sgflags(&termios, tmp.sg_flags);
edc6afc5
AC
679 /* Try and encode into Bfoo format */
680#ifdef BOTHER
355d95a1
AC
681 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
682 termios.c_ospeed);
edc6afc5 683#endif
5785c95b 684 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
685 change_termios(tty, &termios);
686 return 0;
687}
688#endif
689
690#ifdef TIOCGETC
355d95a1 691static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
692{
693 struct tchars tmp;
694
978e595f 695 mutex_lock(&tty->termios_mutex);
1da177e4
LT
696 tmp.t_intrc = tty->termios->c_cc[VINTR];
697 tmp.t_quitc = tty->termios->c_cc[VQUIT];
698 tmp.t_startc = tty->termios->c_cc[VSTART];
699 tmp.t_stopc = tty->termios->c_cc[VSTOP];
700 tmp.t_eofc = tty->termios->c_cc[VEOF];
701 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
978e595f 702 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
703 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
704}
705
355d95a1 706static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
707{
708 struct tchars tmp;
709
710 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
711 return -EFAULT;
978e595f 712 mutex_lock(&tty->termios_mutex);
1da177e4
LT
713 tty->termios->c_cc[VINTR] = tmp.t_intrc;
714 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
715 tty->termios->c_cc[VSTART] = tmp.t_startc;
716 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
717 tty->termios->c_cc[VEOF] = tmp.t_eofc;
718 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
978e595f 719 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
720 return 0;
721}
722#endif
723
724#ifdef TIOCGLTC
355d95a1 725static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
726{
727 struct ltchars tmp;
728
978e595f 729 mutex_lock(&tty->termios_mutex);
1da177e4 730 tmp.t_suspc = tty->termios->c_cc[VSUSP];
355d95a1
AC
731 /* what is dsuspc anyway? */
732 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
1da177e4 733 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
355d95a1
AC
734 /* what is flushc anyway? */
735 tmp.t_flushc = tty->termios->c_cc[VEOL2];
1da177e4
LT
736 tmp.t_werasc = tty->termios->c_cc[VWERASE];
737 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
978e595f 738 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
739 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
740}
741
355d95a1 742static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
743{
744 struct ltchars tmp;
745
746 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
747 return -EFAULT;
748
978e595f 749 mutex_lock(&tty->termios_mutex);
1da177e4 750 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
355d95a1
AC
751 /* what is dsuspc anyway? */
752 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
1da177e4 753 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
355d95a1
AC
754 /* what is flushc anyway? */
755 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
1da177e4
LT
756 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
757 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
978e595f 758 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
759 return 0;
760}
761#endif
762
af9b897e
AC
763/**
764 * send_prio_char - send priority character
765 *
766 * Send a high priority character to the tty even if stopped
767 *
5f412b24 768 * Locking: none for xchar method, write ordering for write method.
1da177e4 769 */
af9b897e 770
5f412b24 771static int send_prio_char(struct tty_struct *tty, char ch)
1da177e4
LT
772{
773 int was_stopped = tty->stopped;
774
f34d7a5b
AC
775 if (tty->ops->send_xchar) {
776 tty->ops->send_xchar(tty, ch);
5f412b24 777 return 0;
1da177e4 778 }
5f412b24 779
9c1729db 780 if (tty_write_lock(tty, 0) < 0)
5f412b24
AC
781 return -ERESTARTSYS;
782
1da177e4
LT
783 if (was_stopped)
784 start_tty(tty);
f34d7a5b 785 tty->ops->write(tty, &ch, 1);
1da177e4
LT
786 if (was_stopped)
787 stop_tty(tty);
9c1729db 788 tty_write_unlock(tty);
5f412b24 789 return 0;
1da177e4
LT
790}
791
1c2630cc
AC
792/**
793 * tty_change_softcar - carrier change ioctl helper
794 * @tty: tty to update
795 * @arg: enable/disable CLOCAL
796 *
797 * Perform a change to the CLOCAL state and call into the driver
798 * layer to make it visible. All done with the termios mutex
799 */
800
801static int tty_change_softcar(struct tty_struct *tty, int arg)
802{
803 int ret = 0;
804 int bit = arg ? CLOCAL : 0;
f34d7a5b 805 struct ktermios old;
1c2630cc
AC
806
807 mutex_lock(&tty->termios_mutex);
f34d7a5b 808 old = *tty->termios;
1c2630cc
AC
809 tty->termios->c_cflag &= ~CLOCAL;
810 tty->termios->c_cflag |= bit;
f34d7a5b
AC
811 if (tty->ops->set_termios)
812 tty->ops->set_termios(tty, &old);
1c2630cc
AC
813 if ((tty->termios->c_cflag & CLOCAL) != bit)
814 ret = -EINVAL;
815 mutex_unlock(&tty->termios_mutex);
816 return ret;
817}
818
0fc00e24
AC
819/**
820 * tty_mode_ioctl - mode related ioctls
821 * @tty: tty for the ioctl
822 * @file: file pointer for the tty
823 * @cmd: command
824 * @arg: ioctl argument
825 *
826 * Perform non line discipline specific mode control ioctls. This
827 * is designed to be called by line disciplines to ensure they provide
828 * consistent mode setting.
829 */
830
355d95a1 831int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24 832 unsigned int cmd, unsigned long arg)
1da177e4 833{
355d95a1 834 struct tty_struct *real_tty;
1da177e4 835 void __user *p = (void __user *)arg;
1da177e4
LT
836
837 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
838 tty->driver->subtype == PTY_TYPE_MASTER)
839 real_tty = tty->link;
840 else
841 real_tty = tty;
842
843 switch (cmd) {
844#ifdef TIOCGETP
355d95a1
AC
845 case TIOCGETP:
846 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
847 case TIOCSETP:
848 case TIOCSETN:
849 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
1da177e4
LT
850#endif
851#ifdef TIOCGETC
355d95a1
AC
852 case TIOCGETC:
853 return get_tchars(real_tty, p);
854 case TIOCSETC:
855 return set_tchars(real_tty, p);
1da177e4
LT
856#endif
857#ifdef TIOCGLTC
355d95a1
AC
858 case TIOCGLTC:
859 return get_ltchars(real_tty, p);
860 case TIOCSLTC:
861 return set_ltchars(real_tty, p);
1da177e4 862#endif
355d95a1
AC
863 case TCSETSF:
864 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
865 case TCSETSW:
866 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
867 case TCSETS:
868 return set_termios(real_tty, p, TERMIOS_OLD);
edc6afc5 869#ifndef TCGETS2
355d95a1
AC
870 case TCGETS:
871 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
872 return -EFAULT;
873 return 0;
edc6afc5 874#else
355d95a1
AC
875 case TCGETS:
876 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
877 return -EFAULT;
878 return 0;
879 case TCGETS2:
880 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
881 return -EFAULT;
882 return 0;
883 case TCSETSF2:
884 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
885 case TCSETSW2:
886 return set_termios(real_tty, p, TERMIOS_WAIT);
887 case TCSETS2:
888 return set_termios(real_tty, p, 0);
edc6afc5 889#endif
355d95a1
AC
890 case TCGETA:
891 return get_termio(real_tty, p);
892 case TCSETAF:
893 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
894 case TCSETAW:
895 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
896 case TCSETA:
897 return set_termios(real_tty, p, TERMIOS_TERMIO);
0fc00e24 898#ifndef TCGETS2
355d95a1
AC
899 case TIOCGLCKTRMIOS:
900 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
901 return -EFAULT;
902 return 0;
903 case TIOCSLCKTRMIOS:
904 if (!capable(CAP_SYS_ADMIN))
905 return -EPERM;
906 if (user_termios_to_kernel_termios(real_tty->termios_locked,
907 (struct termios __user *) arg))
908 return -EFAULT;
909 return 0;
0fc00e24 910#else
355d95a1
AC
911 case TIOCGLCKTRMIOS:
912 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
913 return -EFAULT;
914 return 0;
915 case TIOCSLCKTRMIOS:
916 if (!capable(CAP_SYS_ADMIN))
917 return -EPERM;
918 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
919 (struct termios __user *) arg))
920 return -EFAULT;
0fc00e24
AC
921 return 0;
922#endif
355d95a1
AC
923 case TIOCGSOFTCAR:
924 return put_user(C_CLOCAL(tty) ? 1 : 0,
925 (int __user *)arg);
926 case TIOCSSOFTCAR:
927 if (get_user(arg, (unsigned int __user *) arg))
928 return -EFAULT;
1c2630cc 929 return tty_change_softcar(tty, arg);
355d95a1
AC
930 default:
931 return -ENOIOCTLCMD;
0fc00e24
AC
932 }
933}
0fc00e24
AC
934EXPORT_SYMBOL_GPL(tty_mode_ioctl);
935
936int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
937{
938 struct tty_ldisc *ld;
939 int retval = tty_check_change(tty);
940 if (retval)
941 return retval;
942
943 ld = tty_ldisc_ref(tty);
944 switch (arg) {
945 case TCIFLUSH:
946 if (ld && ld->flush_buffer)
947 ld->flush_buffer(tty);
948 break;
949 case TCIOFLUSH:
950 if (ld && ld->flush_buffer)
951 ld->flush_buffer(tty);
952 /* fall through */
953 case TCOFLUSH:
f34d7a5b 954 tty_driver_flush_buffer(tty);
0fc00e24
AC
955 break;
956 default:
957 tty_ldisc_deref(ld);
958 return -EINVAL;
959 }
960 tty_ldisc_deref(ld);
961 return 0;
962}
0fc00e24
AC
963EXPORT_SYMBOL_GPL(tty_perform_flush);
964
355d95a1 965int n_tty_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24
AC
966 unsigned int cmd, unsigned long arg)
967{
355d95a1 968 struct tty_struct *real_tty;
04f378b1 969 unsigned long flags;
0fc00e24
AC
970 int retval;
971
972 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
973 tty->driver->subtype == PTY_TYPE_MASTER)
974 real_tty = tty->link;
975 else
976 real_tty = tty;
977
978 switch (cmd) {
355d95a1
AC
979 case TCXONC:
980 retval = tty_check_change(tty);
981 if (retval)
982 return retval;
983 switch (arg) {
984 case TCOOFF:
985 if (!tty->flow_stopped) {
986 tty->flow_stopped = 1;
987 stop_tty(tty);
1da177e4 988 }
355d95a1
AC
989 break;
990 case TCOON:
991 if (tty->flow_stopped) {
992 tty->flow_stopped = 0;
993 start_tty(tty);
994 }
995 break;
996 case TCIOFF:
997 if (STOP_CHAR(tty) != __DISABLED_CHAR)
998 return send_prio_char(tty, STOP_CHAR(tty));
999 break;
1000 case TCION:
1001 if (START_CHAR(tty) != __DISABLED_CHAR)
1002 return send_prio_char(tty, START_CHAR(tty));
1003 break;
1da177e4 1004 default:
355d95a1 1005 return -EINVAL;
1da177e4 1006 }
355d95a1
AC
1007 return 0;
1008 case TCFLSH:
1009 return tty_perform_flush(tty, arg);
1010 case TIOCOUTQ:
f34d7a5b 1011 return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
355d95a1
AC
1012 case TIOCINQ:
1013 retval = tty->read_cnt;
1014 if (L_ICANON(tty))
1015 retval = inq_canon(tty);
1016 return put_user(retval, (unsigned int __user *) arg);
1017 case TIOCPKT:
1018 {
1019 int pktmode;
1020
1021 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
1022 tty->driver->subtype != PTY_TYPE_MASTER)
1023 return -ENOTTY;
1024 if (get_user(pktmode, (int __user *) arg))
1025 return -EFAULT;
04f378b1 1026 spin_lock_irqsave(&tty->ctrl_lock, flags);
355d95a1
AC
1027 if (pktmode) {
1028 if (!tty->packet) {
1029 tty->packet = 1;
1030 tty->link->ctrl_status = 0;
1031 }
1032 } else
1033 tty->packet = 0;
04f378b1 1034 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
355d95a1
AC
1035 return 0;
1036 }
1037 default:
1038 /* Try the mode commands */
1039 return tty_mode_ioctl(tty, file, cmd, arg);
1040 }
1da177e4 1041}
1da177e4 1042EXPORT_SYMBOL(n_tty_ioctl);