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