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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [n_tty.c] - Blame information for rev 1275

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * n_tty.c --- implements the N_TTY line discipline.
3
 *
4
 * This code used to be in tty_io.c, but things are getting hairy
5
 * enough that it made sense to split things off.  (The N_TTY
6
 * processing has changed so much that it's hardly recognizable,
7
 * anyway...)
8
 *
9
 * Note that the open routine for N_TTY is guaranteed never to return
10
 * an error.  This is because Linux will fall back to setting a line
11
 * to N_TTY if it can not switch to any other line discipline.
12
 *
13
 * Written by Theodore Ts'o, Copyright 1994.
14
 *
15
 * This file also contains code originally written by Linus Torvalds,
16
 * Copyright 1991, 1992, 1993, and by Julian Cowley, Copyright 1994.
17
 *
18
 * This file may be redistributed under the terms of the GNU General Public
19
 * License.
20
 *
21
 * Reduced memory usage for older ARM systems  - Russell King.
22
 *
23
 * 2000/01/20   Fixed SMP locking on put_tty_queue using bits of
24
 *              the patch by Andrew J. Kroll <ag784@freenet.buffalo.edu>
25
 *              who actually finally proved there really was a race.
26
 *
27
 * 2002/03/18   Implemented n_tty_wakeup to send SIGIO POLL_OUTs to
28
 *              waiting writing processes-Sapan Bhatia <sapan@corewars.org>.
29
 *              Also fixed a bug in BLOCKING mode where write_chan returns
30
 *              EAGAIN
31
 */
32
 
33
#include <linux/types.h>
34
#include <linux/major.h>
35
#include <linux/errno.h>
36
#include <linux/signal.h>
37
#include <linux/fcntl.h>
38
#include <linux/sched.h>
39
#include <linux/interrupt.h>
40
#include <linux/tty.h>
41
#include <linux/timer.h>
42
#include <linux/ctype.h>
43
#include <linux/kd.h>
44
#include <linux/mm.h>
45
#include <linux/string.h>
46
#include <linux/slab.h>
47
#include <linux/poll.h>
48
 
49
#include <asm/uaccess.h>
50
#include <asm/system.h>
51
#include <asm/bitops.h>
52
 
53
#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
54
#define SYSCONS_DEV  MKDEV(TTYAUX_MAJOR,1)
55
 
56
#ifndef MIN
57
#define MIN(a,b)        ((a) < (b) ? (a) : (b))
58
#endif
59
 
60
/* number of characters left in xmit buffer before select has we have room */
61
#define WAKEUP_CHARS 256
62
 
63
/*
64
 * This defines the low- and high-watermarks for throttling and
65
 * unthrottling the TTY driver.  These watermarks are used for
66
 * controlling the space in the read buffer.
67
 */
68
#define TTY_THRESHOLD_THROTTLE          128 /* now based on remaining room */
69
#define TTY_THRESHOLD_UNTHROTTLE        128
70
 
71
static inline unsigned char *alloc_buf(void)
72
{
73
        unsigned char *p;
74
        int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
75
 
76
        if (PAGE_SIZE != N_TTY_BUF_SIZE) {
77
                p = kmalloc(N_TTY_BUF_SIZE, prio);
78
                if (p)
79
                        memset(p, 0, N_TTY_BUF_SIZE);
80
        } else
81
                p = (unsigned char *)get_zeroed_page(prio);
82
 
83
        return p;
84
}
85
 
86
static inline void free_buf(unsigned char *buf)
87
{
88
        if (PAGE_SIZE != N_TTY_BUF_SIZE)
89
                kfree(buf);
90
        else
91
                free_page((unsigned long) buf);
92
}
93
 
94
static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
95
{
96
        if (tty->read_cnt < N_TTY_BUF_SIZE) {
97
                tty->read_buf[tty->read_head] = c;
98
                tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
99
                tty->read_cnt++;
100
        }
101
}
102
 
103
static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
104
{
105
        unsigned long flags;
106
        /*
107
         *      The problem of stomping on the buffers ends here.
108
         *      Why didn't anyone see this one coming? --AJK
109
        */
110
        spin_lock_irqsave(&tty->read_lock, flags);
111
        put_tty_queue_nolock(c, tty);
112
        spin_unlock_irqrestore(&tty->read_lock, flags);
113
}
114
 
115
/*
116
 * Check whether to call the driver.unthrottle function.
117
 * We test the TTY_THROTTLED bit first so that it always
118
 * indicates the current state.
119
 */
120
static void check_unthrottle(struct tty_struct * tty)
121
{
122
        if (tty->count &&
123
            test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
124
            tty->driver.unthrottle)
125
                tty->driver.unthrottle(tty);
126
}
127
 
128
/*
129
 * Reset the read buffer counters, clear the flags,
130
 * and make sure the driver is unthrottled. Called
131
 * from n_tty_open() and n_tty_flush_buffer().
132
 */
133
static void reset_buffer_flags(struct tty_struct *tty)
134
{
135
        unsigned long flags;
136
 
137
        spin_lock_irqsave(&tty->read_lock, flags);
138
        tty->read_head = tty->read_tail = tty->read_cnt = 0;
139
        spin_unlock_irqrestore(&tty->read_lock, flags);
140
        tty->canon_head = tty->canon_data = tty->erasing = 0;
141
        memset(&tty->read_flags, 0, sizeof tty->read_flags);
142
        check_unthrottle(tty);
143
}
144
 
145
/*
146
 * Flush the input buffer
147
 */
