1/*
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>
21#include <linux/mutex.h>
22#include <linux/compat.h>
23
24#include <asm/io.h>
25#include <asm/uaccess.h>
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
37#define TERMIOS_OLD	8
38
39
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
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}
56EXPORT_SYMBOL(tty_chars_in_buffer);
57
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
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}
75EXPORT_SYMBOL(tty_write_room);
76
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 */
85void tty_driver_flush_buffer(struct tty_struct *tty)
86{
87	if (tty->ops->flush_buffer)
88		tty->ops->flush_buffer(tty);
89}
90EXPORT_SYMBOL(tty_driver_flush_buffer);
91
92/**
93 *	tty_throttle		-	flow control
94 *	@tty: terminal
95 *
96 *	Indicate that a tty should stop transmitting data down the stack.
97 *	Takes the termios rwsem to protect against parallel throttle/unthrottle
98 *	and also to ensure the driver can consistently reference its own
99 *	termios data at this point when implementing software flow control.
100 */
101
102void tty_throttle(struct tty_struct *tty)
103{
104	down_write(&tty->termios_rwsem);
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);
109	tty->flow_change = 0;
110	up_write(&tty->termios_rwsem);
111}
112EXPORT_SYMBOL(tty_throttle);
113
114/**
115 *	tty_unthrottle		-	flow control
116 *	@tty: terminal
117 *
118 *	Indicate that a tty may continue transmitting data down the stack.
119 *	Takes the termios rwsem to protect against parallel throttle/unthrottle
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.
125 */
126
127void tty_unthrottle(struct tty_struct *tty)
128{
129	down_write(&tty->termios_rwsem);
130	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
131	    tty->ops->unthrottle)
132		tty->ops->unthrottle(tty);
133	tty->flow_change = 0;
134	up_write(&tty->termios_rwsem);
135}
136EXPORT_SYMBOL(tty_unthrottle);
137
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
154	mutex_lock(&tty->throttle_mutex);
155	if (!test_bit(TTY_THROTTLED, &tty->flags)) {
156		if (tty->flow_change != TTY_THROTTLE_SAFE)
157			ret = 1;
158		else {
159			set_bit(TTY_THROTTLED, &tty->flags);
160			if (tty->ops->throttle)
161				tty->ops->throttle(tty);
162		}
163	}
164	mutex_unlock(&tty->throttle_mutex);
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
185	mutex_lock(&tty->throttle_mutex);
186	if (test_bit(TTY_THROTTLED, &tty->flags)) {
187		if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
188			ret = 1;
189		else {
190			clear_bit(TTY_THROTTLED, &tty->flags);
191			if (tty->ops->unthrottle)
192				tty->ops->unthrottle(tty);
193		}
194	}
195	mutex_unlock(&tty->throttle_mutex);
196
197	return ret;
198}
199
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
211void tty_wait_until_sent(struct tty_struct *tty, long timeout)
212{
213#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
214	char buf[64];
215
216	printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
217#endif
218	if (!timeout)
219		timeout = MAX_SCHEDULE_TIMEOUT;
220
221	timeout = wait_event_interruptible_timeout(tty->write_wait,
222			!tty_chars_in_buffer(tty), timeout);
223	if (timeout <= 0)
224		return;
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);
231}
232EXPORT_SYMBOL(tty_wait_until_sent);
233
234
235/*
236 *		Termios Helper Methods
237 */
238
239static void unset_locked_termios(struct ktermios *termios,
240				 struct ktermios *old,
241				 struct ktermios *locked)
242{
243	int	i;
244
245#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
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;
257	for (i = 0; i < NCCS; i++)
258		termios->c_cc[i] = locked->c_cc[i] ?
259			old->c_cc[i] : termios->c_cc[i];
260	/* FIXME: What should we do for i/ospeed */
261}
262
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
318	/* Magic token for arbitrary speed via c_ispeed/c_ospeed */
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}
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
354	/* Magic token for arbitrary speed via c_ispeed*/
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}
371EXPORT_SYMBOL(tty_termios_input_baud_rate);
372
373/**
374 *	tty_termios_encode_baud_rate
375 *	@termios: ktermios structure holding user requested state
376 *	@ispeed: input speed
377 *	@ospeed: output speed
378 *
379 *	Encode the speeds set into the passed termios structure. This is
380 *	used as a library helper for drivers so that they can report back
381 *	the actual speed selected when it differs from the speed requested
382 *
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
386 *	of the input intent to keep compatibility.
387 *
388 *	Locking: Caller should hold termios lock. This is already held
389 *	when calling this function from the driver termios handler.
390 *
391 *	The ifdefs deal with platforms whose owners have yet to update them
392 *	and will all go away once this is done.
393 */
394
395void tty_termios_encode_baud_rate(struct ktermios *termios,
396				  speed_t ibaud, speed_t obaud)
397{
398	int i = 0;
399	int ifound = -1, ofound = -1;
400	int iclose = ibaud/50, oclose = obaud/50;
401	int ibinput = 0;
402
403	if (obaud == 0)			/* CD dropped 		  */
404		ibaud = 0;		/* Clear ibaud to be sure */
405
406	termios->c_ispeed = ibaud;
407	termios->c_ospeed = obaud;
408
409#ifdef BOTHER
410	/* If the user asked for a precise weird speed give a precise weird
411	   answer. If they asked for a Bfoo speed they may have problems
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 */
420#endif
421	termios->c_cflag &= ~CBAUD;
422
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
430	do {
431		if (obaud - oclose <= baud_table[i] &&
432		    obaud + oclose >= baud_table[i]) {
433			termios->c_cflag |= baud_bits[i];
434			ofound = i;
435		}
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 */
440			if (ofound == i && !ibinput)
441				ifound  = i;
442#ifdef IBSHIFT
443			else {
444				ifound = i;
445				termios->c_cflag |= (baud_bits[i] << IBSHIFT);
446			}
447#endif
448		}
449	} while (++i < n_baud_table);
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
456	if (ofound == -1)
457		termios->c_cflag |= BOTHER;
458	/* Set exact input bits only if the input and output differ or the
459	   user already did */
460	if (ifound == -1 && (ibaud != obaud || ibinput))
461		termios->c_cflag |= (BOTHER << IBSHIFT);
462#else
463	if (ifound == -1 || ofound == -1) {
464		printk_once(KERN_WARNING "tty: Unable to return correct "
465			  "speed data as your architecture needs updating.\n");
466	}
467#endif
468}
469EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
470
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
477 *	settings. The caller must hold the termios_rwsem for the tty in
478 *	question.
479 */
480
481void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
482{
483	tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
484}
485EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
486
487/**
488 *	tty_termios_copy_hw	-	copy hardware settings
489 *	@new: New termios
490 *	@old: Old termios
491 *
492 *	Propagate the hardware specific terminal setting bits from
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}
507EXPORT_SYMBOL(tty_termios_copy_hw);
508
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
528/**
529 *	tty_set_termios		-	update termios values
530 *	@tty: tty to update
531 *	@new_termios: desired new value
532 *
533 *	Perform updates to the termios values set on this terminal.
534 *	A master pty's termios should never be set.
535 *
536 *	Locking: termios_rwsem
537 */
538
539int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
540{
541	struct ktermios old_termios;
542	struct tty_ldisc *ld;
543
544	WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
545		tty->driver->subtype == PTY_TYPE_MASTER);
546	/*
547	 *	Perform the actual termios internal changes under lock.
548	 */
549
550
551	/* FIXME: we need to decide on some locking/ordering semantics
552	   for the set_termios notification eventually */
553	down_write(&tty->termios_rwsem);
554	old_termios = tty->termios;
555	tty->termios = *new_termios;
556	unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked);
557
558	if (tty->ops->set_termios)
559		tty->ops->set_termios(tty, &old_termios);
560	else
561		tty_termios_copy_hw(&tty->termios, &old_termios);
562
563	ld = tty_ldisc_ref(tty);
564	if (ld != NULL) {
565		if (ld->ops->set_termios)
566			ld->ops->set_termios(tty, &old_termios);
567		tty_ldisc_deref(ld);
568	}
569	up_write(&tty->termios_rwsem);
570	return 0;
571}
572EXPORT_SYMBOL_GPL(tty_set_termios);
573
574/**
575 *	set_termios		-	set termios values for a tty
576 *	@tty: terminal device
577 *	@arg: user data
578 *	@opt: option information
579 *
580 *	Helper function to prepare termios data and run necessary other
581 *	functions before using tty_set_termios to do the actual changes.
582 *
583 *	Locking:
584 *		Called functions take ldisc and termios_rwsem locks
585 */
586
587static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
588{
589	struct ktermios tmp_termios;
590	struct tty_ldisc *ld;
591	int retval = tty_check_change(tty);
592
593	if (retval)
594		return retval;
595
596	down_read(&tty->termios_rwsem);
597	tmp_termios = tty->termios;
598	up_read(&tty->termios_rwsem);
599
600	if (opt & TERMIOS_TERMIO) {
601		if (user_termio_to_kernel_termios(&tmp_termios,
602						(struct termio __user *)arg))
603			return -EFAULT;
604#ifdef TCGETS2
605	} else if (opt & TERMIOS_OLD) {
606		if (user_termios_to_kernel_termios_1(&tmp_termios,
607						(struct termios __user *)arg))
608			return -EFAULT;
609	} else {
610		if (user_termios_to_kernel_termios(&tmp_termios,
611						(struct termios2 __user *)arg))
612			return -EFAULT;
613	}
614#else
615	} else if (user_termios_to_kernel_termios(&tmp_termios,
616					(struct termios __user *)arg))
617		return -EFAULT;
618#endif
619
620	/* If old style Bfoo values are used then load c_ispeed/c_ospeed
621	 * with the real speed so its unconditionally usable */
622	tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
623	tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
624
625	ld = tty_ldisc_ref(tty);
626
627	if (ld != NULL) {
628		if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
629			ld->ops->flush_buffer(tty);
630		tty_ldisc_deref(ld);
631	}
632
633	if (opt & TERMIOS_WAIT) {
634		tty_wait_until_sent(tty, 0);
635		if (signal_pending(current))
636			return -ERESTARTSYS;
637	}
638
639	tty_set_termios(tty, &tmp_termios);
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 */
645	return 0;
646}
647
648static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
649{
650	down_read(&tty->termios_rwsem);
651	*kterm = tty->termios;
652	up_read(&tty->termios_rwsem);
653}
654
655static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
656{
657	down_read(&tty->termios_rwsem);
658	*kterm = tty->termios_locked;
659	up_read(&tty->termios_rwsem);
660}
661
662static int get_termio(struct tty_struct *tty, struct termio __user *termio)
663{
664	struct ktermios kterm;
665	copy_termios(tty, &kterm);
666	if (kernel_termios_to_user_termio(termio, &kterm))
667		return -EFAULT;
668	return 0;
669}
670
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))
703			return -ERESTARTSYS;
704	}
705
706	down_write(&tty->termios_rwsem);
707	if (tty->ops->set_termiox)
708		tty->ops->set_termiox(tty, &tnew);
709	up_write(&tty->termios_rwsem);
710	return 0;
711}
712
713#endif
714
715
716#ifdef TIOCGETP
717/*
718 * These are deprecated, but there is limited support..
719 *
720 * The "sg_flags" translation is a joke..
721 */
722static int get_sgflags(struct tty_struct *tty)
723{
724	int flags = 0;
725
726	if (!(tty->termios.c_lflag & ICANON)) {
727		if (tty->termios.c_lflag & ISIG)
728			flags |= 0x02;		/* cbreak */
729		else
730			flags |= 0x20;		/* raw */
731	}
732	if (tty->termios.c_lflag & ECHO)
733		flags |= 0x08;			/* echo */
734	if (tty->termios.c_oflag & OPOST)
735		if (tty->termios.c_oflag & ONLCR)
736			flags |= 0x10;		/* crmod */
737	return flags;
738}
739
740static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
741{
742	struct sgttyb tmp;
743
744	down_read(&tty->termios_rwsem);
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];
749	tmp.sg_flags = get_sgflags(tty);
750	up_read(&tty->termios_rwsem);
751
752	return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
753}
754
755static void set_sgflags(struct ktermios *termios, int flags)
756{
757	termios->c_iflag = ICRNL | IXON;
758	termios->c_oflag = 0;
759	termios->c_lflag = ISIG | ICANON;
760	if (flags & 0x02) {	/* cbreak */
761		termios->c_iflag = 0;
762		termios->c_lflag &= ~ICANON;
763	}
764	if (flags & 0x08) {		/* echo */
765		termios->c_lflag |= ECHO | ECHOE | ECHOK |
766				    ECHOCTL | ECHOKE | IEXTEN;
767	}
768	if (flags & 0x10) {		/* crmod */
769		termios->c_oflag |= OPOST | ONLCR;
770	}
771	if (flags & 0x20) {	/* raw */
772		termios->c_iflag = 0;
773		termios->c_lflag &= ~(ISIG | ICANON);
774	}
775	if (!(termios->c_lflag & ICANON)) {
776		termios->c_cc[VMIN] = 1;
777		termios->c_cc[VTIME] = 0;
778	}
779}
780
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 *
789 *	Locking: termios_rwsem
790 */
791
792static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
793{
794	int retval;
795	struct sgttyb tmp;
796	struct ktermios termios;
797
798	retval = tty_check_change(tty);
799	if (retval)
800		return retval;
801
802	if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
803		return -EFAULT;
804
805	down_write(&tty->termios_rwsem);
806	termios = tty->termios;
807	termios.c_cc[VERASE] = tmp.sg_erase;
808	termios.c_cc[VKILL] = tmp.sg_kill;
809	set_sgflags(&termios, tmp.sg_flags);
810	/* Try and encode into Bfoo format */
811#ifdef BOTHER
812	tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
813						termios.c_ospeed);
814#endif
815	up_write(&tty->termios_rwsem);
816	tty_set_termios(tty, &termios);
817	return 0;
818}
819#endif
820
821#ifdef TIOCGETC
822static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
823{
824	struct tchars tmp;
825
826	down_read(&tty->termios_rwsem);
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? */
833	up_read(&tty->termios_rwsem);
834	return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
835}
836
837static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
838{
839	struct tchars tmp;
840
841	if (copy_from_user(&tmp, tchars, sizeof(tmp)))
842		return -EFAULT;
843	down_write(&tty->termios_rwsem);
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? */
850	up_write(&tty->termios_rwsem);
851	return 0;
852}
853#endif
854
855#ifdef TIOCGLTC
856static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
857{
858	struct ltchars tmp;
859
860	down_read(&tty->termios_rwsem);
861	tmp.t_suspc = tty->termios.c_cc[VSUSP];
862	/* what is dsuspc anyway? */
863	tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
864	tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
865	/* what is flushc anyway? */
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];
869	up_read(&tty->termios_rwsem);
870	return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
871}
872
873static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
874{
875	struct ltchars tmp;
876
877	if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
878		return -EFAULT;
879
880	down_write(&tty->termios_rwsem);
881	tty->termios.c_cc[VSUSP] = tmp.t_suspc;
882	/* what is dsuspc anyway? */
883	tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
884	tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
885	/* what is flushc anyway? */
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;
889	up_write(&tty->termios_rwsem);
890	return 0;
891}
892#endif
893
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
900 *	layer to make it visible. All done with the termios rwsem
901 */
902
903static int tty_change_softcar(struct tty_struct *tty, int arg)
904{
905	int ret = 0;
906	int bit = arg ? CLOCAL : 0;
907	struct ktermios old;
908
909	down_write(&tty->termios_rwsem);
910	old = tty->termios;
911	tty->termios.c_cflag &= ~CLOCAL;
912	tty->termios.c_cflag |= bit;
913	if (tty->ops->set_termios)
914		tty->ops->set_termios(tty, &old);
915	if ((tty->termios.c_cflag & CLOCAL) != bit)
916		ret = -EINVAL;
917	up_write(&tty->termios_rwsem);
918	return ret;
919}
920
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
933int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
934			unsigned int cmd, unsigned long arg)
935{
936	struct tty_struct *real_tty;
937	void __user *p = (void __user *)arg;
938	int ret = 0;
939	struct ktermios kterm;
940
941	BUG_ON(file == NULL);
942
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
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);
956#endif
957#ifdef TIOCGETC
958	case TIOCGETC:
959		return get_tchars(real_tty, p);
960	case TIOCSETC:
961		return set_tchars(real_tty, p);
962#endif
963#ifdef TIOCGLTC
964	case TIOCGLTC:
965		return get_ltchars(real_tty, p);
966	case TIOCSLTC:
967		return set_ltchars(real_tty, p);
968#endif
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);
975#ifndef TCGETS2
976	case TCGETS:
977		copy_termios(real_tty, &kterm);
978		if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
979			ret = -EFAULT;
980		return ret;
981#else
982	case TCGETS:
983		copy_termios(real_tty, &kterm);
984		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
985			ret = -EFAULT;
986		return ret;
987	case TCGETS2:
988		copy_termios(real_tty, &kterm);
989		if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
990			ret = -EFAULT;
991		return ret;
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);
998#endif
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);
1007#ifndef TCGETS2
1008	case TIOCGLCKTRMIOS:
1009		copy_termios_locked(real_tty, &kterm);
1010		if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
1011			ret = -EFAULT;
1012		return ret;
1013	case TIOCSLCKTRMIOS:
1014		if (!capable(CAP_SYS_ADMIN))
1015			return -EPERM;
1016		copy_termios_locked(real_tty, &kterm);
1017		if (user_termios_to_kernel_termios(&kterm,
1018					       (struct termios __user *) arg))
1019			return -EFAULT;
1020		down_write(&real_tty->termios_rwsem);
1021		real_tty->termios_locked = kterm;
1022		up_write(&real_tty->termios_rwsem);
1023		return 0;
1024#else
1025	case TIOCGLCKTRMIOS:
1026		copy_termios_locked(real_tty, &kterm);
1027		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
1028			ret = -EFAULT;
1029		return ret;
1030	case TIOCSLCKTRMIOS:
1031		if (!capable(CAP_SYS_ADMIN))
1032			return -EPERM;
1033		copy_termios_locked(real_tty, &kterm);
1034		if (user_termios_to_kernel_termios_1(&kterm,
1035					       (struct termios __user *) arg))
1036			return -EFAULT;
1037		down_write(&real_tty->termios_rwsem);
1038		real_tty->termios_locked = kterm;
1039		up_write(&real_tty->termios_rwsem);
1040		return ret;
1041#endif
1042#ifdef TCGETX
1043	case TCGETX: {
1044		struct termiox ktermx;
1045		if (real_tty->termiox == NULL)
1046			return -EINVAL;
1047		down_read(&real_tty->termios_rwsem);
1048		memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
1049		up_read(&real_tty->termios_rwsem);
1050		if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
1051			ret = -EFAULT;
1052		return ret;
1053	}
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
1061	case TIOCGSOFTCAR:
1062		copy_termios(real_tty, &kterm);
1063		ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
1064						(int __user *)arg);
1065		return ret;
1066	case TIOCSSOFTCAR:
1067		if (get_user(arg, (unsigned int __user *) arg))
1068			return -EFAULT;
1069		return tty_change_softcar(real_tty, arg);
1070	default:
1071		return -ENOIOCTLCMD;
1072	}
1073}
1074EXPORT_SYMBOL_GPL(tty_mode_ioctl);
1075
1076
1077/* Caller guarantees ldisc reference is held */
1078static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1079{
1080	struct tty_ldisc *ld = tty->ldisc;
1081
1082	switch (arg) {
1083	case TCIFLUSH:
1084		if (ld && ld->ops->flush_buffer) {
1085			ld->ops->flush_buffer(tty);
1086			tty_unthrottle(tty);
1087		}
1088		break;
1089	case TCIOFLUSH:
1090		if (ld && ld->ops->flush_buffer) {
1091			ld->ops->flush_buffer(tty);
1092			tty_unthrottle(tty);
1093		}
1094		/* fall through */
1095	case TCOFLUSH:
1096		tty_driver_flush_buffer(tty);
1097		break;
1098	default:
1099		return -EINVAL;
1100	}
1101	return 0;
1102}
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}
1117EXPORT_SYMBOL_GPL(tty_perform_flush);
1118
1119int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
1120		       unsigned int cmd, unsigned long arg)
1121{
1122	int retval;
1123
1124	switch (cmd) {
1125	case TCXONC:
1126		retval = tty_check_change(tty);
1127		if (retval)
1128			return retval;
1129		switch (arg) {
1130		case TCOOFF:
1131			spin_lock_irq(&tty->flow_lock);
1132			if (!tty->flow_stopped) {
1133				tty->flow_stopped = 1;
1134				__stop_tty(tty);
1135			}
1136			spin_unlock_irq(&tty->flow_lock);
1137			break;
1138		case TCOON:
1139			spin_lock_irq(&tty->flow_lock);
1140			if (tty->flow_stopped) {
1141				tty->flow_stopped = 0;
1142				__start_tty(tty);
1143			}
1144			spin_unlock_irq(&tty->flow_lock);
1145			break;
1146		case TCIOFF:
1147			if (STOP_CHAR(tty) != __DISABLED_CHAR)
1148				retval = tty_send_xchar(tty, STOP_CHAR(tty));
1149			break;
1150		case TCION:
1151			if (START_CHAR(tty) != __DISABLED_CHAR)
1152				retval = tty_send_xchar(tty, START_CHAR(tty));
1153			break;
1154		default:
1155			return -EINVAL;
1156		}
1157		return retval;
1158	case TCFLSH:
1159		retval = tty_check_change(tty);
1160		if (retval)
1161			return retval;
1162		return __tty_perform_flush(tty, arg);
1163	default:
1164		/* Try the mode commands */
1165		return tty_mode_ioctl(tty, file, cmd, arg);
1166	}
1167}
1168EXPORT_SYMBOL(n_tty_ioctl_helper);
1169
1170#ifdef CONFIG_COMPAT
1171long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
1172					unsigned int cmd, unsigned long arg)
1173{
1174	switch (cmd) {
1175	case TIOCGLCKTRMIOS:
1176	case TIOCSLCKTRMIOS:
1177		return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
1178	default:
1179		return -ENOIOCTLCMD;
1180	}
1181}
1182EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
1183#endif
1184
1185