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