148
void n_tty_flush_buffer(struct tty_struct * tty)
149
{
150
        /* clear everything and unthrottle the driver */
151
        reset_buffer_flags(tty);
152
 
153
        if (!tty->link)
154
                return;
155
 
156
        if (tty->link->packet) {
157
                tty->ctrl_status |= TIOCPKT_FLUSHREAD;
158
                wake_up_interruptible(&tty->link->read_wait);
159
        }
160
}
161
 
162
/*
163
 * Return number of characters buffered to be delivered to user
164
 */
165
ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
166
{
167
        unsigned long flags;
168
        ssize_t n = 0;
169
 
170
        spin_lock_irqsave(&tty->read_lock, flags);
171
        if (!tty->icanon) {
172
                n = tty->read_cnt;
173
        } else if (tty->canon_data) {
174
                n = (tty->canon_head > tty->read_tail) ?
175
                        tty->canon_head - tty->read_tail :
176
                        tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
177
        }
178
        spin_unlock_irqrestore(&tty->read_lock, flags);
179
        return n;
180
}
181
 
182
/*
183
 * Perform OPOST processing.  Returns -1 when the output device is
184
 * full and the character must be retried.
185
 */
186
static int opost(unsigned char c, struct tty_struct *tty)
187
{
188
        int     space, spaces;
189
 
190
        space = tty->driver.write_room(tty);
191
        if (!space)
192
                return -1;
193
 
194
        if (O_OPOST(tty)) {
195
                switch (c) {
196
                case '\n':
197
                        if (O_ONLRET(tty))
198
                                tty->column = 0;
199
                        if (O_ONLCR(tty)) {
200
                                if (space < 2)
201
                                        return -1;
202
                                tty->driver.put_char(tty, '\r');
203
                                tty->column = 0;
204
                        }
205
                        tty->canon_column = tty->column;
206
                        break;
207
                case '\r':
208
                        if (O_ONOCR(tty) && tty->column == 0)
209
                                return 0;
210
                        if (O_OCRNL(tty)) {
211
                                c = '\n';
212
                                if (O_ONLRET(tty))
213
                                        tty->canon_column = tty->column = 0;
214
                                break;
215
                        }
216
                        tty->canon_column = tty->column = 0;
217
                        break;
218
                case '\t':
219
                        spaces = 8 - (tty->column & 7);
220
                        if (O_TABDLY(tty) == XTABS) {
221
                                if (space < spaces)
222
                                        return -1;
223
                                tty->column += spaces;
224
                                tty->driver.write(tty, 0, "        ", spaces);
225
                                return 0;
226
                        }
227
                        tty->column += spaces;
228
                        break;
229
                case '\b':
230
                        if (tty->column > 0)
231
                                tty->column--;
232
                        break;
233
                default:
234
                        if (O_OLCUC(tty))
235
                                c = toupper(c);
236
                        if (!iscntrl(c))
237
                                tty->column++;
238
                        break;
239
                }
240
        }
241
        tty->driver.put_char(tty, c);
242
        return 0;
243
}
244
 
245
/*
246
 * opost_block --- to speed up block console writes, among other
247
 * things.
248
 */
249
static ssize_t opost_block(struct tty_struct * tty,
250
                       const unsigned char * inbuf, unsigned int nr)
251
{
252
        char    buf[80];
253
        int     space;
254
        int     i;
255
        char    *cp;
256
 
257
        space = tty->driver.write_room(tty);
258
        if (!space)
259
                return 0;
260
        if (nr > space)
261
                nr = space;
262
        if (nr > sizeof(buf))
263
            nr = sizeof(buf);
264
 
265
        if (copy_from_user(buf, inbuf, nr))
266
                return -EFAULT;
267
 
268
        for (i = 0, cp = buf; i < nr; i++, cp++) {
269
                switch (*cp) {
270
                case '\n':
271
                        if (O_ONLRET(tty))
272
                                tty->column = 0;
273
                        if (O_ONLCR(tty))
274
                                goto break_out;
275
                        tty->canon_column = tty->column;
276
                        break;
277
                case '\r':
278
                        if (O_ONOCR(tty) && tty->column == 0)
279
                                goto break_out;
280
                        if (O_OCRNL(tty)) {
281
                                *cp = '\n';
282
                                if (O_ONLRET(tty))
283
                                        tty->canon_column = tty->column = 0;
284
                                break;
285
                        }
286
                        tty->canon_column = tty->column = 0;
287
                        break;
288
                case '\t':
289
                        goto break_out;
290
                case '\b':
291
                        if (tty->column > 0)
292
                                tty->column--;
293
                        break;
294
                default:
295
                        if (O_OLCUC(tty))
296
                                *cp = toupper(*cp);
297
                        if (!iscntrl(*cp))
298
                                tty->column++;
299
                        break;
300
                }
301
        }
302
break_out:
303
        if (tty->driver.flush_chars)
304
                tty->driver.flush_chars(tty);
305
        i = tty->driver.write(tty, 0, buf, i);
306
        return i;
307
}
308
 
309
 
310
 
311
static inline void put_char(unsigned char c, struct tty_struct *tty)
312
{
313
        tty->driver.put_char(tty, c);
314
}
315
 
316
/* Must be called only when L_ECHO(tty) is true. */
317
 
318
static void echo_char(unsigned char c, struct tty_struct *tty)
319
{
320
        if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
321
                put_char('^', tty);
322
                put_char(c ^ 0100, tty);
323
                tty->column += 2;
324
        } else
325
                opost(c, tty);
326
}
327
 
328
static inline void finish_erasing(struct tty_struct *tty)
329
{
330
        if (tty->erasing) {
331
                put_char('/', tty);
332
                tty->column += 2;
333
                tty->erasing = 0;
334
        }
335
}
336
 
