root/kernel/chr_drv/tty_io.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. put_tty_queue
  2. get_tty_queue
  3. tty_write_flush
  4. tty_read_flush
  5. change_console
  6. sleep_if_empty
  7. wait_for_keypress
  8. copy_to_cooked
  9. is_ignored
  10. tty_signal
  11. wait_for_canon_input
  12. read_chan
  13. write_chan
  14. tty_read
  15. tty_write
  16. tty_lseek
  17. tty_open
  18. tty_release
  19. tty_select
  20. tty_init

   1 /*
   2  *  linux/kernel/tty_io.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
   9  * or rs-channels. It also implements echoing, cooked mode etc.
  10  *
  11  * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
  12  */
  13 
  14 #include <linux/types.h>
  15 #include <linux/errno.h>
  16 #include <linux/signal.h>
  17 #include <linux/fcntl.h>
  18 #include <linux/sched.h>
  19 #include <linux/tty.h>
  20 #include <linux/ctype.h>
  21 
  22 #include <asm/io.h>
  23 #include <asm/segment.h>
  24 #include <asm/system.h>
  25 
  26 #include <sys/kd.h>
  27 #include "vt_kern.h"
  28 
  29 #define QUEUES  (3*(NR_CONSOLES+NR_SERIALS+2*NR_PTYS))
  30 static struct tty_queue * tty_queues;
  31 struct tty_struct tty_table[256];
  32 
  33 #define con_queues tty_queues
  34 #define rs_queues ((3*NR_CONSOLES) + tty_queues)
  35 #define mpty_queues ((3*(NR_CONSOLES+NR_SERIALS)) + tty_queues)
  36 #define spty_queues ((3*(NR_CONSOLES+NR_SERIALS+NR_PTYS)) + tty_queues)
  37 
  38 #define con_table tty_table
  39 #define rs_table (64+tty_table)
  40 #define mpty_table (128+tty_table)
  41 #define spty_table (192+tty_table)
  42 
  43 /*
  44  * fg_console is the current virtual console,
  45  * redirect is the pseudo-tty that console output
  46  * is redirected to if asked by TIOCCONS.
  47  */
  48 int fg_console = 0;
  49 struct tty_struct * redirect = NULL;
  50 
  51 /*
  52  * these are the tables used by the machine code handlers.
  53  * you can implement virtual consoles.
  54  */
  55 struct tty_queue * table_list[] = { NULL, NULL };
  56 
  57 void inline put_tty_queue(char c, struct tty_queue * queue)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         int head;
  60         unsigned long flags;
  61 
  62         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
  63         head = (queue->head + 1) & (TTY_BUF_SIZE-1);
  64         if (head != queue->tail) {
  65                 queue->buf[queue->head] = c;
  66                 queue->head = head;
  67         }
  68         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
  69 }
  70 
  71 int inline get_tty_queue(struct tty_queue * queue)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         int result = -1;
  74         unsigned long flags;
  75 
  76         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
  77         if (queue->tail != queue->head) {
  78                 result = 0xff & queue->buf[queue->tail];
  79                 queue->tail = (queue->tail + 1) & (TTY_BUF_SIZE-1);
  80         }
  81         __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
  82         return result;
  83 }
  84 
  85 void inline tty_write_flush(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87         if (EMPTY(tty->write_q))
  88                 return;
  89         if (set_bit(TTY_WRITE_BUSY,&tty->flags))
  90                 return;
  91         tty->write(tty);
  92         if (clear_bit(TTY_WRITE_BUSY,&tty->flags))
  93                 printk("tty_write_flush: bit already cleared\n");
  94 }
  95 
  96 void tty_read_flush(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98         if (EMPTY(tty->read_q))
  99                 return;
 100         if (set_bit(TTY_READ_BUSY, &tty->flags))
 101                 return;
 102         copy_to_cooked(tty);
 103         if (clear_bit(TTY_READ_BUSY, &tty->flags))
 104                 printk("tty_read_flush: bit already cleared\n");
 105 }
 106 
 107 void change_console(unsigned int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
 110                 return;
 111         if (new_console == fg_console || new_console >= NR_CONSOLES)
 112                 return;
 113         table_list[0] = con_queues + 0 + new_console*3;
 114         table_list[1] = con_queues + 1 + new_console*3;
 115         update_screen(new_console);
 116 }
 117 
 118 static void sleep_if_empty(struct tty_queue * queue)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120         cli();
 121         while (!(current->signal & ~current->blocked) && EMPTY(queue))
 122                 interruptible_sleep_on(&queue->proc_list);
 123         sti();
 124 }
 125 
 126 void wait_for_keypress(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128         sleep_if_empty(tty_table[fg_console].secondary);
 129         flush_input(&tty_table[fg_console]);
 130 }
 131 
 132 void copy_to_cooked(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 133 {
 134         int c;
 135 
 136         if (!(tty && tty->write && tty->read_q &&
 137             tty->write_q && tty->secondary)) {
 138                 printk("copy_to_cooked: missing queues\n\r");
 139                 return;
 140         }
 141         while (1) {
 142                 if (FULL(tty->secondary))
 143                         break;
 144                 c = get_tty_queue(tty->read_q);
 145                 if (c < 0)
 146                         break;
 147                 if (I_STRP(tty))
 148                         c &= 0x7f;
 149                 if (c==13) {
 150                         if (I_CRNL(tty))
 151                                 c=10;
 152                         else if (I_NOCR(tty))
 153                                 continue;
 154                 } else if (c==10 && I_NLCR(tty))
 155                         c=13;
 156                 if (I_UCLC(tty))
 157                         c=tolower(c);
 158                 if (L_CANON(tty)) {
 159                         if ((KILL_CHAR(tty) != __DISABLED_CHAR) &&
 160                             (c==KILL_CHAR(tty))) {
 161                                 /* deal with killing the input line */
 162                                 while(!(EMPTY(tty->secondary) ||
 163                                         (c=LAST(tty->secondary))==10 ||
 164                                         ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
 165                                          (c==EOF_CHAR(tty))))) {
 166                                         if (L_ECHO(tty)) {
 167                                                 if (c<32) {
 168                                                         put_tty_queue(8,tty->write_q);
 169                                                         put_tty_queue(' ',tty->write_q);
 170                                                         put_tty_queue(8,tty->write_q);
 171                                                 }
 172                                                 put_tty_queue(8,tty->write_q);
 173                                                 put_tty_queue(' ',tty->write_q);
 174                                                 put_tty_queue(8,tty->write_q);
 175                                         }
 176                                         DEC(tty->secondary->head);
 177                                 }
 178                                 continue;
 179                         }
 180                         if ((ERASE_CHAR(tty) != __DISABLED_CHAR) &&
 181                             (c==ERASE_CHAR(tty))) {
 182                                 if (EMPTY(tty->secondary) ||
 183                                    (c=LAST(tty->secondary))==10 ||
 184                                    ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
 185                                     (c==EOF_CHAR(tty))))
 186                                         continue;
 187                                 if (L_ECHO(tty)) {
 188                                         if (c<32) {
 189                                                 put_tty_queue(8,tty->write_q);
 190                                                 put_tty_queue(' ',tty->write_q);
 191                                                 put_tty_queue(8,tty->write_q);
 192                                         }
 193                                         put_tty_queue(8,tty->write_q);
 194                                         put_tty_queue(32,tty->write_q);
 195                                         put_tty_queue(8,tty->write_q);
 196                                 }
 197                                 DEC(tty->secondary->head);
 198                                 continue;
 199                         }
 200                 }
 201                 if (I_IXON(tty)) {
 202                         if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
 203                             (c==STOP_CHAR(tty))) {
 204                                 tty->stopped=1;
 205                                 continue;
 206                         }
 207                         if ((START_CHAR(tty) != __DISABLED_CHAR) &&
 208                             (c==START_CHAR(tty))) {
 209                                 tty->stopped=0;
 210                                 continue;
 211                         }
 212                 }
 213                 if (L_ISIG(tty)) {
 214                         if ((INTR_CHAR(tty) != __DISABLED_CHAR) &&
 215                             (c==INTR_CHAR(tty))) {
 216                                 kill_pg(tty->pgrp, SIGINT, 1);
 217                                 flush_input(tty);
 218                                 continue;
 219                         }
 220                         if ((QUIT_CHAR(tty) != __DISABLED_CHAR) &&
 221                             (c==QUIT_CHAR(tty))) {
 222                                 kill_pg(tty->pgrp, SIGQUIT, 1);
 223                                 flush_input(tty);
 224                                 continue;
 225                         }
 226                         if ((SUSPEND_CHAR(tty) != __DISABLED_CHAR) &&
 227                             (c==SUSPEND_CHAR(tty))) {
 228                                 if (!is_orphaned_pgrp(tty->pgrp))
 229                                         kill_pg(tty->pgrp, SIGTSTP, 1);
 230                                 continue;
 231                         }
 232                 }
 233                 if (c==10 || (EOF_CHAR(tty) != __DISABLED_CHAR &&
 234                     c==EOF_CHAR(tty)))
 235                         tty->secondary->data++;
 236                 if ((c==10) && (L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty)))) {
 237                         put_tty_queue(10,tty->write_q);
 238                         put_tty_queue(13,tty->write_q);
 239                 } else if (L_ECHO(tty)) {
 240                         if (c<32 && L_ECHOCTL(tty)) {
 241                                 put_tty_queue('^',tty->write_q);
 242                                 put_tty_queue(c+64,tty->write_q);
 243                         } else
 244                                 put_tty_queue(c,tty->write_q);
 245                 }
 246                 put_tty_queue(c,tty->secondary);
 247         }
 248         TTY_WRITE_FLUSH(tty);
 249         if (!EMPTY(tty->secondary))
 250                 wake_up(&tty->secondary->proc_list);
 251         if (tty->write_q->proc_list && LEFT(tty->write_q) > TTY_BUF_SIZE/2)
 252                 wake_up(&tty->write_q->proc_list);
 253 }
 254 
 255 int is_ignored(int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257         return ((current->blocked & (1<<(sig-1))) ||
 258                 (current->sigaction[sig-1].sa_handler == SIG_IGN));
 259 }
 260 
 261 /*
 262  * Called when we need to send a SIGTTIN or SIGTTOU to our process
 263  * group
 264  * 
 265  * We only request that a system call be restarted if there was if the 
 266  * default signal handler is being used.  The reason for this is that if
 267  * a job is catching SIGTTIN or SIGTTOU, the signal handler may not want 
 268  * the system call to be restarted blindly.  If there is no way to reset the
 269  * terminal pgrp back to the current pgrp (perhaps because the controlling
 270  * tty has been released on logout), we don't want to be in an infinite loop
 271  * while restarting the system call, and have it always generate a SIGTTIN
 272  * or SIGTTOU.  The default signal handler will cause the process to stop
 273  * thus avoiding the infinite loop problem.  Presumably the job-control
 274  * cognizant parent will fix things up before continuging its child process.
 275  */
 276 int tty_signal(int sig, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 277 {
 278         (void) kill_pg(current->pgrp,sig,1);
 279         return -ERESTARTSYS;
 280 }
 281 
 282 static void wait_for_canon_input(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 283 {
 284         while (1) {
 285                 TTY_READ_FLUSH(tty);
 286                 if (tty->link)
 287                         if (tty->link->count)
 288                                 TTY_WRITE_FLUSH(tty->link);
 289                         else
 290                                 return;
 291                 if (current->signal & ~current->blocked)
 292                         return;
 293                 if (FULL(tty->read_q))
 294                         return;
 295                 if (tty->secondary->data)
 296                         return;
 297                 cli();
 298                 if (!tty->secondary->data)
 299                         interruptible_sleep_on(&tty->secondary->proc_list);
 300                 sti();
 301         }
 302 }
 303 
 304 static int read_chan(unsigned int channel, struct file * file, char * buf, int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 305 {
 306         struct tty_struct * tty;
 307         int c;
 308         char * b=buf;
 309         int minimum,time;
 310 
 311         if (channel > 255)
 312                 return -EIO;
 313         tty = TTY_TABLE(channel);
 314         if (!(tty->read_q && tty->secondary))
 315                 return -EIO;
 316         if ((tty->pgrp > 0) &&
 317             (current->tty == channel) &&
 318             (tty->pgrp != current->pgrp))
 319                 if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
 320                         return -EIO;
 321                 else
 322                         return(tty_signal(SIGTTIN, tty));
 323         if (L_CANON(tty))
 324                 minimum = time = current->timeout = 0;
 325         else {
 326                 time = 10L*tty->termios.c_cc[VTIME];
 327                 minimum = tty->termios.c_cc[VMIN];
 328                 if (minimum)
 329                         current->timeout = 0xffffffff;
 330                 else {
 331                         if (time)
 332                                 current->timeout = time + jiffies;
 333                         else
 334                                 current->timeout = 0;
 335                         time = 0;
 336                         minimum = 1;
 337                 }
 338         }
 339         if (file->f_flags & O_NONBLOCK)
 340                 time = current->timeout = 0;
 341         else if (L_CANON(tty))
 342                 wait_for_canon_input(tty);
 343         if (minimum>nr)
 344                 minimum = nr;
 345         while (nr>0) {
 346                 TTY_READ_FLUSH(tty);
 347                 if (tty->link)
 348                         TTY_WRITE_FLUSH(tty->link);
 349                 while (nr > 0 && ((c = get_tty_queue(tty->secondary)) >= 0)) {
 350                         if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
 351                              c==EOF_CHAR(tty)) || c==10)
 352                                 tty->secondary->data--;
 353                         if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
 354                              c==EOF_CHAR(tty)) && L_CANON(tty))
 355                                 break;
 356                         put_fs_byte(c,b++);
 357                         nr--;
 358                         if (time)
 359                                 current->timeout = time+jiffies;
 360                         if (c==10 && L_CANON(tty))
 361                                 break;
 362                 };
 363                 wake_up(&tty->read_q->proc_list);
 364                 if (b-buf >= minimum || !current->timeout)
 365                         break;
 366                 if (current->signal & ~current->blocked) 
 367                         break;
 368                 if (tty->link && !tty->link->count)
 369                         break;
 370                 TTY_READ_FLUSH(tty);
 371                 if (tty->link)
 372                         TTY_WRITE_FLUSH(tty->link);
 373                 cli();
 374                 if (EMPTY(tty->secondary))
 375                         interruptible_sleep_on(&tty->secondary->proc_list);
 376                 sti();
 377         }
 378         TTY_READ_FLUSH(tty);
 379         if (tty->link && tty->link->write)
 380                 TTY_WRITE_FLUSH(tty->link);
 381         current->timeout = 0;
 382         if (b-buf)
 383                 return b-buf;
 384         if (current->signal & ~current->blocked)
 385                 return -ERESTARTSYS;
 386         if (file->f_flags & O_NONBLOCK)
 387                 return -EAGAIN;
 388         return 0;
 389 }
 390 
 391 static int write_chan(unsigned int channel, struct file * file, char * buf, int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 392 {
 393         struct tty_struct * tty;
 394         char c, *b=buf;
 395 
 396         if (channel > 255)
 397                 return -EIO;
 398         tty = TTY_TABLE(channel);
 399         if (L_TOSTOP(tty) && (tty->pgrp > 0) &&
 400             (current->tty == channel) && (tty->pgrp != current->pgrp)) {
 401                 if (is_orphaned_pgrp(tty->pgrp))
 402                         return -EIO;
 403                 if (!is_ignored(SIGTTOU))
 404                         return tty_signal(SIGTTOU, tty);
 405         }
 406         if (nr < 0)
 407                 return -EINVAL;
 408         if (!nr)
 409                 return 0;
 410         if (redirect && tty == TTY_TABLE(0))
 411                 tty = redirect;
 412         if (!(tty->write_q && tty->write))
 413                 return -EIO;
 414         while (nr>0) {
 415                 if (current->signal & ~current->blocked)
 416                         break;
 417                 if (tty->link && !tty->link->count) {
 418                         send_sig(SIGPIPE,current,0);
 419                         break;
 420                 }
 421                 if (FULL(tty->write_q)) {
 422                         TTY_WRITE_FLUSH(tty);
 423                         cli();
 424                         if (FULL(tty->write_q))
 425                                 interruptible_sleep_on(&tty->write_q->proc_list);
 426                         sti();
 427                         continue;
 428                 }
 429                 while (nr>0 && !FULL(tty->write_q)) {
 430                         c=get_fs_byte(b);
 431                         if (O_POST(tty)) {
 432                                 if (c=='\r' && O_CRNL(tty))
 433                                         c='\n';
 434                                 else if (c=='\n' && O_NLRET(tty))
 435                                         c='\r';
 436                                 if (c=='\n' && O_NLCR(tty) &&
 437                                     !set_bit(TTY_CR_PENDING,&tty->flags)) {
 438                                         put_tty_queue(13,tty->write_q);
 439                                         continue;
 440                                 }
 441                                 if (O_LCUC(tty))
 442                                         c=toupper(c);
 443                         }
 444                         b++; nr--;
 445                         clear_bit(TTY_CR_PENDING,&tty->flags);
 446                         put_tty_queue(c,tty->write_q);
 447                 }
 448                 if (nr>0)
 449                         schedule();
 450         }
 451         TTY_WRITE_FLUSH(tty);
 452         if (b-buf)
 453                 return b-buf;
 454         if (tty->link && !tty->link->count)
 455                 return -EPIPE;
 456         if (current->signal & ~current->blocked)
 457                 return -ERESTARTSYS;
 458         return 0;
 459 }
 460 
 461 static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463         int i;
 464 
 465         if (MAJOR(file->f_rdev) != 4) {
 466                 printk("tty_read: pseudo-major != 4\n");
 467                 return -EINVAL;
 468         }
 469         i = read_chan(MINOR(file->f_rdev),file,buf,count);
 470         if (i > 0)
 471                 inode->i_atime = CURRENT_TIME;
 472         return i;
 473 }
 474 
 475 static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 476 {
 477         int i;
 478         
 479         if (MAJOR(file->f_rdev) != 4) {
 480                 printk("tty_write: pseudo-major != 4\n");
 481                 return -EINVAL;
 482         }
 483         i = write_chan(MINOR(file->f_rdev),file,buf,count);
 484         if (i > 0)
 485                 inode->i_mtime = CURRENT_TIME;
 486         return i;
 487 }
 488 
 489 static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 490 {
 491         return -EBADF;
 492 }
 493 
 494 /*
 495  * tty_open and tty_release keep up the tty count that contains the
 496  * number of opens done on a tty. We cannot use the inode-count, as
 497  * different inodes might point to the same tty.
 498  *
 499  * Open-counting is needed for pty masters, as well as for keeping
 500  * track of serial lines: DTR is dropped when the last close happens.
 501  */
 502 static int tty_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 503 {
 504         struct tty_struct *tty;
 505         int dev, retval;
 506 
 507         dev = inode->i_rdev;
 508         if (MAJOR(dev) == 5)
 509                 dev = current->tty;
 510         else
 511                 dev = MINOR(dev);
 512         if (dev < 0)
 513                 return -ENODEV;
 514         filp->f_rdev = 0x0400 | dev;
 515         tty = TTY_TABLE(dev);
 516         if (!tty->count && !(tty->link && tty->link->count)) {
 517                 flush_input(tty);
 518                 flush_output(tty);
 519                 tty->stopped = 0;
 520         }
 521         if (IS_A_PTY_MASTER(dev)) {
 522                 if (tty->count)
 523                         return -EAGAIN;
 524                 if (tty->link)
 525                         tty->link->count++;
 526         }
 527         tty->count++;
 528         retval = 0;
 529         if (!(filp->f_flags & O_NOCTTY) &&
 530             current->leader &&
 531             current->tty<0 &&
 532             tty->session==0) {
 533                 current->tty = dev;
 534                 tty->session = current->session;
 535                 tty->pgrp = current->pgrp;
 536         }
 537         if (IS_A_SERIAL(dev) && tty->count < 2)
 538                 retval = serial_open(dev-64,filp);
 539         else if (IS_A_PTY(dev))
 540                 retval = pty_open(dev,filp);
 541         if (retval) {
 542                 tty->count--;
 543                 if (IS_A_PTY_MASTER(dev) && tty->link)
 544                         tty->link->count--;
 545         }
 546         return retval;
 547 }
 548 
 549 /*
 550  * Note that releasing a pty master also releases the child, so
 551  * we have to make the redirection checks after that and on both
 552  * sides of a pty.
 553  */
 554 static void tty_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 555 {
 556         int dev;
 557         struct tty_struct * tty;
 558 
 559         dev = filp->f_rdev;
 560         if (MAJOR(dev) != 4) {
 561                 printk("tty_close: tty pseudo-major != 4\n");
 562                 return;
 563         }
 564         dev = MINOR(filp->f_rdev);
 565         tty = TTY_TABLE(dev);
 566         if (IS_A_PTY_MASTER(dev) && tty->link)
 567                 tty->link->count--;
 568         tty->count--;
 569         if (tty->count)
 570                 return;
 571         if (IS_A_SERIAL(dev)) {
 572                 wait_until_sent(tty);
 573                 serial_close(dev-64,filp);
 574         } else if (IS_A_PTY(dev))
 575                 pty_close(dev,filp);
 576         if (!tty->count && (tty == redirect))
 577                 redirect = NULL;
 578         if (tty = tty->link)
 579                 if (!tty->count && (tty == redirect))
 580                         redirect = NULL;
 581 }
 582 
 583 static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 584 {
 585         int dev;
 586         struct tty_struct * tty;
 587 
 588         dev = filp->f_rdev;
 589         if (MAJOR(dev) != 4) {
 590                 printk("tty_select: tty pseudo-major != 4\n");
 591                 return 0;
 592         }
 593         dev = MINOR(filp->f_rdev);
 594         tty = TTY_TABLE(dev);
 595         switch (sel_type) {
 596                 case SEL_IN:
 597                         if (!EMPTY(tty->secondary))
 598                                 return 1;
 599                         if (tty->link && !tty->link->count)
 600                                 return 1;
 601                         select_wait(&tty->secondary->proc_list, wait);
 602                         return 0;
 603                 case SEL_OUT:
 604                         if (!FULL(tty->write_q))
 605                                 return 1;
 606                         select_wait(&tty->write_q->proc_list, wait);
 607                         return 0;
 608                 case SEL_EX:
 609                         if (tty->link && !tty->link->count)
 610                                 return 1;
 611                         return 0;
 612         }
 613         return 0;
 614 }
 615 
 616 static struct file_operations tty_fops = {
 617         tty_lseek,
 618         tty_read,
 619         tty_write,
 620         NULL,           /* tty_readdir */
 621         tty_select,
 622         tty_ioctl,
 623         tty_open,
 624         tty_release
 625 };
 626 
 627 long tty_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 628 {
 629         int i;
 630 
 631         tty_queues = (struct tty_queue *) kmem_start;
 632         kmem_start += QUEUES * (sizeof (struct tty_queue));
 633         table_list[0] = con_queues + 0;
 634         table_list[1] = con_queues + 1;
 635         chrdev_fops[4] = &tty_fops;
 636         chrdev_fops[5] = &tty_fops;
 637         for (i=0 ; i < QUEUES ; i++)
 638                 tty_queues[i] = (struct tty_queue) {0,0,0,0,""};
 639         for (i=0 ; i<256 ; i++) {
 640                 tty_table[i] =  (struct tty_struct) {
 641                         {0, 0, 0, 0, 0, INIT_C_CC},
 642                         -1, 0, 0, 0, 0, {0,0,0,0},
 643                         NULL, NULL, NULL, NULL, NULL
 644                 };
 645         }
 646         kmem_start = con_init(kmem_start);
 647         for (i = 0 ; i<NR_CONSOLES ; i++) {
 648                 con_table[i] = (struct tty_struct) {
 649                         {ICRNL,         /* change incoming CR to NL */
 650                         OPOST|ONLCR,    /* change outgoing NL to CRNL */
 651                         B38400 | CS8,
 652                         IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
 653                         0,              /* console termio */
 654                         INIT_C_CC},
 655                         -1,             /* initial pgrp */
 656                         0,                      /* initial session */
 657                         0,                      /* initial stopped */
 658                         0,                      /* initial flags */
 659                         0,                      /* initial count */
 660                         {video_num_lines,video_num_columns,0,0},
 661                         con_write,
 662                         NULL,           /* other-tty */
 663                         con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
 664                 };
 665         }
 666         for (i = 0 ; i<NR_SERIALS ; i++) {
 667                 rs_table[i] = (struct tty_struct) {
 668                         {0, /* no translation */
 669                         0,  /* no translation */
 670                         B2400 | CS8,
 671                         0,
 672                         0,
 673                         INIT_C_CC},
 674                         -1,
 675                         0,
 676                         0,
 677                         0,
 678                         0,
 679                         {25,80,0,0},
 680                         rs_write,
 681                         NULL,           /* other-tty */
 682                         rs_queues+0+i*3,rs_queues+1+i*3,rs_queues+2+i*3
 683                 };
 684         }
 685         for (i = 0 ; i<NR_PTYS ; i++) {
 686                 mpty_table[i] = (struct tty_struct) {
 687                         {0, /* no translation */
 688                         0,  /* no translation */
 689                         B9600 | CS8,
 690                         0,
 691                         0,
 692                         INIT_C_CC},
 693                         -1,
 694                         0,
 695                         0,
 696                         0,
 697                         0,
 698                         {25,80,0,0},
 699                         mpty_write,
 700                         spty_table+i,
 701                         mpty_queues+0+i*3,mpty_queues+1+i*3,mpty_queues+2+i*3
 702                 };
 703                 spty_table[i] = (struct tty_struct) {
 704                         {0, /* no translation */
 705                         0,  /* no translation */
 706                         B9600 | CS8,
 707                         IXON | ISIG | ICANON,
 708                         0,
 709                         INIT_C_CC},
 710                         -1,
 711                         0,
 712                         0,
 713                         0,
 714                         0,
 715                         {25,80,0,0},
 716                         spty_write,
 717                         mpty_table+i,
 718                         spty_queues+0+i*3,spty_queues+1+i*3,spty_queues+2+i*3
 719                 };
 720         }
 721         kmem_start = rs_init(kmem_start);
 722         printk("%d virtual consoles\n\r",NR_CONSOLES);
 723         printk("%d pty's\n\r",NR_PTYS);
 724         return kmem_start;
 725 }

/* [previous][next][first][last][top][bottom][index][help] */