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