337
static void eraser(unsigned char c, struct tty_struct *tty)
338
{
339
        enum { ERASE, WERASE, KILL } kill_type;
340
        int head, seen_alnums;
341
        unsigned long flags;
342
 
343
        if (tty->read_head == tty->canon_head) {
344
                /* opost('\a', tty); */         /* what do you think? */
345
                return;
346
        }
347
        if (c == ERASE_CHAR(tty))
348
                kill_type = ERASE;
349
        else if (c == WERASE_CHAR(tty))
350
                kill_type = WERASE;
351
        else {
352
                if (!L_ECHO(tty)) {
353
                        spin_lock_irqsave(&tty->read_lock, flags);
354
                        tty->read_cnt -= ((tty->read_head - tty->canon_head) &
355
                                          (N_TTY_BUF_SIZE - 1));
356
                        tty->read_head = tty->canon_head;
357
                        spin_unlock_irqrestore(&tty->read_lock, flags);
358
                        return;
359
                }
360
                if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
361
                        spin_lock_irqsave(&tty->read_lock, flags);
362
                        tty->read_cnt -= ((tty->read_head - tty->canon_head) &
363
                                          (N_TTY_BUF_SIZE - 1));
364
                        tty->read_head = tty->canon_head;
365
                        spin_unlock_irqrestore(&tty->read_lock, flags);
366
                        finish_erasing(tty);
367
                        echo_char(KILL_CHAR(tty), tty);
368
                        /* Add a newline if ECHOK is on and ECHOKE is off. */
369
                        if (L_ECHOK(tty))
370
                                opost('\n', tty);
371
                        return;
372
                }
373
                kill_type = KILL;
374
        }
375
 
376
        seen_alnums = 0;
377
        while (tty->read_head != tty->canon_head) {
378
                head = (tty->read_head - 1) & (N_TTY_BUF_SIZE-1);
379
                c = tty->read_buf[head];
380
                if (kill_type == WERASE) {
381
                        /* Equivalent to BSD's ALTWERASE. */
382
                        if (isalnum(c) || c == '_')
383
                                seen_alnums++;
384
                        else if (seen_alnums)
385
                                break;
386
                }
387
                spin_lock_irqsave(&tty->read_lock, flags);
388
                tty->read_head = head;
389
                tty->read_cnt--;
390
                spin_unlock_irqrestore(&tty->read_lock, flags);
391
                if (L_ECHO(tty)) {
392
                        if (L_ECHOPRT(tty)) {
393
                                if (!tty->erasing) {
394
                                        put_char('\\', tty);
395
                                        tty->column++;
396
                                        tty->erasing = 1;
397
                                }
398
                                echo_char(c, tty);
399
                        } else if (kill_type == ERASE && !L_ECHOE(tty)) {
400
                                echo_char(ERASE_CHAR(tty), tty);
401
                        } else if (c == '\t') {
402
                                unsigned int col = tty->canon_column;
403
                                unsigned long tail = tty->canon_head;
404
 
405
                                /* Find the column of the last char. */
406
                                while (tail != tty->read_head) {
407
                                        c = tty->read_buf[tail];
408
                                        if (c == '\t')
409
                                                col = (col | 7) + 1;
410
                                        else if (iscntrl(c)) {
411
                                                if (L_ECHOCTL(tty))
412
                                                        col += 2;
413
                                        } else
414
                                                col++;
415
                                        tail = (tail+1) & (N_TTY_BUF_SIZE-1);
416
                                }
417
 
418
                                /* should never happen */
419
                                if (tty->column > 0x80000000)
420
                                        tty->column = 0;
421
 
422
                                /* Now backup to that column. */
423
                                while (tty->column > col) {
424
                                        /* Can't use opost here. */
425
                                        put_char('\b', tty);
426
                                        if (tty->column > 0)
427
                                                tty->column--;
428
                                }
429
                        } else {
430
                                if (iscntrl(c) && L_ECHOCTL(tty)) {
431
                                        put_char('\b', tty);
432
                                        put_char(' ', tty);
433
                                        put_char('\b', tty);
434
                                        if (tty->column > 0)
435
                                                tty->column--;
436
                                }
437
                                if (!iscntrl(c) || L_ECHOCTL(tty)) {
438
                                        put_char('\b', tty);
439
                                        put_char(' ', tty);
440
                                        put_char('\b', tty);
441
                                        if (tty->column > 0)
442
                                                tty->column--;
443
                                }
444
                        }
445
                }
446
                if (kill_type == ERASE)
447
                        break;
448
        }
449
        if (tty->read_head == tty->canon_head)
450
                finish_erasing(tty);
451
}
452
 
453
static inline void isig(int sig, struct tty_struct *tty, int flush)
454
{
455
        if (tty->pgrp > 0)
456
                kill_pg(tty->pgrp, sig, 1);
457
        if (flush || !L_NOFLSH(tty)) {
458
                n_tty_flush_buffer(tty);
459
                if (tty->driver.flush_buffer)
460
                        tty->driver.flush_buffer(tty);
461
        }
462
}
463
 
464
static inline void n_tty_receive_break(struct tty_struct *tty)
465
{
466
        if (I_IGNBRK(tty))
467
                return;
468
        if (I_BRKINT(tty)) {
469
                isig(SIGINT, tty, 1);
470
                return;
471
        }
472
        if (I_PARMRK(tty)) {
473
                put_tty_queue('\377', tty);
474
                put_tty_queue('\0', tty);
475
        }
476
        put_tty_queue('\0', tty);
477
        wake_up_interruptible(&tty->read_wait);
478
}
479
 
