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