aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r--drivers/char/tty_ioctl.c299
1 files changed, 269 insertions, 30 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 4ad47d321bd4..dee47f40c6a3 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -20,6 +20,7 @@
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/bitops.h> 22#include <linux/bitops.h>
23#include <linux/mutex.h>
23 24
24#include <asm/io.h> 25#include <asm/io.h>
25#include <asm/uaccess.h> 26#include <asm/uaccess.h>
@@ -35,6 +36,7 @@
35#define TERMIOS_FLUSH 1 36#define TERMIOS_FLUSH 1
36#define TERMIOS_WAIT 2 37#define TERMIOS_WAIT 2
37#define TERMIOS_TERMIO 4 38#define TERMIOS_TERMIO 4
39#define TERMIOS_OLD 8
38 40
39 41
40/** 42/**
@@ -83,9 +85,9 @@ stop_waiting:
83 85
84EXPORT_SYMBOL(tty_wait_until_sent); 86EXPORT_SYMBOL(tty_wait_until_sent);
85 87
86static void unset_locked_termios(struct termios *termios, 88static void unset_locked_termios(struct ktermios *termios,
87 struct termios *old, 89 struct ktermios *old,
88 struct termios *locked) 90 struct ktermios *locked)
89{ 91{
90 int i; 92 int i;
91 93
@@ -104,8 +106,204 @@ static void unset_locked_termios(struct termios *termios,
104 for (i=0; i < NCCS; i++) 106 for (i=0; i < NCCS; i++)
105 termios->c_cc[i] = locked->c_cc[i] ? 107 termios->c_cc[i] = locked->c_cc[i] ?
106 old->c_cc[i] : termios->c_cc[i]; 108 old->c_cc[i] : termios->c_cc[i];
109 /* FIXME: What should we do for i/ospeed */
107} 110}
108 111
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
109/** 307/**
110 * change_termios - update termios values 308 * change_termios - update termios values
111 * @tty: tty to update 309 * @tty: tty to update
@@ -118,10 +316,10 @@ static void unset_locked_termios(struct termios *termios,
118 * Locking: termios_sem 316 * Locking: termios_sem
119 */ 317 */
120 318
121static void change_termios(struct tty_struct * tty, struct termios * new_termios) 319static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
122{ 320{
123 int canon_change; 321 int canon_change;
124 struct termios old_termios = *tty->termios; 322 struct ktermios old_termios = *tty->termios;
125 struct tty_ldisc *ld; 323 struct tty_ldisc *ld;
126 324
127 /* 325 /*
@@ -131,7 +329,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
131 329
132 /* FIXME: we need to decide on some locking/ordering semantics 330 /* FIXME: we need to decide on some locking/ordering semantics
133 for the set_termios notification eventually */ 331 for the set_termios notification eventually */
134 down(&tty->termios_sem); 332 mutex_lock(&tty->termios_mutex);
135 333
136 *tty->termios = *new_termios; 334 *tty->termios = *new_termios;
137 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); 335 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
@@ -176,7 +374,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
176 (ld->set_termios)(tty, &old_termios); 374 (ld->set_termios)(tty, &old_termios);
177 tty_ldisc_deref(ld); 375 tty_ldisc_deref(ld);
178 } 376 }
179 up(&tty->termios_sem); 377 mutex_unlock(&tty->termios_mutex);
180} 378}
181 379
182/** 380/**
@@ -194,23 +392,39 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
194 392
195static int set_termios(struct tty_struct * tty, void __user *arg, int opt) 393static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
196{ 394{
197 struct termios tmp_termios; 395 struct ktermios tmp_termios;
198 struct tty_ldisc *ld; 396 struct tty_ldisc *ld;
199 int retval = tty_check_change(tty); 397 int retval = tty_check_change(tty);
200 398
201 if (retval) 399 if (retval)
202 return retval; 400 return retval;
203 401
402 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
403
204 if (opt & TERMIOS_TERMIO) { 404 if (opt & TERMIOS_TERMIO) {
205 memcpy(&tmp_termios, tty->termios, sizeof(struct termios));
206 if (user_termio_to_kernel_termios(&tmp_termios, 405 if (user_termio_to_kernel_termios(&tmp_termios,
207 (struct termio __user *)arg)) 406 (struct termio __user *)arg))
208 return -EFAULT; 407 return -EFAULT;
408#ifdef TCGETS2
409 } else if (opt & TERMIOS_OLD) {
410 if (user_termios_to_kernel_termios_1(&tmp_termios,
411 (struct termios __user *)arg))
412 return -EFAULT;
209 } else { 413 } else {
210 if (user_termios_to_kernel_termios(&tmp_termios, 414 if (user_termios_to_kernel_termios(&tmp_termios,
211 (struct termios __user *)arg)) 415 (struct termios2 __user *)arg))
212 return -EFAULT; 416 return -EFAULT;
213 } 417 }
418#else
419 } else if (user_termios_to_kernel_termios(&tmp_termios,
420 (struct termios __user *)arg))
421 return -EFAULT;
422#endif
423
424 /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
425 so its unconditionally usable */
426 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
427 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
214 428
215 ld = tty_ldisc_ref(tty); 429 ld = tty_ldisc_ref(tty);
216 430
@@ -284,18 +498,18 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
284{ 498{
285 struct sgttyb tmp; 499 struct sgttyb tmp;
286 500
287 down(&tty->termios_sem); 501 mutex_lock(&tty->termios_mutex);
288 tmp.sg_ispeed = 0; 502 tmp.sg_ispeed = tty->termios->c_ispeed;
289 tmp.sg_ospeed = 0; 503 tmp.sg_ospeed = tty->termios->c_ospeed;
290 tmp.sg_erase = tty->termios->c_cc[VERASE]; 504 tmp.sg_erase = tty->termios->c_cc[VERASE];
291 tmp.sg_kill = tty->termios->c_cc[VKILL]; 505 tmp.sg_kill = tty->termios->c_cc[VKILL];
292 tmp.sg_flags = get_sgflags(tty); 506 tmp.sg_flags = get_sgflags(tty);
293 up(&tty->termios_sem); 507 mutex_unlock(&tty->termios_mutex);
294 508
295 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; 509 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
296} 510}
297 511
298static void set_sgflags(struct termios * termios, int flags) 512static void set_sgflags(struct ktermios * termios, int flags)
299{ 513{
300 termios->c_iflag = ICRNL | IXON; 514 termios->c_iflag = ICRNL | IXON;
301 termios->c_oflag = 0; 515 termios->c_oflag = 0;
@@ -336,7 +550,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
336{ 550{
337 int retval; 551 int retval;
338 struct sgttyb tmp; 552 struct sgttyb tmp;
339 struct termios termios; 553 struct ktermios termios;
340 554
341 retval = tty_check_change(tty); 555 retval = tty_check_change(tty);
342 if (retval) 556 if (retval)
@@ -345,12 +559,16 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
345 if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) 559 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
346 return -EFAULT; 560 return -EFAULT;
347 561
348 down(&tty->termios_sem); 562 mutex_lock(&tty->termios_mutex);
349 termios = *tty->termios; 563 termios = *tty->termios;
350 termios.c_cc[VERASE] = tmp.sg_erase; 564 termios.c_cc[VERASE] = tmp.sg_erase;
351 termios.c_cc[VKILL] = tmp.sg_kill; 565 termios.c_cc[VKILL] = tmp.sg_kill;
352 set_sgflags(&termios, tmp.sg_flags); 566 set_sgflags(&termios, tmp.sg_flags);
353 up(&tty->termios_sem); 567 /* Try and encode into Bfoo format */
568#ifdef BOTHER
569 tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
570#endif
571 mutex_unlock(&tty->termios_mutex);
354 change_termios(tty, &termios); 572 change_termios(tty, &termios);
355 return 0; 573 return 0;
356} 574}
@@ -422,24 +640,28 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
422 * 640 *
423 * Send a high priority character to the tty even if stopped 641 * Send a high priority character to the tty even if stopped
424 * 642 *
425 * Locking: none 643 * Locking: none for xchar method, write ordering for write method.
426 *
427 * FIXME: overlapping calls with start/stop tty lose state of tty
428 */ 644 */
429 645
430static void send_prio_char(struct tty_struct *tty, char ch) 646static int send_prio_char(struct tty_struct *tty, char ch)
431{ 647{
432 int was_stopped = tty->stopped; 648 int was_stopped = tty->stopped;
433 649
434 if (tty->driver->send_xchar) { 650 if (tty->driver->send_xchar) {
435 tty->driver->send_xchar(tty, ch); 651 tty->driver->send_xchar(tty, ch);
436 return; 652 return 0;
437 } 653 }
654
655 if (mutex_lock_interruptible(&tty->atomic_write_lock))
656 return -ERESTARTSYS;
657
438 if (was_stopped) 658 if (was_stopped)
439 start_tty(tty); 659 start_tty(tty);
440 tty->driver->write(tty, &ch, 1); 660 tty->driver->write(tty, &ch, 1);
441 if (was_stopped) 661 if (was_stopped)
442 stop_tty(tty); 662 stop_tty(tty);
663 mutex_unlock(&tty->atomic_write_lock);
664 return 0;
443} 665}
444 666
445int n_tty_ioctl(struct tty_struct * tty, struct file * file, 667int n_tty_ioctl(struct tty_struct * tty, struct file * file,
@@ -476,16 +698,33 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
476 case TIOCSLTC: 698 case TIOCSLTC:
477 return set_ltchars(real_tty, p); 699 return set_ltchars(real_tty, p);
478#endif 700#endif
701 case TCSETSF:
702 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
703 case TCSETSW:
704 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
705 case TCSETS:
706 return set_termios(real_tty, p, TERMIOS_OLD);
707#ifndef TCGETS2
479 case TCGETS: 708 case TCGETS:
480 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) 709 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
481 return -EFAULT; 710 return -EFAULT;
482 return 0; 711 return 0;
483 case TCSETSF: 712#else
713 case TCGETS:
714 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
715 return -EFAULT;
716 return 0;
717 case TCGETS2:
718 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
719 return -EFAULT;
720 return 0;
721 case TCSETSF2:
484 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); 722 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
485 case TCSETSW: 723 case TCSETSW2:
486 return set_termios(real_tty, p, TERMIOS_WAIT); 724 return set_termios(real_tty, p, TERMIOS_WAIT);
487 case TCSETS: 725 case TCSETS2:
488 return set_termios(real_tty, p, 0); 726 return set_termios(real_tty, p, 0);
727#endif
489 case TCGETA: 728 case TCGETA:
490 return get_termio(real_tty, p); 729 return get_termio(real_tty, p);
491 case TCSETAF: 730 case TCSETAF:
@@ -513,11 +752,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
513 break; 752 break;
514 case TCIOFF: 753 case TCIOFF:
515 if (STOP_CHAR(tty) != __DISABLED_CHAR) 754 if (STOP_CHAR(tty) != __DISABLED_CHAR)
516 send_prio_char(tty, STOP_CHAR(tty)); 755 return send_prio_char(tty, STOP_CHAR(tty));
517 break; 756 break;
518 case TCION: 757 case TCION:
519 if (START_CHAR(tty) != __DISABLED_CHAR) 758 if (START_CHAR(tty) != __DISABLED_CHAR)
520 send_prio_char(tty, START_CHAR(tty)); 759 return send_prio_char(tty, START_CHAR(tty));
521 break; 760 break;
522 default: 761 default:
523 return -EINVAL; 762 return -EINVAL;
@@ -592,11 +831,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
592 case TIOCSSOFTCAR: 831 case TIOCSSOFTCAR:
593 if (get_user(arg, (unsigned int __user *) arg)) 832 if (get_user(arg, (unsigned int __user *) arg))
594 return -EFAULT; 833 return -EFAULT;
595 down(&tty->termios_sem); 834 mutex_lock(&tty->termios_mutex);
596 tty->termios->c_cflag = 835 tty->termios->c_cflag =
597 ((tty->termios->c_cflag & ~CLOCAL) | 836 ((tty->termios->c_cflag & ~CLOCAL) |
598 (arg ? CLOCAL : 0)); 837 (arg ? CLOCAL : 0));
599 up(&tty->termios_sem); 838 mutex_unlock(&tty->termios_mutex);
600 return 0; 839 return 0;
601 default: 840 default:
602 return -ENOIOCTLCMD; 841 return -ENOIOCTLCMD;