This source file includes following definitions.
- tty_register_ldisc
- put_tty_queue
- get_tty_queue
- tty_read_raw_data
- tty_write_flush
- tty_read_flush
- hung_up_tty_read
- hung_up_tty_write
- hung_up_tty_select
- hung_up_tty_ioctl
- tty_lseek
- do_tty_hangup
- tty_hangup
- tty_vhangup
- tty_hung_up_p
- disassociate_ctty
- vt_waitactive
- complete_change_console
- change_console
- wait_for_keypress
- stop_tty
- start_tty
- opost
- echo_char
- eraser
- isig
- copy_to_cooked
- is_ignored
- input_available_p
- read_chan
- write_chan
- tty_read
- tty_write
- init_dev
- release_dev
- tty_open
- tty_release
- tty_select
- normal_select
- do_SAK
- tty_write_data
- tty_bh_routine
- initialize_tty_struct
- initialize_termios
- tty_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <linux/types.h>
41 #include <linux/major.h>
42 #include <linux/errno.h>
43 #include <linux/signal.h>
44 #include <linux/fcntl.h>
45 #include <linux/sched.h>
46 #include <linux/tty.h>
47 #include <linux/timer.h>
48 #include <linux/ctype.h>
49 #include <linux/kd.h>
50 #include <linux/mm.h>
51 #include <linux/string.h>
52 #include <linux/malloc.h>
53
54 #include <asm/segment.h>
55 #include <asm/system.h>
56 #include <asm/bitops.h>
57
58 #include "kbd_kern.h"
59 #include "vt_kern.h"
60
61 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
62
63 #define MAX_TTYS 256
64
65 struct tty_struct *tty_table[MAX_TTYS];
66 struct termios *tty_termios[MAX_TTYS];
67
68 struct termios *termios_locked[MAX_TTYS];
69 struct tty_ldisc ldiscs[NR_LDISCS];
70 int tty_check_write[MAX_TTYS/32];
71
72
73
74
75
76
77 int fg_console = 0;
78 struct tty_struct * redirect = NULL;
79 struct wait_queue * keypress_wait = NULL;
80
81 static void initialize_tty_struct(int line, struct tty_struct *tty);
82 static void initialize_termios(int line, struct termios *tp);
83
84 static int tty_read(struct inode *, struct file *, char *, int);
85 static int tty_write(struct inode *, struct file *, char *, int);
86 static int tty_select(struct inode *, struct file *, int, select_table *);
87 static int tty_open(struct inode *, struct file *);
88 static void tty_release(struct inode *, struct file *);
89
90 int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
91 {
92 if (disc < N_TTY || disc >= NR_LDISCS)
93 return -EINVAL;
94
95 if (new_ldisc) {
96 ldiscs[disc] = *new_ldisc;
97 ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
98 } else
99 memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
100
101 return 0;
102 }
103
104 void put_tty_queue(unsigned char c, struct tty_queue * queue)
105 {
106 int head;
107 unsigned long flags;
108
109 save_flags(flags);
110 cli();
111 head = (queue->head + 1) & (TTY_BUF_SIZE-1);
112 if (head != queue->tail) {
113 queue->buf[queue->head] = c;
114 queue->head = head;
115 }
116 restore_flags(flags);
117 }
118
119 int get_tty_queue(struct tty_queue * queue)
120 {
121 int result = -1;
122 unsigned long flags;
123
124 save_flags(flags);
125 cli();
126 if (queue->tail != queue->head) {
127 result = queue->buf[queue->tail];
128 INC(queue->tail);
129 }
130 restore_flags(flags);
131 return result;
132 }
133
134
135
136
137
138
139
140
141
142 int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen)
143 {
144 int result = 0;
145 unsigned char *p = bufp;
146 unsigned long flags;
147 int head, tail;
148 int ok = 1;
149
150 save_flags(flags);
151 cli();
152 tail = tty->read_q.tail;
153 head = tty->read_q.head;
154 while ((result < buflen) && (tail!=head) && ok) {
155 ok = !clear_bit (tail, &tty->readq_flags);
156 *p++ = tty->read_q.buf[tail++];
157 tail &= TTY_BUF_SIZE-1;
158 result++;
159 }
160 tty->read_q.tail = tail;
161 restore_flags(flags);
162 return (ok) ? result : -result;
163 }
164
165
166 void tty_write_flush(struct tty_struct * tty)
167 {
168 if (!tty->write || EMPTY(&tty->write_q))
169 return;
170 if (set_bit(TTY_WRITE_BUSY,&tty->flags))
171 return;
172 tty->write(tty);
173 if (!clear_bit(TTY_WRITE_BUSY,&tty->flags))
174 printk("tty_write_flush: bit already cleared\n");
175 }
176
177 void tty_read_flush(struct tty_struct * tty)
178 {
179 if (!tty || EMPTY(&tty->read_q))
180 return;
181 if (set_bit(TTY_READ_BUSY, &tty->flags))
182 return;
183 ldiscs[tty->disc].handler(tty);
184 if (!clear_bit(TTY_READ_BUSY, &tty->flags))
185 printk("tty_read_flush: bit already cleared\n");
186 }
187
188 static int hung_up_tty_read(struct inode * inode, struct file * file, char * buf, int count)
189 {
190 return 0;
191 }
192
193 static int hung_up_tty_write(struct inode * inode, struct file * file, char * buf, int count)
194 {
195 return -EIO;
196 }
197
198 static int hung_up_tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
199 {
200 return 1;
201 }
202
203 static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
204 unsigned int cmd, unsigned long arg)
205 {
206 return -EIO;
207 }
208
209 static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
210 {
211 return -ESPIPE;
212 }
213
214 static struct file_operations tty_fops = {
215 tty_lseek,
216 tty_read,
217 tty_write,
218 NULL,
219 tty_select,
220 tty_ioctl,
221 NULL,
222 tty_open,
223 tty_release
224 };
225
226 static struct file_operations hung_up_tty_fops = {
227 tty_lseek,
228 hung_up_tty_read,
229 hung_up_tty_write,
230 NULL,
231 hung_up_tty_select,
232 hung_up_tty_ioctl,
233 NULL,
234 NULL,
235 tty_release
236 };
237
238 void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops)
239 {
240 int i;
241 struct file * filp;
242 struct task_struct *p;
243 int dev;
244
245 if (!tty)
246 return;
247 dev = MKDEV(TTY_MAJOR,tty->line);
248 for (filp = first_file, i=0; i<nr_files; i++, filp = filp->f_next) {
249 if (!filp->f_count)
250 continue;
251 if (filp->f_rdev != dev)
252 continue;
253 if (filp->f_inode && filp->f_inode->i_rdev == CONSOLE_DEV)
254 continue;
255 if (filp->f_op != &tty_fops)
256 continue;
257 filp->f_op = fops;
258 }
259 flush_input(tty);
260 flush_output(tty);
261 wake_up_interruptible(&tty->secondary.proc_list);
262 if (tty->session > 0)
263 kill_sl(tty->session,SIGHUP,1);
264 tty->session = 0;
265 tty->pgrp = -1;
266 for_each_task(p) {
267 if (p->tty == tty->line)
268 p->tty = -1;
269 }
270 if (tty->hangup)
271 (tty->hangup)(tty);
272 }
273
274 void tty_hangup(struct tty_struct * tty)
275 {
276 #ifdef TTY_DEBUG_HANGUP
277 printk("tty%d hangup...\n", tty->line);
278 #endif
279 do_tty_hangup(tty, &hung_up_tty_fops);
280 }
281
282 void tty_vhangup(struct tty_struct * tty)
283 {
284 #ifdef TTY_DEBUG_HANGUP
285 printk("tty%d vhangup...\n", tty->line);
286 #endif
287 do_tty_hangup(tty, &hung_up_tty_fops);
288 }
289
290 int tty_hung_up_p(struct file * filp)
291 {
292 return (filp->f_op == &hung_up_tty_fops);
293 }
294
295
296
297
298
299
300
301
302
303
304
305 void disassociate_ctty(int priv)
306 {
307 struct tty_struct *tty;
308 struct task_struct *p;
309
310 if (current->tty >= 0) {
311 tty = tty_table[current->tty];
312 if (tty) {
313 if (tty->pgrp > 0)
314 kill_pg(tty->pgrp, SIGHUP, priv);
315 tty->session = 0;
316 tty->pgrp = -1;
317 } else
318 printk("disassociate_ctty: ctty is NULL?!?");
319 }
320
321 for_each_task(p)
322 if (p->session == current->session)
323 p->tty = -1;
324 }
325
326
327
328
329
330
331
332
333 static struct wait_queue *vt_activate_queue = NULL;
334
335
336
337
338
339 int vt_waitactive(void)
340 {
341 interruptible_sleep_on(&vt_activate_queue);
342 return (current->signal & ~current->blocked) ? -1 : 0;
343 }
344
345 #define vt_wake_waitactive() wake_up(&vt_activate_queue)
346
347 extern int kill_proc(int pid, int sig, int priv);
348
349
350
351
352 void complete_change_console(unsigned int new_console)
353 {
354 unsigned char old_vc_mode;
355
356 if (new_console == fg_console || new_console >= NR_CONSOLES)
357 return;
358
359
360
361
362
363
364 old_vc_mode = vt_cons[fg_console].vc_mode;
365 update_screen(new_console);
366
367
368
369
370
371
372 if (vt_cons[new_console].vt_mode.mode == VT_PROCESS)
373 {
374
375
376
377
378
379 if (kill_proc(vt_cons[new_console].vt_pid,
380 vt_cons[new_console].vt_mode.acqsig,
381 1) != 0)
382 {
383
384
385
386
387
388
389
390
391
392 vt_cons[new_console].vc_mode = KD_TEXT;
393 clr_vc_kbd_mode(kbd_table + new_console, VC_RAW);
394 clr_vc_kbd_mode(kbd_table + new_console, VC_MEDIUMRAW);
395 vt_cons[new_console].vt_mode.mode = VT_AUTO;
396 vt_cons[new_console].vt_mode.waitv = 0;
397 vt_cons[new_console].vt_mode.relsig = 0;
398 vt_cons[new_console].vt_mode.acqsig = 0;
399 vt_cons[new_console].vt_mode.frsig = 0;
400 vt_cons[new_console].vt_pid = -1;
401 vt_cons[new_console].vt_newvt = -1;
402 }
403 }
404
405
406
407
408
409 if (old_vc_mode != vt_cons[new_console].vc_mode)
410 {
411 if (vt_cons[new_console].vc_mode == KD_TEXT)
412 unblank_screen();
413 else {
414 timer_active &= ~(1<<BLANK_TIMER);
415 blank_screen();
416 }
417 }
418
419
420
421
422 vt_wake_waitactive();
423 return;
424 }
425
426
427
428
429 void change_console(unsigned int new_console)
430 {
431 if (new_console == fg_console || new_console >= NR_CONSOLES)
432 return;
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 if (vt_cons[fg_console].vt_mode.mode == VT_PROCESS)
450 {
451
452
453
454
455
456 if (kill_proc(vt_cons[fg_console].vt_pid,
457 vt_cons[fg_console].vt_mode.relsig,
458 1) == 0)
459 {
460
461
462
463
464
465 vt_cons[fg_console].vt_newvt = new_console;
466 return;
467 }
468
469
470
471
472
473
474
475
476
477
478 vt_cons[fg_console].vc_mode = KD_TEXT;
479 clr_vc_kbd_mode(kbd_table + fg_console, VC_RAW);
480 clr_vc_kbd_mode(kbd_table + fg_console, VC_MEDIUMRAW);
481 vt_cons[fg_console].vt_mode.mode = VT_AUTO;
482 vt_cons[fg_console].vt_mode.waitv = 0;
483 vt_cons[fg_console].vt_mode.relsig = 0;
484 vt_cons[fg_console].vt_mode.acqsig = 0;
485 vt_cons[fg_console].vt_mode.frsig = 0;
486 vt_cons[fg_console].vt_pid = -1;
487 vt_cons[fg_console].vt_newvt = -1;
488
489
490
491 }
492
493
494
495
496 if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
497 return;
498
499 complete_change_console(new_console);
500 }
501
502 void wait_for_keypress(void)
503 {
504 sleep_on(&keypress_wait);
505 }
506
507 void stop_tty(struct tty_struct *tty)
508 {
509 if (tty->stopped)
510 return;
511 tty->stopped = 1;
512 if (tty->link && tty->link->packet) {
513 tty->ctrl_status &= ~TIOCPKT_START;
514 tty->ctrl_status |= TIOCPKT_STOP;
515 wake_up_interruptible(&tty->link->secondary.proc_list);
516 }
517 if (tty->stop)
518 (tty->stop)(tty);
519 if (IS_A_CONSOLE(tty->line)) {
520 set_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
521 set_leds();
522 }
523 }
524
525 void start_tty(struct tty_struct *tty)
526 {
527 if (!tty->stopped)
528 return;
529 tty->stopped = 0;
530 if (tty->link && tty->link->packet) {
531 tty->ctrl_status &= ~TIOCPKT_STOP;
532 tty->ctrl_status |= TIOCPKT_START;
533 wake_up_interruptible(&tty->link->secondary.proc_list);
534 }
535 if (tty->start)
536 (tty->start)(tty);
537 TTY_WRITE_FLUSH(tty);
538 if (IS_A_CONSOLE(tty->line)) {
539 clr_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
540 set_leds();
541 }
542 }
543
544
545
546
547 static int opost(unsigned char c, struct tty_struct *tty)
548 {
549 if (FULL(&tty->write_q))
550 return -1;
551 if (O_OPOST(tty)) {
552 switch (c) {
553 case '\n':
554 if (O_ONLRET(tty))
555 tty->column = 0;
556 if (O_ONLCR(tty)) {
557 if (LEFT(&tty->write_q) < 2)
558 return -1;
559 put_tty_queue('\r', &tty->write_q);
560 tty->column = 0;
561 }
562 tty->canon_column = tty->column;
563 break;
564 case '\r':
565 if (O_ONOCR(tty) && tty->column == 0)
566 return 0;
567 if (O_OCRNL(tty)) {
568 c = '\n';
569 if (O_ONLRET(tty))
570 tty->canon_column = tty->column = 0;
571 break;
572 }
573 tty->canon_column = tty->column = 0;
574 break;
575 case '\t':
576 if (O_TABDLY(tty) == XTABS) {
577 if (LEFT(&tty->write_q) < 8)
578 return -1;
579 do
580 put_tty_queue(' ', &tty->write_q);
581 while (++tty->column % 8);
582 return 0;
583 }
584 tty->column = (tty->column | 7) + 1;
585 break;
586 case '\b':
587 if (tty->column > 0)
588 tty->column--;
589 break;
590 default:
591 if (O_OLCUC(tty))
592 c = toupper(c);
593 if (!iscntrl(c))
594 tty->column++;
595 break;
596 }
597 }
598 put_tty_queue(c, &tty->write_q);
599 return 0;
600 }
601
602
603
604 static void echo_char(unsigned char c, struct tty_struct *tty)
605 {
606 if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
607 opost('^', tty);
608 opost(c ^ 0100, tty);
609 } else
610 opost(c, tty);
611 }
612
613 static void eraser(unsigned char c, struct tty_struct *tty)
614 {
615 enum { ERASE, WERASE, KILL } kill_type;
616 int seen_alnums;
617
618 if (tty->secondary.head == tty->canon_head) {
619
620 return;
621 }
622 if (c == ERASE_CHAR(tty))
623 kill_type = ERASE;
624 else if (c == WERASE_CHAR(tty))
625 kill_type = WERASE;
626 else {
627 if (!L_ECHO(tty)) {
628 tty->secondary.head = tty->canon_head;
629 return;
630 }
631 if (!L_ECHOK(tty) || !L_ECHOKE(tty)) {
632 tty->secondary.head = tty->canon_head;
633 if (tty->erasing) {
634 opost('/', tty);
635 tty->erasing = 0;
636 }
637 echo_char(KILL_CHAR(tty), tty);
638
639 if (L_ECHOK(tty))
640 opost('\n', tty);
641 return;
642 }
643 kill_type = KILL;
644 }
645
646 seen_alnums = 0;
647 while (tty->secondary.head != tty->canon_head) {
648 c = LAST(&tty->secondary);
649 if (kill_type == WERASE) {
650
651 if (isalnum(c) || c == '_')
652 seen_alnums++;
653 else if (seen_alnums)
654 break;
655 }
656 DEC(tty->secondary.head);
657 if (L_ECHO(tty)) {
658 if (L_ECHOPRT(tty)) {
659 if (!tty->erasing) {
660 opost('\\', tty);
661 tty->erasing = 1;
662 }
663 echo_char(c, tty);
664 } else if (!L_ECHOE(tty)) {
665 echo_char(ERASE_CHAR(tty), tty);
666 } else if (c == '\t') {
667 unsigned int col = tty->canon_column;
668 unsigned long tail = tty->canon_head;
669
670
671 while (tail != tty->secondary.head) {
672 c = tty->secondary.buf[tail];
673 if (c == '\t')
674 col = (col | 7) + 1;
675 else if (iscntrl(c)) {
676 if (L_ECHOCTL(tty))
677 col += 2;
678 } else
679 col++;
680 INC(tail);
681 }
682
683
684 while (tty->column > col) {
685
686 put_tty_queue('\b', &tty->write_q);
687 tty->column--;
688 }
689 } else {
690 if (iscntrl(c) && L_ECHOCTL(tty)) {
691 opost('\b', tty);
692 opost(' ', tty);
693 opost('\b', tty);
694 }
695 if (!iscntrl(c) || L_ECHOCTL(tty)) {
696 opost('\b', tty);
697 opost(' ', tty);
698 opost('\b', tty);
699 }
700 }
701 }
702 if (kill_type == ERASE)
703 break;
704 }
705 if (tty->erasing && tty->secondary.head == tty->canon_head) {
706 opost('/', tty);
707 tty->erasing = 0;
708 }
709 }
710
711 static void isig(int sig, struct tty_struct *tty)
712 {
713 kill_pg(tty->pgrp, sig, 1);
714 if (!L_NOFLSH(tty)) {
715 flush_input(tty);
716 flush_output(tty);
717 }
718 }
719
720 static void copy_to_cooked(struct tty_struct * tty)
721 {
722 int c, special_flag;
723 unsigned long flags;
724
725 if (!tty) {
726 printk("copy_to_cooked: called with NULL tty\n");
727 return;
728 }
729 if (!tty->write) {
730 printk("copy_to_cooked: tty %d has null write routine\n",
731 tty->line);
732 }
733 while (1) {
734
735
736
737
738
739 c = LEFT(&tty->secondary);
740 if (tty->throttle && (c < SQ_THRESHOLD_LW)
741 && !set_bit(TTY_SQ_THROTTLED, &tty->flags))
742 tty->throttle(tty, TTY_THROTTLE_SQ_FULL);
743 if (c == 0)
744 break;
745 save_flags(flags); cli();
746 if (!EMPTY(&tty->read_q)) {
747 c = tty->read_q.buf[tty->read_q.tail];
748 special_flag = clear_bit(tty->read_q.tail,
749 &tty->readq_flags);
750 INC(tty->read_q.tail);
751 restore_flags(flags);
752 } else {
753 restore_flags(flags);
754 break;
755 }
756 if (special_flag) {
757 tty->char_error = c;
758 continue;
759 }
760 if (tty->char_error) {
761 if (tty->char_error == TTY_BREAK) {
762 tty->char_error = 0;
763 if (I_IGNBRK(tty))
764 continue;
765
766 if (I_BRKINT(tty))
767 continue;
768 if (I_PARMRK(tty)) {
769 put_tty_queue('\377', &tty->secondary);
770 put_tty_queue('\0', &tty->secondary);
771 }
772 put_tty_queue('\0', &tty->secondary);
773 continue;
774 }
775 if (tty->char_error == TTY_OVERRUN) {
776 tty->char_error = 0;
777 printk("tty%d: input overrun\n", tty->line);
778 continue;
779 }
780
781 tty->char_error = 0;
782 if (I_IGNPAR(tty)) {
783 continue;
784 }
785 if (I_PARMRK(tty)) {
786 put_tty_queue('\377', &tty->secondary);
787 put_tty_queue('\0', &tty->secondary);
788 put_tty_queue(c, &tty->secondary);
789 } else
790 put_tty_queue('\0', &tty->secondary);
791 continue;
792 }
793 if (I_ISTRIP(tty))
794 c &= 0x7f;
795 if (!tty->lnext) {
796 if (c == '\r') {
797 if (I_IGNCR(tty))
798 continue;
799 if (I_ICRNL(tty))
800 c = '\n';
801 } else if (c == '\n' && I_INLCR(tty))
802 c = '\r';
803 }
804 if (I_IUCLC(tty) && L_IEXTEN(tty))
805 c=tolower(c);
806 if (c == __DISABLED_CHAR)
807 tty->lnext = 1;
808 if (L_ICANON(tty) && !tty->lnext) {
809 if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
810 (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
811 eraser(c, tty);
812 continue;
813 }
814 if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
815 tty->lnext = 1;
816 if (L_ECHO(tty)) {
817 if (tty->erasing) {
818 opost('/', tty);
819 tty->erasing = 0;
820 }
821 if (L_ECHOCTL(tty)) {
822 opost('^', tty);
823 opost('\b', tty);
824 }
825 }
826 continue;
827 }
828 if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
829 L_IEXTEN(tty)) {
830 unsigned long tail = tty->canon_head;
831
832 if (tty->erasing) {
833 opost('/', tty);
834 tty->erasing = 0;
835 }
836 echo_char(c, tty);
837 opost('\n', tty);
838 while (tail != tty->secondary.head) {
839 echo_char(tty->secondary.buf[tail],
840 tty);
841 INC(tail);
842 }
843 continue;
844 }
845 }
846 if (I_IXON(tty) && !tty->lnext) {
847 if ((tty->stopped && I_IXANY(tty) && L_IEXTEN(tty)) ||
848 c == START_CHAR(tty)) {
849 start_tty(tty);
850 continue;
851 }
852 if (c == STOP_CHAR(tty)) {
853 stop_tty(tty);
854 continue;
855 }
856 }
857 if (L_ISIG(tty) && !tty->lnext) {
858 if (c == INTR_CHAR(tty)) {
859 isig(SIGINT, tty);
860 continue;
861 }
862 if (c == QUIT_CHAR(tty)) {
863 isig(SIGQUIT, tty);
864 continue;
865 }
866 if (c == SUSP_CHAR(tty)) {
867 if (!is_orphaned_pgrp(tty->pgrp))
868 isig(SIGTSTP, tty);
869 continue;
870 }
871 }
872
873 if (tty->erasing) {
874 opost('/', tty);
875 tty->erasing = 0;
876 }
877 if (c == '\n' && !tty->lnext) {
878 if (L_ECHO(tty) || (L_ICANON(tty) && L_ECHONL(tty)))
879 opost('\n', tty);
880 } else if (L_ECHO(tty)) {
881
882
883
884 if (c != EOF_CHAR(tty) || !L_ICANON(tty) ||
885 tty->lnext) {
886
887 if (tty->canon_head == tty->secondary.head)
888 tty->canon_column = tty->column;
889 echo_char(c, tty);
890 }
891 }
892
893 if (I_PARMRK(tty) && c == (unsigned char) '\377' &&
894 (c != EOF_CHAR(tty) || !L_ICANON(tty) || tty->lnext))
895 put_tty_queue(c, &tty->secondary);
896
897 if (L_ICANON(tty) && !tty->lnext &&
898 (c == '\n' || c == EOF_CHAR(tty) || c == EOL_CHAR(tty) ||
899 (c == EOL2_CHAR(tty) && L_IEXTEN(tty)))) {
900 if (c == EOF_CHAR(tty))
901 c = __DISABLED_CHAR;
902 set_bit(tty->secondary.head, &tty->secondary_flags);
903 put_tty_queue(c, &tty->secondary);
904 tty->canon_head = tty->secondary.head;
905 tty->canon_data++;
906 } else
907 put_tty_queue(c, &tty->secondary);
908 tty->lnext = 0;
909 }
910 if (!EMPTY(&tty->write_q))
911 TTY_WRITE_FLUSH(tty);
912 if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
913 wake_up_interruptible(&tty->secondary.proc_list);
914
915 if (tty->throttle && (LEFT(&tty->read_q) >= RQ_THRESHOLD_HW)
916 && clear_bit(TTY_RQ_THROTTLED, &tty->flags))
917 tty->throttle(tty, TTY_THROTTLE_RQ_AVAIL);
918 }
919
920 int is_ignored(int sig)
921 {
922 return ((current->blocked & (1<<(sig-1))) ||
923 (current->sigaction[sig-1].sa_handler == SIG_IGN));
924 }
925
926 static inline int input_available_p(struct tty_struct *tty)
927 {
928
929 if (L_ICANON(tty)) {
930 if (tty->canon_data || FULL(&tty->read_q))
931 return 1;
932 } else if (!EMPTY(&tty->secondary))
933 return 1;
934
935
936 TTY_READ_FLUSH(tty);
937 if (tty->link)
938 TTY_WRITE_FLUSH(tty->link);
939
940 if (L_ICANON(tty)) {
941 if (tty->canon_data || FULL(&tty->read_q))
942 return 1;
943 } else if (!EMPTY(&tty->secondary))
944 return 1;
945 return 0;
946 }
947
948 static int read_chan(struct tty_struct *tty, struct file *file,
949 unsigned char *buf, unsigned int nr)
950 {
951 struct wait_queue wait = { current, NULL };
952 int c;
953 unsigned char *b = buf;
954 int minimum, time;
955 int retval = 0;
956
957
958
959
960
961
962 if (file->f_inode->i_rdev != CONSOLE_DEV &&
963 current->tty == tty->line) {
964 if (tty->pgrp <= 0)
965 printk("read_chan: tty->pgrp <= 0!\n");
966 else if (current->pgrp != tty->pgrp) {
967 if (is_ignored(SIGTTIN) ||
968 is_orphaned_pgrp(current->pgrp))
969 return -EIO;
970 kill_pg(current->pgrp, SIGTTIN, 1);
971 return -ERESTARTSYS;
972 }
973 }
974
975 if (L_ICANON(tty)) {
976 minimum = time = 0;
977 current->timeout = (unsigned long) -1;
978 } else {
979 time = (HZ / 10) * TIME_CHAR(tty);
980 minimum = MIN_CHAR(tty);
981 if (minimum)
982 current->timeout = (unsigned long) -1;
983 else {
984 if (time) {
985 current->timeout = time + jiffies;
986 time = 0;
987 } else
988 current->timeout = 0;
989 minimum = 1;
990 }
991 }
992
993 add_wait_queue(&tty->secondary.proc_list, &wait);
994 while (1) {
995
996 if (tty->packet && tty->link->ctrl_status) {
997 if (b != buf)
998 break;
999 put_fs_byte(tty->link->ctrl_status, b++);
1000 tty->link->ctrl_status = 0;
1001 break;
1002 }
1003
1004
1005
1006 current->state = TASK_INTERRUPTIBLE;
1007 if (!input_available_p(tty)) {
1008 if (tty->flags & (1 << TTY_SLAVE_CLOSED)) {
1009 retval = -EIO;
1010 break;
1011 }
1012 if (tty_hung_up_p(file))
1013 break;
1014 if (!current->timeout)
1015 break;
1016 if (file->f_flags & O_NONBLOCK) {
1017 retval = -EAGAIN;
1018 break;
1019 }
1020 if (current->signal & ~current->blocked) {
1021 retval = -ERESTARTSYS;
1022 break;
1023 }
1024 schedule();
1025 continue;
1026 }
1027 current->state = TASK_RUNNING;
1028
1029
1030 if (tty->packet && b == buf) {
1031 put_fs_byte(TIOCPKT_DATA, b++);
1032 nr--;
1033 }
1034
1035 while (nr > 0) {
1036 int eol;
1037
1038 cli();
1039 if (EMPTY(&tty->secondary)) {
1040 sti();
1041 break;
1042 }
1043 eol = clear_bit(tty->secondary.tail,
1044 &tty->secondary_flags);
1045 c = tty->secondary.buf[tty->secondary.tail];
1046 INC(tty->secondary.tail);
1047 sti();
1048 if (eol) {
1049 if (--tty->canon_data < 0) {
1050 printk("read_chan: canon_data < 0!\n");
1051 tty->canon_data = 0;
1052 }
1053 if (c == __DISABLED_CHAR)
1054 break;
1055 put_fs_byte(c, b++);
1056 nr--;
1057 break;
1058 }
1059 put_fs_byte(c, b++);
1060 nr--;
1061 }
1062
1063
1064
1065 if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
1066 && !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
1067 tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
1068
1069
1070 if (b - buf >= minimum || !nr)
1071 break;
1072 if (time)
1073 current->timeout = time + jiffies;
1074 }
1075 remove_wait_queue(&tty->secondary.proc_list, &wait);
1076 current->state = TASK_RUNNING;
1077 current->timeout = 0;
1078 return (b - buf) ? b - buf : retval;
1079 }
1080
1081 static int write_chan(struct tty_struct * tty, struct file * file,
1082 unsigned char * buf, unsigned int nr)
1083 {
1084 struct wait_queue wait = { current, NULL };
1085 int c;
1086 unsigned char *b = buf;
1087 int retval = 0;
1088
1089
1090 if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) {
1091 retval = check_change(tty, tty->line);
1092 if (retval)
1093 return retval;
1094 }
1095
1096 add_wait_queue(&tty->write_q.proc_list, &wait);
1097 while (1) {
1098 current->state = TASK_INTERRUPTIBLE;
1099 if (current->signal & ~current->blocked) {
1100 retval = -ERESTARTSYS;
1101 break;
1102 }
1103 if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) {
1104 retval = -EIO;
1105 break;
1106 }
1107 while (nr > 0) {
1108 c = get_fs_byte(b);
1109
1110
1111 if (opost(c, tty) < 0)
1112 break;
1113 b++; nr--;
1114 }
1115 TTY_WRITE_FLUSH(tty);
1116 if (!nr)
1117 break;
1118 if (EMPTY(&tty->write_q) && !need_resched)
1119 continue;
1120 schedule();
1121 }
1122 current->state = TASK_RUNNING;
1123 remove_wait_queue(&tty->write_q.proc_list, &wait);
1124 return (b - buf) ? b - buf : retval;
1125 }
1126
1127 static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
1128 {
1129 int i, dev;
1130 struct tty_struct * tty;
1131
1132 dev = file->f_rdev;
1133 if (MAJOR(dev) != TTY_MAJOR) {
1134 printk("tty_read: bad pseudo-major nr #%d\n", MAJOR(dev));
1135 return -EINVAL;
1136 }
1137 dev = MINOR(dev);
1138 tty = TTY_TABLE(dev);
1139 if (!tty || (tty->flags & (1 << TTY_IO_ERROR)))
1140 return -EIO;
1141
1142
1143
1144
1145
1146 #if 0
1147 if ((inode->i_rdev != CONSOLE_DEV) &&
1148 (tty->pgrp > 0) &&
1149 (current->tty == dev) &&
1150 (tty->pgrp != current->pgrp))
1151 if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
1152 return -EIO;
1153 else {
1154 (void) kill_pg(current->pgrp, SIGTTIN, 1);
1155 return -ERESTARTSYS;
1156 }
1157 #endif
1158 if (ldiscs[tty->disc].read)
1159
1160 i = (ldiscs[tty->disc].read)(tty,file,(unsigned char *)buf,(unsigned int)count);
1161 else
1162 i = -EIO;
1163 if (i > 0)
1164 inode->i_atime = CURRENT_TIME;
1165 return i;
1166 }
1167
1168 static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
1169 {
1170 int dev, i, is_console;
1171 struct tty_struct * tty;
1172
1173 dev = file->f_rdev;
1174 is_console = (inode->i_rdev == CONSOLE_DEV);
1175 if (MAJOR(dev) != TTY_MAJOR) {
1176 printk("tty_write: pseudo-major != TTY_MAJOR\n");
1177 return -EINVAL;
1178 }
1179 dev = MINOR(dev);
1180 if (is_console && redirect)
1181 tty = redirect;
1182 else
1183 tty = TTY_TABLE(dev);
1184 if (!tty || !tty->write || (tty->flags & (1 << TTY_IO_ERROR)))
1185 return -EIO;
1186 #if 0
1187 if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) &&
1188 (current->tty == dev) && (tty->pgrp != current->pgrp)) {
1189 if (is_orphaned_pgrp(current->pgrp))
1190 return -EIO;
1191 if (!is_ignored(SIGTTOU)) {
1192 (void) kill_pg(current->pgrp, SIGTTOU, 1);
1193 return -ERESTARTSYS;
1194 }
1195 }
1196 #endif
1197 if (ldiscs[tty->disc].write)
1198
1199 i = (ldiscs[tty->disc].write)(tty,file,(unsigned char *)buf,(unsigned int)count);
1200 else
1201 i = -EIO;
1202 if (i > 0)
1203 inode->i_mtime = CURRENT_TIME;
1204 return i;
1205 }
1206
1207
1208
1209
1210
1211
1212 static int init_dev(int dev)
1213 {
1214 struct tty_struct *tty, *o_tty;
1215 struct termios *tp, *o_tp, *ltp, *o_ltp;
1216 int retval;
1217 int o_dev;
1218
1219 o_dev = PTY_OTHER(dev);
1220 tty = o_tty = NULL;
1221 tp = o_tp = NULL;
1222 ltp = o_ltp = NULL;
1223 repeat:
1224 retval = -EAGAIN;
1225 if (IS_A_PTY_MASTER(dev) && tty_table[dev] && tty_table[dev]->count)
1226 goto end_init;
1227 retval = -ENOMEM;
1228 if (!tty_table[dev] && !tty) {
1229 if (!(tty = (struct tty_struct*) get_free_page(GFP_KERNEL)))
1230 goto end_init;
1231 initialize_tty_struct(dev, tty);
1232 goto repeat;
1233 }
1234 if (!tty_termios[dev] && !tp) {
1235 tp = (struct termios *) kmalloc(sizeof(struct termios),
1236 GFP_KERNEL);
1237 if (!tp)
1238 goto end_init;
1239 initialize_termios(dev, tp);
1240 goto repeat;
1241 }
1242 if (!termios_locked[dev] && !ltp) {
1243 ltp = (struct termios *) kmalloc(sizeof(struct termios),
1244 GFP_KERNEL);
1245 if (!ltp)
1246 goto end_init;
1247 memset(ltp, 0, sizeof(struct termios));
1248 goto repeat;
1249 }
1250 if (IS_A_PTY(dev)) {
1251 if (!tty_table[o_dev] && !o_tty) {
1252 o_tty = (struct tty_struct *)
1253 get_free_page(GFP_KERNEL);
1254 if (!o_tty)
1255 goto end_init;
1256 initialize_tty_struct(o_dev, o_tty);
1257 goto repeat;
1258 }
1259 if (!tty_termios[o_dev] && !o_tp) {
1260 o_tp = (struct termios *)
1261 kmalloc(sizeof(struct termios), GFP_KERNEL);
1262 if (!o_tp)
1263 goto end_init;
1264 initialize_termios(o_dev, o_tp);
1265 goto repeat;
1266 }
1267 if (!termios_locked[o_dev] && !o_ltp) {
1268 o_ltp = (struct termios *)
1269 kmalloc(sizeof(struct termios), GFP_KERNEL);
1270 if (!o_ltp)
1271 goto end_init;
1272 memset(o_ltp, 0, sizeof(struct termios));
1273 goto repeat;
1274 }
1275
1276 }
1277
1278 if (!tty_termios[dev]) {
1279 tty_termios[dev] = tp;
1280 tp = NULL;
1281 }
1282 if (!tty_table[dev]) {
1283 tty->termios = tty_termios[dev];
1284 tty_table[dev] = tty;
1285 tty = NULL;
1286 }
1287 if (!termios_locked[dev]) {
1288 termios_locked[dev] = ltp;
1289 ltp = NULL;
1290 }
1291 if (IS_A_PTY(dev)) {
1292 if (!tty_termios[o_dev]) {
1293 tty_termios[o_dev] = o_tp;
1294 o_tp = NULL;
1295 }
1296 if (!termios_locked[o_dev]) {
1297 termios_locked[o_dev] = o_ltp;
1298 o_ltp = NULL;
1299 }
1300 if (!tty_table[o_dev]) {
1301 o_tty->termios = tty_termios[o_dev];
1302 tty_table[o_dev] = o_tty;
1303 o_tty = NULL;
1304 }
1305 tty_table[dev]->link = tty_table[o_dev];
1306 tty_table[o_dev]->link = tty_table[dev];
1307 }
1308 tty_table[dev]->count++;
1309 if (IS_A_PTY_MASTER(dev))
1310 tty_table[o_dev]->count++;
1311 retval = 0;
1312 end_init:
1313 if (tty)
1314 free_page((unsigned long) tty);
1315 if (o_tty)
1316 free_page((unsigned long) o_tty);
1317 if (tp)
1318 kfree_s(tp, sizeof(struct termios));
1319 if (o_tp)
1320 kfree_s(o_tp, sizeof(struct termios));
1321 if (ltp)
1322 kfree_s(ltp, sizeof(struct termios));
1323 if (o_ltp)
1324 kfree_s(o_ltp, sizeof(struct termios));
1325 return retval;
1326 }
1327
1328
1329
1330
1331
1332
1333 static void release_dev(int dev, struct file * filp)
1334 {
1335 struct tty_struct *tty, *o_tty;
1336 struct termios *tp, *o_tp;
1337 struct task_struct **p;
1338
1339 tty = tty_table[dev];
1340 tp = tty_termios[dev];
1341 o_tty = NULL;
1342 o_tp = NULL;
1343 if (!tty) {
1344 printk("release_dev: tty_table[%d] was NULL\n", dev);
1345 return;
1346 }
1347 if (!tp) {
1348 printk("release_dev: tty_termios[%d] was NULL\n", dev);
1349 return;
1350 }
1351 #ifdef TTY_DEBUG_HANGUP
1352 printk("release_dev of tty%d (tty count=%d)...", dev, tty->count);
1353 #endif
1354 if (IS_A_PTY(dev)) {
1355 o_tty = tty_table[PTY_OTHER(dev)];
1356 o_tp = tty_termios[PTY_OTHER(dev)];
1357 if (!o_tty) {
1358 printk("release_dev: pty pair(%d) was NULL\n", dev);
1359 return;
1360 }
1361 if (!o_tp) {
1362 printk("release_dev: pty pair(%d) termios was NULL\n", dev);
1363 return;
1364 }
1365 if (tty->link != o_tty || o_tty->link != tty) {
1366 printk("release_dev: bad pty pointers\n");
1367 return;
1368 }
1369 }
1370 tty->write_data_cnt = 0;
1371 if (tty->close)
1372 tty->close(tty, filp);
1373 if (IS_A_PTY_MASTER(dev)) {
1374 if (--tty->link->count < 0) {
1375 printk("release_dev: bad tty slave count (dev = %d): %d\n",
1376 dev, tty->count);
1377 tty->link->count = 0;
1378 }
1379 }
1380 if (--tty->count < 0) {
1381 printk("release_dev: bad tty_table[%d]->count: %d\n",
1382 dev, tty->count);
1383 tty->count = 0;
1384 }
1385 if (tty->count)
1386 return;
1387
1388 #ifdef TTY_DEBUG_HANGUP
1389 printk("freeing tty structure...");
1390 #endif
1391
1392
1393
1394
1395
1396 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
1397 if ((*p) && (*p)->tty == tty->line)
1398 (*p)->tty = -1;
1399 }
1400
1401
1402
1403
1404
1405 if (ldiscs[tty->disc].close != NULL)
1406 ldiscs[tty->disc].close(tty);
1407 tty->disc = N_TTY;
1408 tty->termios->c_line = N_TTY;
1409
1410 if (o_tty) {
1411 if (o_tty->count)
1412 return;
1413 else {
1414 tty_table[PTY_OTHER(dev)] = NULL;
1415 tty_termios[PTY_OTHER(dev)] = NULL;
1416 }
1417 }
1418 tty_table[dev] = NULL;
1419 if (IS_A_PTY(dev)) {
1420 tty_termios[dev] = NULL;
1421 kfree_s(tp, sizeof(struct termios));
1422 }
1423 if (tty == redirect || o_tty == redirect)
1424 redirect = NULL;
1425 free_page((unsigned long) tty);
1426 if (o_tty)
1427 free_page((unsigned long) o_tty);
1428 if (o_tp)
1429 kfree_s(o_tp, sizeof(struct termios));
1430 }
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444 static int tty_open(struct inode * inode, struct file * filp)
1445 {
1446 struct tty_struct *tty;
1447 int major, minor;
1448 int noctty, retval;
1449
1450 retry_open:
1451 minor = MINOR(inode->i_rdev);
1452 major = MAJOR(inode->i_rdev);
1453 noctty = filp->f_flags & O_NOCTTY;
1454 if (major == TTYAUX_MAJOR) {
1455 if (!minor) {
1456 major = TTY_MAJOR;
1457 minor = current->tty;
1458 }
1459
1460 } else if (major == TTY_MAJOR) {
1461 if (!minor) {
1462 minor = fg_console + 1;
1463 noctty = 1;
1464 }
1465 } else {
1466 printk("Bad major #%d in tty_open\n", MAJOR(inode->i_rdev));
1467 return -ENODEV;
1468 }
1469 if (minor <= 0)
1470 return -ENXIO;
1471 if (IS_A_PTY_MASTER(minor))
1472 noctty = 1;
1473 filp->f_rdev = (major << 8) | minor;
1474 retval = init_dev(minor);
1475 if (retval)
1476 return retval;
1477 tty = tty_table[minor];
1478 #ifdef TTY_DEBUG_HANGUP
1479 printk("opening tty%d...", tty->line);
1480 #endif
1481 if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser())
1482 return -EBUSY;
1483
1484 #if 0
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497 tty->ctrl_status = 0;
1498 tty->packet = 0;
1499 #endif
1500
1501 if (tty->open) {
1502 retval = tty->open(tty, filp);
1503 } else {
1504 retval = -ENODEV;
1505 }
1506 if (retval) {
1507 #ifdef TTY_DEBUG_HANGUP
1508 printk("error %d in opening tty%d...", retval, tty->line);
1509 #endif
1510
1511 release_dev(minor, filp);
1512 if (retval != -ERESTARTSYS)
1513 return retval;
1514 if (current->signal & ~current->blocked)
1515 return retval;
1516 schedule();
1517 goto retry_open;
1518 }
1519 if (!noctty &&
1520 current->leader &&
1521 current->tty<0 &&
1522 tty->session==0) {
1523 current->tty = minor;
1524 tty->session = current->session;
1525 tty->pgrp = current->pgrp;
1526 }
1527 filp->f_rdev = MKDEV(TTY_MAJOR,minor);
1528 return 0;
1529 }
1530
1531
1532
1533
1534
1535
1536 static void tty_release(struct inode * inode, struct file * filp)
1537 {
1538 int dev;
1539
1540 dev = filp->f_rdev;
1541 if (MAJOR(dev) != TTY_MAJOR) {
1542 printk("tty_release: tty pseudo-major != TTY_MAJOR\n");
1543 return;
1544 }
1545 dev = MINOR(filp->f_rdev);
1546 if (!dev) {
1547 printk("tty_release: bad f_rdev\n");
1548 return;
1549 }
1550 release_dev(dev, filp);
1551 }
1552
1553 static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
1554 {
1555 int dev;
1556 struct tty_struct * tty;
1557
1558 dev = filp->f_rdev;
1559 if (MAJOR(dev) != TTY_MAJOR) {
1560 printk("tty_select: tty pseudo-major != TTY_MAJOR\n");
1561 return 0;
1562 }
1563 dev = MINOR(filp->f_rdev);
1564 tty = TTY_TABLE(dev);
1565 if (!tty) {
1566 printk("tty_select: tty struct for dev %d was NULL\n", dev);
1567 return 0;
1568 }
1569 if (ldiscs[tty->disc].select)
1570 return (ldiscs[tty->disc].select)(tty, inode, filp,
1571 sel_type, wait);
1572 return 0;
1573 }
1574
1575 static int normal_select(struct tty_struct * tty, struct inode * inode,
1576 struct file * file, int sel_type, select_table *wait)
1577 {
1578 switch (sel_type) {
1579 case SEL_IN:
1580 if (input_available_p(tty))
1581 return 1;
1582
1583 case SEL_EX:
1584 if (tty->packet && tty->link->ctrl_status)
1585 return 1;
1586 if (tty->flags & (1 << TTY_SLAVE_CLOSED))
1587 return 1;
1588 if (tty_hung_up_p(file))
1589 return 1;
1590 select_wait(&tty->secondary.proc_list, wait);
1591 return 0;
1592 case SEL_OUT:
1593 if (!FULL(&tty->write_q))
1594 return 1;
1595 select_wait(&tty->write_q.proc_list, wait);
1596 return 0;
1597 }
1598 return 0;
1599 }
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613 void do_SAK( struct tty_struct *tty)
1614 {
1615 #ifdef TTY_SOFT_SAK
1616 tty_hangup(tty);
1617 #else
1618 struct task_struct **p;
1619 int line = tty->line;
1620 int session = tty->session;
1621 int i;
1622 struct file *filp;
1623
1624 flush_input(tty);
1625 flush_output(tty);
1626 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
1627 if (!(*p))
1628 continue;
1629 if (((*p)->tty == line) ||
1630 ((session > 0) && ((*p)->session == session)))
1631 send_sig(SIGKILL, *p, 1);
1632 else {
1633 for (i=0; i < NR_OPEN; i++) {
1634 filp = (*p)->filp[i];
1635 if (filp && (filp->f_op == &tty_fops) &&
1636 (MINOR(filp->f_rdev) == line)) {
1637 send_sig(SIGKILL, *p, 1);
1638 break;
1639 }
1640 }
1641 }
1642 }
1643 #endif
1644 }
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661 int tty_write_data(struct tty_struct *tty, char *bufp, int buflen,
1662 void (*callback)(void * data), void * callarg)
1663 {
1664 int head, tail, count;
1665 unsigned long flags;
1666 char *p;
1667
1668 #define VLEFT ((tail-head-1)&(TTY_BUF_SIZE-1))
1669
1670 save_flags(flags);
1671 cli();
1672 if (tty->write_data_cnt) {
1673 restore_flags(flags);
1674 return -EBUSY;
1675 }
1676
1677 head = tty->write_q.head;
1678 tail = tty->write_q.tail;
1679 count = buflen;
1680 p = bufp;
1681
1682 while (count && VLEFT > 0) {
1683 tty->write_q.buf[head++] = *p++;
1684 head &= TTY_BUF_SIZE-1;
1685 count--;
1686 }
1687 tty->write_q.head = head;
1688 if (count) {
1689 tty->write_data_cnt = count;
1690 tty->write_data_ptr = (unsigned char *) p;
1691 tty->write_data_callback = callback;
1692 tty->write_data_arg = callarg;
1693 }
1694 restore_flags(flags);
1695 tty->write(tty);
1696 return count;
1697 }
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707 void tty_bh_routine(void * unused)
1708 {
1709 int i, j, line, mask;
1710 int head, tail, count;
1711 unsigned char * p;
1712 struct tty_struct * tty;
1713
1714 for (i = 0, line = 0; i < MAX_TTYS / 32; i++) {
1715 if (!tty_check_write[i]) {
1716 line += 32;
1717 continue;
1718 }
1719 for (j=0, mask=0; j < 32; j++, line++, mask <<= 1) {
1720 if (clear_bit(j, &tty_check_write[i])) {
1721 tty = tty_table[line];
1722 if (!tty || !tty->write_data_cnt)
1723 continue;
1724 cli();
1725 head = tty->write_q.head;
1726 tail = tty->write_q.tail;
1727 count = tty->write_data_cnt;
1728 p = tty->write_data_ptr;
1729
1730 while (count && VLEFT > 0) {
1731 tty->write_q.buf[head++] = *p++;
1732 head &= TTY_BUF_SIZE-1;
1733 count--;
1734 }
1735 tty->write_q.head = head;
1736 tty->write_data_ptr = p;
1737 tty->write_data_cnt = count;
1738 sti();
1739 if (!count)
1740 (tty->write_data_callback)
1741 (tty->write_data_arg);
1742 }
1743 }
1744 }
1745
1746 }
1747
1748
1749
1750
1751
1752 static void initialize_tty_struct(int line, struct tty_struct *tty)
1753 {
1754 memset(tty, 0, sizeof(struct tty_struct));
1755 tty->line = line;
1756 tty->disc = N_TTY;
1757 tty->pgrp = -1;
1758 if (IS_A_CONSOLE(line)) {
1759 tty->open = con_open;
1760 tty->winsize.ws_row = video_num_lines;
1761 tty->winsize.ws_col = video_num_columns;
1762 } else if IS_A_SERIAL(line) {
1763 tty->open = rs_open;
1764 } else if IS_A_PTY(line) {
1765 tty->open = pty_open;
1766 }
1767 }
1768
1769 static void initialize_termios(int line, struct termios * tp)
1770 {
1771 memset(tp, 0, sizeof(struct termios));
1772 memcpy(tp->c_cc, INIT_C_CC, NCCS);
1773 if (IS_A_CONSOLE(line) || IS_A_PTY_SLAVE(line)) {
1774 tp->c_iflag = ICRNL | IXON;
1775 tp->c_oflag = OPOST | ONLCR;
1776 tp->c_cflag = B38400 | CS8 | CREAD;
1777 tp->c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
1778 ECHOCTL | ECHOKE | IEXTEN;
1779 } else if (IS_A_SERIAL(line)) {
1780 tp->c_iflag = ICRNL | IXON;
1781 tp->c_oflag = OPOST | ONLCR | XTABS;
1782 tp->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1783 tp->c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
1784 ECHOCTL | ECHOKE | IEXTEN;
1785 } else if (IS_A_PTY_MASTER(line))
1786 tp->c_cflag = B9600 | CS8 | CREAD;
1787 }
1788
1789 static struct tty_ldisc tty_ldisc_N_TTY = {
1790 0,
1791 NULL,
1792 NULL,
1793 read_chan,
1794 write_chan,
1795 NULL,
1796 normal_select,
1797 copy_to_cooked
1798 };
1799
1800
1801 long tty_init(long kmem_start)
1802 {
1803 int i;
1804
1805 if (sizeof(struct tty_struct) > PAGE_SIZE)
1806 panic("size of tty structure > PAGE_SIZE!");
1807 if (register_chrdev(TTY_MAJOR,"tty",&tty_fops))
1808 panic("unable to get major %d for tty device", TTY_MAJOR);
1809 if (register_chrdev(TTYAUX_MAJOR,"tty",&tty_fops))
1810 panic("unable to get major %d for tty device", TTYAUX_MAJOR);
1811 for (i=0 ; i< MAX_TTYS ; i++) {
1812 tty_table[i] = 0;
1813 tty_termios[i] = 0;
1814 }
1815 memset(tty_check_write, 0, sizeof(tty_check_write));
1816 bh_base[TTY_BH].routine = tty_bh_routine;
1817
1818
1819 memset(ldiscs, 0, sizeof(ldiscs));
1820 (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
1821
1822 kmem_start = kbd_init(kmem_start);
1823 kmem_start = con_init(kmem_start);
1824 kmem_start = rs_init(kmem_start);
1825 return kmem_start;
1826 }