480
static inline void n_tty_receive_overrun(struct tty_struct *tty)
481
{
482
        char buf[64];
483
 
484
        tty->num_overrun++;
485
        if (time_before(tty->overrun_time, jiffies - HZ)) {
486
                printk("%s: %d input overrun(s)\n", tty_name(tty, buf),
487
                       tty->num_overrun);
488
                tty->overrun_time = jiffies;
489
                tty->num_overrun = 0;
490
        }
491
}
492
 
493
static inline void n_tty_receive_parity_error(struct tty_struct *tty,
494
                                              unsigned char c)
495
{
496
        if (I_IGNPAR(tty)) {
497
                return;
498
        }
499
        if (I_PARMRK(tty)) {
500
                put_tty_queue('\377', tty);
501
                put_tty_queue('\0', tty);
502
                put_tty_queue(c, tty);
503
        } else  if (I_INPCK(tty))
504
                put_tty_queue('\0', tty);
505
        else
506
                put_tty_queue(c, tty);
507
        wake_up_interruptible(&tty->read_wait);
508
}
509
 
510
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
511
{
512
        unsigned long flags;
513
 
514
        if (tty->raw) {
515
                put_tty_queue(c, tty);
516
                return;
517
        }
518
 
519
        if (tty->stopped && !tty->flow_stopped &&
520
            I_IXON(tty) && I_IXANY(tty)) {
521
                start_tty(tty);
522
                return;
523
        }
524
 
525
        if (I_ISTRIP(tty))
526
                c &= 0x7f;
527
        if (I_IUCLC(tty) && L_IEXTEN(tty))
528
                c=tolower(c);
529
 
530
        if (tty->closing) {
531
                if (I_IXON(tty)) {
532
                        if (c == START_CHAR(tty))
533
                                start_tty(tty);
534
                        else if (c == STOP_CHAR(tty))
535
                                stop_tty(tty);
536
                }
537
                return;
538
        }
539
 
540
        /*
541
         * If the previous character was LNEXT, or we know that this
542
         * character is not one of the characters that we'll have to
543
         * handle specially, do shortcut processing to speed things
544
         * up.
545
         */
546
        if (!test_bit(c, &tty->process_char_map) || tty->lnext) {
547
                finish_erasing(tty);
548
                tty->lnext = 0;
549
                if (L_ECHO(tty)) {
550
                        if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
551
                                put_char('\a', tty); /* beep if no space */
552
                                return;
553
                        }
554
                        /* Record the column of first canon char. */
555
                        if (tty->canon_head == tty->read_head)
556
                                tty->canon_column = tty->column;
557
                        echo_char(c, tty);
558
                }
559
                if (I_PARMRK(tty) && c == (unsigned char) '\377')
560
                        put_tty_queue(c, tty);
561
                put_tty_queue(c, tty);
562
                return;
563
        }
564
 
565
        if (c == '\r') {
566
                if (I_IGNCR(tty))
567
                        return;
568
                if (I_ICRNL(tty))
569
                        c = '\n';
570
        } else if (c == '\n' && I_INLCR(tty))
571
                c = '\r';
572
        if (I_IXON(tty)) {
573
                if (c == START_CHAR(tty)) {
574
                        start_tty(tty);
575
                        return;
576
                }
577
                if (c == STOP_CHAR(tty)) {
578
                        stop_tty(tty);
579
                        return;
580
                }
581
        }
582
        if (L_ISIG(tty)) {
583
                int signal;
584
                signal = SIGINT;
585
                if (c == INTR_CHAR(tty))
586
                        goto send_signal;
587
                signal = SIGQUIT;
588
                if (c == QUIT_CHAR(tty))
589
                        goto send_signal;
590
                signal = SIGTSTP;
591
                if (c == SUSP_CHAR(tty)) {
592
send_signal:
593
                        isig(signal, tty, 0);
594
                        return;
595
                }
596
        }
597
        if (tty->icanon) {
598
                if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
599
                    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
600
                        eraser(c, tty);
601
                        return;
602
                }
603
                if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
604
                        tty->lnext = 1;
605
                        if (L_ECHO(tty)) {
606
                                finish_erasing(tty);
607
                                if (L_ECHOCTL(tty)) {
608
                                        put_char('^', tty);
609
                                        put_char('\b', tty);
610
                                }
611
                        }
612
                        return;
613
                }
614
                if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
615
                    L_IEXTEN(tty)) {
616
                        unsigned long tail = tty->canon_head;
617
 
618
                        finish_erasing(tty);
619
                        echo_char(c, tty);
620
                        opost('\n', tty);
621
                        while (tail != tty->read_head) {
622
                                echo_char(tty->read_buf[tail], tty);
623
                                tail = (tail+1) & (N_TTY_BUF_SIZE-1);
624
                        }
625
                        return;
626
                }
627
                if (c == '\n') {
628
                        if (L_ECHO(tty) || L_ECHONL(tty)) {
629
                                if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
630
                                        put_char('\a', tty);
631
                                        return;
632
                                }
633
                                opost('\n', tty);
634
                        }
635
                        goto handle_newline;
636
                }
637
                if (c == EOF_CHAR(tty)) {
638
                        if (tty->canon_head != tty->read_head)
639
                                set_bit(TTY_PUSH, &tty->flags);
640
                        c = __DISABLED_CHAR;
641
                        goto handle_newline;
642
                }
