[PATCH] tty: switch to ktermios
[linux-2.6-block.git] / drivers / char / tty_ioctl.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/char/tty_ioctl.c
3 *
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
5 *
6 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
7 * which can be dynamically activated and de-activated by the line
8 * discipline handling modules (like SLIP).
9 */
10
11#include <linux/types.h>
12#include <linux/termios.h>
13#include <linux/errno.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/major.h>
17#include <linux/tty.h>
18#include <linux/fcntl.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/module.h>
22#include <linux/bitops.h>
5785c95b 23#include <linux/mutex.h>
1da177e4
LT
24
25#include <asm/io.h>
26#include <asm/uaccess.h>
27#include <asm/system.h>
28
29#undef TTY_DEBUG_WAIT_UNTIL_SENT
30
31#undef DEBUG
32
33/*
34 * Internal flag options for termios setting behavior
35 */
36#define TERMIOS_FLUSH 1
37#define TERMIOS_WAIT 2
38#define TERMIOS_TERMIO 4
edc6afc5 39#define TERMIOS_OLD 8
1da177e4 40
af9b897e
AC
41
42/**
43 * tty_wait_until_sent - wait for I/O to finish
44 * @tty: tty we are waiting for
45 * @timeout: how long we will wait
46 *
47 * Wait for characters pending in a tty driver to hit the wire, or
48 * for a timeout to occur (eg due to flow control)
49 *
50 * Locking: none
51 */
52
1da177e4
LT
53void tty_wait_until_sent(struct tty_struct * tty, long timeout)
54{
55 DECLARE_WAITQUEUE(wait, current);
56
57#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
58 char buf[64];
59
60 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
61#endif
62 if (!tty->driver->chars_in_buffer)
63 return;
64 add_wait_queue(&tty->write_wait, &wait);
65 if (!timeout)
66 timeout = MAX_SCHEDULE_TIMEOUT;
67 do {
68#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
69 printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
70 tty->driver->chars_in_buffer(tty));
71#endif
72 set_current_state(TASK_INTERRUPTIBLE);
73 if (signal_pending(current))
74 goto stop_waiting;
75 if (!tty->driver->chars_in_buffer(tty))
76 break;
77 timeout = schedule_timeout(timeout);
78 } while (timeout);
79 if (tty->driver->wait_until_sent)
80 tty->driver->wait_until_sent(tty, timeout);
81stop_waiting:
82 set_current_state(TASK_RUNNING);
83 remove_wait_queue(&tty->write_wait, &wait);
84}
85
86EXPORT_SYMBOL(tty_wait_until_sent);
87
edc6afc5
AC
88static void unset_locked_termios(struct ktermios *termios,
89 struct ktermios *old,
90 struct ktermios *locked)
1da177e4
LT
91{
92 int i;
93
94#define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
95
96 if (!locked) {
97 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
98 return;
99 }
100
101 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
102 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
103 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
104 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
105 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
106 for (i=0; i < NCCS; i++)
107 termios->c_cc[i] = locked->c_cc[i] ?
108 old->c_cc[i] : termios->c_cc[i];
edc6afc5 109 /* FIXME: What should we do for i/ospeed */
1da177e4
LT
110}
111
edc6afc5
AC
112/*
113 * Routine which returns the baud rate of the tty
114 *
115 * Note that the baud_table needs to be kept in sync with the
116 * include/asm/termbits.h file.
117 */
118static const speed_t baud_table[] = {
119 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
120 9600, 19200, 38400, 57600, 115200, 230400, 460800,
121#ifdef __sparc__
122 76800, 153600, 307200, 614400, 921600
123#else
124 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
125 2500000, 3000000, 3500000, 4000000
126#endif
127};
128
129#ifndef __sparc__
130static const tcflag_t baud_bits[] = {
131 B0, B50, B75, B110, B134, B150, B200, B300, B600,
132 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
133 B57600, B115200, B230400, B460800, B500000, B576000,
134 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
135 B3000000, B3500000, B4000000
136};
137#else
138static const tcflag_t baud_bits[] = {
139 B0, B50, B75, B110, B134, B150, B200, B300, B600,
140 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
141 B57600, B115200, B230400, B460800, B76800, B153600,
142 B307200, B614400, B921600
143};
144#endif
145
146static int n_baud_table = ARRAY_SIZE(baud_table);
147
148/**
149 * tty_termios_baud_rate
150 * @termios: termios structure
151 *
152 * Convert termios baud rate data into a speed. This should be called
153 * with the termios lock held if this termios is a terminal termios
154 * structure. May change the termios data. Device drivers can call this
155 * function but should use ->c_[io]speed directly as they are updated.
156 *
157 * Locking: none
158 */
159
160speed_t tty_termios_baud_rate(struct ktermios *termios)
161{
162 unsigned int cbaud;
163
164 cbaud = termios->c_cflag & CBAUD;
165
166#ifdef BOTHER
167 /* Magic token for arbitary speed via c_ispeed/c_ospeed */
168 if (cbaud == BOTHER)
169 return termios->c_ospeed;
170#endif
171 if (cbaud & CBAUDEX) {
172 cbaud &= ~CBAUDEX;
173
174 if (cbaud < 1 || cbaud + 15 > n_baud_table)
175 termios->c_cflag &= ~CBAUDEX;
176 else
177 cbaud += 15;
178 }
179 return baud_table[cbaud];
180}
181
182EXPORT_SYMBOL(tty_termios_baud_rate);
183
184/**
185 * tty_termios_input_baud_rate
186 * @termios: termios structure
187 *
188 * Convert termios baud rate data into a speed. This should be called
189 * with the termios lock held if this termios is a terminal termios
190 * structure. May change the termios data. Device drivers can call this
191 * function but should use ->c_[io]speed directly as they are updated.
192 *
193 * Locking: none
194 */
195
196speed_t tty_termios_input_baud_rate(struct ktermios *termios)
197{
198#ifdef IBSHIFT
199 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
200
201 if (cbaud == B0)
202 return tty_termios_baud_rate(termios);
203
204 /* Magic token for arbitary speed via c_ispeed*/
205 if (cbaud == BOTHER)
206 return termios->c_ispeed;
207
208 if (cbaud & CBAUDEX) {
209 cbaud &= ~CBAUDEX;
210
211 if (cbaud < 1 || cbaud + 15 > n_baud_table)
212 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
213 else
214 cbaud += 15;
215 }
216 return baud_table[cbaud];
217#else
218 return tty_termios_baud_rate(termios);
219#endif
220}
221
222EXPORT_SYMBOL(tty_termios_input_baud_rate);
223
224#ifdef BOTHER
225
226/**
227 * tty_termios_encode_baud_rate
228 * @termios: termios structure
229 * @ispeed: input speed
230 * @ospeed: output speed
231 *
232 * Encode the speeds set into the passed termios structure. This is
233 * used as a library helper for drivers os that they can report back
234 * the actual speed selected when it differs from the speed requested
235 *
236 * For now input and output speed must agree.
237 *
238 * Locking: Caller should hold termios lock. This is already held
239 * when calling this function from the driver termios handler.
240 */
241
242void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
243{
244 int i = 0;
245 int ifound = 0, ofound = 0;
246
247 termios->c_ispeed = ibaud;
248 termios->c_ospeed = obaud;
249
250 termios->c_cflag &= ~CBAUD;
251 /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/
252 if (termios->c_ispeed == termios->c_ospeed)
253 ifound = 1;
254
255 do {
256 if (obaud == baud_table[i]) {
257 termios->c_cflag |= baud_bits[i];
258 ofound = 1;
259 /* So that if ibaud == obaud we don't set it */
260 continue;
261 }
262 if (ibaud == baud_table[i]) {
263 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
264 ifound = 1;
265 }
266 }
267 while(++i < n_baud_table);
268 if (!ofound)
269 termios->c_cflag |= BOTHER;
270 if (!ifound)
271 termios->c_cflag |= (BOTHER << IBSHIFT);
272}
273
274EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
275
276#endif
277
278/**
279 * tty_get_baud_rate - get tty bit rates
280 * @tty: tty to query
281 *
282 * Returns the baud rate as an integer for this terminal. The
283 * termios lock must be held by the caller and the terminal bit
284 * flags may be updated.
285 *
286 * Locking: none
287 */
288
289speed_t tty_get_baud_rate(struct tty_struct *tty)
290{
291 speed_t baud = tty_termios_baud_rate(tty->termios);
292
293 if (baud == 38400 && tty->alt_speed) {
294 if (!tty->warned) {
295 printk(KERN_WARNING "Use of setserial/setrocket to "
296 "set SPD_* flags is deprecated\n");
297 tty->warned = 1;
298 }
299 baud = tty->alt_speed;
300 }
301
302 return baud;
303}
304
305EXPORT_SYMBOL(tty_get_baud_rate);
306
af9b897e
AC
307/**
308 * change_termios - update termios values
309 * @tty: tty to update
310 * @new_termios: desired new value
311 *
312 * Perform updates to the termios values set on this terminal. There
313 * is a bit of layering violation here with n_tty in terms of the
314 * internal knowledge of this function.
315 *
316 * Locking: termios_sem
317 */
318
edc6afc5 319static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
1da177e4
LT
320{
321 int canon_change;
edc6afc5 322 struct ktermios old_termios = *tty->termios;
1da177e4
LT
323 struct tty_ldisc *ld;
324
325 /*
326 * Perform the actual termios internal changes under lock.
327 */
328
329
330 /* FIXME: we need to decide on some locking/ordering semantics
331 for the set_termios notification eventually */
5785c95b 332 mutex_lock(&tty->termios_mutex);
1da177e4
LT
333
334 *tty->termios = *new_termios;
335 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
336 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
337 if (canon_change) {
338 memset(&tty->read_flags, 0, sizeof tty->read_flags);
339 tty->canon_head = tty->read_tail;
340 tty->canon_data = 0;
341 tty->erasing = 0;
342 }
343
344
345 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
346 /* Get characters left over from canonical mode. */
347 wake_up_interruptible(&tty->read_wait);
348
349 /* See if packet mode change of state. */
350
351 if (tty->link && tty->link->packet) {
352 int old_flow = ((old_termios.c_iflag & IXON) &&
353 (old_termios.c_cc[VSTOP] == '\023') &&
354 (old_termios.c_cc[VSTART] == '\021'));
355 int new_flow = (I_IXON(tty) &&
356 STOP_CHAR(tty) == '\023' &&
357 START_CHAR(tty) == '\021');
358 if (old_flow != new_flow) {
359 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
360 if (new_flow)
361 tty->ctrl_status |= TIOCPKT_DOSTOP;
362 else
363 tty->ctrl_status |= TIOCPKT_NOSTOP;
364 wake_up_interruptible(&tty->link->read_wait);
365 }
366 }
367
368 if (tty->driver->set_termios)
369 (*tty->driver->set_termios)(tty, &old_termios);
370
371 ld = tty_ldisc_ref(tty);
372 if (ld != NULL) {
373 if (ld->set_termios)
374 (ld->set_termios)(tty, &old_termios);
375 tty_ldisc_deref(ld);
376 }
5785c95b 377 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
378}
379
af9b897e
AC
380/**
381 * set_termios - set termios values for a tty
382 * @tty: terminal device
383 * @arg: user data
384 * @opt: option information
385 *
386 * Helper function to prepare termios data and run neccessary other
387 * functions before using change_termios to do the actual changes.
388 *
389 * Locking:
390 * Called functions take ldisc and termios_sem locks
391 */
392
1da177e4
LT
393static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
394{
edc6afc5 395 struct ktermios tmp_termios;
1da177e4
LT
396 struct tty_ldisc *ld;
397 int retval = tty_check_change(tty);
398
399 if (retval)
400 return retval;
401
402 if (opt & TERMIOS_TERMIO) {
edc6afc5 403 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
1da177e4
LT
404 if (user_termio_to_kernel_termios(&tmp_termios,
405 (struct termio __user *)arg))
406 return -EFAULT;
edc6afc5
AC
407#ifdef TCGETS2
408 } else if (opt & TERMIOS_OLD) {
409 memcpy(&tmp_termios, tty->termios, sizeof(struct termios));
410 if (user_termios_to_kernel_termios_1(&tmp_termios,
411 (struct termios_v1 __user *)arg))
412 return -EFAULT;
413#endif
1da177e4
LT
414 } else {
415 if (user_termios_to_kernel_termios(&tmp_termios,
416 (struct termios __user *)arg))
417 return -EFAULT;
418 }
419
edc6afc5
AC
420 /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
421 so its unconditionally usable */
422 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
423 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
424
1da177e4
LT
425 ld = tty_ldisc_ref(tty);
426
427 if (ld != NULL) {
428 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
429 ld->flush_buffer(tty);
430 tty_ldisc_deref(ld);
431 }
432
433 if (opt & TERMIOS_WAIT) {
434 tty_wait_until_sent(tty, 0);
435 if (signal_pending(current))
436 return -EINTR;
437 }
438
439 change_termios(tty, &tmp_termios);
440 return 0;
441}
442
443static int get_termio(struct tty_struct * tty, struct termio __user * termio)
444{
445 if (kernel_termios_to_user_termio(termio, tty->termios))
446 return -EFAULT;
447 return 0;
448}
449
450static unsigned long inq_canon(struct tty_struct * tty)
451{
452 int nr, head, tail;
453
454 if (!tty->canon_data || !tty->read_buf)
455 return 0;
456 head = tty->canon_head;
457 tail = tty->read_tail;
458 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
459 /* Skip EOF-chars.. */
460 while (head != tail) {
461 if (test_bit(tail, tty->read_flags) &&
462 tty->read_buf[tail] == __DISABLED_CHAR)
463 nr--;
464 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
465 }
466 return nr;
467}
468
469#ifdef TIOCGETP
470/*
471 * These are deprecated, but there is limited support..
472 *
473 * The "sg_flags" translation is a joke..
474 */
475static int get_sgflags(struct tty_struct * tty)
476{
477 int flags = 0;
478
479 if (!(tty->termios->c_lflag & ICANON)) {
480 if (tty->termios->c_lflag & ISIG)
481 flags |= 0x02; /* cbreak */
482 else
483 flags |= 0x20; /* raw */
484 }
485 if (tty->termios->c_lflag & ECHO)
486 flags |= 0x08; /* echo */
487 if (tty->termios->c_oflag & OPOST)
488 if (tty->termios->c_oflag & ONLCR)
489 flags |= 0x10; /* crmod */
490 return flags;
491}
492
493static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
494{
495 struct sgttyb tmp;
496
5785c95b 497 mutex_lock(&tty->termios_mutex);
606d099c
AC
498 tmp.sg_ispeed = tty->termios->c_ispeed;
499 tmp.sg_ospeed = tty->termios->c_ospeed;
1da177e4
LT
500 tmp.sg_erase = tty->termios->c_cc[VERASE];
501 tmp.sg_kill = tty->termios->c_cc[VKILL];
502 tmp.sg_flags = get_sgflags(tty);
5785c95b 503 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
504
505 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
506}
507
edc6afc5 508static void set_sgflags(struct ktermios * termios, int flags)
1da177e4
LT
509{
510 termios->c_iflag = ICRNL | IXON;
511 termios->c_oflag = 0;
512 termios->c_lflag = ISIG | ICANON;
513 if (flags & 0x02) { /* cbreak */
514 termios->c_iflag = 0;
515 termios->c_lflag &= ~ICANON;
516 }
517 if (flags & 0x08) { /* echo */
518 termios->c_lflag |= ECHO | ECHOE | ECHOK |
519 ECHOCTL | ECHOKE | IEXTEN;
520 }
521 if (flags & 0x10) { /* crmod */
522 termios->c_oflag |= OPOST | ONLCR;
523 }
524 if (flags & 0x20) { /* raw */
525 termios->c_iflag = 0;
526 termios->c_lflag &= ~(ISIG | ICANON);
527 }
528 if (!(termios->c_lflag & ICANON)) {
529 termios->c_cc[VMIN] = 1;
530 termios->c_cc[VTIME] = 0;
531 }
532}
533
af9b897e
AC
534/**
535 * set_sgttyb - set legacy terminal values
536 * @tty: tty structure
537 * @sgttyb: pointer to old style terminal structure
538 *
539 * Updates a terminal from the legacy BSD style terminal information
540 * structure.
541 *
542 * Locking: termios_sem
543 */
544
1da177e4
LT
545static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
546{
547 int retval;
548 struct sgttyb tmp;
edc6afc5 549 struct ktermios termios;
1da177e4
LT
550
551 retval = tty_check_change(tty);
552 if (retval)
553 return retval;
554
555 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
556 return -EFAULT;
557
5785c95b 558 mutex_lock(&tty->termios_mutex);
1da177e4
LT
559 termios = *tty->termios;
560 termios.c_cc[VERASE] = tmp.sg_erase;
561 termios.c_cc[VKILL] = tmp.sg_kill;
562 set_sgflags(&termios, tmp.sg_flags);
edc6afc5
AC
563 /* Try and encode into Bfoo format */
564#ifdef BOTHER
565 tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
566#endif
5785c95b 567 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
568 change_termios(tty, &termios);
569 return 0;
570}
571#endif
572
573#ifdef TIOCGETC
574static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
575{
576 struct tchars tmp;
577
578 tmp.t_intrc = tty->termios->c_cc[VINTR];
579 tmp.t_quitc = tty->termios->c_cc[VQUIT];
580 tmp.t_startc = tty->termios->c_cc[VSTART];
581 tmp.t_stopc = tty->termios->c_cc[VSTOP];
582 tmp.t_eofc = tty->termios->c_cc[VEOF];
583 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
584 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
585}
586
587static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
588{
589 struct tchars tmp;
590
591 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
592 return -EFAULT;
593 tty->termios->c_cc[VINTR] = tmp.t_intrc;
594 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
595 tty->termios->c_cc[VSTART] = tmp.t_startc;
596 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
597 tty->termios->c_cc[VEOF] = tmp.t_eofc;
598 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
599 return 0;
600}
601#endif
602
603#ifdef TIOCGLTC
604static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
605{
606 struct ltchars tmp;
607
608 tmp.t_suspc = tty->termios->c_cc[VSUSP];
609 tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */
610 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
611 tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */
612 tmp.t_werasc = tty->termios->c_cc[VWERASE];
613 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
614 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
615}
616
617static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
618{
619 struct ltchars tmp;
620
621 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
622 return -EFAULT;
623
624 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
625 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */
626 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
627 tty->termios->c_cc[VEOL2] = tmp.t_flushc; /* what is flushc anyway? */
628 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
629 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
630 return 0;
631}
632#endif
633
af9b897e
AC
634/**
635 * send_prio_char - send priority character
636 *
637 * Send a high priority character to the tty even if stopped
638 *
5f412b24 639 * Locking: none for xchar method, write ordering for write method.
1da177e4 640 */
af9b897e 641
5f412b24 642static int send_prio_char(struct tty_struct *tty, char ch)
1da177e4
LT
643{
644 int was_stopped = tty->stopped;
645
646 if (tty->driver->send_xchar) {
647 tty->driver->send_xchar(tty, ch);
5f412b24 648 return 0;
1da177e4 649 }
5f412b24
AC
650
651 if (mutex_lock_interruptible(&tty->atomic_write_lock))
652 return -ERESTARTSYS;
653
1da177e4
LT
654 if (was_stopped)
655 start_tty(tty);
656 tty->driver->write(tty, &ch, 1);
657 if (was_stopped)
658 stop_tty(tty);
5f412b24
AC
659 mutex_unlock(&tty->atomic_write_lock);
660 return 0;
1da177e4
LT
661}
662
663int n_tty_ioctl(struct tty_struct * tty, struct file * file,
664 unsigned int cmd, unsigned long arg)
665{
666 struct tty_struct * real_tty;
667 void __user *p = (void __user *)arg;
668 int retval;
669 struct tty_ldisc *ld;
670
671 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
672 tty->driver->subtype == PTY_TYPE_MASTER)
673 real_tty = tty->link;
674 else
675 real_tty = tty;
676
677 switch (cmd) {
678#ifdef TIOCGETP
679 case TIOCGETP:
680 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
681 case TIOCSETP:
682 case TIOCSETN:
683 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
684#endif
685#ifdef TIOCGETC
686 case TIOCGETC:
687 return get_tchars(real_tty, p);
688 case TIOCSETC:
689 return set_tchars(real_tty, p);
690#endif
691#ifdef TIOCGLTC
692 case TIOCGLTC:
693 return get_ltchars(real_tty, p);
694 case TIOCSLTC:
695 return set_ltchars(real_tty, p);
696#endif
edc6afc5
AC
697 case TCSETSF:
698 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
699 case TCSETSW:
700 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
701 case TCSETS:
702 return set_termios(real_tty, p, TERMIOS_OLD);
703#ifndef TCGETS2
1da177e4
LT
704 case TCGETS:
705 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
706 return -EFAULT;
707 return 0;
edc6afc5
AC
708#else
709 case TCGETS:
710 if (kernel_termios_to_user_termios_1((struct termios_v1 __user *)arg, real_tty->termios))
711 return -EFAULT;
712 return 0;
713 case TCGETS2:
714 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
715 return -EFAULT;
716 return 0;
717 case TCSETSF2:
1da177e4 718 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
edc6afc5 719 case TCSETSW2:
1da177e4 720 return set_termios(real_tty, p, TERMIOS_WAIT);
edc6afc5 721 case TCSETS2:
1da177e4 722 return set_termios(real_tty, p, 0);
edc6afc5 723#endif
1da177e4
LT
724 case TCGETA:
725 return get_termio(real_tty, p);
726 case TCSETAF:
727 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
728 case TCSETAW:
729 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
730 case TCSETA:
731 return set_termios(real_tty, p, TERMIOS_TERMIO);
732 case TCXONC:
733 retval = tty_check_change(tty);
734 if (retval)
735 return retval;
736 switch (arg) {
737 case TCOOFF:
738 if (!tty->flow_stopped) {
739 tty->flow_stopped = 1;
740 stop_tty(tty);
741 }
742 break;
743 case TCOON:
744 if (tty->flow_stopped) {
745 tty->flow_stopped = 0;
746 start_tty(tty);
747 }
748 break;
749 case TCIOFF:
750 if (STOP_CHAR(tty) != __DISABLED_CHAR)
5f412b24 751 return send_prio_char(tty, STOP_CHAR(tty));
1da177e4
LT
752 break;
753 case TCION:
754 if (START_CHAR(tty) != __DISABLED_CHAR)
5f412b24 755 return send_prio_char(tty, START_CHAR(tty));
1da177e4
LT
756 break;
757 default:
758 return -EINVAL;
759 }
760 return 0;
761 case TCFLSH:
762 retval = tty_check_change(tty);
763 if (retval)
764 return retval;
765
766 ld = tty_ldisc_ref(tty);
767 switch (arg) {
768 case TCIFLUSH:
69f63c5c 769 if (ld && ld->flush_buffer)
1da177e4
LT
770 ld->flush_buffer(tty);
771 break;
772 case TCIOFLUSH:
69f63c5c 773 if (ld && ld->flush_buffer)
1da177e4
LT
774 ld->flush_buffer(tty);
775 /* fall through */
776 case TCOFLUSH:
777 if (tty->driver->flush_buffer)
778 tty->driver->flush_buffer(tty);
779 break;
780 default:
781 tty_ldisc_deref(ld);
782 return -EINVAL;
783 }
784 tty_ldisc_deref(ld);
785 return 0;
786 case TIOCOUTQ:
787 return put_user(tty->driver->chars_in_buffer ?
788 tty->driver->chars_in_buffer(tty) : 0,
789 (int __user *) arg);
790 case TIOCINQ:
791 retval = tty->read_cnt;
792 if (L_ICANON(tty))
793 retval = inq_canon(tty);
794 return put_user(retval, (unsigned int __user *) arg);
795 case TIOCGLCKTRMIOS:
796 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
797 return -EFAULT;
798 return 0;
799
800 case TIOCSLCKTRMIOS:
801 if (!capable(CAP_SYS_ADMIN))
802 return -EPERM;
803 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
804 return -EFAULT;
805 return 0;
806
807 case TIOCPKT:
808 {
809 int pktmode;
810
811 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
812 tty->driver->subtype != PTY_TYPE_MASTER)
813 return -ENOTTY;
814 if (get_user(pktmode, (int __user *) arg))
815 return -EFAULT;
816 if (pktmode) {
817 if (!tty->packet) {
818 tty->packet = 1;
819 tty->link->ctrl_status = 0;
820 }
821 } else
822 tty->packet = 0;
823 return 0;
824 }
825 case TIOCGSOFTCAR:
826 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
827 case TIOCSSOFTCAR:
828 if (get_user(arg, (unsigned int __user *) arg))
829 return -EFAULT;
5785c95b 830 mutex_lock(&tty->termios_mutex);
1da177e4
LT
831 tty->termios->c_cflag =
832 ((tty->termios->c_cflag & ~CLOCAL) |
833 (arg ? CLOCAL : 0));
5785c95b 834 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
835 return 0;
836 default:
837 return -ENOIOCTLCMD;
838 }
839}
840
841EXPORT_SYMBOL(n_tty_ioctl);