OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [tty_ioctl.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.