This source file includes following definitions.
- put_tty_queue
 
- n_tty_flush_buffer
 
- n_tty_chars_in_buffer
 
- opost
 
- put_char
 
- echo_char
 
- finish_erasing
 
- eraser
 
- isig
 
- n_tty_receive_break
 
- n_tty_receive_overrun
 
- n_tty_receive_parity_error
 
- n_tty_receive_char
 
- n_tty_receive_buf
 
- n_tty_receive_room
 
- is_ignored
 
- n_tty_set_termios
 
- n_tty_close
 
- n_tty_open
 
- input_available_p
 
- copy_from_read_buf
 
- read_chan
 
- write_chan
 
- normal_select
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  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 
  48 #define WAKEUP_CHARS 256
  49 
  50 
  51 
  52 
  53 
  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)
     
  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 
  69 
  70 void n_tty_flush_buffer(struct tty_struct * tty)
     
  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         if (tty->driver.unthrottle)
  80                 (tty->driver.unthrottle)(tty);
  81         if (tty->link->packet) {
  82                 tty->ctrl_status |= TIOCPKT_FLUSHREAD;
  83                 wake_up_interruptible(&tty->link->read_wait);
  84         }
  85 }
  86 
  87 
  88 
  89 
  90 int n_tty_chars_in_buffer(struct tty_struct *tty)
     
  91 {
  92         return tty->read_cnt;
  93 }
  94 
  95 
  96 
  97 
  98 
  99 static int opost(unsigned char c, struct tty_struct *tty)
     
 100 {
 101         int     space, spaces;
 102 
 103         space = tty->driver.write_room(tty);
 104         if (!space)
 105                 return -1;
 106 
 107         if (O_OPOST(tty)) {
 108                 switch (c) {
 109                 case '\n':
 110                         if (O_ONLRET(tty))
 111                                 tty->column = 0;
 112                         if (O_ONLCR(tty)) {
 113                                 if (space < 2)
 114                                         return -1;
 115                                 tty->driver.put_char(tty, '\r');
 116                                 tty->column = 0;
 117                         }
 118                         tty->canon_column = tty->column;
 119                         break;
 120                 case '\r':
 121                         if (O_ONOCR(tty) && tty->column == 0)
 122                                 return 0;
 123                         if (O_OCRNL(tty)) {
 124                                 c = '\n';
 125                                 if (O_ONLRET(tty))
 126                                         tty->canon_column = tty->column = 0;
 127                                 break;
 128                         }
 129                         tty->canon_column = tty->column = 0;
 130                         break;
 131                 case '\t':
 132                         spaces = 8 - (tty->column & 7);
 133                         if (O_TABDLY(tty) == XTABS) {
 134                                 if (space < spaces)
 135                                         return -1;
 136                                 tty->column += spaces;
 137                                 tty->driver.write(tty, 0, "        ", spaces);
 138                                 return 0;
 139                         }
 140                         tty->column += spaces;
 141                         break;
 142                 case '\b':
 143                         if (tty->column > 0)
 144                                 tty->column--;
 145                         break;
 146                 default:
 147                         if (O_OLCUC(tty))
 148                                 c = toupper(c);
 149                         if (!iscntrl(c))
 150                                 tty->column++;
 151                         break;
 152                 }
 153         }
 154         tty->driver.put_char(tty, c);
 155         return 0;
 156 }
 157 
 158 static inline void put_char(unsigned char c, struct tty_struct *tty)
     
 159 {
 160         tty->driver.put_char(tty, c);
 161 }
 162 
 163 
 164 
 165 static void echo_char(unsigned char c, struct tty_struct *tty)
     
 166 {
 167         if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
 168                 put_char('^', tty);
 169                 put_char(c ^ 0100, tty);
 170                 tty->column += 2;
 171         } else
 172                 opost(c, tty);
 173 }
 174 
 175 static inline void finish_erasing(struct tty_struct *tty)
     
 176 {
 177         if (tty->erasing) {
 178                 put_char('/', tty);
 179                 tty->column += 2;
 180                 tty->erasing = 0;
 181         }
 182 }
 183 
 184 static void eraser(unsigned char c, struct tty_struct *tty)
     
 185 {
 186         enum { ERASE, WERASE, KILL } kill_type;
 187         int head, seen_alnums;
 188 
 189         if (tty->read_head == tty->canon_head) {
 190                          
 191                 return;
 192         }
 193         if (c == ERASE_CHAR(tty))
 194                 kill_type = ERASE;
 195         else if (c == WERASE_CHAR(tty))
 196                 kill_type = WERASE;
 197         else {
 198                 if (!L_ECHO(tty)) {
 199                         tty->read_cnt -= ((tty->read_head - tty->canon_head) &
 200                                           (N_TTY_BUF_SIZE - 1));
 201                         tty->read_head = tty->canon_head;
 202                         return;
 203                 }
 204                 if (!L_ECHOK(tty) || !L_ECHOKE(tty)) {
 205                         tty->read_cnt -= ((tty->read_head - tty->canon_head) &
 206                                           (N_TTY_BUF_SIZE - 1));
 207                         tty->read_head = tty->canon_head;
 208                         finish_erasing(tty);
 209                         echo_char(KILL_CHAR(tty), tty);
 210                         
 211                         if (L_ECHOK(tty))
 212                                 opost('\n', tty);
 213                         return;
 214                 }
 215                 kill_type = KILL;
 216         }
 217 
 218         seen_alnums = 0;
 219         while (tty->read_head != tty->canon_head) {
 220                 head = (tty->read_head - 1) & (N_TTY_BUF_SIZE-1);
 221                 c = tty->read_buf[head];
 222                 if (kill_type == WERASE) {
 223                         
 224                         if (isalnum(c) || c == '_')
 225                                 seen_alnums++;
 226                         else if (seen_alnums)
 227                                 break;
 228                 }
 229                 tty->read_head = head;
 230                 tty->read_cnt--;
 231                 if (L_ECHO(tty)) {
 232                         if (L_ECHOPRT(tty)) {
 233                                 if (!tty->erasing) {
 234                                         put_char('\\', tty);
 235                                         tty->column++;
 236                                         tty->erasing = 1;
 237                                 }
 238                                 echo_char(c, tty);
 239                         } else if (!L_ECHOE(tty)) {
 240                                 echo_char(ERASE_CHAR(tty), tty);
 241                         } else if (c == '\t') {
 242                                 unsigned int col = tty->canon_column;
 243                                 unsigned long tail = tty->canon_head;
 244 
 245                                 
 246                                 while (tail != tty->read_head) {
 247                                         c = tty->read_buf[tail];
 248                                         if (c == '\t')
 249                                                 col = (col | 7) + 1;
 250                                         else if (iscntrl(c)) {
 251                                                 if (L_ECHOCTL(tty))
 252                                                         col += 2;
 253                                         } else
 254                                                 col++;
 255                                         tail = (tail+1) & (N_TTY_BUF_SIZE-1);
 256                                 }
 257 
 258                                 
 259                                 if (tty->column > 0x80000000)
 260                                         tty->column = 0; 
 261 
 262                                 
 263                                 while (tty->column > col) {
 264                                         
 265                                         put_char('\b', tty);
 266                                         if (tty->column > 0)
 267                                                 tty->column--;
 268                                 }
 269                         } else {
 270                                 if (iscntrl(c) && L_ECHOCTL(tty)) {
 271                                         put_char('\b', tty);
 272                                         put_char(' ', tty);
 273                                         put_char('\b', tty);
 274                                         if (tty->column > 0)
 275                                                 tty->column--;
 276                                 }
 277                                 if (!iscntrl(c) || L_ECHOCTL(tty)) {
 278                                         put_char('\b', tty);
 279                                         put_char(' ', tty);
 280                                         put_char('\b', tty);
 281                                         if (tty->column > 0)
 282                                                 tty->column--;
 283                                 }
 284                         }
 285                 }
 286                 if (kill_type == ERASE)
 287                         break;
 288         }
 289         if (tty->read_head == tty->canon_head)
 290                 finish_erasing(tty);
 291 }
 292 
 293 static void isig(int sig, struct tty_struct *tty)
     
 294 {
 295         if (tty->pgrp > 0)
 296                 kill_pg(tty->pgrp, sig, 1);
 297         if (!L_NOFLSH(tty)) {
 298                 n_tty_flush_buffer(tty);
 299                 if (tty->driver.flush_buffer)
 300                         tty->driver.flush_buffer(tty);
 301         }
 302 }
 303 
 304 static inline void n_tty_receive_break(struct tty_struct *tty)
     
 305 {
 306         if (I_IGNBRK(tty))
 307                 return;
 308         if (I_BRKINT(tty)) {
 309                 isig(SIGINT, tty);
 310                 return;
 311         }
 312         if (I_PARMRK(tty)) {
 313                 put_tty_queue('\377', tty);
 314                 put_tty_queue('\0', tty);
 315         }
 316         put_tty_queue('\0', tty);
 317         wake_up_interruptible(&tty->read_wait);
 318 }
 319 
 320 static inline void n_tty_receive_overrun(struct tty_struct *tty)
     
 321 {
 322         char buf[64];
 323 
 324         tty->num_overrun++;
 325         if (tty->overrun_time < (jiffies - HZ)) {
 326                 printk("%s: %d input overrun(s)\n", _tty_name(tty, buf),
 327                        tty->num_overrun);
 328                 tty->overrun_time = jiffies;
 329                 tty->num_overrun = 0;
 330         }
 331 }
 332 
 333 static inline void n_tty_receive_parity_error(struct tty_struct *tty,
     
 334                                               unsigned char c)
 335 {
 336         if (I_IGNPAR(tty)) {
 337                 return;
 338         }
 339         if (I_PARMRK(tty)) {
 340                 put_tty_queue('\377', tty);
 341                 put_tty_queue('\0', tty);
 342                 put_tty_queue(c, tty);
 343         } else
 344                 put_tty_queue('\0', tty);
 345         wake_up_interruptible(&tty->read_wait);
 346 }
 347 
 348 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
     
 349 {
 350         if (tty->raw) {
 351                 put_tty_queue(c, tty);
 352                 return;
 353         }
 354         
 355         if (tty->stopped && I_IXON(tty) && I_IXANY(tty)) {
 356                 start_tty(tty);
 357                 return;
 358         }
 359         
 360         if (I_ISTRIP(tty))
 361                 c &= 0x7f;
 362         if (I_IUCLC(tty) && L_IEXTEN(tty))
 363                 c=tolower(c);
 364 
 365         if (tty->closing) {
 366                 if (I_IXON(tty)) {
 367                         if (c == START_CHAR(tty))
 368                                 start_tty(tty);
 369                         else if (c == STOP_CHAR(tty))
 370                                 stop_tty(tty);
 371                 }
 372                 return;
 373         }
 374 
 375         
 376 
 377 
 378 
 379 
 380 
 381         if (!test_bit(c, &tty->process_char_map) || tty->lnext) {
 382                 finish_erasing(tty);
 383                 tty->lnext = 0;
 384                 if (L_ECHO(tty)) {
 385                         if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 386                                 put_char('\a', tty); 
 387                                 return;
 388                         }
 389                         
 390                         if (tty->canon_head == tty->read_head)
 391                                 tty->canon_column = tty->column;
 392                         echo_char(c, tty);
 393                 }
 394                 if (I_PARMRK(tty) && c == (unsigned char) '\377')
 395                         put_tty_queue(c, tty);
 396                 put_tty_queue(c, tty);
 397                 return;
 398         }
 399                 
 400         if (c == '\r') {
 401                 if (I_IGNCR(tty))
 402                         return;
 403                 if (I_ICRNL(tty))
 404                         c = '\n';
 405         } else if (c == '\n' && I_INLCR(tty))
 406                 c = '\r';
 407         if (I_IXON(tty)) {
 408                 if (c == START_CHAR(tty)) {
 409                         start_tty(tty);
 410                         return;
 411                 }
 412                 if (c == STOP_CHAR(tty)) {
 413                         stop_tty(tty);
 414                         return;
 415                 }
 416         }
 417         if (L_ISIG(tty)) {
 418                 if (c == INTR_CHAR(tty)) {
 419                         isig(SIGINT, tty);
 420                         return;
 421                 }
 422                 if (c == QUIT_CHAR(tty)) {
 423                         isig(SIGQUIT, tty);
 424                         return;
 425                 }
 426                 if (c == SUSP_CHAR(tty)) {
 427                         if (!is_orphaned_pgrp(tty->pgrp))
 428                                 isig(SIGTSTP, tty);
 429                         return;
 430                 }
 431         }
 432         if (L_ICANON(tty)) {
 433                 if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
 434                     (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
 435                         eraser(c, tty);
 436                         return;
 437                 }
 438                 if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
 439                         tty->lnext = 1;
 440                         if (L_ECHO(tty)) {
 441                                 finish_erasing(tty);
 442                                 if (L_ECHOCTL(tty)) {
 443                                         put_char('^', tty);
 444                                         put_char('\b', tty);
 445                                 }
 446                         }
 447                         return;
 448                 }
 449                 if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
 450                     L_IEXTEN(tty)) {
 451                         unsigned long tail = tty->canon_head;
 452 
 453                         finish_erasing(tty);
 454                         echo_char(c, tty);
 455                         opost('\n', tty);
 456                         while (tail != tty->read_head) {
 457                                 echo_char(tty->read_buf[tail], tty);
 458                                 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
 459                         }
 460                         return;
 461                 }
 462                 if (c == '\n') {
 463                         if (L_ECHO(tty) || L_ECHONL(tty)) {
 464                                 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 465                                         put_char('\a', tty);
 466                                         return;
 467                                 }
 468                                 opost('\n', tty);
 469                         }
 470                         goto handle_newline;
 471                 }
 472                 if (c == EOF_CHAR(tty)) {
 473                         if (tty->canon_head != tty->read_head)
 474                                 set_bit(TTY_PUSH, &tty->flags);
 475                         c = __DISABLED_CHAR;
 476                         goto handle_newline;
 477                 }
 478                 if ((c == EOL_CHAR(tty)) ||
 479                     (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
 480                         
 481 
 482 
 483                         if (L_ECHO(tty)) {
 484                                 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 485                                         put_char('\a', tty);
 486                                         return;
 487                                 }
 488                                 
 489                                 if (tty->canon_head == tty->read_head)
 490                                         tty->canon_column = tty->column;
 491                                 echo_char(c, tty);
 492                         }
 493                         
 494 
 495 
 496 
 497                         if (I_PARMRK(tty) && c == (unsigned char) '\377')
 498                                 put_tty_queue(c, tty);
 499 
 500                 handle_newline:
 501                         set_bit(tty->read_head, &tty->read_flags);
 502                         put_tty_queue(c, tty);
 503                         tty->canon_head = tty->read_head;
 504                         tty->canon_data++;
 505                         if (tty->fasync)
 506                                 kill_fasync(tty->fasync, SIGIO);
 507                         if (tty->read_wait)
 508                                 wake_up_interruptible(&tty->read_wait);
 509                         return;
 510                 }
 511         }
 512         
 513         finish_erasing(tty);
 514         if (L_ECHO(tty)) {
 515                 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
 516                         put_char('\a', tty); 
 517                         return;
 518                 }
 519                 if (c == '\n')
 520                         opost('\n', tty);
 521                 else {
 522                         
 523                         if (tty->canon_head == tty->read_head)
 524                                 tty->canon_column = tty->column;
 525                         echo_char(c, tty);
 526                 }
 527         }
 528 
 529         if (I_PARMRK(tty) && c == (unsigned char) '\377')
 530                 put_tty_queue(c, tty);
 531 
 532         put_tty_queue(c, tty);
 533 }       
 534 
 535 static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
     
 536                               char *fp, int count)
 537 {
 538         const unsigned char *p;
 539         char *f, flags = 0;
 540         int     i;
 541 
 542         if (!tty->read_buf)
 543                 return;
 544 
 545         if (tty->real_raw) {
 546                 i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
 547                                    N_TTY_BUF_SIZE - tty->read_head));
 548                 memcpy(tty->read_buf + tty->read_head, cp, i);
 549                 tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
 550                 tty->read_cnt += i;
 551                 cp += i;
 552                 count -= i;
 553 
 554                 i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,
 555                                N_TTY_BUF_SIZE - tty->read_head));
 556                 memcpy(tty->read_buf + tty->read_head, cp, i);
 557                 tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
 558                 tty->read_cnt += i;
 559         } else {
 560                 for (i=count, p = cp, f = fp; i; i--, p++) {
 561                         if (f)
 562                                 flags = *f++;
 563                         switch (flags) {
 564                         case TTY_NORMAL:
 565                                 n_tty_receive_char(tty, *p);
 566                                 break;
 567                         case TTY_BREAK:
 568                                 n_tty_receive_break(tty);
 569                                 break;
 570                         case TTY_PARITY:
 571                         case TTY_FRAME:
 572                                 n_tty_receive_parity_error(tty, *p);
 573                                 break;
 574                         case TTY_OVERRUN:
 575                                 n_tty_receive_overrun(tty);
 576                                 break;
 577                         default:
 578                                 printk("%s: unknown flag %d\n", tty_name(tty),
 579                                        flags);
 580                                 break;
 581                         }
 582                 }
 583                 if (tty->driver.flush_chars)
 584                         tty->driver.flush_chars(tty);
 585         }
 586 
 587         if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
 588                 if (tty->fasync)
 589                         kill_fasync(tty->fasync, SIGIO);
 590                 if (tty->read_wait)
 591                         wake_up_interruptible(&tty->read_wait);
 592         }
 593 
 594         if ((tty->read_cnt >= TTY_THRESHOLD_THROTTLE) &&
 595             tty->driver.throttle &&
 596             !set_bit(TTY_THROTTLED, &tty->flags))
 597                 tty->driver.throttle(tty);
 598 }
 599 
 600 static int n_tty_receive_room(struct tty_struct *tty)
     
 601 {
 602         int     left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
 603 
 604         
 605 
 606 
 607 
 608 
 609 
 610         if (tty->icanon && !tty->canon_data)
 611                 return N_TTY_BUF_SIZE;
 612 
 613         if (left > 0)
 614                 return left;
 615         return 0;
 616 }
 617 
 618 int is_ignored(int sig)
     
 619 {
 620         return ((current->blocked & (1<<(sig-1))) ||
 621                 (current->sig->action[sig-1].sa_handler == SIG_IGN));
 622 }
 623 
 624 static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
     
 625 {
 626         if (!tty)
 627                 return;
 628         
 629         tty->icanon = (L_ICANON(tty) != 0);
 630         if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
 631             I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
 632             I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
 633             I_PARMRK(tty)) {
 634                 cli();
 635                 memset(tty->process_char_map, 0, 256/8);
 636 
 637                 if (I_IGNCR(tty) || I_ICRNL(tty))
 638                         set_bit('\r', &tty->process_char_map);
 639                 if (I_INLCR(tty))
 640                         set_bit('\n', &tty->process_char_map);
 641 
 642                 if (L_ICANON(tty)) {
 643                         set_bit(ERASE_CHAR(tty), &tty->process_char_map);
 644                         set_bit(KILL_CHAR(tty), &tty->process_char_map);
 645                         set_bit(EOF_CHAR(tty), &tty->process_char_map);
 646                         set_bit('\n', &tty->process_char_map);
 647                         set_bit(EOL_CHAR(tty), &tty->process_char_map);
 648                         if (L_IEXTEN(tty)) {
 649                                 set_bit(WERASE_CHAR(tty),
 650                                         &tty->process_char_map);
 651                                 set_bit(LNEXT_CHAR(tty),
 652                                         &tty->process_char_map);
 653                                 set_bit(EOL2_CHAR(tty),
 654                                         &tty->process_char_map);
 655                                 if (L_ECHO(tty))
 656                                         set_bit(REPRINT_CHAR(tty),
 657                                                 &tty->process_char_map);
 658                         }
 659                 }
 660                 if (I_IXON(tty)) {
 661                         set_bit(START_CHAR(tty), &tty->process_char_map);
 662                         set_bit(STOP_CHAR(tty), &tty->process_char_map);
 663                 }
 664                 if (L_ISIG(tty)) {
 665                         set_bit(INTR_CHAR(tty), &tty->process_char_map);
 666                         set_bit(QUIT_CHAR(tty), &tty->process_char_map);
 667                         set_bit(SUSP_CHAR(tty), &tty->process_char_map);
 668                 }
 669                 clear_bit(__DISABLED_CHAR, &tty->process_char_map);
 670                 sti();
 671                 tty->raw = 0;
 672                 tty->real_raw = 0;
 673         } else {
 674                 tty->raw = 1;
 675                 if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
 676                     (I_IGNPAR(tty) || !I_INPCK(tty)) &&
 677                     (tty->driver.flags & TTY_DRIVER_REAL_RAW))
 678                         tty->real_raw = 1;
 679                 else
 680                         tty->real_raw = 0;
 681         }
 682 }
 683 
 684 static void n_tty_close(struct tty_struct *tty)
     
 685 {
 686         n_tty_flush_buffer(tty);
 687         if (tty->read_buf) {
 688                 free_page((unsigned long) tty->read_buf);
 689                 tty->read_buf = 0;
 690         }
 691 }
 692 
 693 static int n_tty_open(struct tty_struct *tty)
     
 694 {
 695         if (!tty)
 696                 return -EINVAL;
 697 
 698         if (!tty->read_buf) {
 699                 tty->read_buf = (unsigned char *)
 700                         get_free_page(intr_count ? GFP_ATOMIC : GFP_KERNEL);
 701                 if (!tty->read_buf)
 702                         return -ENOMEM;
 703         }
 704         memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
 705         tty->read_head = tty->read_tail = tty->read_cnt = 0;
 706         tty->canon_head = tty->canon_data = tty->erasing = 0;
 707         tty->column = 0;
 708         memset(tty->read_flags, 0, sizeof(tty->read_flags));
 709         n_tty_set_termios(tty, 0);
 710         tty->minimum_to_wake = 1;
 711         tty->closing = 0;
 712         return 0;
 713 }
 714 
 715 static inline int input_available_p(struct tty_struct *tty, int amt)
     
 716 {
 717         if (L_ICANON(tty)) {
 718                 if (tty->canon_data)
 719                         return 1;
 720         } else if (tty->read_cnt >= (amt ? amt : 1))
 721                 return 1;
 722 
 723         return 0;
 724 }
 725 
 726 
 727 
 728 
 729 
 730 
 731 
 732 
 733 
 734 static inline void copy_from_read_buf(struct tty_struct *tty,
     
 735                                       unsigned char **b,
 736                                       unsigned int *nr)
 737 
 738 {
 739         int     n;
 740 
 741         n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
 742         if (!n)
 743                 return;
 744         memcpy_tofs(*b, &tty->read_buf[tty->read_tail], n);
 745         tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
 746         tty->read_cnt -= n;
 747         *b += n;
 748         *nr -= n;
 749 }
 750 
 751 static int read_chan(struct tty_struct *tty, struct file *file,
     
 752                      unsigned char *buf, unsigned int nr)
 753 {
 754         struct wait_queue wait = { current, NULL };
 755         int c;
 756         unsigned char *b = buf;
 757         int minimum, time;
 758         int retval = 0;
 759         int size;
 760 
 761 do_it_again:
 762 
 763         if (!tty->read_buf) {
 764                 printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
 765                 return -EIO;
 766         }
 767 
 768         
 769 
 770         
 771 
 772         
 773         if (file->f_inode->i_rdev != CONSOLE_DEV &&
 774             current->tty == tty) {
 775                 if (tty->pgrp <= 0)
 776                         printk("read_chan: tty->pgrp <= 0!\n");
 777                 else if (current->pgrp != tty->pgrp) {
 778                         if (is_ignored(SIGTTIN) ||
 779                             is_orphaned_pgrp(current->pgrp))
 780                                 return -EIO;
 781                         kill_pg(current->pgrp, SIGTTIN, 1);
 782                         return -ERESTARTSYS;
 783                 }
 784         }
 785 
 786         if (L_ICANON(tty)) {
 787                 minimum = time = 0;
 788                 current->timeout = (unsigned long) -1;
 789         } else {
 790                 time = (HZ / 10) * TIME_CHAR(tty);
 791                 minimum = MIN_CHAR(tty);
 792                 if (minimum) {
 793                         current->timeout = (unsigned long) -1;
 794                         if (time)
 795                                 tty->minimum_to_wake = 1;
 796                         else if (!tty->read_wait ||
 797                                  (tty->minimum_to_wake > minimum))
 798                                 tty->minimum_to_wake = minimum;
 799                 } else {
 800                         if (time) {
 801                                 current->timeout = time + jiffies;
 802                                 time = 0;
 803                         } else
 804                                 current->timeout = 0;
 805                         tty->minimum_to_wake = minimum = 1;
 806                 }
 807         }
 808 
 809         add_wait_queue(&tty->read_wait, &wait);
 810         while (1) {
 811                 
 812                 if (tty->packet && tty->link->ctrl_status) {
 813                         if (b != buf)
 814                                 break;
 815                         put_user(tty->link->ctrl_status, b++);
 816                         tty->link->ctrl_status = 0;
 817                         break;
 818                 }
 819                 
 820 
 821 
 822                 current->state = TASK_INTERRUPTIBLE;
 823                 
 824                 if (((minimum - (b - buf)) < tty->minimum_to_wake) &&
 825                     ((minimum - (b - buf)) >= 1))
 826                         tty->minimum_to_wake = (minimum - (b - buf));
 827                 
 828                 if (!input_available_p(tty, 0)) {
 829                         if (tty->flags & (1 << TTY_SLAVE_CLOSED)) {
 830                                 retval = -EIO;
 831                                 break;
 832                         }
 833                         if (tty_hung_up_p(file))
 834                                 break;
 835                         if (!current->timeout)
 836                                 break;
 837                         if (file->f_flags & O_NONBLOCK) {
 838                                 retval = -EAGAIN;
 839                                 break;
 840                         }
 841                         if (current->signal & ~current->blocked) {
 842                                 retval = -ERESTARTSYS;
 843                                 break;
 844                         }
 845                         schedule();
 846                         continue;
 847                 }
 848                 current->state = TASK_RUNNING;
 849 
 850                 
 851                 if (tty->packet && b == buf) {
 852                         put_user(TIOCPKT_DATA, b++);
 853                         nr--;
 854                 }
 855 
 856                 if (L_ICANON(tty)) {
 857                         while (1) {
 858                                 int eol;
 859 
 860                                 disable_bh(TQUEUE_BH);
 861                                 if (!tty->read_cnt) {
 862                                         enable_bh(TQUEUE_BH);
 863                                         break;
 864                                 }
 865                                 eol = clear_bit(tty->read_tail,
 866                                                 &tty->read_flags);
 867                                 c = tty->read_buf[tty->read_tail];
 868                                 tty->read_tail = ((tty->read_tail+1) &
 869                                                   (N_TTY_BUF_SIZE-1));
 870                                 tty->read_cnt--;
 871                                 enable_bh(TQUEUE_BH);
 872                                 if (!eol) {
 873                                         put_user(c, b++);
 874                                         if (--nr)
 875                                                 continue;
 876                                         break;
 877                                 }
 878                                 if (--tty->canon_data < 0) {
 879                                         tty->canon_data = 0;
 880                                 }
 881                                 if (c != __DISABLED_CHAR) {
 882                                         put_user(c, b++);
 883                                         nr--;
 884                                 }
 885                                 break;
 886                         }
 887                 } else {
 888                         disable_bh(TQUEUE_BH);
 889                         copy_from_read_buf(tty, &b, &nr);
 890                         copy_from_read_buf(tty, &b, &nr);
 891                         enable_bh(TQUEUE_BH);
 892                 }
 893 
 894                 
 895 
 896                 if (tty->driver.unthrottle &&
 897                     (tty->read_cnt <= TTY_THRESHOLD_UNTHROTTLE)
 898                     && clear_bit(TTY_THROTTLED, &tty->flags))
 899                         tty->driver.unthrottle(tty);
 900 
 901                 if (b - buf >= minimum || !nr)
 902                         break;
 903                 if (time)
 904                         current->timeout = time + jiffies;
 905         }
 906         remove_wait_queue(&tty->read_wait, &wait);
 907 
 908         if (!tty->read_wait)
 909                 tty->minimum_to_wake = minimum;
 910 
 911         current->state = TASK_RUNNING;
 912         current->timeout = 0;
 913         size = b - buf;
 914         if (size && nr)
 915                 clear_bit(TTY_PUSH, &tty->flags);
 916         if (!size && clear_bit(TTY_PUSH, &tty->flags))
 917                 goto do_it_again;
 918         if (!size && !retval)
 919                 clear_bit(TTY_PUSH, &tty->flags);
 920         return (size ? size : retval);
 921 }
 922 
 923 static int write_chan(struct tty_struct * tty, struct file * file,
     
 924                       const unsigned char * buf, unsigned int nr)
 925 {
 926         struct wait_queue wait = { current, NULL };
 927         int c;
 928         const unsigned char *b = buf;
 929         int retval = 0;
 930 
 931         
 932         if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) {
 933                 retval = tty_check_change(tty);
 934                 if (retval)
 935                         return retval;
 936         }
 937 
 938         add_wait_queue(&tty->write_wait, &wait);
 939         while (1) {
 940                 current->state = TASK_INTERRUPTIBLE;
 941                 if (current->signal & ~current->blocked) {
 942                         retval = -ERESTARTSYS;
 943                         break;
 944                 }
 945                 if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) {
 946                         retval = -EIO;
 947                         break;
 948                 }
 949                 if (O_OPOST(tty)) {
 950                         while (nr > 0) {
 951                                 c = get_user(b);
 952                                 if (opost(c, tty) < 0)
 953                                         break;
 954                                 b++; nr--;
 955                         }
 956                         if (tty->driver.flush_chars)
 957                                 tty->driver.flush_chars(tty);
 958                 } else {
 959                         c = tty->driver.write(tty, 1, b, nr);
 960                         b += c;
 961                         nr -= c;
 962                 }
 963                 if (!nr)
 964                         break;
 965                 if (file->f_flags & O_NONBLOCK) {
 966                         retval = -EAGAIN;
 967                         break;
 968                 }
 969                 schedule();
 970         }
 971         current->state = TASK_RUNNING;
 972         remove_wait_queue(&tty->write_wait, &wait);
 973         return (b - buf) ? b - buf : retval;
 974 }
 975 
 976 static int normal_select(struct tty_struct * tty, struct inode * inode,
     
 977                          struct file * file, int sel_type, select_table *wait)
 978 {
 979         switch (sel_type) {
 980                 case SEL_IN:
 981                         if (input_available_p(tty, TIME_CHAR(tty) ? 0 :
 982                                               MIN_CHAR(tty)))
 983                                 return 1;
 984                         
 985                 case SEL_EX:
 986                         if (tty->packet && tty->link->ctrl_status)
 987                                 return 1;
 988                         if (tty->flags & (1 << TTY_SLAVE_CLOSED))
 989                                 return 1;
 990                         if (tty_hung_up_p(file))
 991                                 return 1;
 992                         if (!tty->read_wait) {
 993                                 if (MIN_CHAR(tty) && !TIME_CHAR(tty))
 994                                         tty->minimum_to_wake = MIN_CHAR(tty);
 995                                 else
 996                                         tty->minimum_to_wake = 1;
 997                         }
 998                         select_wait(&tty->read_wait, wait);
 999                         return 0;
1000                 case SEL_OUT:
1001                         if (tty->driver.chars_in_buffer(tty) < WAKEUP_CHARS)
1002                                 return 1;
1003                         select_wait(&tty->write_wait, wait);
1004                         return 0;
1005         }
1006         return 0;
1007 }
1008 
1009 struct tty_ldisc tty_ldisc_N_TTY = {
1010         TTY_LDISC_MAGIC,        
1011         0,                      
1012         0,                      
1013         n_tty_open,             
1014         n_tty_close,            
1015         n_tty_flush_buffer,     
1016         n_tty_chars_in_buffer,  
1017         read_chan,              
1018         write_chan,             
1019         n_tty_ioctl,            
1020         n_tty_set_termios,      
1021         normal_select,          
1022         n_tty_receive_buf,      
1023         n_tty_receive_room,     
1024         0                       
1025 };
1026