643
                if ((c == EOL_CHAR(tty)) ||
644
                    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
645
                        /*
646
                         * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
647
                         */
648
                        if (L_ECHO(tty)) {
649
                                if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
650
                                        put_char('\a', tty);
651
                                        return;
652
                                }
653
                                /* Record the column of first canon char. */
654
                                if (tty->canon_head == tty->read_head)
655
                                        tty->canon_column = tty->column;
656
                                echo_char(c, tty);
657
                        }
658
                        /*
659
                         * XXX does PARMRK doubling happen for
660
                         * EOL_CHAR and EOL2_CHAR?
661
                         */
662
                        if (I_PARMRK(tty) && c == (unsigned char) '\377')
663
                                put_tty_queue(c, tty);
664
 
665
                handle_newline:
666
                        spin_lock_irqsave(&tty->read_lock, flags);
667
                        set_bit(tty->read_head, &tty->read_flags);
668
                        put_tty_queue_nolock(c, tty);
669
                        tty->canon_head = tty->read_head;
670
                        tty->canon_data++;
671
                        spin_unlock_irqrestore(&tty->read_lock, flags);
672
                        kill_fasync(&tty->fasync, SIGIO, POLL_IN);
673
                        if (waitqueue_active(&tty->read_wait))
674
                                wake_up_interruptible(&tty->read_wait);
675
                        return;
676
                }
677
        }
678
 
679
        finish_erasing(tty);
680
        if (L_ECHO(tty)) {
681
                if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
682
                        put_char('\a', tty); /* beep if no space */
683
                        return;
684
                }
685
                if (c == '\n')
686
                        opost('\n', tty);
687
                else {
688
                        /* Record the column of first canon char. */
689
                        if (tty->canon_head == tty->read_head)
690
                                tty->canon_column = tty->column;
691
                        echo_char(c, tty);
692
                }
693
        }
694
 
695
        if (I_PARMRK(tty) && c == (unsigned char) '\377')
696
                put_tty_queue(c, tty);
697
 
698
        put_tty_queue(c, tty);
699
}
700
 
701
static int n_tty_receive_room(struct tty_struct *tty)
702
{
703
        int     left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
704
 
705
        /*
706
         * If we are doing input canonicalization, and there are no
707
         * pending newlines, let characters through without limit, so
708
         * that erase characters will be handled.  Other excess
709
         * characters will be beeped.
710
         */
711
        if (tty->icanon && !tty->canon_data)
712
                return N_TTY_BUF_SIZE;
713
 
714
        if (left > 0)
715
                return left;
716
        return 0;
717
}
718
 
719
/*
720
 * Required for the ptys, serial driver etc. since processes
721
 * that attach themselves to the master and rely on ASYNC
722
 * IO must be woken up
723
 */
724
 
725
static void n_tty_write_wakeup(struct tty_struct *tty)
726
{
727
        if (tty->fasync)
728
        {
729
                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
730
                kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
731
        }
732
        return;
733
}
734
 
735
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
736
                              char *fp, int count)
737
{
738
        const unsigned char *p;
739
        char *f, flags = TTY_NORMAL;
740
        int     i;
741
        char    buf[64];
742
        unsigned long cpuflags;
743
 
744
        if (!tty->read_buf)
745
                return;
746
 
747
        if (tty->real_raw) {
748
                spin_lock_irqsave(&tty->read_lock, cpuflags);
749
                i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
750
                                   N_TTY_BUF_SIZE - tty->read_head));
751
                memcpy(tty->read_buf + tty->read_head, cp, i);
752
                tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
753
                tty->read_cnt += i;
754
                cp += i;
755
                count -= i;
756
 
757
                i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
758
                               N_TTY_BUF_SIZE - tty->read_head));
759
                memcpy(tty->read_buf + tty->read_head, cp, i);
760
                tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
761
                tty->read_cnt += i;
762
                spin_unlock_irqrestore(&tty->read_lock, cpuflags);
763
        } else {
764
                for (i=count, p = cp, f = fp; i; i--, p++) {
765
                        if (f)
766
                                flags = *f++;
767
                        switch (flags) {
768
                        case TTY_NORMAL:
769
                                n_tty_receive_char(tty, *p);
770
                                break;
771
                        case TTY_BREAK:
772
                                n_tty_receive_break(tty);
773
                                break;
774
                        case TTY_PARITY:
775
                        case TTY_FRAME:
776
                                n_tty_receive_parity_error(tty, *p);
777
                                break;
778
                        case TTY_OVERRUN:
779
                                n_tty_receive_overrun(tty);
780
                                break;
781
                        default:
782
                                printk("%s: unknown flag %d\n",
783
                                       tty_name(tty, buf), flags);
784
                                break;
785
                        }
786
                }
787
                if (tty->driver.flush_chars)
788
                        tty->driver.flush_chars(tty);
789
        }
790
 
791
        if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
792
                kill_fasync(&tty->fasync, SIGIO, POLL_IN);
793
                if (waitqueue_active(&tty->read_wait))
794
                        wake_up_interruptible(&tty->read_wait);
795
        }
796
 
797
        /*
798
         * Check the remaining room for the input canonicalization
799
         * mode.  We don't want to throttle the driver if we're in
800
         * canonical mode and don't have a newline yet!
801
         */
802
        if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) {
803
                /* check TTY_THROTTLED first so it indicates our state */
804
                if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
805
                    tty->driver.throttle)
806
                        tty->driver.throttle(tty);
807
        }
808
}
809
 
810
int is_ignored(int sig)
811
{
812
        return (sigismember(&current->blocked, sig) ||
813
                current->sig->action[sig-1].sa.sa_handler == SIG_IGN);
814
}
815
 
