Merge branches 'acpi-resources', 'acpi-battery', 'acpi-doc' and 'acpi-pnp'
[linux-2.6-block.git] / drivers / tty / tty_ioctl.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
3 *
4 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
5 * which can be dynamically activated and de-activated by the line
6 * discipline handling modules (like SLIP).
7 */
8
9#include <linux/types.h>
10#include <linux/termios.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/major.h>
15#include <linux/tty.h>
16#include <linux/fcntl.h>
17#include <linux/string.h>
18#include <linux/mm.h>
19#include <linux/module.h>
20#include <linux/bitops.h>
5785c95b 21#include <linux/mutex.h>
8193c429 22#include <linux/compat.h>
1da177e4
LT
23
24#include <asm/io.h>
25#include <asm/uaccess.h>
1da177e4
LT
26
27#undef TTY_DEBUG_WAIT_UNTIL_SENT
28
29#undef DEBUG
30
31/*
32 * Internal flag options for termios setting behavior
33 */
34#define TERMIOS_FLUSH 1
35#define TERMIOS_WAIT 2
36#define TERMIOS_TERMIO 4
edc6afc5 37#define TERMIOS_OLD 8
1da177e4 38
af9b897e 39
d81ed103
AC
40/**
41 * tty_chars_in_buffer - characters pending
42 * @tty: terminal
43 *
44 * Return the number of bytes of data in the device private
45 * output queue. If no private method is supplied there is assumed
46 * to be no queue on the device.
47 */
48
f34d7a5b
AC
49int tty_chars_in_buffer(struct tty_struct *tty)
50{
51 if (tty->ops->chars_in_buffer)
52 return tty->ops->chars_in_buffer(tty);
53 else
54 return 0;
55}
f34d7a5b
AC
56EXPORT_SYMBOL(tty_chars_in_buffer);
57
d81ed103
AC
58/**
59 * tty_write_room - write queue space
60 * @tty: terminal
61 *
62 * Return the number of bytes that can be queued to this device
63 * at the present time. The result should be treated as a guarantee
64 * and the driver cannot offer a value it later shrinks by more than
65 * the number of bytes written. If no method is provided 2K is always
66 * returned and data may be lost as there will be no flow control.
67 */
68
f34d7a5b
AC
69int tty_write_room(struct tty_struct *tty)
70{
71 if (tty->ops->write_room)
72 return tty->ops->write_room(tty);
73 return 2048;
74}
f34d7a5b
AC
75EXPORT_SYMBOL(tty_write_room);
76
d81ed103
AC
77/**
78 * tty_driver_flush_buffer - discard internal buffer
79 * @tty: terminal
80 *
81 * Discard the internal output buffer for this device. If no method
82 * is provided then either the buffer cannot be hardware flushed or
83 * there is no buffer driver side.
84 */
f34d7a5b
AC
85void tty_driver_flush_buffer(struct tty_struct *tty)
86{
87 if (tty->ops->flush_buffer)
88 tty->ops->flush_buffer(tty);
89}
f34d7a5b
AC
90EXPORT_SYMBOL(tty_driver_flush_buffer);
91
d81ed103
AC
92/**
93 * tty_throttle - flow control
94 * @tty: terminal
95 *
96 * Indicate that a tty should stop transmitting data down the stack.
6a1c0680 97 * Takes the termios rwsem to protect against parallel throttle/unthrottle
38db8979
AC
98 * and also to ensure the driver can consistently reference its own
99 * termios data at this point when implementing software flow control.
d81ed103
AC
100 */
101
39c2e60f
AC
102void tty_throttle(struct tty_struct *tty)
103{
6a1c0680 104 down_write(&tty->termios_rwsem);
39c2e60f
AC
105 /* check TTY_THROTTLED first so it indicates our state */
106 if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
107 tty->ops->throttle)
108 tty->ops->throttle(tty);
70bc1264 109 tty->flow_change = 0;
6a1c0680 110 up_write(&tty->termios_rwsem);
39c2e60f
AC
111}
112EXPORT_SYMBOL(tty_throttle);
113
d81ed103
AC
114/**
115 * tty_unthrottle - flow control
116 * @tty: terminal
117 *
118 * Indicate that a tty may continue transmitting data down the stack.
6a1c0680 119 * Takes the termios rwsem to protect against parallel throttle/unthrottle
38db8979
AC
120 * and also to ensure the driver can consistently reference its own
121 * termios data at this point when implementing software flow control.
122 *
123 * Drivers should however remember that the stack can issue a throttle,
124 * then change flow control method, then unthrottle.
d81ed103
AC
125 */
126
39c2e60f
AC
127void tty_unthrottle(struct tty_struct *tty)
128{
6a1c0680 129 down_write(&tty->termios_rwsem);
39c2e60f
AC
130 if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
131 tty->ops->unthrottle)
132 tty->ops->unthrottle(tty);
70bc1264 133 tty->flow_change = 0;
6a1c0680 134 up_write(&tty->termios_rwsem);
39c2e60f
AC
135}
136EXPORT_SYMBOL(tty_unthrottle);
f34d7a5b 137
70bc1264
PH
138/**
139 * tty_throttle_safe - flow control
140 * @tty: terminal
141 *
142 * Similar to tty_throttle() but will only attempt throttle
143 * if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
144 * throttle due to race conditions when throttling is conditional
145 * on factors evaluated prior to throttling.
146 *
147 * Returns 0 if tty is throttled (or was already throttled)
148 */
149
150int tty_throttle_safe(struct tty_struct *tty)
151{
152 int ret = 0;
153
d8c1f929 154 mutex_lock(&tty->throttle_mutex);
70bc1264
PH
155 if (!test_bit(TTY_THROTTLED, &tty->flags)) {
156 if (tty->flow_change != TTY_THROTTLE_SAFE)
157 ret = 1;
158 else {
579a00a5 159 set_bit(TTY_THROTTLED, &tty->flags);
70bc1264
PH
160 if (tty->ops->throttle)
161 tty->ops->throttle(tty);
162 }
163 }
d8c1f929 164 mutex_unlock(&tty->throttle_mutex);
70bc1264
PH
165
166 return ret;
167}
168
169/**
170 * tty_unthrottle_safe - flow control
171 * @tty: terminal
172 *
173 * Similar to tty_unthrottle() but will only attempt unthrottle
174 * if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
175 * unthrottle due to race conditions when unthrottling is conditional
176 * on factors evaluated prior to unthrottling.
177 *
178 * Returns 0 if tty is unthrottled (or was already unthrottled)
179 */
180
181int tty_unthrottle_safe(struct tty_struct *tty)
182{
183 int ret = 0;
184
d8c1f929 185 mutex_lock(&tty->throttle_mutex);
70bc1264
PH
186 if (test_bit(TTY_THROTTLED, &tty->flags)) {
187 if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
188 ret = 1;
189 else {
579a00a5 190 clear_bit(TTY_THROTTLED, &tty->flags);
70bc1264
PH
191 if (tty->ops->unthrottle)
192 tty->ops->unthrottle(tty);
193 }
194 }
d8c1f929 195 mutex_unlock(&tty->throttle_mutex);
70bc1264
PH
196
197 return ret;
198}
199
af9b897e
AC
200/**
201 * tty_wait_until_sent - wait for I/O to finish
202 * @tty: tty we are waiting for
203 * @timeout: how long we will wait
204 *
205 * Wait for characters pending in a tty driver to hit the wire, or
206 * for a timeout to occur (eg due to flow control)
207 *
208 * Locking: none
209 */
210
355d95a1 211void tty_wait_until_sent(struct tty_struct *tty, long timeout)
1da177e4 212{
1da177e4
LT
213#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
214 char buf[64];
355d95a1 215
1da177e4
LT
216 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
217#endif
1da177e4
LT
218 if (!timeout)
219 timeout = MAX_SCHEDULE_TIMEOUT;
79fbf4a5 220
c37bc682
JH
221 timeout = wait_event_interruptible_timeout(tty->write_wait,
222 !tty_chars_in_buffer(tty), timeout);
223 if (timeout <= 0)
79fbf4a5 224 return;
79fbf4a5
JH
225
226 if (timeout == MAX_SCHEDULE_TIMEOUT)
227 timeout = 0;
228
229 if (tty->ops->wait_until_sent)
230 tty->ops->wait_until_sent(tty, timeout);
1da177e4 231}
1da177e4
LT
232EXPORT_SYMBOL(tty_wait_until_sent);
233
d81ed103
AC
234
235/*
236 * Termios Helper Methods
237 */
238
edc6afc5
AC
239static void unset_locked_termios(struct ktermios *termios,
240 struct ktermios *old,
241 struct ktermios *locked)
1da177e4
LT
242{
243 int i;
355d95a1
AC
244
245#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
1da177e4
LT
246
247 if (!locked) {
248 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
249 return;
250 }
251
252 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
253 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
254 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
255 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
256 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
355d95a1 257 for (i = 0; i < NCCS; i++)
1da177e4
LT
258 termios->c_cc[i] = locked->c_cc[i] ?
259 old->c_cc[i] : termios->c_cc[i];
edc6afc5 260 /* FIXME: What should we do for i/ospeed */
1da177e4
LT
261}
262
edc6afc5
AC
263/*
264 * Routine which returns the baud rate of the tty
265 *
266 * Note that the baud_table needs to be kept in sync with the
267 * include/asm/termbits.h file.
268 */
269static const speed_t baud_table[] = {
270 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
271 9600, 19200, 38400, 57600, 115200, 230400, 460800,
272#ifdef __sparc__
273 76800, 153600, 307200, 614400, 921600
274#else
275 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
276 2500000, 3000000, 3500000, 4000000
277#endif
278};
279
280#ifndef __sparc__
281static const tcflag_t baud_bits[] = {
282 B0, B50, B75, B110, B134, B150, B200, B300, B600,
283 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
284 B57600, B115200, B230400, B460800, B500000, B576000,
285 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
286 B3000000, B3500000, B4000000
287};
288#else
289static const tcflag_t baud_bits[] = {
290 B0, B50, B75, B110, B134, B150, B200, B300, B600,
291 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
292 B57600, B115200, B230400, B460800, B76800, B153600,
293 B307200, B614400, B921600
294};
295#endif
296
297static int n_baud_table = ARRAY_SIZE(baud_table);
298
299/**
300 * tty_termios_baud_rate
301 * @termios: termios structure
302 *
303 * Convert termios baud rate data into a speed. This should be called
304 * with the termios lock held if this termios is a terminal termios
305 * structure. May change the termios data. Device drivers can call this
306 * function but should use ->c_[io]speed directly as they are updated.
307 *
308 * Locking: none
309 */
310
311speed_t tty_termios_baud_rate(struct ktermios *termios)
312{
313 unsigned int cbaud;
314
315 cbaud = termios->c_cflag & CBAUD;
316
317#ifdef BOTHER
25985edc 318 /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
edc6afc5
AC
319 if (cbaud == BOTHER)
320 return termios->c_ospeed;
321#endif
322 if (cbaud & CBAUDEX) {
323 cbaud &= ~CBAUDEX;
324
325 if (cbaud < 1 || cbaud + 15 > n_baud_table)
326 termios->c_cflag &= ~CBAUDEX;
327 else
328 cbaud += 15;
329 }
330 return baud_table[cbaud];
331}
edc6afc5
AC
332EXPORT_SYMBOL(tty_termios_baud_rate);
333
334/**
335 * tty_termios_input_baud_rate
336 * @termios: termios structure
337 *
338 * Convert termios baud rate data into a speed. This should be called
339 * with the termios lock held if this termios is a terminal termios
340 * structure. May change the termios data. Device drivers can call this
341 * function but should use ->c_[io]speed directly as they are updated.
342 *
343 * Locking: none
344 */
345
346speed_t tty_termios_input_baud_rate(struct ktermios *termios)
347{
348#ifdef IBSHIFT
349 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
350
351 if (cbaud == B0)
352 return tty_termios_baud_rate(termios);
353
25985edc 354 /* Magic token for arbitrary speed via c_ispeed*/
edc6afc5
AC
355 if (cbaud == BOTHER)
356 return termios->c_ispeed;
357
358 if (cbaud & CBAUDEX) {
359 cbaud &= ~CBAUDEX;
360
361 if (cbaud < 1 || cbaud + 15 > n_baud_table)
362 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
363 else
364 cbaud += 15;
365 }
366 return baud_table[cbaud];
367#else
368 return tty_termios_baud_rate(termios);
369#endif
370}
edc6afc5
AC
371EXPORT_SYMBOL(tty_termios_input_baud_rate);
372
edc6afc5
AC
373/**
374 * tty_termios_encode_baud_rate
78137e3b 375 * @termios: ktermios structure holding user requested state
edc6afc5
AC
376 * @ispeed: input speed
377 * @ospeed: output speed
378 *
379 * Encode the speeds set into the passed termios structure. This is
f98e5b80 380 * used as a library helper for drivers so that they can report back
edc6afc5
AC
381 * the actual speed selected when it differs from the speed requested
382 *
78137e3b
AC
383 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
384 * we need to carefully set the bits when the user does not get the
385 * desired speed. We allow small margins and preserve as much of possible
06fe9fb4 386 * of the input intent to keep compatibility.
edc6afc5
AC
387 *
388 * Locking: Caller should hold termios lock. This is already held
389 * when calling this function from the driver termios handler.
5f519d72
AC
390 *
391 * The ifdefs deal with platforms whose owners have yet to update them
392 * and will all go away once this is done.
edc6afc5
AC
393 */
394
75e8b71d
MR
395void tty_termios_encode_baud_rate(struct ktermios *termios,
396 speed_t ibaud, speed_t obaud)
edc6afc5
AC
397{
398 int i = 0;
78137e3b
AC
399 int ifound = -1, ofound = -1;
400 int iclose = ibaud/50, oclose = obaud/50;
401 int ibinput = 0;
edc6afc5 402
5f519d72
AC
403 if (obaud == 0) /* CD dropped */
404 ibaud = 0; /* Clear ibaud to be sure */
405
edc6afc5
AC
406 termios->c_ispeed = ibaud;
407 termios->c_ospeed = obaud;
408
5f519d72 409#ifdef BOTHER
78137e3b 410 /* If the user asked for a precise weird speed give a precise weird
a1d51aa2 411 answer. If they asked for a Bfoo speed they may have problems
78137e3b
AC
412 digesting non-exact replies so fuzz a bit */
413
414 if ((termios->c_cflag & CBAUD) == BOTHER)
415 oclose = 0;
416 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
417 iclose = 0;
418 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
419 ibinput = 1; /* An input speed was specified */
5f519d72 420#endif
edc6afc5 421 termios->c_cflag &= ~CBAUD;
edc6afc5 422
5f519d72
AC
423 /*
424 * Our goal is to find a close match to the standard baud rate
425 * returned. Walk the baud rate table and if we get a very close
426 * match then report back the speed as a POSIX Bxxxx value by
427 * preference
428 */
429
edc6afc5 430 do {
75e8b71d
MR
431 if (obaud - oclose <= baud_table[i] &&
432 obaud + oclose >= baud_table[i]) {
edc6afc5 433 termios->c_cflag |= baud_bits[i];
78137e3b 434 ofound = i;
edc6afc5 435 }
75e8b71d
MR
436 if (ibaud - iclose <= baud_table[i] &&
437 ibaud + iclose >= baud_table[i]) {
438 /* For the case input == output don't set IBAUD bits
439 if the user didn't do so */
5f519d72
AC
440 if (ofound == i && !ibinput)
441 ifound = i;
442#ifdef IBSHIFT
443 else {
444 ifound = i;
78137e3b 445 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
5f519d72
AC
446 }
447#endif
edc6afc5 448 }
6804396f 449 } while (++i < n_baud_table);
5f519d72
AC
450
451 /*
452 * If we found no match then use BOTHER if provided or warn
453 * the user their platform maintainer needs to wake up if not.
454 */
455#ifdef BOTHER
78137e3b 456 if (ofound == -1)
edc6afc5 457 termios->c_cflag |= BOTHER;
78137e3b
AC
458 /* Set exact input bits only if the input and output differ or the
459 user already did */
6804396f 460 if (ifound == -1 && (ibaud != obaud || ibinput))
edc6afc5 461 termios->c_cflag |= (BOTHER << IBSHIFT);
5f519d72
AC
462#else
463 if (ifound == -1 || ofound == -1) {
9074d963 464 printk_once(KERN_WARNING "tty: Unable to return correct "
5f519d72
AC
465 "speed data as your architecture needs updating.\n");
466 }
467#endif
edc6afc5 468}
edc6afc5
AC
469EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
470
d81ed103
AC
471/**
472 * tty_encode_baud_rate - set baud rate of the tty
473 * @ibaud: input baud rate
474 * @obad: output baud rate
475 *
476 * Update the current termios data for the tty with the new speed
6a1c0680 477 * settings. The caller must hold the termios_rwsem for the tty in
d81ed103
AC
478 * question.
479 */
480
5f519d72
AC
481void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
482{
adc8d746 483 tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
5f519d72
AC
484}
485EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
edc6afc5 486
5f519d72
AC
487/**
488 * tty_termios_copy_hw - copy hardware settings
489 * @new: New termios
490 * @old: Old termios
491 *
25985edc 492 * Propagate the hardware specific terminal setting bits from
5f519d72
AC
493 * the old termios structure to the new one. This is used in cases
494 * where the hardware does not support reconfiguration or as a helper
495 * in some cases where only minimal reconfiguration is supported
496 */
497
498void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
499{
500 /* The bits a dumb device handles in software. Smart devices need
501 to always provide a set_termios method */
502 new->c_cflag &= HUPCL | CREAD | CLOCAL;
503 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
504 new->c_ispeed = old->c_ispeed;
505 new->c_ospeed = old->c_ospeed;
506}
5f519d72
AC
507EXPORT_SYMBOL(tty_termios_copy_hw);
508
bf5e5834
AC
509/**
510 * tty_termios_hw_change - check for setting change
511 * @a: termios
512 * @b: termios to compare
513 *
514 * Check if any of the bits that affect a dumb device have changed
515 * between the two termios structures, or a speed change is needed.
516 */
517
518int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
519{
520 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
521 return 1;
522 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
523 return 1;
524 return 0;
525}
526EXPORT_SYMBOL(tty_termios_hw_change);
527
af9b897e 528/**
8d075b19 529 * tty_set_termios - update termios values
af9b897e
AC
530 * @tty: tty to update
531 * @new_termios: desired new value
532 *
dbfcd851 533 * Perform updates to the termios values set on this terminal.
6460fbbf
PH
534 * A master pty's termios should never be set.
535 *
6a1c0680 536 * Locking: termios_rwsem
af9b897e
AC
537 */
538
b00f5c2d 539int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
1da177e4 540{
978e595f 541 struct ktermios old_termios;
1da177e4 542 struct tty_ldisc *ld;
355d95a1 543
6460fbbf
PH
544 WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
545 tty->driver->subtype == PTY_TYPE_MASTER);
1da177e4
LT
546 /*
547 * Perform the actual termios internal changes under lock.
548 */
355d95a1 549
1da177e4
LT
550
551 /* FIXME: we need to decide on some locking/ordering semantics
552 for the set_termios notification eventually */
6a1c0680 553 down_write(&tty->termios_rwsem);
adc8d746
AC
554 old_termios = tty->termios;
555 tty->termios = *new_termios;
556 unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked);
1da177e4 557
f34d7a5b 558 if (tty->ops->set_termios)
c961bfb1 559 tty->ops->set_termios(tty, &old_termios);
5f519d72 560 else
adc8d746 561 tty_termios_copy_hw(&tty->termios, &old_termios);
1da177e4
LT
562
563 ld = tty_ldisc_ref(tty);
564 if (ld != NULL) {
a352def2 565 if (ld->ops->set_termios)
c961bfb1 566 ld->ops->set_termios(tty, &old_termios);
1da177e4
LT
567 tty_ldisc_deref(ld);
568 }
6a1c0680 569 up_write(&tty->termios_rwsem);
8d075b19 570 return 0;
1da177e4 571}
b00f5c2d 572EXPORT_SYMBOL_GPL(tty_set_termios);
1da177e4 573
af9b897e
AC
574/**
575 * set_termios - set termios values for a tty
576 * @tty: terminal device
577 * @arg: user data
578 * @opt: option information
579 *
3a4fa0a2 580 * Helper function to prepare termios data and run necessary other
8d075b19 581 * functions before using tty_set_termios to do the actual changes.
af9b897e
AC
582 *
583 * Locking:
6a1c0680 584 * Called functions take ldisc and termios_rwsem locks
af9b897e
AC
585 */
586
355d95a1 587static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
1da177e4 588{
edc6afc5 589 struct ktermios tmp_termios;
1da177e4
LT
590 struct tty_ldisc *ld;
591 int retval = tty_check_change(tty);
592
593 if (retval)
594 return retval;
595
6a1c0680 596 down_read(&tty->termios_rwsem);
adc8d746 597 tmp_termios = tty->termios;
6a1c0680 598 up_read(&tty->termios_rwsem);
64bb6c5e 599
1da177e4 600 if (opt & TERMIOS_TERMIO) {
1da177e4
LT
601 if (user_termio_to_kernel_termios(&tmp_termios,
602 (struct termio __user *)arg))
603 return -EFAULT;
edc6afc5
AC
604#ifdef TCGETS2
605 } else if (opt & TERMIOS_OLD) {
edc6afc5 606 if (user_termios_to_kernel_termios_1(&tmp_termios,
64bb6c5e 607 (struct termios __user *)arg))
edc6afc5 608 return -EFAULT;
1da177e4
LT
609 } else {
610 if (user_termios_to_kernel_termios(&tmp_termios,
64bb6c5e 611 (struct termios2 __user *)arg))
1da177e4
LT
612 return -EFAULT;
613 }
64bb6c5e
AC
614#else
615 } else if (user_termios_to_kernel_termios(&tmp_termios,
616 (struct termios __user *)arg))
617 return -EFAULT;
618#endif
1da177e4 619
355d95a1
AC
620 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
621 * with the real speed so its unconditionally usable */
edc6afc5
AC
622 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
623 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
624
1da177e4 625 ld = tty_ldisc_ref(tty);
355d95a1 626
1da177e4 627 if (ld != NULL) {
a352def2
AC
628 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
629 ld->ops->flush_buffer(tty);
1da177e4
LT
630 tty_ldisc_deref(ld);
631 }
355d95a1 632
1da177e4
LT
633 if (opt & TERMIOS_WAIT) {
634 tty_wait_until_sent(tty, 0);
635 if (signal_pending(current))
183d95cd 636 return -ERESTARTSYS;
1da177e4
LT
637 }
638
8d075b19 639 tty_set_termios(tty, &tmp_termios);
5f519d72
AC
640
641 /* FIXME: Arguably if tmp_termios == tty->termios AND the
642 actual requested termios was not tmp_termios then we may
643 want to return an error as no user requested change has
644 succeeded */
1da177e4
LT
645 return 0;
646}
647
26a2e20f
AC
648static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
649{
6a1c0680 650 down_read(&tty->termios_rwsem);
adc8d746 651 *kterm = tty->termios;
6a1c0680 652 up_read(&tty->termios_rwsem);
26a2e20f
AC
653}
654
655static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
656{
6a1c0680 657 down_read(&tty->termios_rwsem);
adc8d746 658 *kterm = tty->termios_locked;
6a1c0680 659 up_read(&tty->termios_rwsem);
26a2e20f
AC
660}
661
355d95a1 662static int get_termio(struct tty_struct *tty, struct termio __user *termio)
1da177e4 663{
26a2e20f
AC
664 struct ktermios kterm;
665 copy_termios(tty, &kterm);
666 if (kernel_termios_to_user_termio(termio, &kterm))
1da177e4
LT
667 return -EFAULT;
668 return 0;
669}
670
1d65b4a0
AC
671
672#ifdef TCGETX
673
674/**
675 * set_termiox - set termiox fields if possible
676 * @tty: terminal
677 * @arg: termiox structure from user
678 * @opt: option flags for ioctl type
679 *
680 * Implement the device calling points for the SYS5 termiox ioctl
681 * interface in Linux
682 */
683
684static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
685{
686 struct termiox tnew;
687 struct tty_ldisc *ld;
688
689 if (tty->termiox == NULL)
690 return -EINVAL;
691 if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
692 return -EFAULT;
693
694 ld = tty_ldisc_ref(tty);
695 if (ld != NULL) {
696 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
697 ld->ops->flush_buffer(tty);
698 tty_ldisc_deref(ld);
699 }
700 if (opt & TERMIOS_WAIT) {
701 tty_wait_until_sent(tty, 0);
702 if (signal_pending(current))
183d95cd 703 return -ERESTARTSYS;
1d65b4a0
AC
704 }
705
6a1c0680 706 down_write(&tty->termios_rwsem);
1d65b4a0
AC
707 if (tty->ops->set_termiox)
708 tty->ops->set_termiox(tty, &tnew);
6a1c0680 709 up_write(&tty->termios_rwsem);
1d65b4a0
AC
710 return 0;
711}
712
713#endif
714
1da177e4
LT
715
716#ifdef TIOCGETP
717/*
718 * These are deprecated, but there is limited support..
719 *
720 * The "sg_flags" translation is a joke..
721 */
355d95a1 722static int get_sgflags(struct tty_struct *tty)
1da177e4
LT
723{
724 int flags = 0;
725
adc8d746
AC
726 if (!(tty->termios.c_lflag & ICANON)) {
727 if (tty->termios.c_lflag & ISIG)
1da177e4
LT
728 flags |= 0x02; /* cbreak */
729 else
730 flags |= 0x20; /* raw */
731 }
adc8d746 732 if (tty->termios.c_lflag & ECHO)
1da177e4 733 flags |= 0x08; /* echo */
adc8d746
AC
734 if (tty->termios.c_oflag & OPOST)
735 if (tty->termios.c_oflag & ONLCR)
1da177e4
LT
736 flags |= 0x10; /* crmod */
737 return flags;
738}
739
355d95a1 740static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
741{
742 struct sgttyb tmp;
743
6a1c0680 744 down_read(&tty->termios_rwsem);
adc8d746
AC
745 tmp.sg_ispeed = tty->termios.c_ispeed;
746 tmp.sg_ospeed = tty->termios.c_ospeed;
747 tmp.sg_erase = tty->termios.c_cc[VERASE];
748 tmp.sg_kill = tty->termios.c_cc[VKILL];
1da177e4 749 tmp.sg_flags = get_sgflags(tty);
6a1c0680 750 up_read(&tty->termios_rwsem);
355d95a1 751
1da177e4
LT
752 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
753}
754
355d95a1 755static void set_sgflags(struct ktermios *termios, int flags)
1da177e4 756{
9833facf
AC
757 termios->c_iflag = ICRNL | IXON;
758 termios->c_oflag = 0;
759 termios->c_lflag = ISIG | ICANON;
1da177e4 760 if (flags & 0x02) { /* cbreak */
9833facf
AC
761 termios->c_iflag = 0;
762 termios->c_lflag &= ~ICANON;
1da177e4
LT
763 }
764 if (flags & 0x08) { /* echo */
9833facf 765 termios->c_lflag |= ECHO | ECHOE | ECHOK |
1da177e4
LT
766 ECHOCTL | ECHOKE | IEXTEN;
767 }
768 if (flags & 0x10) { /* crmod */
9833facf 769 termios->c_oflag |= OPOST | ONLCR;
1da177e4
LT
770 }
771 if (flags & 0x20) { /* raw */
9833facf
AC
772 termios->c_iflag = 0;
773 termios->c_lflag &= ~(ISIG | ICANON);
1da177e4 774 }
9833facf
AC
775 if (!(termios->c_lflag & ICANON)) {
776 termios->c_cc[VMIN] = 1;
777 termios->c_cc[VTIME] = 0;
1da177e4
LT
778 }
779}
780
af9b897e
AC
781/**
782 * set_sgttyb - set legacy terminal values
783 * @tty: tty structure
784 * @sgttyb: pointer to old style terminal structure
785 *
786 * Updates a terminal from the legacy BSD style terminal information
787 * structure.
788 *
6a1c0680 789 * Locking: termios_rwsem
af9b897e
AC
790 */
791
355d95a1 792static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
793{
794 int retval;
795 struct sgttyb tmp;
edc6afc5 796 struct ktermios termios;
1da177e4
LT
797
798 retval = tty_check_change(tty);
799 if (retval)
800 return retval;
355d95a1 801
1da177e4
LT
802 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
803 return -EFAULT;
804
6a1c0680 805 down_write(&tty->termios_rwsem);
adc8d746 806 termios = tty->termios;
1da177e4
LT
807 termios.c_cc[VERASE] = tmp.sg_erase;
808 termios.c_cc[VKILL] = tmp.sg_kill;
809 set_sgflags(&termios, tmp.sg_flags);
edc6afc5
AC
810 /* Try and encode into Bfoo format */
811#ifdef BOTHER
355d95a1
AC
812 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
813 termios.c_ospeed);
edc6afc5 814#endif
6a1c0680 815 up_write(&tty->termios_rwsem);
8d075b19 816 tty_set_termios(tty, &termios);
1da177e4
LT
817 return 0;
818}
819#endif
820
821#ifdef TIOCGETC
355d95a1 822static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
823{
824 struct tchars tmp;
825
6a1c0680 826 down_read(&tty->termios_rwsem);
adc8d746
AC
827 tmp.t_intrc = tty->termios.c_cc[VINTR];
828 tmp.t_quitc = tty->termios.c_cc[VQUIT];
829 tmp.t_startc = tty->termios.c_cc[VSTART];
830 tmp.t_stopc = tty->termios.c_cc[VSTOP];
831 tmp.t_eofc = tty->termios.c_cc[VEOF];
832 tmp.t_brkc = tty->termios.c_cc[VEOL2]; /* what is brkc anyway? */
6a1c0680 833 up_read(&tty->termios_rwsem);
1da177e4
LT
834 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
835}
836
355d95a1 837static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
838{
839 struct tchars tmp;
840
841 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
842 return -EFAULT;
6a1c0680 843 down_write(&tty->termios_rwsem);
adc8d746
AC
844 tty->termios.c_cc[VINTR] = tmp.t_intrc;
845 tty->termios.c_cc[VQUIT] = tmp.t_quitc;
846 tty->termios.c_cc[VSTART] = tmp.t_startc;
847 tty->termios.c_cc[VSTOP] = tmp.t_stopc;
848 tty->termios.c_cc[VEOF] = tmp.t_eofc;
849 tty->termios.c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
6a1c0680 850 up_write(&tty->termios_rwsem);
1da177e4
LT
851 return 0;
852}
853#endif
854
855#ifdef TIOCGLTC
355d95a1 856static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
857{
858 struct ltchars tmp;
859
6a1c0680 860 down_read(&tty->termios_rwsem);
adc8d746 861 tmp.t_suspc = tty->termios.c_cc[VSUSP];
355d95a1 862 /* what is dsuspc anyway? */
adc8d746
AC
863 tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
864 tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
355d95a1 865 /* what is flushc anyway? */
adc8d746
AC
866 tmp.t_flushc = tty->termios.c_cc[VEOL2];
867 tmp.t_werasc = tty->termios.c_cc[VWERASE];
868 tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
6a1c0680 869 up_read(&tty->termios_rwsem);
1da177e4
LT
870 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
871}
872
355d95a1 873static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
874{
875 struct ltchars tmp;
876
877 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
878 return -EFAULT;
879
6a1c0680 880 down_write(&tty->termios_rwsem);
adc8d746 881 tty->termios.c_cc[VSUSP] = tmp.t_suspc;
355d95a1 882 /* what is dsuspc anyway? */
adc8d746
AC
883 tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
884 tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
355d95a1 885 /* what is flushc anyway? */
adc8d746
AC
886 tty->termios.c_cc[VEOL2] = tmp.t_flushc;
887 tty->termios.c_cc[VWERASE] = tmp.t_werasc;
888 tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
6a1c0680 889 up_write(&tty->termios_rwsem);
1da177e4
LT
890 return 0;
891}
892#endif
893
1c2630cc
AC
894/**
895 * tty_change_softcar - carrier change ioctl helper
896 * @tty: tty to update
897 * @arg: enable/disable CLOCAL
898 *
899 * Perform a change to the CLOCAL state and call into the driver
6a1c0680 900 * layer to make it visible. All done with the termios rwsem
1c2630cc
AC
901 */
902
903static int tty_change_softcar(struct tty_struct *tty, int arg)
904{
905 int ret = 0;
906 int bit = arg ? CLOCAL : 0;
f34d7a5b 907 struct ktermios old;
1c2630cc 908
6a1c0680 909 down_write(&tty->termios_rwsem);
adc8d746
AC
910 old = tty->termios;
911 tty->termios.c_cflag &= ~CLOCAL;
912 tty->termios.c_cflag |= bit;
f34d7a5b
AC
913 if (tty->ops->set_termios)
914 tty->ops->set_termios(tty, &old);
adc8d746 915 if ((tty->termios.c_cflag & CLOCAL) != bit)
1c2630cc 916 ret = -EINVAL;
6a1c0680 917 up_write(&tty->termios_rwsem);
1c2630cc
AC
918 return ret;
919}
920
0fc00e24
AC
921/**
922 * tty_mode_ioctl - mode related ioctls
923 * @tty: tty for the ioctl
924 * @file: file pointer for the tty
925 * @cmd: command
926 * @arg: ioctl argument
927 *
928 * Perform non line discipline specific mode control ioctls. This
929 * is designed to be called by line disciplines to ensure they provide
930 * consistent mode setting.
931 */
932
355d95a1 933int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24 934 unsigned int cmd, unsigned long arg)
1da177e4 935{
355d95a1 936 struct tty_struct *real_tty;
1da177e4 937 void __user *p = (void __user *)arg;
8f520021 938 int ret = 0;
26a2e20f 939 struct ktermios kterm;
1da177e4 940
8d075b19
AC
941 BUG_ON(file == NULL);
942
1da177e4
LT
943 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
944 tty->driver->subtype == PTY_TYPE_MASTER)
945 real_tty = tty->link;
946 else
947 real_tty = tty;
948
949 switch (cmd) {
950#ifdef TIOCGETP
355d95a1
AC
951 case TIOCGETP:
952 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
953 case TIOCSETP:
954 case TIOCSETN:
955 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
1da177e4
LT
956#endif
957#ifdef TIOCGETC
355d95a1
AC
958 case TIOCGETC:
959 return get_tchars(real_tty, p);
960 case TIOCSETC:
961 return set_tchars(real_tty, p);
1da177e4
LT
962#endif
963#ifdef TIOCGLTC
355d95a1
AC
964 case TIOCGLTC:
965 return get_ltchars(real_tty, p);
966 case TIOCSLTC:
967 return set_ltchars(real_tty, p);
1da177e4 968#endif
355d95a1
AC
969 case TCSETSF:
970 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
971 case TCSETSW:
972 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
973 case TCSETS:
974 return set_termios(real_tty, p, TERMIOS_OLD);
edc6afc5 975#ifndef TCGETS2
355d95a1 976 case TCGETS:
26a2e20f
AC
977 copy_termios(real_tty, &kterm);
978 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
8f520021 979 ret = -EFAULT;
8f520021 980 return ret;
edc6afc5 981#else
355d95a1 982 case TCGETS:
26a2e20f
AC
983 copy_termios(real_tty, &kterm);
984 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
8f520021 985 ret = -EFAULT;
8f520021 986 return ret;
355d95a1 987 case TCGETS2:
26a2e20f
AC
988 copy_termios(real_tty, &kterm);
989 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
8f520021 990 ret = -EFAULT;
8f520021 991 return ret;
355d95a1
AC
992 case TCSETSF2:
993 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
994 case TCSETSW2:
995 return set_termios(real_tty, p, TERMIOS_WAIT);
996 case TCSETS2:
997 return set_termios(real_tty, p, 0);
edc6afc5 998#endif
355d95a1
AC
999 case TCGETA:
1000 return get_termio(real_tty, p);
1001 case TCSETAF:
1002 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
1003 case TCSETAW:
1004 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
1005 case TCSETA:
1006 return set_termios(real_tty, p, TERMIOS_TERMIO);
0fc00e24 1007#ifndef TCGETS2
355d95a1 1008 case TIOCGLCKTRMIOS:
26a2e20f
AC
1009 copy_termios_locked(real_tty, &kterm);
1010 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
8f520021 1011 ret = -EFAULT;
8f520021 1012 return ret;
355d95a1
AC
1013 case TIOCSLCKTRMIOS:
1014 if (!capable(CAP_SYS_ADMIN))
1015 return -EPERM;
26a2e20f
AC
1016 copy_termios_locked(real_tty, &kterm);
1017 if (user_termios_to_kernel_termios(&kterm,
355d95a1 1018 (struct termios __user *) arg))
26a2e20f 1019 return -EFAULT;
6a1c0680 1020 down_write(&real_tty->termios_rwsem);
adc8d746 1021 real_tty->termios_locked = kterm;
6a1c0680 1022 up_write(&real_tty->termios_rwsem);
26a2e20f 1023 return 0;
0fc00e24 1024#else
355d95a1 1025 case TIOCGLCKTRMIOS:
26a2e20f
AC
1026 copy_termios_locked(real_tty, &kterm);
1027 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
8f520021 1028 ret = -EFAULT;
8f520021 1029 return ret;
355d95a1
AC
1030 case TIOCSLCKTRMIOS:
1031 if (!capable(CAP_SYS_ADMIN))
26a2e20f
AC
1032 return -EPERM;
1033 copy_termios_locked(real_tty, &kterm);
1034 if (user_termios_to_kernel_termios_1(&kterm,
355d95a1 1035 (struct termios __user *) arg))
26a2e20f 1036 return -EFAULT;
6a1c0680 1037 down_write(&real_tty->termios_rwsem);
adc8d746 1038 real_tty->termios_locked = kterm;
6a1c0680 1039 up_write(&real_tty->termios_rwsem);
8f520021 1040 return ret;
0fc00e24 1041#endif
1d65b4a0 1042#ifdef TCGETX
5dca607b
MF
1043 case TCGETX: {
1044 struct termiox ktermx;
1d65b4a0
AC
1045 if (real_tty->termiox == NULL)
1046 return -EINVAL;
6a1c0680 1047 down_read(&real_tty->termios_rwsem);
26a2e20f 1048 memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
6a1c0680 1049 up_read(&real_tty->termios_rwsem);
26a2e20f
AC
1050 if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
1051 ret = -EFAULT;
8f520021 1052 return ret;
5dca607b 1053 }
1d65b4a0
AC
1054 case TCSETX:
1055 return set_termiox(real_tty, p, 0);
1056 case TCSETXW:
1057 return set_termiox(real_tty, p, TERMIOS_WAIT);
1058 case TCSETXF:
1059 return set_termiox(real_tty, p, TERMIOS_FLUSH);
1060#endif
355d95a1 1061 case TIOCGSOFTCAR:
26a2e20f
AC
1062 copy_termios(real_tty, &kterm);
1063 ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
355d95a1 1064 (int __user *)arg);
8f520021 1065 return ret;
355d95a1
AC
1066 case TIOCSSOFTCAR:
1067 if (get_user(arg, (unsigned int __user *) arg))
1068 return -EFAULT;
f753f327 1069 return tty_change_softcar(real_tty, arg);
355d95a1
AC
1070 default:
1071 return -ENOIOCTLCMD;
0fc00e24
AC
1072 }
1073}
0fc00e24
AC
1074EXPORT_SYMBOL_GPL(tty_mode_ioctl);
1075
e7f3880c
PH
1076
1077/* Caller guarantees ldisc reference is held */
1078static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
0fc00e24 1079{
e7f3880c 1080 struct tty_ldisc *ld = tty->ldisc;
0fc00e24 1081
0fc00e24
AC
1082 switch (arg) {
1083 case TCIFLUSH:
a1bf9584 1084 if (ld && ld->ops->flush_buffer) {
a352def2 1085 ld->ops->flush_buffer(tty);
a1bf9584
IZ
1086 tty_unthrottle(tty);
1087 }
0fc00e24
AC
1088 break;
1089 case TCIOFLUSH:
a1bf9584 1090 if (ld && ld->ops->flush_buffer) {
a352def2 1091 ld->ops->flush_buffer(tty);
a1bf9584
IZ
1092 tty_unthrottle(tty);
1093 }
0fc00e24
AC
1094 /* fall through */
1095 case TCOFLUSH:
f34d7a5b 1096 tty_driver_flush_buffer(tty);
0fc00e24
AC
1097 break;
1098 default:
0fc00e24
AC
1099 return -EINVAL;
1100 }
0fc00e24
AC
1101 return 0;
1102}
e7f3880c
PH
1103
1104int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1105{
1106 struct tty_ldisc *ld;
1107 int retval = tty_check_change(tty);
1108 if (retval)
1109 return retval;
1110
1111 ld = tty_ldisc_ref_wait(tty);
1112 retval = __tty_perform_flush(tty, arg);
1113 if (ld)
1114 tty_ldisc_deref(ld);
1115 return retval;
1116}
0fc00e24
AC
1117EXPORT_SYMBOL_GPL(tty_perform_flush);
1118
47afa7a5 1119int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
0fc00e24
AC
1120 unsigned int cmd, unsigned long arg)
1121{
0fc00e24
AC
1122 int retval;
1123
0fc00e24 1124 switch (cmd) {
355d95a1
AC
1125 case TCXONC:
1126 retval = tty_check_change(tty);
1127 if (retval)
1128 return retval;
1129 switch (arg) {
1130 case TCOOFF:
c545b66c 1131 spin_lock_irq(&tty->flow_lock);
355d95a1
AC
1132 if (!tty->flow_stopped) {
1133 tty->flow_stopped = 1;
c545b66c 1134 __stop_tty(tty);
1da177e4 1135 }
c545b66c 1136 spin_unlock_irq(&tty->flow_lock);
355d95a1
AC
1137 break;
1138 case TCOON:
c545b66c 1139 spin_lock_irq(&tty->flow_lock);
355d95a1
AC
1140 if (tty->flow_stopped) {
1141 tty->flow_stopped = 0;
c545b66c 1142 __start_tty(tty);
355d95a1 1143 }
c545b66c 1144 spin_unlock_irq(&tty->flow_lock);
355d95a1
AC
1145 break;
1146 case TCIOFF:
c274f6ef 1147 down_read(&tty->termios_rwsem);
355d95a1 1148 if (STOP_CHAR(tty) != __DISABLED_CHAR)
c274f6ef
PH
1149 retval = tty_send_xchar(tty, STOP_CHAR(tty));
1150 up_read(&tty->termios_rwsem);
355d95a1
AC
1151 break;
1152 case TCION:
c274f6ef 1153 down_read(&tty->termios_rwsem);
355d95a1 1154 if (START_CHAR(tty) != __DISABLED_CHAR)
c274f6ef
PH
1155 retval = tty_send_xchar(tty, START_CHAR(tty));
1156 up_read(&tty->termios_rwsem);
355d95a1 1157 break;
1da177e4 1158 default:
355d95a1 1159 return -EINVAL;
1da177e4 1160 }
c274f6ef 1161 return retval;
355d95a1 1162 case TCFLSH:
5cec7bf6
PH
1163 retval = tty_check_change(tty);
1164 if (retval)
1165 return retval;
e7f3880c 1166 return __tty_perform_flush(tty, arg);
355d95a1
AC
1167 default:
1168 /* Try the mode commands */
1169 return tty_mode_ioctl(tty, file, cmd, arg);
1170 }
1da177e4 1171}
47afa7a5 1172EXPORT_SYMBOL(n_tty_ioctl_helper);
8193c429
TM
1173
1174#ifdef CONFIG_COMPAT
1175long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
1176 unsigned int cmd, unsigned long arg)
1177{
1178 switch (cmd) {
1179 case TIOCGLCKTRMIOS:
1180 case TIOCSLCKTRMIOS:
1181 return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
1182 default:
1183 return -ENOIOCTLCMD;
1184 }
1185}
1186EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
1187#endif
1188