root/drivers/char/n_tty.c

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

DEFINITIONS

This source file includes following definitions.
  1. put_tty_queue
  2. n_tty_flush_buffer
  3. n_tty_chars_in_buffer
  4. opost
  5. put_char
  6. echo_char
  7. finish_erasing
  8. eraser
  9. isig
  10. n_tty_receive_break
  11. n_tty_receive_overrun
  12. n_tty_receive_parity_error
  13. n_tty_receive_char
  14. n_tty_receive_buf
  15. n_tty_receive_room
  16. is_ignored
  17. n_tty_set_termios
  18. n_tty_close
  19. n_tty_open
  20. input_available_p
  21. copy_from_read_buf
  22. gobble_eof
  23. read_chan
  24. write_chan
  25. normal_select

   1 /*
   2  * n_tty.c --- implements the N_TTY line discpline.
   3  * 
   4  * This code used to be in tty_io.c, but things are getting hairy
   5  * enough that it made sense to split things off.  (The N_TTY
   6  * processing has changed so much that it's hardly recognizable,
   7  * anyway...)
   8  *
   9  * Note that the open routine for N_TTY is guaranteed never to return
  10  * an error.  This is because Linux will fall back to setting a line
  11  * to N_TTY if it can not switch to any other line discpline.  
  12  *
  13  * Written by Theodore Ts'o, Copyright 1994.
  14  * 
  15  * This file also contains code originally written by Linus Torvalds,
  16  * Copyright 1991, 1992, 1993, and by Julian Cowley, Copyright 1994.
  17  * 
  18  * This file may be redistributed under the terms of the GNU Public
  19  * License.
  20  */
  21 
  22 #include <linux/types.h>
  23 #include <linux/major.h>
  24 #include <linux/errno.h>
  25 #include <linux/signal.h>
  26 #include <linux/fcntl.h>
  27 #include <linux/sched.h>
  28 #include <linux/interrupt.h>
  29 #include <linux/tty.h>
  30 #include <linux/timer.h>
  31 #include <linux/ctype.h>
  32 #include <linux/kd.h>
  33 #include <linux/mm.h>
  34 #include <linux/string.h>
  35 #include <linux/malloc.h>
  36 
  37 #include <asm/segment.h>
  38 #include <asm/system.h>
  39 #include <asm/bitops.h>
  40 
  41 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
  42 
  43 #ifndef MIN
  44 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
  45 #endif
  46 
  47 /* number of characters left in xmit buffer before select has we have room */
  48 #define WAKEUP_CHARS 256
  49 
  50 /*
  51  * This defines the low- and high-watermarks for throttling and
  52  * unthrottling the TTY driver.  These watermarks are used for
  53  * controlling the space in the read buffer.
  54  */
  55 #define TTY_THRESHOLD_THROTTLE          (N_TTY_BUF_SIZE - 128)
  56 #define TTY_THRESHOLD_UNTHROTTLE        128
  57 
  58 static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         if (tty->read_cnt < N_TTY_BUF_SIZE) {
  61                 tty->read_buf[tty->read_head] = c;
  62                 tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
  63                 tty->read_cnt++;
  64         }
  65 }
  66 
  67 /*
  68  * Flush the input buffer
  69  */
  70 void n_tty_flush_buffer(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         tty->read_head = tty->read_tail = tty->read_cnt = 0;
  73         tty->canon_head = tty->canon_data = tty->erasing = 0;
  74         memset(&tty->read_flags, 0, sizeof tty->read_flags);
  75         
  76         if (!tty->link)
  77                 return;
  78 
  79         wake_up_interruptible(&tty->link->write_wait);
  80         if (tty->link->packet) {
  81                 tty->ctrl_status |= TIOCPKT_FLUSHREAD;
  82                 wake_up_interruptible(&tty->link->read_wait);
  83         }
  84 }
  85 
  86 /*
  87  * Return number of characters buffered to be delievered to user
  88  */
  89 int n_tty_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         return tty->read_cnt;
  92 }
  93 
  94 /*
  95  * Perform OPOST processing.  Returns -1 when the output device is
  96  * full and the character must be retried.
  97  */
  98 static int opost(unsigned char c, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100         int     space, spaces;
 101 
 102         space = tty->driver.write_room(tty);
 103         if (!space)
 104                 return -1;
 105 
 106         if (O_OPOST(tty)) {
 107                 switch (c) {
 108                 case '\n':
 109                         if (O_ONLRET(tty))
 110                                 tty->column = 0;
 111                         if (O_ONLCR(tty)) {
 112                                 if (space < 2)
 113                                         return -1;
 114                                 tty->driver.write(tty, 0, "\r", 1);
 115                                 tty->column = 0;
 116                         }
 117                         tty->canon_column = tty->column;
 118                         break;
 119                 case '\r':
 120                         if (O_ONOCR(tty) && tty->column == 0)
 121                                 return 0;
 122                         if (O_OCRNL(tty)) {
 123                                 c = '\n';
 124                                 if (O_ONLRET(tty))
 125                                         tty->canon_column = tty->column = 0;
 126                                 break;
 127                         }
 128                         tty->canon_column = tty->column = 0;
 129                         break;
 130                 case '\t':
 131                         spaces = 8 - (tty->column & 7);
 132                         if (O_TABDLY(tty) == XTABS) {
 133                                 if (space < spaces)
 134                                         return -1;
 135                                 tty->column += spaces;
 136                                 tty->driver.write(tty, 0, "        ", spaces);
 137                                 return 0;
 138                         }
 139                         tty->column += spaces;
 140                         break;
 141                 case '\b':
 142                         if (tty->column > 0)
 143                                 tty->column--;
 144                         break;
 145                 default:
 146                         if (O_OLCUC(tty))
 147                                 c = toupper(c);
 148                         if (!iscntrl(c))
 149                                 tty->column++;
 150                         break;
 151                 }
 152         }
 153         tty->driver.put_char(tty, c);
 154         return 0;
 155 }
 156 
 157 static inline void put_char(unsigned char c, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159         tty->driver.put_char(tty, c);
 160 }
 161 
 162 /* Must be called only when L_ECHO(tty) is true. */
 163 
 164 static void echo_char(unsigned char c, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166         if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
 167                 put_char('^', tty);
 168                 put_char(c ^ 0100, tty);
 169                 tty->column += 2;
 170         } else
 171                 opost(c, tty);
 172 }
 173 
 174 static inline void finish_erasing(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176         if (tty->erasing) {
 177                 put_char('/', tty);
 178                 tty->column += 2;
 179                 tty->erasing = 0;
 180         }
 181 }
 182 
 183 static void eraser(unsigned char c, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185         enum { ERASE, WERASE, KILL } kill_type;
 186         int head, seen_alnums;
 187 
 188         if (tty->read_head == tty->canon_head) {
 189                 /* opost('\a', tty); */         /* what do you think? */
 190                 return;
 191         }
 192         if (c == ERASE_CHAR(tty))
 193                 kill_type = ERASE;
 194         else if (c == WERASE_CHAR(tty))
 195                 kill_type = WERASE;
 196         else {
 197                 if (!L_ECHO(tty)) {
 198                         tty->read_cnt -= ((tty->read_head - tty->canon_head) &
 199                                           (N_TTY_BUF_SIZE - 1));
 200                         tty->read_head = tty->canon_head;
 201                         return;
 202                 }
 203                 if (!L_ECHOK(tty) || !L_ECHOKE(tty)) {
 204                         tty->read_cnt -= ((tty->read_head - tty->canon_head) &
 205                                           (N_TTY_BUF_SIZE - 1));
 206                         tty->read_head = tty->canon_head;
 207                         finish_erasing(tty);
 208                         echo_char(KILL_CHAR(tty), tty);
 209                         /* Add a newline if ECHOK is on and ECHOKE is off. */
 210                         if (L_ECHOK(tty))
 211                                 opost('\n', tty);
 212                         return;
 213                 }
 214                 kill_type = KILL;
 215         }
 216 
 217         seen_alnums = 0;
 218         while (tty->read_head != tty->canon_head) {
 219                 head = (tty->read_head - 1) & (N_TTY_BUF_SIZE-1);
 220                 c = tty->read_buf[head];
 221                 if (kill_type == WERASE) {
 222                         /* Equivalent to BSD's ALTWERASE. */
 223                         if (isalnum(c) || c == '_')
 224                                 seen_alnums++;
 225                         else if (seen_alnums)
 226                                 break;
 227                 }
 228                 tty->read_head = head;
 229                 tty->read_cnt--;
 230                 if (L_ECHO(tty)) {
 231                         if (L_ECHOPRT(tty)) {
 232                                 if (!tty->erasing) {
 233                                         put_char('\\', tty);
 234                                         tty->column++;
 235                                         tty->erasing = 1;
 236                                 }
 237                                 echo_char(c, tty);
 238                         } else if (!L_ECHOE(tty)) {
 239                                 echo_char(ERASE_CHAR(tty), tty);
 240                         } else if (c == '\t') {
 241                                 unsigned int col = tty->canon_column;
 242                                 unsigned long tail = tty->canon_head;
 243 
 244                                 /* Find the column of the last char. */
 245                                 while (tail != tty->read_head) {
 246                                         c = tty->read_buf[tail];
 247                                         if (c == '\t')
 248                                                 col = (col | 7) + 1;
 249                                         else if (iscntrl(c)) {
 250                                                 if (L_ECHOCTL(tty))
 251                                                         col += 2;
 252                                         } else
 253                                                 col++;
 254                                         tail = (tail+1) & (N_TTY_BUF_SIZE-1);
 255                                 }
 256 
 257                                 /* Now backup to that column. */
 258                                 while (tty->column > col) {
 259                                         /* Can't use opost here. */
 260                                         put_char('\b', tty);
 261                                         tty->column--;
 262                                 }
 263                         } else {
 264                                 if (iscntrl(c) && L_ECHOCTL(tty)) {
 265                                         put_char('\b', tty);
 266                                         put_char(' ', tty);
 267                                         put_char('\b', tty);
 268                                         tty->column--;
 269                                 }
 270                                 if (!iscntrl(c) || L_ECHOCTL(tty)) {
 271                                         put_char('\b', tty);
 272                                         put_char(' ', tty);
 273                                         put_char('\b', tty);
 274                                         tty->column--;
 275                                 }
 276                         }
 277                 }
 278                 if (kill_type == ERASE)
 279                         break;
 280         }
 281         if (tty->read_head == tty->canon_head)
 282                 finish_erasing(tty);
 283 }
 284 
 285 static void isig(int sig, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287         if (tty->pgrp > 0)
 288                 kill_pg(tty->pgrp, sig, 1);
 289         if (!L_NOFLSH(tty)) {
 290                 n_tty_flush_buffer(tty);
 291                 if (tty->driver.flush_buffer)
 292                         tty->driver.flush_buffer(tty);
 293         }
 294 }
 295 
 296 static inline void n_tty_receive_break(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 297 {
 298         if (I_IGNBRK(tty))
 299                 return;
 300         if (I_BRKINT(tty)) {
 301                 isig(SIGINT, tty);
 302                 return;
 303         }
 304         if (I_PARMRK(tty)) {
 305                 put_tty_queue('\377', tty);
 306                 put_tty_queue('\0', tty);
 307         }
 308         put_tty_queue('\0', tty);
 309         wake_up_interruptible(&tty->read_wait);
 310 }
 311 
 312 static inline void n_tty_receive_overrun(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 313 {
 314         char buf[64];
 315 
 316         tty->num_overrun++;
 317         if (tty->overrun_time < (jiffies - HZ)) {
 318                 printk("%s: %d input overrun(s)\n", _tty_name(tty, buf),
 319                        tty->num_overrun);
 320                 tty->overrun_time = jiffies;
 321                 tty->num_overrun = 0;
 322         }
 323 }
 324 
 325 static inline void n_tty_receive_parity_error(struct tty_struct *tty,
     /* [previous][next][first][last][top][bottom][index][help] */
 326                                               unsigned char c)
 327 {
 328         if (I_IGNPAR(tty)) {
 329                 return;
 330         }
 331         if (I_PARMRK(tty)) {
 332                 put_tty_queue('\377', tty);
 333                 put_tty_queue('\0', tty);
 334                 put_tty_queue(c, tty);
 335         } else
 336                 put_tty_queue('\0', tty);
 337         wake_up_interruptible(&tty->read_wait);
 338 }
 339 
 340 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 341 {
 342         if (tty->raw) {
 343                 put_tty_queue(c, tty);
 344                 return;
 345         }
 346         
 347         if (tty->stopped && I_IXON(tty) && I_IXANY(tty) && L_IEXTEN(tty)) {
 348                 start_tty(tty);
 349                 return;
 350         }
 351         
 352         if (I_ISTRIP(tty))
 353                 c &= 0x7f;
 354         if (I_IUCLC(tty) && L_IEXTEN(tty))
 355                 c=tolower(c);
 356 
 357         /*
 358          * If the previous character was LNEXT, or we know that this
 359          * character is not one of the characters that we'll have to
 360          * handle specially, do shortcut processing to speed things
 361          * up.
 362          */
 363         if (!test_bit(c, &tty->process_char_map) || tty->lnext) {
 364                 finish_erasing(tty);
 365                 tty->lnext = 0;
 366                 if (L_ECHO(tty)) {
 367                         if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 368                                 put_char('\a', tty); /* beep if no space */
 369                                 return;
 370                         }
 371                         /* Record the column of first canon char. */
 372                         if (tty->canon_head == tty->read_head)
 373                                 tty->canon_column = tty->column;
 374                         echo_char(c, tty);
 375                 }
 376                 if (I_PARMRK(tty) && c == (unsigned char) '\377')
 377                         put_tty_queue(c, tty);
 378                 put_tty_queue(c, tty);
 379                 return;
 380         }
 381                 
 382         if (c == '\r') {
 383                 if (I_IGNCR(tty))
 384                         return;
 385                 if (I_ICRNL(tty))
 386                         c = '\n';
 387         } else if (c == '\n' && I_INLCR(tty))
 388                 c = '\r';
 389         if (I_IXON(tty)) {
 390                 if (c == START_CHAR(tty)) {
 391                         start_tty(tty);
 392                         return;
 393                 }
 394                 if (c == STOP_CHAR(tty)) {
 395                         stop_tty(tty);
 396                         return;
 397                 }
 398         }
 399         if (L_ISIG(tty)) {
 400                 if (c == INTR_CHAR(tty)) {
 401                         isig(SIGINT, tty);
 402                         return;
 403                 }
 404                 if (c == QUIT_CHAR(tty)) {
 405                         isig(SIGQUIT, tty);
 406                         return;
 407                 }
 408                 if (c == SUSP_CHAR(tty)) {
 409                         if (!is_orphaned_pgrp(tty->pgrp))
 410                                 isig(SIGTSTP, tty);
 411                         return;
 412                 }
 413         }
 414         if (L_ICANON(tty)) {
 415                 if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
 416                     (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
 417                         eraser(c, tty);
 418                         return;
 419                 }
 420                 if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
 421                         tty->lnext = 1;
 422                         if (L_ECHO(tty)) {
 423                                 finish_erasing(tty);
 424                                 if (L_ECHOCTL(tty)) {
 425                                         put_char('^', tty);
 426                                         put_char('\b', tty);
 427                                 }
 428                         }
 429                         return;
 430                 }
 431                 if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
 432                     L_IEXTEN(tty)) {
 433                         unsigned long tail = tty->canon_head;
 434 
 435                         finish_erasing(tty);
 436                         echo_char(c, tty);
 437                         opost('\n', tty);
 438                         while (tail != tty->read_head) {
 439                                 echo_char(tty->read_buf[tail], tty);
 440                                 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
 441                         }
 442                         return;
 443                 }
 444                 if (c == '\n') {
 445                         if (L_ECHO(tty) || L_ECHONL(tty)) {
 446                                 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 447                                         put_char('\a', tty);
 448                                         return;
 449                                 }
 450                                 opost('\n', tty);
 451                         }
 452                         goto handle_newline;
 453                 }
 454                 if (c == EOF_CHAR(tty)) {
 455                         c = __DISABLED_CHAR;
 456                         goto handle_newline;
 457                 }
 458                 if ((c == EOL_CHAR(tty)) ||
 459                     (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
 460                         /*
 461                          * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
 462                          */
 463                         if (L_ECHO(tty)) {
 464                                 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 465                                         put_char('\a', tty);
 466                                         return;
 467                                 }
 468                                 /* Record the column of first canon char. */
 469                                 if (tty->canon_head == tty->read_head)
 470                                         tty->canon_column = tty->column;
 471                                 echo_char(c, tty);
 472                         }
 473                         /*
 474                          * XXX does PARMRK doubling happen for
 475                          * EOL_CHAR and EOL2_CHAR?
 476                          */
 477                         if (I_PARMRK(tty) && c == (unsigned char) '\377')
 478                                 put_tty_queue(c, tty);
 479 
 480                 handle_newline:
 481                         set_bit(tty->read_head, &tty->read_flags);
 482                         put_tty_queue(c, tty);
 483                         tty->canon_head = tty->read_head;
 484                         tty->canon_data++;
 485                         if (tty->fasync)
 486                                 kill_fasync(tty->fasync, SIGIO);
 487                         if (tty->read_wait)
 488                                 wake_up_interruptible(&tty->read_wait);
 489                         return;
 490                 }
 491         }
 492         
 493         finish_erasing(tty);
 494         if (L_ECHO(tty)) {
 495                 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 496                         put_char('\a', tty); /* beep if no space */
 497                         return;
 498                 }
 499                 if (c == '\n')
 500                         opost('\n', tty);
 501                 else {
 502                         /* Record the column of first canon char. */
 503                         if (tty->canon_head == tty->read_head)
 504                                 tty->canon_column = tty->column;
 505                         echo_char(c, tty);
 506                 }
 507         }
 508 
 509         if (I_PARMRK(tty) && c == (unsigned char) '\377')
 510                 put_tty_queue(c, tty);
 511 
 512         put_tty_queue(c, tty);
 513 }       
 514 
 515 static void n_tty_receive_buf(struct tty_struct *tty, unsigned char *cp,
     /* [previous][next][first][last][top][bottom][index][help] */
 516                               char *fp, int count)
 517 {
 518         unsigned char *p;
 519         char *f, flags = 0;
 520         int     i;
 521 
 522         if (!tty->read_buf)
 523                 return;
 524 
 525         if (tty->real_raw) {
 526                 i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
 527                                    N_TTY_BUF_SIZE - tty->read_head));
 528                 memcpy(tty->read_buf + tty->read_head, cp, i);
 529                 tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
 530                 tty->read_cnt += i;
 531                 cp += i;
 532                 count -= i;
 533 
 534                 i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
 535                                N_TTY_BUF_SIZE - tty->read_head));
 536                 memcpy(tty->read_buf + tty->read_head, cp, i);
 537                 tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
 538                 tty->read_cnt += i;
 539         } else {
 540                 for (i=count, p = cp, f = fp; i; i--, p++) {
 541                         if (f)
 542                                 flags = *f++;
 543                         switch (flags) {
 544                         case TTY_NORMAL:
 545                                 n_tty_receive_char(tty, *p);
 546                                 break;
 547                         case TTY_BREAK:
 548                                 n_tty_receive_break(tty);
 549                                 break;
 550                         case TTY_PARITY:
 551                         case TTY_FRAME:
 552                                 n_tty_receive_parity_error(tty, *p);
 553                                 break;
 554                         case TTY_OVERRUN:
 555                                 n_tty_receive_overrun(tty);
 556                                 break;
 557                         default:
 558                                 printk("%s: unknown flag %d\n", tty_name(tty),
 559                                        flags);
 560                                 break;
 561                         }
 562                 }
 563                 if (tty->driver.flush_chars)
 564                         tty->driver.flush_chars(tty);
 565         }
 566 
 567         if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
 568                 if (tty->fasync)
 569                         kill_fasync(tty->fasync, SIGIO);
 570                 if (tty->read_wait)
 571                         wake_up_interruptible(&tty->read_wait);
 572         }
 573 
 574         if ((tty->read_cnt >= TTY_THRESHOLD_THROTTLE) &&
 575             tty->driver.throttle &&
 576             !set_bit(TTY_THROTTLED, &tty->flags))
 577                 tty->driver.throttle(tty);
 578 }
 579 
 580 static int n_tty_receive_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 581 {
 582         int     left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
 583 
 584         if (left > 0)
 585                 return left;
 586         return 0;
 587 }
 588 
 589 int is_ignored(int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
 590 {
 591         return ((current->blocked & (1<<(sig-1))) ||
 592                 (current->sigaction[sig-1].sa_handler == SIG_IGN));
 593 }
 594 
 595 static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
     /* [previous][next][first][last][top][bottom][index][help] */
 596 {
 597         tty->icanon = (L_ICANON(tty) != 0);
 598         if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
 599             I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
 600             I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
 601             I_PARMRK(tty)) {
 602                 cli();
 603                 memset(tty->process_char_map, 0, 256/32);
 604 
 605                 if (I_IGNCR(tty) || I_ICRNL(tty))
 606                         set_bit('\r', &tty->process_char_map);
 607                 if (I_INLCR(tty))
 608                         set_bit('\n', &tty->process_char_map);
 609 
 610                 if (L_ICANON(tty)) {
 611                         set_bit(ERASE_CHAR(tty), &tty->process_char_map);
 612                         set_bit(KILL_CHAR(tty), &tty->process_char_map);
 613                         set_bit(EOF_CHAR(tty), &tty->process_char_map);
 614                         set_bit('\n', &tty->process_char_map);
 615                         set_bit(EOL_CHAR(tty), &tty->process_char_map);
 616                         if (L_IEXTEN(tty)) {
 617                                 set_bit(WERASE_CHAR(tty),
 618                                         &tty->process_char_map);
 619                                 set_bit(LNEXT_CHAR(tty),
 620                                         &tty->process_char_map);
 621                                 set_bit(EOL2_CHAR(tty),
 622                                         &tty->process_char_map);
 623                                 if (L_ECHO(tty))
 624                                         set_bit(REPRINT_CHAR(tty),
 625                                                 &tty->process_char_map);
 626                         }
 627                 }
 628                 if (I_IXON(tty)) {
 629                         set_bit(START_CHAR(tty), &tty->process_char_map);
 630                         set_bit(STOP_CHAR(tty), &tty->process_char_map);
 631                 }
 632                 if (L_ISIG(tty)) {
 633                         set_bit(INTR_CHAR(tty), &tty->process_char_map);
 634                         set_bit(QUIT_CHAR(tty), &tty->process_char_map);
 635                         set_bit(SUSP_CHAR(tty), &tty->process_char_map);
 636                 }
 637                 clear_bit(__DISABLED_CHAR, &tty->process_char_map);
 638                 sti();
 639                 tty->raw = 0;
 640                 tty->real_raw = 0;
 641         } else {
 642                 tty->raw = 1;
 643                 if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
 644                     (I_IGNPAR(tty) || !I_INPCK(tty)) &&
 645                     (tty->driver.flags & TTY_DRIVER_REAL_RAW))
 646                         tty->real_raw = 1;
 647                 else
 648                         tty->real_raw = 0;
 649         }
 650 }
 651 
 652 static void n_tty_close(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 653 {
 654         wait_until_sent(tty, 0);
 655         n_tty_flush_buffer(tty);
 656         if (tty->read_buf) {
 657                 free_page((unsigned long) tty->read_buf);
 658                 tty->read_buf = 0;
 659         }
 660 }
 661 
 662 static int n_tty_open(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 663 {
 664         if (!tty->read_buf) {
 665                 tty->read_buf = (unsigned char *)
 666                         get_free_page(intr_count ? GFP_ATOMIC : GFP_KERNEL);
 667                 if (!tty->read_buf)
 668                         return -ENOMEM;
 669         }
 670         memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
 671         tty->read_head = tty->read_tail = tty->read_cnt = 0;
 672         memset(tty->read_flags, 0, sizeof(tty->read_flags));
 673         n_tty_set_termios(tty, 0);
 674         tty->minimum_to_wake = 1;
 675         return 0;
 676 }
 677 
 678 static inline int input_available_p(struct tty_struct *tty, int amt)
     /* [previous][next][first][last][top][bottom][index][help] */
 679 {
 680         if (L_ICANON(tty)) {
 681                 if (tty->canon_data)
 682                         return 1;
 683         } else if (tty->read_cnt >= (amt ? amt : 1))
 684                 return 1;
 685 
 686         return 0;
 687 }
 688 
 689 /*
 690  * Helper function to speed up read_chan.  It is only called when
 691  * ICANON is off; it copies characters straight from the tty queue to
 692  * user space directly.  It can be profitably called twice; once to
 693  * drain the space from the tail pointer to the (physical) end of the
 694  * buffer, and once to drain the space from the (physical) beginning of
 695  * the buffer to head pointer.
 696  */
 697 static inline void copy_from_read_buf(struct tty_struct *tty,
     /* [previous][next][first][last][top][bottom][index][help] */
 698                                       unsigned char **b,
 699                                       unsigned int *nr)
 700 
 701 {
 702         int     n;
 703 
 704         n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
 705         if (!n)
 706                 return;
 707         memcpy_tofs(*b, &tty->read_buf[tty->read_tail], n);
 708         tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
 709         tty->read_cnt -= n;
 710         *b += n;
 711         *nr -= n;
 712 }
 713 
 714 /*
 715  * Called to gobble up an immediately following EOF when there is no
 716  * more room in buf (this can happen if the user "pushes" some
 717  * characters using ^D).  This prevents the next read() from falsely
 718  * returning EOF.
 719  */
 720 static inline void gobble_eof(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 721 {
 722         cli();
 723         if ((tty->read_cnt) &&
 724             (tty->read_buf[tty->read_tail] == __DISABLED_CHAR) &&
 725             clear_bit(tty->read_tail, &tty->read_flags)) {
 726                 tty->read_tail = (tty->read_tail+1) & (N_TTY_BUF_SIZE-1);
 727                 tty->read_cnt--;
 728         }
 729         sti();
 730 }
 731 
 732 static int read_chan(struct tty_struct *tty, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 733                      unsigned char *buf, unsigned int nr)
 734 {
 735         struct wait_queue wait = { current, NULL };
 736         int c;
 737         unsigned char *b = buf;
 738         int minimum, time;
 739         int retval = 0;
 740 
 741         if (!tty->read_buf) {
 742                 printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
 743                 return -EIO;
 744         }
 745 
 746         /* Job control check -- must be done at start and after
 747            every sleep (POSIX.1 7.1.1.4). */
 748         /* NOTE: not yet done after every sleep pending a thorough
 749            check of the logic of this change. -- jlc */
 750         /* don't stop on /dev/console */
 751         if (file->f_inode->i_rdev != CONSOLE_DEV &&
 752             current->tty == tty) {
 753                 if (tty->pgrp <= 0)
 754                         printk("read_chan: tty->pgrp <= 0!\n");
 755                 else if (current->pgrp != tty->pgrp) {
 756                         if (is_ignored(SIGTTIN) ||
 757                             is_orphaned_pgrp(current->pgrp))
 758                                 return -EIO;
 759                         kill_pg(current->pgrp, SIGTTIN, 1);
 760                         return -ERESTARTSYS;
 761                 }
 762         }
 763 
 764         if (L_ICANON(tty)) {
 765                 minimum = time = 0;
 766                 current->timeout = (unsigned long) -1;
 767         } else {
 768                 time = (HZ / 10) * TIME_CHAR(tty);
 769                 minimum = MIN_CHAR(tty);
 770                 if (minimum) {
 771                         current->timeout = (unsigned long) -1;
 772                         if (time)
 773                                 tty->minimum_to_wake = 1;
 774                         else if (!tty->read_wait ||
 775                                  (tty->minimum_to_wake > minimum))
 776                                 tty->minimum_to_wake = minimum;
 777                 } else {
 778                         if (time) {
 779                                 current->timeout = time + jiffies;
 780                                 time = 0;
 781                         } else
 782                                 current->timeout = 0;
 783                         tty->minimum_to_wake = minimum = 1;
 784                 }
 785         }
 786 
 787         add_wait_queue(&tty->read_wait, &wait);
 788         while (1) {
 789                 /* First test for status change. */
 790                 if (tty->packet && tty->link->ctrl_status) {
 791                         if (b != buf)
 792                                 break;
 793                         put_fs_byte(tty->link->ctrl_status, b++);
 794                         tty->link->ctrl_status = 0;
 795                         break;
 796                 }
 797                 /* This statement must be first before checking for input
 798                    so that any interrupt will set the state back to
 799                    TASK_RUNNING. */
 800                 current->state = TASK_INTERRUPTIBLE;
 801                 
 802                 if (((minimum - (b - buf)) < tty->minimum_to_wake) &&
 803                     ((minimum - (b - buf)) >= 1))
 804                         tty->minimum_to_wake = (minimum - (b - buf));
 805                 
 806                 if (!input_available_p(tty, 0)) {
 807                         if (tty->flags & (1 << TTY_SLAVE_CLOSED)) {
 808                                 retval = -EIO;
 809                                 break;
 810                         }
 811                         if (tty_hung_up_p(file))
 812                                 break;
 813                         if (!current->timeout)
 814                                 break;
 815                         if (file->f_flags & O_NONBLOCK) {
 816                                 retval = -EAGAIN;
 817                                 break;
 818                         }
 819                         if (current->signal & ~current->blocked) {
 820                                 retval = -ERESTARTSYS;
 821                                 break;
 822                         }
 823                         schedule();
 824                         continue;
 825                 }
 826                 current->state = TASK_RUNNING;
 827 
 828                 /* Deal with packet mode. */
 829                 if (tty->packet && b == buf) {
 830                         put_fs_byte(TIOCPKT_DATA, b++);
 831                         nr--;
 832                 }
 833 
 834                 if (L_ICANON(tty)) {
 835                         while (1) {
 836                                 int eol;
 837 
 838                                 disable_bh(TQUEUE_BH);
 839                                 if (!tty->read_cnt) {
 840                                         enable_bh(TQUEUE_BH);
 841                                         break;
 842                                 }
 843                                 eol = clear_bit(tty->read_tail,
 844                                                 &tty->read_flags);
 845                                 c = tty->read_buf[tty->read_tail];
 846                                 tty->read_tail = ((tty->read_tail+1) &
 847                                                   (N_TTY_BUF_SIZE-1));
 848                                 tty->read_cnt--;
 849                                 enable_bh(TQUEUE_BH);
 850                                 if (!eol) {
 851                                         put_fs_byte(c, b++);
 852                                         if (--nr)
 853                                                 continue;
 854                                         gobble_eof(tty);
 855                                         break;
 856                                 }
 857                                 if (--tty->canon_data < 0) {
 858                                         tty->canon_data = 0;
 859                                 }
 860                                 if (c != __DISABLED_CHAR) {
 861                                         put_fs_byte(c, b++);
 862                                         nr--;
 863                                 }
 864                                 break;
 865                         }
 866                 } else {
 867                         disable_bh(TQUEUE_BH);
 868                         copy_from_read_buf(tty, &b, &nr);
 869                         copy_from_read_buf(tty, &b, &nr);
 870                         enable_bh(TQUEUE_BH);
 871                 }
 872 
 873                 /* If there is enough space in the read buffer now, let the
 874                    low-level driver know. */
 875                 if (tty->driver.unthrottle &&
 876                     (tty->read_cnt <= TTY_THRESHOLD_UNTHROTTLE)
 877                     && clear_bit(TTY_THROTTLED, &tty->flags))
 878                         tty->driver.unthrottle(tty);
 879 
 880                 if (b - buf >= minimum || !nr)
 881                         break;
 882                 if (time)
 883                         current->timeout = time + jiffies;
 884         }
 885         remove_wait_queue(&tty->read_wait, &wait);
 886 
 887         if (!tty->read_wait)
 888                 tty->minimum_to_wake = minimum;
 889 
 890         current->state = TASK_RUNNING;
 891         current->timeout = 0;
 892         /*
 893          * Hack for PTY's; we need to wake up the other tty if there's
 894          * enough space.
 895          */
 896         if (tty->link && tty->read_cnt <= TTY_THRESHOLD_UNTHROTTLE)
 897                 wake_up_interruptible(&tty->link->write_wait);
 898         return (b - buf) ? b - buf : retval;
 899 }
 900 
 901 static int write_chan(struct tty_struct * tty, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 902                       unsigned char * buf, unsigned int nr)
 903 {
 904         struct wait_queue wait = { current, NULL };
 905         int c;
 906         unsigned char *b = buf;
 907         int retval = 0;
 908 
 909         /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
 910         if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) {
 911                 retval = tty_check_change(tty);
 912                 if (retval)
 913                         return retval;
 914         }
 915 
 916         add_wait_queue(&tty->write_wait, &wait);
 917         while (1) {
 918                 current->state = TASK_INTERRUPTIBLE;
 919                 if (current->signal & ~current->blocked) {
 920                         retval = -ERESTARTSYS;
 921                         break;
 922                 }
 923                 if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) {
 924                         retval = -EIO;
 925                         break;
 926                 }
 927                 if (O_OPOST(tty)) {
 928                         while (nr > 0) {
 929                                 c = get_fs_byte(b);
 930                                 if (opost(c, tty) < 0)
 931                                         break;
 932                                 b++; nr--;
 933                                 if (tty->driver.flush_chars)
 934                                         tty->driver.flush_chars(tty);
 935                         }
 936                 } else {
 937                         c = tty->driver.write(tty, 1, b, nr);
 938                         b += c;
 939                         nr -= c;
 940                 }
 941                 if (!nr)
 942                         break;
 943                 if (file->f_flags & O_NONBLOCK) {
 944                         retval = -EAGAIN;
 945                         break;
 946                 }
 947                 schedule();
 948         }
 949         current->state = TASK_RUNNING;
 950         remove_wait_queue(&tty->write_wait, &wait);
 951         return (b - buf) ? b - buf : retval;
 952 }
 953 
 954 static int normal_select(struct tty_struct * tty, struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
 955                          struct file * file, int sel_type, select_table *wait)
 956 {
 957         switch (sel_type) {
 958                 case SEL_IN:
 959                         if (input_available_p(tty, MIN_CHAR(tty)))
 960                                 return 1;
 961                         /* fall through */
 962                 case SEL_EX:
 963                         if (tty->packet && tty->link->ctrl_status)
 964                                 return 1;
 965                         if (tty->flags & (1 << TTY_SLAVE_CLOSED))
 966                                 return 1;
 967                         if (tty_hung_up_p(file))
 968                                 return 1;
 969                         if (!tty->read_wait)
 970                                 tty->minimum_to_wake = MIN_CHAR(tty) ?
 971                                         MIN_CHAR(tty) : 1;
 972                         select_wait(&tty->read_wait, wait);
 973                         return 0;
 974                 case SEL_OUT:
 975                         if (tty->driver.chars_in_buffer(tty) < WAKEUP_CHARS)
 976                                 return 1;
 977                         select_wait(&tty->write_wait, wait);
 978                         return 0;
 979         }
 980         return 0;
 981 }
 982 
 983 struct tty_ldisc tty_ldisc_N_TTY = {
 984         TTY_LDISC_MAGIC,        /* magic */
 985         0,                      /* num */
 986         0,                      /* flags */
 987         n_tty_open,             /* open */
 988         n_tty_close,            /* close */
 989         n_tty_flush_buffer,     /* flush_buffer */
 990         n_tty_chars_in_buffer,  /* chars_in_buffer */
 991         read_chan,              /* read */
 992         write_chan,             /* write */
 993         n_tty_ioctl,            /* ioctl */
 994         n_tty_set_termios,      /* set_termios */
 995         normal_select,          /* select */
 996         n_tty_receive_buf,      /* receive_buf */
 997         n_tty_receive_room,     /* receive_room */
 998         0                       /* write_wakeup */
 999 };
1000 

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