816
static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
817
{
818
        if (!tty)
819
                return;
820
 
821
        tty->icanon = (L_ICANON(tty) != 0);
822
        if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
823
                tty->raw = 1;
824
                tty->real_raw = 1;
825
                return;
826
        }
827
        if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
828
            I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
829
            I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
830
            I_PARMRK(tty)) {
831
                cli();
832
                memset(tty->process_char_map, 0, 256/8);
833
 
834
                if (I_IGNCR(tty) || I_ICRNL(tty))
835
                        set_bit('\r', &tty->process_char_map);
836
                if (I_INLCR(tty))
837
                        set_bit('\n', &tty->process_char_map);
838
 
839
                if (L_ICANON(tty)) {
840
                        set_bit(ERASE_CHAR(tty), &tty->process_char_map);
841
                        set_bit(KILL_CHAR(tty), &tty->process_char_map);
842
                        set_bit(EOF_CHAR(tty), &tty->process_char_map);
843
                        set_bit('\n', &tty->process_char_map);
844
                        set_bit(EOL_CHAR(tty), &tty->process_char_map);
845
                        if (L_IEXTEN(tty)) {
846
                                set_bit(WERASE_CHAR(tty),
847
                                        &tty->process_char_map);
848
                                set_bit(LNEXT_CHAR(tty),
849
                                        &tty->process_char_map);
850
                                set_bit(EOL2_CHAR(tty),
851
                                        &tty->process_char_map);
852
                                if (L_ECHO(tty))
853
                                        set_bit(REPRINT_CHAR(tty),
854
                                                &tty->process_char_map);
855
                        }
856
                }
857
                if (I_IXON(tty)) {
858
                        set_bit(START_CHAR(tty), &tty->process_char_map);
859
                        set_bit(STOP_CHAR(tty), &tty->process_char_map);
860
                }
861
                if (L_ISIG(tty)) {
862
                        set_bit(INTR_CHAR(tty), &tty->process_char_map);
863
                        set_bit(QUIT_CHAR(tty), &tty->process_char_map);
864
                        set_bit(SUSP_CHAR(tty), &tty->process_char_map);
865
                }
866
                clear_bit(__DISABLED_CHAR, &tty->process_char_map);
867
                sti();
868
                tty->raw = 0;
869
                tty->real_raw = 0;
870
        } else {
871
                tty->raw = 1;
872
                if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
873
                    (I_IGNPAR(tty) || !I_INPCK(tty)) &&
874
                    (tty->driver.flags & TTY_DRIVER_REAL_RAW))
875
                        tty->real_raw = 1;
876
                else
877
                        tty->real_raw = 0;
878
        }
879
}
880
 
881
static void n_tty_close(struct tty_struct *tty)
882
{
883
        n_tty_flush_buffer(tty);
884
        if (tty->read_buf) {
885
                free_buf(tty->read_buf);
886
                tty->read_buf = 0;
887
        }
888
}
889
 
890
static int n_tty_open(struct tty_struct *tty)
891
{
892
        if (!tty)
893
                return -EINVAL;
894
 
895
        if (!tty->read_buf) {
896
                tty->read_buf = alloc_buf();
897
                if (!tty->read_buf)
898
                        return -ENOMEM;
899
        }
900
        memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
901
        reset_buffer_flags(tty);
902
        tty->column = 0;
903
        n_tty_set_termios(tty, 0);
904
        tty->minimum_to_wake = 1;
905
        tty->closing = 0;
906
        return 0;
907
}
908
 
909
static inline int input_available_p(struct tty_struct *tty, int amt)
910
{
911
        if (tty->icanon) {
912
                if (tty->canon_data)
913
                        return 1;
914
        } else if (tty->read_cnt >= (amt ? amt : 1))
915
                return 1;
916
 
917
        return 0;
918
}
919
 
920
/*
921
 * Helper function to speed up read_chan.  It is only called when
922
 * ICANON is off; it copies characters straight from the tty queue to
923
 * user space directly.  It can be profitably called twice; once to
924
 * drain the space from the tail pointer to the (physical) end of the
925
 * buffer, and once to drain the space from the (physical) beginning of
926
 * the buffer to head pointer.
927
 */
928
static inline int copy_from_read_buf(struct tty_struct *tty,
929
                                      unsigned char **b,
930
                                      size_t *nr)
931
 
932
{
933
        int retval;
934
        ssize_t n;
935
        unsigned long flags;
936
 
937
        retval = 0;
938
        spin_lock_irqsave(&tty->read_lock, flags);
939
        n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
940
        spin_unlock_irqrestore(&tty->read_lock, flags);
941
        if (n) {
942
                mb();
943
                retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
944
                n -= retval;
945
                spin_lock_irqsave(&tty->read_lock, flags);
946
                tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
947
                tty->read_cnt -= n;
948
                spin_unlock_irqrestore(&tty->read_lock, flags);
949
                *b += n;
950
                *nr -= n;
951
        }
952
        return retval;
953
}
954
 
955
static ssize_t read_chan(struct tty_struct *tty, struct file *file,
956
                         unsigned char *buf, size_t nr)
