sl82c105: DMA support code cleanup (take 4)
[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         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);
81 stop_waiting:
82         set_current_state(TASK_RUNNING);
83         remove_wait_queue(&tty->write_wait, &wait);
84 }
85
86 EXPORT_SYMBOL(tty_wait_until_sent);
87
88 static void unset_locked_termios(struct ktermios *termios,
89                                  struct ktermios *old,
90                                  struct ktermios *locked)
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];
109         /* FIXME: What should we do for i/ospeed */
110 }
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  */
118 static 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__
130 static 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
138 static 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
146 static 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
160 speed_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
182 EXPORT_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
196 speed_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
222 EXPORT_SYMBOL(tty_termios_input_baud_rate);
223
224 #ifdef BOTHER
225
226 /**
227  *      tty_termios_encode_baud_rate
228  *      @termios: ktermios structure holding user requested state
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 maximal back compatibility with legacy SYS5/POSIX *nix behaviour
237  *      we need to carefully set the bits when the user does not get the
238  *      desired speed. We allow small margins and preserve as much of possible
239  *      of the input intent to keep compatiblity.
240  *
241  *      Locking: Caller should hold termios lock. This is already held
242  *      when calling this function from the driver termios handler.
243  */
244
245 void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
246 {
247         int i = 0;
248         int ifound = -1, ofound = -1;
249         int iclose = ibaud/50, oclose = obaud/50;
250         int ibinput = 0;
251
252         termios->c_ispeed = ibaud;
253         termios->c_ospeed = obaud;
254
255         /* If the user asked for a precise weird speed give a precise weird
256            answer. If they asked for a Bfoo speed they many have problems
257            digesting non-exact replies so fuzz a bit */
258
259         if ((termios->c_cflag & CBAUD) == BOTHER)
260                 oclose = 0;
261         if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
262                 iclose = 0;
263         if ((termios->c_cflag >> IBSHIFT) & CBAUD)
264                 ibinput = 1;    /* An input speed was specified */
265
266         termios->c_cflag &= ~CBAUD;
267
268         do {
269                 if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
270                         termios->c_cflag |= baud_bits[i];
271                         ofound = i;
272                 }
273                 if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) {
274                         /* For the case input == output don't set IBAUD bits if the user didn't do so */
275                         if (ofound != i || ibinput)
276                                 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
277                         ifound = i;
278                 }
279         }
280         while(++i < n_baud_table);
281         if (ofound == -1)
282                 termios->c_cflag |= BOTHER;
283         /* Set exact input bits only if the input and output differ or the
284            user already did */
285         if (ifound == -1 && (ibaud != obaud  || ibinput))
286                 termios->c_cflag |= (BOTHER << IBSHIFT);
287 }
288
289 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
290
291 #endif
292
293 /**
294  *      tty_get_baud_rate       -       get tty bit rates
295  *      @tty: tty to query
296  *
297  *      Returns the baud rate as an integer for this terminal. The
298  *      termios lock must be held by the caller and the terminal bit
299  *      flags may be updated.
300  *
301  *      Locking: none
302  */
303
304 speed_t tty_get_baud_rate(struct tty_struct *tty)
305 {
306         speed_t baud = tty_termios_baud_rate(tty->termios);
307
308         if (baud == 38400 && tty->alt_speed) {
309                 if (!tty->warned) {
310                         printk(KERN_WARNING "Use of setserial/setrocket to "
311                                             "set SPD_* flags is deprecated\n");
312                         tty->warned = 1;
313                 }
314                 baud = tty->alt_speed;
315         }
316
317         return baud;
318 }
319
320 EXPORT_SYMBOL(tty_get_baud_rate);
321
322 /**
323  *      change_termios          -       update termios values
324  *      @tty: tty to update
325  *      @new_termios: desired new value
326  *
327  *      Perform updates to the termios values set on this terminal. There
328  *      is a bit of layering violation here with n_tty in terms of the
329  *      internal knowledge of this function.
330  *
331  *      Locking: termios_sem
332  */
333
334 static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
335 {
336         int canon_change;
337         struct ktermios old_termios = *tty->termios;
338         struct tty_ldisc *ld;
339         
340         /*
341          *      Perform the actual termios internal changes under lock.
342          */
343          
344
345         /* FIXME: we need to decide on some locking/ordering semantics
346            for the set_termios notification eventually */
347         mutex_lock(&tty->termios_mutex);
348
349         *tty->termios = *new_termios;
350         unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
351         canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
352         if (canon_change) {
353                 memset(&tty->read_flags, 0, sizeof tty->read_flags);
354                 tty->canon_head = tty->read_tail;
355                 tty->canon_data = 0;
356                 tty->erasing = 0;
357         }
358         
359         
360         if (canon_change && !L_ICANON(tty) && tty->read_cnt)
361                 /* Get characters left over from canonical mode. */
362                 wake_up_interruptible(&tty->read_wait);
363
364         /* See if packet mode change of state. */
365
366         if (tty->link && tty->link->packet) {
367                 int old_flow = ((old_termios.c_iflag & IXON) &&
368                                 (old_termios.c_cc[VSTOP] == '\023') &&
369                                 (old_termios.c_cc[VSTART] == '\021'));
370                 int new_flow = (I_IXON(tty) &&
371                                 STOP_CHAR(tty) == '\023' &&
372                                 START_CHAR(tty) == '\021');
373                 if (old_flow != new_flow) {
374                         tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
375                         if (new_flow)
376                                 tty->ctrl_status |= TIOCPKT_DOSTOP;
377                         else
378                                 tty->ctrl_status |= TIOCPKT_NOSTOP;
379                         wake_up_interruptible(&tty->link->read_wait);
380                 }
381         }
382            
383         if (tty->driver->set_termios)
384                 (*tty->driver->set_termios)(tty, &old_termios);
385
386         ld = tty_ldisc_ref(tty);
387         if (ld != NULL) {
388                 if (ld->set_termios)
389                         (ld->set_termios)(tty, &old_termios);
390                 tty_ldisc_deref(ld);
391         }
392         mutex_unlock(&tty->termios_mutex);
393 }
394
395 /**
396  *      set_termios             -       set termios values for a tty
397  *      @tty: terminal device
398  *      @arg: user data
399  *      @opt: option information
400  *
401  *      Helper function to prepare termios data and run neccessary other
402  *      functions before using change_termios to do the actual changes.
403  *
404  *      Locking:
405  *              Called functions take ldisc and termios_sem locks
406  */
407
408 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
409 {
410         struct ktermios tmp_termios;
411         struct tty_ldisc *ld;
412         int retval = tty_check_change(tty);
413
414         if (retval)
415                 return retval;
416
417         memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
418
419         if (opt & TERMIOS_TERMIO) {
420                 if (user_termio_to_kernel_termios(&tmp_termios,
421                                                 (struct termio __user *)arg))
422                         return -EFAULT;
423 #ifdef TCGETS2
424         } else if (opt & TERMIOS_OLD) {
425                 if (user_termios_to_kernel_termios_1(&tmp_termios,
426                                                 (struct termios __user *)arg))
427                         return -EFAULT;
428         } else {
429                 if (user_termios_to_kernel_termios(&tmp_termios,
430                                                 (struct termios2 __user *)arg))
431                         return -EFAULT;
432         }
433 #else
434         } else if (user_termios_to_kernel_termios(&tmp_termios,
435                                         (struct termios __user *)arg))
436                 return -EFAULT;
437 #endif
438
439         /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
440            so its unconditionally usable */
441         tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
442         tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
443
444         ld = tty_ldisc_ref(tty);
445         
446         if (ld != NULL) {
447                 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
448                         ld->flush_buffer(tty);
449                 tty_ldisc_deref(ld);
450         }
451         
452         if (opt & TERMIOS_WAIT) {
453                 tty_wait_until_sent(tty, 0);
454                 if (signal_pending(current))
455                         return -EINTR;
456         }
457
458         change_termios(tty, &tmp_termios);
459         return 0;
460 }
461
462 static int get_termio(struct tty_struct * tty, struct termio __user * termio)
463 {
464         if (kernel_termios_to_user_termio(termio, tty->termios))
465                 return -EFAULT;
466         return 0;
467 }
468
469 static unsigned long inq_canon(struct tty_struct * tty)
470 {
471         int nr, head, tail;
472
473         if (!tty->canon_data || !tty->read_buf)
474                 return 0;
475         head = tty->canon_head;
476         tail = tty->read_tail;
477         nr = (head - tail) & (N_TTY_BUF_SIZE-1);
478         /* Skip EOF-chars.. */
479         while (head != tail) {
480                 if (test_bit(tail, tty->read_flags) &&
481                     tty->read_buf[tail] == __DISABLED_CHAR)
482                         nr--;
483                 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
484         }
485         return nr;
486 }
487
488 #ifdef TIOCGETP
489 /*
490  * These are deprecated, but there is limited support..
491  *
492  * The "sg_flags" translation is a joke..
493  */
494 static int get_sgflags(struct tty_struct * tty)
495 {
496         int flags = 0;
497
498         if (!(tty->termios->c_lflag & ICANON)) {
499                 if (tty->termios->c_lflag & ISIG)
500                         flags |= 0x02;          /* cbreak */
501                 else
502                         flags |= 0x20;          /* raw */
503         }
504         if (tty->termios->c_lflag & ECHO)
505                 flags |= 0x08;                  /* echo */
506         if (tty->termios->c_oflag & OPOST)
507                 if (tty->termios->c_oflag & ONLCR)
508                         flags |= 0x10;          /* crmod */
509         return flags;
510 }
511
512 static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
513 {
514         struct sgttyb tmp;
515
516         mutex_lock(&tty->termios_mutex);
517         tmp.sg_ispeed = tty->termios->c_ispeed;
518         tmp.sg_ospeed = tty->termios->c_ospeed;
519         tmp.sg_erase = tty->termios->c_cc[VERASE];
520         tmp.sg_kill = tty->termios->c_cc[VKILL];
521         tmp.sg_flags = get_sgflags(tty);
522         mutex_unlock(&tty->termios_mutex);
523         
524         return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
525 }
526
527 static void set_sgflags(struct ktermios * termios, int flags)
528 {
529         termios->c_iflag = ICRNL | IXON;
530         termios->c_oflag = 0;
531         termios->c_lflag = ISIG | ICANON;
532         if (flags & 0x02) {     /* cbreak */
533                 termios->c_iflag = 0;
534                 termios->c_lflag &= ~ICANON;
535         }
536         if (flags & 0x08) {             /* echo */
537                 termios->c_lflag |= ECHO | ECHOE | ECHOK |
538                                     ECHOCTL | ECHOKE | IEXTEN;
539         }
540         if (flags & 0x10) {             /* crmod */
541                 termios->c_oflag |= OPOST | ONLCR;
542         }
543         if (flags & 0x20) {     /* raw */
544                 termios->c_iflag = 0;
545                 termios->c_lflag &= ~(ISIG | ICANON);
546         }
547         if (!(termios->c_lflag & ICANON)) {
548                 termios->c_cc[VMIN] = 1;
549                 termios->c_cc[VTIME] = 0;
550         }
551 }
552
553 /**
554  *      set_sgttyb              -       set legacy terminal values
555  *      @tty: tty structure
556  *      @sgttyb: pointer to old style terminal structure
557  *
558  *      Updates a terminal from the legacy BSD style terminal information
559  *      structure.
560  *
561  *      Locking: termios_sem
562  */
563
564 static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
565 {
566         int retval;
567         struct sgttyb tmp;
568         struct ktermios termios;
569
570         retval = tty_check_change(tty);
571         if (retval)
572                 return retval;
573         
574         if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
575                 return -EFAULT;
576
577         mutex_lock(&tty->termios_mutex);
578         termios =  *tty->termios;
579         termios.c_cc[VERASE] = tmp.sg_erase;
580         termios.c_cc[VKILL] = tmp.sg_kill;
581         set_sgflags(&termios, tmp.sg_flags);
582         /* Try and encode into Bfoo format */
583 #ifdef BOTHER
584         tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
585 #endif
586         mutex_unlock(&tty->termios_mutex);
587         change_termios(tty, &termios);
588         return 0;
589 }
590 #endif
591
592 #ifdef TIOCGETC
593 static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
594 {
595         struct tchars tmp;
596
597         tmp.t_intrc = tty->termios->c_cc[VINTR];
598         tmp.t_quitc = tty->termios->c_cc[VQUIT];
599         tmp.t_startc = tty->termios->c_cc[VSTART];
600         tmp.t_stopc = tty->termios->c_cc[VSTOP];
601         tmp.t_eofc = tty->termios->c_cc[VEOF];
602         tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
603         return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
604 }
605
606 static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
607 {
608         struct tchars tmp;
609
610         if (copy_from_user(&tmp, tchars, sizeof(tmp)))
611                 return -EFAULT;
612         tty->termios->c_cc[VINTR] = tmp.t_intrc;
613         tty->termios->c_cc[VQUIT] = tmp.t_quitc;
614         tty->termios->c_cc[VSTART] = tmp.t_startc;
615         tty->termios->c_cc[VSTOP] = tmp.t_stopc;
616         tty->termios->c_cc[VEOF] = tmp.t_eofc;
617         tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
618         return 0;
619 }
620 #endif
621
622 #ifdef TIOCGLTC
623 static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
624 {
625         struct ltchars tmp;
626
627         tmp.t_suspc = tty->termios->c_cc[VSUSP];
628         tmp.t_dsuspc = tty->termios->c_cc[VSUSP];       /* what is dsuspc anyway? */
629         tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
630         tmp.t_flushc = tty->termios->c_cc[VEOL2];       /* what is flushc anyway? */
631         tmp.t_werasc = tty->termios->c_cc[VWERASE];
632         tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
633         return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
634 }
635
636 static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
637 {
638         struct ltchars tmp;
639
640         if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
641                 return -EFAULT;
642
643         tty->termios->c_cc[VSUSP] = tmp.t_suspc;
644         tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;       /* what is dsuspc anyway? */
645         tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
646         tty->termios->c_cc[VEOL2] = tmp.t_flushc;       /* what is flushc anyway? */
647         tty->termios->c_cc[VWERASE] = tmp.t_werasc;
648         tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
649         return 0;
650 }
651 #endif
652
653 /**
654  *      send_prio_char          -       send priority character
655  *
656  *      Send a high priority character to the tty even if stopped
657  *
658  *      Locking: none for xchar method, write ordering for write method.
659  */
660
661 static int send_prio_char(struct tty_struct *tty, char ch)
662 {
663         int     was_stopped = tty->stopped;
664
665         if (tty->driver->send_xchar) {
666                 tty->driver->send_xchar(tty, ch);
667                 return 0;
668         }
669
670         if (mutex_lock_interruptible(&tty->atomic_write_lock))
671                 return -ERESTARTSYS;
672
673         if (was_stopped)
674                 start_tty(tty);
675         tty->driver->write(tty, &ch, 1);
676         if (was_stopped)
677                 stop_tty(tty);
678         mutex_unlock(&tty->atomic_write_lock);
679         return 0;
680 }
681
682 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
683                        unsigned int cmd, unsigned long arg)
684 {
685         struct tty_struct * real_tty;
686         void __user *p = (void __user *)arg;
687         int retval;
688         struct tty_ldisc *ld;
689
690         if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
691             tty->driver->subtype == PTY_TYPE_MASTER)
692                 real_tty = tty->link;
693         else
694                 real_tty = tty;
695
696         switch (cmd) {
697 #ifdef TIOCGETP
698                 case TIOCGETP:
699                         return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
700                 case TIOCSETP:
701                 case TIOCSETN:
702                         return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
703 #endif
704 #ifdef TIOCGETC
705                 case TIOCGETC:
706                         return get_tchars(real_tty, p);
707                 case TIOCSETC:
708                         return set_tchars(real_tty, p);
709 #endif
710 #ifdef TIOCGLTC
711                 case TIOCGLTC:
712                         return get_ltchars(real_tty, p);
713                 case TIOCSLTC:
714                         return set_ltchars(real_tty, p);
715 #endif
716                 case TCSETSF:
717                         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
718                 case TCSETSW:
719                         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
720                 case TCSETS:
721                         return set_termios(real_tty, p, TERMIOS_OLD);
722 #ifndef TCGETS2
723                 case TCGETS:
724                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
725                                 return -EFAULT;
726                         return 0;
727 #else
728                 case TCGETS:
729                         if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
730                                 return -EFAULT;
731                         return 0;
732                 case TCGETS2:
733                         if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
734                                 return -EFAULT;
735                         return 0;
736                 case TCSETSF2:
737                         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
738                 case TCSETSW2:
739                         return set_termios(real_tty, p, TERMIOS_WAIT);
740                 case TCSETS2:
741                         return set_termios(real_tty, p, 0);
742 #endif
743                 case TCGETA:
744                         return get_termio(real_tty, p);
745                 case TCSETAF:
746                         return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
747                 case TCSETAW:
748                         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
749                 case TCSETA:
750                         return set_termios(real_tty, p, TERMIOS_TERMIO);
751                 case TCXONC:
752                         retval = tty_check_change(tty);
753                         if (retval)
754                                 return retval;
755                         switch (arg) {
756                         case TCOOFF:
757                                 if (!tty->flow_stopped) {
758                                         tty->flow_stopped = 1;
759                                         stop_tty(tty);
760                                 }
761                                 break;
762                         case TCOON:
763                                 if (tty->flow_stopped) {
764                                         tty->flow_stopped = 0;
765                                         start_tty(tty);
766                                 }
767                                 break;
768                         case TCIOFF:
769                                 if (STOP_CHAR(tty) != __DISABLED_CHAR)
770                                         return send_prio_char(tty, STOP_CHAR(tty));
771                                 break;
772                         case TCION:
773                                 if (START_CHAR(tty) != __DISABLED_CHAR)
774                                         return send_prio_char(tty, START_CHAR(tty));
775                                 break;
776                         default:
777                                 return -EINVAL;
778                         }
779                         return 0;
780                 case TCFLSH:
781                         retval = tty_check_change(tty);
782                         if (retval)
783                                 return retval;
784                                 
785                         ld = tty_ldisc_ref(tty);
786                         switch (arg) {
787                         case TCIFLUSH:
788                                 if (ld && ld->flush_buffer)
789                                         ld->flush_buffer(tty);
790                                 break;
791                         case TCIOFLUSH:
792                                 if (ld && ld->flush_buffer)
793                                         ld->flush_buffer(tty);
794                                 /* fall through */
795                         case TCOFLUSH:
796                                 if (tty->driver->flush_buffer)
797                                         tty->driver->flush_buffer(tty);
798                                 break;
799                         default:
800                                 tty_ldisc_deref(ld);
801                                 return -EINVAL;
802                         }
803                         tty_ldisc_deref(ld);
804                         return 0;
805                 case TIOCOUTQ:
806                         return put_user(tty->driver->chars_in_buffer ?
807                                         tty->driver->chars_in_buffer(tty) : 0,
808                                         (int __user *) arg);
809                 case TIOCINQ:
810                         retval = tty->read_cnt;
811                         if (L_ICANON(tty))
812                                 retval = inq_canon(tty);
813                         return put_user(retval, (unsigned int __user *) arg);
814                 case TIOCGLCKTRMIOS:
815                         if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
816                                 return -EFAULT;
817                         return 0;
818
819                 case TIOCSLCKTRMIOS:
820                         if (!capable(CAP_SYS_ADMIN))
821                                 return -EPERM;
822                         if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
823                                 return -EFAULT;
824                         return 0;
825
826                 case TIOCPKT:
827                 {
828                         int pktmode;
829
830                         if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
831                             tty->driver->subtype != PTY_TYPE_MASTER)
832                                 return -ENOTTY;
833                         if (get_user(pktmode, (int __user *) arg))
834                                 return -EFAULT;
835                         if (pktmode) {
836                                 if (!tty->packet) {
837                                         tty->packet = 1;
838                                         tty->link->ctrl_status = 0;
839                                 }
840                         } else
841                                 tty->packet = 0;
842                         return 0;
843                 }
844                 case TIOCGSOFTCAR:
845                         return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
846                 case TIOCSSOFTCAR:
847                         if (get_user(arg, (unsigned int __user *) arg))
848                                 return -EFAULT;
849                         mutex_lock(&tty->termios_mutex);
850                         tty->termios->c_cflag =
851                                 ((tty->termios->c_cflag & ~CLOCAL) |
852                                  (arg ? CLOCAL : 0));
853                         mutex_unlock(&tty->termios_mutex);
854                         return 0;
855                 default:
856                         return -ENOIOCTLCMD;
857                 }
858 }
859
860 EXPORT_SYMBOL(n_tty_ioctl);