957
{
958
        unsigned char *b = buf;
959
        DECLARE_WAITQUEUE(wait, current);
960
        int c;
961
        int minimum, time;
962
        ssize_t retval = 0;
963
        ssize_t size;
964
        long timeout;
965
        unsigned long flags;
966
 
967
do_it_again:
968
 
969
        if (!tty->read_buf) {
970
                printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
971
                return -EIO;
972
        }
973
 
974
        /* Job control check -- must be done at start and after
975
           every sleep (POSIX.1 7.1.1.4). */
976
        /* NOTE: not yet done after every sleep pending a thorough
977
           check of the logic of this change. -- jlc */
978
        /* don't stop on /dev/console */
979
        if (file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
980
            file->f_dentry->d_inode->i_rdev != SYSCONS_DEV &&
981
            current->tty == tty) {
982
                if (tty->pgrp <= 0)
983
                        printk("read_chan: tty->pgrp <= 0!\n");
984
                else if (current->pgrp != tty->pgrp) {
985
                        if (is_ignored(SIGTTIN) ||
986
                            is_orphaned_pgrp(current->pgrp))
987
                                return -EIO;
988
                        kill_pg(current->pgrp, SIGTTIN, 1);
989
                        return -ERESTARTSYS;
990
                }
991
        }
992
 
993
        minimum = time = 0;
994
        timeout = MAX_SCHEDULE_TIMEOUT;
995
        if (!tty->icanon) {
996
                time = (HZ / 10) * TIME_CHAR(tty);
997
                minimum = MIN_CHAR(tty);
998
                if (minimum) {
999
                        if (time)
1000
                                tty->minimum_to_wake = 1;
1001
                        else if (!waitqueue_active(&tty->read_wait) ||
1002
                                 (tty->minimum_to_wake > minimum))
1003
                                tty->minimum_to_wake = minimum;
1004
                } else {
1005
                        timeout = 0;
1006
                        if (time) {
1007
                                timeout = time;
1008
                                time = 0;
1009
                        }
1010
                        tty->minimum_to_wake = minimum = 1;
1011
                }
1012
        }
1013
 
1014
        if (file->f_flags & O_NONBLOCK) {
1015
                if (down_trylock(&tty->atomic_read))
1016
                        return -EAGAIN;
1017
        }
1018
        else {
1019
                if (down_interruptible(&tty->atomic_read))
1020
                        return -ERESTARTSYS;
1021
        }
1022
 
1023
        add_wait_queue(&tty->read_wait, &wait);
1024
        set_bit(TTY_DONT_FLIP, &tty->flags);
1025
        while (nr) {
1026
                /* First test for status change. */
1027
                if (tty->packet && tty->link->ctrl_status) {
1028
                        unsigned char cs;
1029
                        if (b != buf)
1030
                                break;
1031
                        cs = tty->link->ctrl_status;
1032
                        tty->link->ctrl_status = 0;
1033
                        put_user(cs, b++);
1034
                        nr--;
1035
                        break;
1036
                }
1037
                /* This statement must be first before checking for input
1038
                   so that any interrupt will set the state back to
1039
                   TASK_RUNNING. */
1040
                set_current_state(TASK_INTERRUPTIBLE);
1041
 
1042
                if (((minimum - (b - buf)) < tty->minimum_to_wake) &&
1043
                    ((minimum - (b - buf)) >= 1))
1044
                        tty->minimum_to_wake = (minimum - (b - buf));
1045
 
1046
                if (!input_available_p(tty, 0)) {
1047
                        if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
1048
                                retval = -EIO;
1049
                                break;
1050
                        }
1051
                        if (tty_hung_up_p(file))
1052
                                break;
1053
                        if (!timeout)
1054
                                break;
1055
                        if (file->f_flags & O_NONBLOCK) {
1056
                                retval = -EAGAIN;
1057
                                break;
1058
                        }
1059
                        if (signal_pending(current)) {
1060
                                retval = -ERESTARTSYS;
1061
                                break;
1062
                        }
1063
                        clear_bit(TTY_DONT_FLIP, &tty->flags);
1064
                        timeout = schedule_timeout(timeout);
1065
                        set_bit(TTY_DONT_FLIP, &tty->flags);
1066
                        continue;
1067
                }
1068
                current->state = TASK_RUNNING;
1069
 
1070
                /* Deal with packet mode. */
1071
                if (tty->packet && b == buf) {
1072
                        put_user(TIOCPKT_DATA, b++);
1073
                        nr--;
1074
                }
1075
 
1076
                if (tty->icanon) {
1077
                        /* N.B. avoid overrun if nr == 0 */
1078
                        while (nr && tty->read_cnt) {
1079
                                int eol;
1080
 
1081
                                eol = test_and_clear_bit(tty->read_tail,
1082
                                                &tty->read_flags);
1083
                                c = tty->read_buf[tty->read_tail];
1084
                                spin_lock_irqsave(&tty->read_lock, flags);
1085
                                tty->read_tail = ((tty->read_tail+1) &
1086
                                                  (N_TTY_BUF_SIZE-1));
1087
                                tty->read_cnt--;
1088
                                if (eol) {
1089
                                        /* this test should be redundant:
1090
                                         * we shouldn't be reading data if
1091
                                         * canon_data is 0
1092
                                         */
1093
                                        if (--tty->canon_data < 0)
1094
                                                tty->canon_data = 0;
1095
                                }
1096
                                spin_unlock_irqrestore(&tty->read_lock, flags);
1097
 
1098
                                if (!eol || (c != __DISABLED_CHAR)) {
1099
                                        put_user(c, b++);
1100
                                        nr--;
1101
                                }
1102
                                if (eol)
1103
                                        break;
1104
                        }
1105
                } else {
1106
                        int uncopied;
1107
                        uncopied = copy_from_read_buf(tty, &b, &nr);
1108
                        uncopied += copy_from_read_buf(tty, &b, &nr);
1109
                        if (uncopied) {
1110
                                retval = -EFAULT;
1111
                                break;
1112
                        }
1113
                }
1114
 
1115
                /* If there is enough space in the read buffer now, let the
1116
                 * low-level driver know. We use n_tty_chars_in_buffer() to
1117
                 * check the buffer, as it now knows about canonical mode.
1118
                 * Otherwise, if the driver is throttled and the line is
1119
                 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
1120
                 * we won't get any more characters.
1121
                 */
1122
                if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
1123
                        check_unthrottle(tty);
1124
 
1125
                if (b - buf >= minimum)
1126
                        break;
1127
                if (time)
1128
                        timeout = time;
1129
        }
1130
        clear_bit(TTY_DONT_FLIP, &tty->flags);
1131
        up(&tty->atomic_read);
1132
        remove_wait_queue(&tty->read_wait, &wait);
1133
 
1134
        if (!waitqueue_active(&tty->read_wait))
1135
                tty->minimum_to_wake = minimum;
1136
 
1137
        current->state = TASK_RUNNING;
1138
        size = b - buf;
1139
        if (size) {
1140
                retval = size;
1141
                if (nr)
1142
                        clear_bit(TTY_PUSH, &tty->flags);
1143
        } else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
1144
                 goto do_it_again;
1145
 
1146
        return retval;
1147
}
1148
 
1149
static ssize_t write_chan(struct tty_struct * tty, struct file * file,
1150
                          const unsigned char * buf, size_t nr)
1151
{
1152
        const unsigned char *b = buf;
1153
        DECLARE_WAITQUEUE(wait, current);
1154
        int c;
1155
        ssize_t retval = 0;
1156
 
1157
        /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
1158
        if (L_TOSTOP(tty) &&
1159
            file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
1160
            file->f_dentry->d_inode->i_rdev != SYSCONS_DEV) {
1161
                retval = tty_check_change(tty);
1162
                if (retval)
1163
                        return retval;
1164
        }
1165
 
1166
        add_wait_queue(&tty->write_wait, &wait);
1167
        while (1) {
1168
                set_current_state(TASK_INTERRUPTIBLE);
1169
                if (signal_pending(current)) {
1170
                        retval = -ERESTARTSYS;
1171
                        break;
1172
                }
1173
                if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) {
1174
                        retval = -EIO;
1175
                        break;
1176
                }
1177
                if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) {
1178
                        while (nr > 0) {
1179
                                ssize_t num = opost_block(tty, b, nr);
1180
                                if (num < 0) {
1181
                                        if (num == -EAGAIN)
1182
                                                break;
1183
                                        retval = num;
1184
                                        goto break_out;
1185
                                }
1186
                                b += num;
1187
                                nr -= num;
1188
                                if (nr == 0)
1189
                                        break;
1190
                                get_user(c, b);
1191
                                if (opost(c, tty) < 0)
1192
                                        break;
1193
                                b++; nr--;
1194
                        }
1195
                        if (tty->driver.flush_chars)
1196
                                tty->driver.flush_chars(tty);
1197
                } else {
1198
                        c = tty->driver.write(tty, 1, b, nr);
1199
                        if (c < 0) {
1200
                                retval = c;
1201
                                goto break_out;
1202
                        }
1203
                        b += c;
1204
                        nr -= c;
1205
                }
1206
                if (!nr)
1207
                        break;
1208
                if (file->f_flags & O_NONBLOCK) {
1209
                        retval = -EAGAIN;
1210
                        break;
1211
                }
1212
                schedule();
1213
        }
1214
break_out:
1215
        current->state = TASK_RUNNING;
1216
        remove_wait_queue(&tty->write_wait, &wait);
1217
        return (b - buf) ? b - buf : retval;
1218
}
1219
 
1220
/* Called without the kernel lock held - fine */
1221
static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
1222
{
1223
        unsigned int mask = 0;
1224
 
1225
        poll_wait(file, &tty->read_wait, wait);
1226
        poll_wait(file, &tty->write_wait, wait);
1227
        if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty)))
1228
                mask |= POLLIN | POLLRDNORM;
1229
        if (tty->packet && tty->link->ctrl_status)
1230
                mask |= POLLPRI | POLLIN | POLLRDNORM;
1231
        if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
1232
                mask |= POLLHUP;
1233
        if (tty_hung_up_p(file))
1234
                mask |= POLLHUP;
1235
        if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
1236
                if (MIN_CHAR(tty) && !TIME_CHAR(tty))
1237
                        tty->minimum_to_wake = MIN_CHAR(tty);
1238
                else
1239
                        tty->minimum_to_wake = 1;
1240
        }
1241
        if (tty->driver.chars_in_buffer(tty) < WAKEUP_CHARS &&
1242
                        tty->driver.write_room(tty) > 0)
1243
                mask |= POLLOUT | POLLWRNORM;
1244
        return mask;
1245
}
1246
 
1247
struct tty_ldisc tty_ldisc_N_TTY = {
1248
        TTY_LDISC_MAGIC,        /* magic */
1249
        "n_tty",                /* name */
1250
        0,                       /* num */
1251
        0,                       /* flags */
1252
        n_tty_open,             /* open */
1253
        n_tty_close,            /* close */
1254
        n_tty_flush_buffer,     /* flush_buffer */
1255
        n_tty_chars_in_buffer,  /* chars_in_buffer */
1256
        read_chan,              /* read */
1257
        write_chan,             /* write */
1258
        n_tty_ioctl,            /* ioctl */
1259
        n_tty_set_termios,      /* set_termios */
1260
        normal_poll,            /* poll */
1261
        n_tty_receive_buf,      /* receive_buf */
1262
        n_tty_receive_room,     /* receive_room */
1263
        n_tty_write_wakeup      /* write_wakeup */
1264
};
1265
 

powered by: WebSVN 2.1.0

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