1*7436Skre /* tty.c 4.23 82/07/15 */ 239Sbill 339Sbill /* 4903Sbill * TTY subroutines common to more than one line discipline 539Sbill */ 639Sbill #include "../h/param.h" 739Sbill #include "../h/systm.h" 839Sbill #include "../h/dir.h" 939Sbill #include "../h/user.h" 1039Sbill #include "../h/tty.h" 1139Sbill #include "../h/proc.h" 1239Sbill #include "../h/inode.h" 1339Sbill #include "../h/file.h" 1439Sbill #include "../h/reg.h" 1539Sbill #include "../h/conf.h" 1639Sbill #include "../h/buf.h" 17340Sbill #include "../h/dk.h" 1839Sbill 19*7436Skre /* 20*7436Skre * Table giving parity for characters and indicating 21*7436Skre * character classes to tty driver. In particular, 22*7436Skre * if the low 6 bits are 0, then the character needs 23*7436Skre * no special processing on output. 24*7436Skre */ 2539Sbill 26*7436Skre char partab[] = { 27*7436Skre 0001,0201,0201,0001,0201,0001,0001,0201, 28*7436Skre 0202,0004,0003,0201,0005,0206,0201,0001, 29*7436Skre 0201,0001,0001,0201,0001,0201,0201,0001, 30*7436Skre 0001,0201,0201,0001,0201,0001,0001,0201, 31*7436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 32*7436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 33*7436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 34*7436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 35*7436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 36*7436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 37*7436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 38*7436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 39*7436Skre 0000,0200,0200,0000,0200,0000,0000,0200, 40*7436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 41*7436Skre 0200,0000,0000,0200,0000,0200,0200,0000, 42*7436Skre 0000,0200,0200,0000,0200,0000,0000,0201, 43*7436Skre 44*7436Skre /* 45*7436Skre * 7 bit ascii ends with the last character above, 46*7436Skre * but we contine through all 256 codes for the sake 47*7436Skre * of the tty output routines which use special vax 48*7436Skre * instructions which need a 256 character trt table. 49*7436Skre */ 50*7436Skre 51*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 52*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 53*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 54*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 55*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 56*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 57*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 58*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 59*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 60*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 61*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 62*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 63*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 64*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 65*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007, 66*7436Skre 0007,0007,0007,0007,0007,0007,0007,0007 67*7436Skre }; 68*7436Skre 69146Sbill /* 7039Sbill * Input mapping table-- if an entry is non-zero, when the 7139Sbill * corresponding character is typed preceded by "\" the escape 7239Sbill * sequence is replaced by the table value. Mostly used for 7339Sbill * upper-case only terminals. 7439Sbill */ 7539Sbill 7639Sbill char maptab[] ={ 7739Sbill 000,000,000,000,000,000,000,000, 7839Sbill 000,000,000,000,000,000,000,000, 7939Sbill 000,000,000,000,000,000,000,000, 8039Sbill 000,000,000,000,000,000,000,000, 8139Sbill 000,'|',000,000,000,000,000,'`', 8239Sbill '{','}',000,000,000,000,000,000, 8339Sbill 000,000,000,000,000,000,000,000, 8439Sbill 000,000,000,000,000,000,000,000, 8539Sbill 000,000,000,000,000,000,000,000, 8639Sbill 000,000,000,000,000,000,000,000, 8739Sbill 000,000,000,000,000,000,000,000, 8839Sbill 000,000,000,000,000,000,'~',000, 8939Sbill 000,'A','B','C','D','E','F','G', 9039Sbill 'H','I','J','K','L','M','N','O', 9139Sbill 'P','Q','R','S','T','U','V','W', 9239Sbill 'X','Y','Z',000,000,000,000,000, 9339Sbill }; 9439Sbill 95925Sbill short tthiwat[16] = 96925Sbill { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 }; 97925Sbill short ttlowat[16] = 98925Sbill { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; 99925Sbill 10039Sbill #define OBUFSIZ 100 10139Sbill 10239Sbill /* 10339Sbill * set default control characters. 10439Sbill */ 10539Sbill ttychars(tp) 10639Sbill register struct tty *tp; 10739Sbill { 108174Sbill 10939Sbill tun.t_intrc = CINTR; 11039Sbill tun.t_quitc = CQUIT; 11139Sbill tun.t_startc = CSTART; 11239Sbill tun.t_stopc = CSTOP; 11339Sbill tun.t_eofc = CEOT; 11439Sbill tun.t_brkc = CBRK; 11539Sbill tp->t_erase = CERASE; 11639Sbill tp->t_kill = CKILL; 117174Sbill /* begin local */ 118208Sbill tlun.t_suspc = CTRL(z); 119208Sbill tlun.t_dsuspc = CTRL(y); 120174Sbill tlun.t_rprntc = CTRL(r); 121174Sbill tlun.t_flushc = CTRL(o); 122174Sbill tlun.t_werasc = CTRL(w); 123174Sbill tlun.t_lnextc = CTRL(v); 124174Sbill tp->t_local = 0; 125174Sbill tp->t_lstate = 0; 126174Sbill /* end local */ 12739Sbill } 12839Sbill 12939Sbill /* 130903Sbill * Wait for output to drain, then flush input waiting. 13139Sbill */ 132903Sbill wflushtty(tp) 1335408Swnj register struct tty *tp; 13439Sbill { 13539Sbill 136903Sbill (void) spl5(); 1375622Swnj while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON 1385622Swnj && tp->t_oproc) { /* kludge for pty */ 139903Sbill (*tp->t_oproc)(tp); 1405408Swnj tp->t_state |= TS_ASLEEP; 141903Sbill sleep((caddr_t)&tp->t_outq, TTOPRI); 142903Sbill } 1435426Swnj flushtty(tp, FREAD); 144903Sbill (void) spl0(); 14539Sbill } 14639Sbill 14739Sbill /* 148903Sbill * flush all TTY queues 14939Sbill */ 150903Sbill flushtty(tp, rw) 151903Sbill register struct tty *tp; 15239Sbill { 153903Sbill register s; 154903Sbill 155903Sbill s = spl6(); 156903Sbill if (rw & FREAD) { 157903Sbill while (getc(&tp->t_canq) >= 0) 158903Sbill ; 159903Sbill wakeup((caddr_t)&tp->t_rawq); 160903Sbill } 161903Sbill if (rw & FWRITE) { 162903Sbill wakeup((caddr_t)&tp->t_outq); 1635408Swnj tp->t_state &= ~TS_TTSTOP; 1645426Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 165903Sbill while (getc(&tp->t_outq) >= 0) 166903Sbill ; 167903Sbill } 168903Sbill if (rw & FREAD) { 169903Sbill while (getc(&tp->t_rawq) >= 0) 170903Sbill ; 171903Sbill tp->t_delct = 0; 172903Sbill tp->t_rocount = 0; /* local */ 173903Sbill tp->t_rocol = 0; 174903Sbill tp->t_lstate = 0; 175903Sbill } 176903Sbill splx(s); 17739Sbill } 17839Sbill 179903Sbill /* 180903Sbill * Send stop character on input overflow. 181903Sbill */ 182903Sbill ttyblock(tp) 183903Sbill register struct tty *tp; 18439Sbill { 185903Sbill register x; 186903Sbill x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 187903Sbill if (tp->t_rawq.c_cc > TTYHOG) { 188903Sbill flushtty(tp, FREAD|FWRITE); 1895408Swnj tp->t_state &= ~TS_TBLOCK; 190903Sbill } 191903Sbill if (x >= TTYHOG/2) { 192903Sbill if (putc(tun.t_stopc, &tp->t_outq)==0) { 1935408Swnj tp->t_state |= TS_TBLOCK; 194903Sbill tp->t_char++; 195903Sbill ttstart(tp); 196903Sbill } 197903Sbill } 19839Sbill } 19939Sbill 20039Sbill /* 201903Sbill * Restart typewriter output following a delay 202903Sbill * timeout. 203903Sbill * The name of the routine is passed to the timeout 204903Sbill * subroutine and it is called during a clock interrupt. 205121Sbill */ 206903Sbill ttrstrt(tp) 207121Sbill register struct tty *tp; 208121Sbill { 209121Sbill 2103351Swnj if (tp == 0) { 2113351Swnj printf("ttrstrt: arg was 0!\n"); 2123351Swnj return; 2133351Swnj } 2145408Swnj tp->t_state &= ~TS_TIMEOUT; 215903Sbill ttstart(tp); 216121Sbill } 217121Sbill 218121Sbill /* 219903Sbill * Start output on the typewriter. It is used from the top half 220903Sbill * after some characters have been put on the output queue, 221903Sbill * from the interrupt routine to transmit the next 222903Sbill * character, and after a timeout has finished. 22339Sbill */ 224903Sbill ttstart(tp) 225903Sbill register struct tty *tp; 22639Sbill { 227903Sbill register s; 22839Sbill 229903Sbill s = spl5(); 2305622Swnj if((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 && 2315622Swnj tp->t_oproc) /* kludge for pty */ 232903Sbill (*tp->t_oproc)(tp); 233903Sbill splx(s); 23439Sbill } 23539Sbill 23639Sbill /* 237903Sbill * Common code for tty ioctls. 23839Sbill */ 2391780Sbill /*ARGSUSED*/ 2401904Swnj ttioctl(tp, com, addr, flag) 24139Sbill register struct tty *tp; 24239Sbill caddr_t addr; 24339Sbill { 2441904Swnj int dev; 24539Sbill unsigned t; 246174Sbill struct sgttyb iocb; 247191Sbill struct clist tq; 24839Sbill extern int nldisp; 249887Sbill register c; 250728Sbill int temp; 25139Sbill 252903Sbill /* 253915Sbill * This is especially so that isatty() will 254915Sbill * fail when carrier is gone. 255915Sbill */ 2565408Swnj if ((tp->t_state&TS_CARR_ON) == 0) { 257915Sbill u.u_error = EBADF; 258915Sbill return (1); 259915Sbill } 260915Sbill 2611904Swnj dev = tp->t_dev; 262915Sbill /* 263903Sbill * If the ioctl involves modification, 264903Sbill * insist on being able to write the device, 265903Sbill * and hang if in the background. 266903Sbill */ 26739Sbill switch(com) { 26839Sbill 269915Sbill case TIOCSETD: 270915Sbill case TIOCSETP: 271915Sbill case TIOCSETN: 272903Sbill case TIOCFLUSH: 273903Sbill case TIOCSETC: 274903Sbill case TIOCSLTC: 275903Sbill case TIOCSPGRP: 276903Sbill case TIOCLBIS: 277903Sbill case TIOCLBIC: 278903Sbill case TIOCLSET: 279903Sbill case TIOCSTI: 280915Sbill /* this is reasonable, but impractical... 281903Sbill if ((flag & FWRITE) == 0) { 282903Sbill u.u_error = EBADF; 283903Sbill return (1); 284903Sbill } 285915Sbill */ 286903Sbill while (tp->t_line == NTTYDISC && 287903Sbill u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 288903Sbill (u.u_procp->p_flag&SVFORK) == 0 && 289903Sbill u.u_signal[SIGTTOU] != SIG_IGN && 2905626Swnj u.u_signal[SIGTTOU] != SIG_HOLD 2915626Swnj /* 2925626Swnj && 293903Sbill (u.u_procp->p_flag&SDETACH)==0) { 2945626Swnj */ 2955626Swnj ) { 296903Sbill gsignal(u.u_procp->p_pgrp, SIGTTOU); 297903Sbill sleep((caddr_t)&lbolt, TTOPRI); 298903Sbill } 299903Sbill break; 300903Sbill } 301903Sbill 30239Sbill /* 303903Sbill * Process the ioctl. 30439Sbill */ 305903Sbill switch(com) { 306903Sbill 307903Sbill /* 308903Sbill * Get discipline number 309903Sbill */ 31039Sbill case TIOCGETD: 31139Sbill t = tp->t_line; 31239Sbill if (copyout((caddr_t)&t, addr, sizeof(t))) 31339Sbill u.u_error = EFAULT; 31439Sbill break; 31539Sbill 31639Sbill /* 317903Sbill * Set line discipline 31839Sbill */ 31939Sbill case TIOCSETD: 32039Sbill if (copyin(addr, (caddr_t)&t, sizeof(t))) { 32139Sbill u.u_error = EFAULT; 32239Sbill break; 32339Sbill } 32439Sbill if (t >= nldisp) { 32539Sbill u.u_error = ENXIO; 32639Sbill break; 32739Sbill } 328174Sbill (void) spl5(); 32939Sbill if (tp->t_line) 33039Sbill (*linesw[tp->t_line].l_close)(tp); 33139Sbill if (t) 33239Sbill (*linesw[t].l_open)(dev, tp, addr); 33339Sbill if (u.u_error==0) 33439Sbill tp->t_line = t; 335174Sbill (void) spl0(); 33639Sbill break; 33739Sbill 33839Sbill /* 3395614Swnj * Prevent more opens on channel 3405614Swnj */ 3415614Swnj case TIOCEXCL: 3425614Swnj tp->t_state |= TS_XCLUDE; 3435614Swnj break; 3445614Swnj 3455614Swnj case TIOCNXCL: 3465614Swnj tp->t_state &= ~TS_XCLUDE; 3475614Swnj break; 3485614Swnj 3495614Swnj /* 35039Sbill * Set new parameters 35139Sbill */ 35239Sbill case TIOCSETP: 353191Sbill case TIOCSETN: 35439Sbill if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { 35539Sbill u.u_error = EFAULT; 35639Sbill return(1); 35739Sbill } 358121Sbill (void) spl5(); 3594484Swnj if (tp->t_flags&RAW || iocb.sg_flags&RAW || 3604484Swnj com == TIOCSETP) 3614484Swnj wflushtty(tp); 3624484Swnj else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) { 3634484Swnj if (iocb.sg_flags & CBREAK) { 3644484Swnj catq(&tp->t_rawq, &tp->t_canq); 3654484Swnj tq = tp->t_rawq; 3664484Swnj tp->t_rawq = tp->t_canq; 3674484Swnj tp->t_canq = tq; 3684484Swnj } else { 3694484Swnj tp->t_local |= LPENDIN; 3704484Swnj ttwakeup(tp); 371174Sbill } 372174Sbill } 3734484Swnj tp->t_ispeed = iocb.sg_ispeed; 3744484Swnj tp->t_ospeed = iocb.sg_ospeed; 375174Sbill tp->t_erase = iocb.sg_erase; 376174Sbill tp->t_kill = iocb.sg_kill; 377174Sbill tp->t_flags = iocb.sg_flags; 3783941Sbugs if (tp->t_flags & RAW) { 3795408Swnj tp->t_state &= ~TS_TTSTOP; 3803941Sbugs ttstart(tp); 3813941Sbugs } 382121Sbill (void) spl0(); 38339Sbill break; 38439Sbill 38539Sbill /* 386903Sbill * Send current parameters to user 38739Sbill */ 38839Sbill case TIOCGETP: 389174Sbill iocb.sg_ispeed = tp->t_ispeed; 390174Sbill iocb.sg_ospeed = tp->t_ospeed; 391174Sbill iocb.sg_erase = tp->t_erase; 392174Sbill iocb.sg_kill = tp->t_kill; 393174Sbill iocb.sg_flags = tp->t_flags; 39439Sbill if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) 39539Sbill u.u_error = EFAULT; 39639Sbill break; 39739Sbill 39839Sbill /* 39939Sbill * Hang up line on last close 40039Sbill */ 40139Sbill case TIOCHPCL: 4025408Swnj tp->t_state |= TS_HUPCLS; 40339Sbill break; 40439Sbill 4053942Sbugs case TIOCFLUSH: { 4063942Sbugs int flags; 4073942Sbugs if (addr == 0) 4083942Sbugs flags = FREAD|FWRITE; 4093942Sbugs else if (copyin(addr, (caddr_t)&flags, sizeof (flags))) { 4103942Sbugs u.u_error = EFAULT; 4113983Sroot return(1); 4123942Sbugs } 4133942Sbugs flushtty(tp, flags); 41439Sbill break; 4153944Sbugs } 41639Sbill 4175408Swnj case FIONBIO: { 4185408Swnj int nbio; 4195408Swnj if (copyin(addr, (caddr_t)&nbio, sizeof (nbio))) { 4205408Swnj u.u_error = EFAULT; 4215408Swnj return(1); 4225408Swnj } 4235408Swnj if (nbio) 4245408Swnj tp->t_state |= TS_NBIO; 4255408Swnj else 4265408Swnj tp->t_state &= ~TS_NBIO; 4275408Swnj break; 4285408Swnj } 4295408Swnj 4306216Swnj case FIOASYNC: { 4316216Swnj int async; 4326216Swnj if (copyin(addr, (caddr_t)&async, sizeof (async))) { 4336216Swnj u.u_error = EFAULT; 4346216Swnj return(1); 4356216Swnj } 4366216Swnj if (async) 4376216Swnj tp->t_state |= TS_ASYNC; 4386216Swnj else 4396216Swnj tp->t_state &= ~TS_ASYNC; 4406216Swnj break; 4416216Swnj } 4426216Swnj 44339Sbill /* 444903Sbill * Set and fetch special characters 44539Sbill */ 44639Sbill case TIOCSETC: 447174Sbill if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars))) 44839Sbill u.u_error = EFAULT; 44939Sbill break; 45039Sbill 45139Sbill case TIOCGETC: 452174Sbill if (copyout((caddr_t)&tun, addr, sizeof(struct tchars))) 45339Sbill u.u_error = EFAULT; 45439Sbill break; 45539Sbill 456174Sbill /* local ioctls */ 457903Sbill /* 458903Sbill * Set/get local special characters. 459903Sbill */ 460174Sbill case TIOCSLTC: 461174Sbill if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars))) 462174Sbill u.u_error = EFAULT; 463174Sbill break; 464174Sbill 465174Sbill case TIOCGLTC: 466174Sbill if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars))) 467174Sbill u.u_error = EFAULT; 468174Sbill break; 469174Sbill 470903Sbill /* 471903Sbill * Return number of characters immediately available. 472903Sbill */ 473174Sbill case FIONREAD: { 4744484Swnj off_t nread = ttnread(tp); 475174Sbill if (copyout((caddr_t)&nread, addr, sizeof (off_t))) 476174Sbill u.u_error = EFAULT; 477174Sbill break; 478174Sbill } 479174Sbill 480174Sbill /* 481174Sbill * Should allow SPGRP and GPGRP only if tty open for reading. 482174Sbill */ 483174Sbill case TIOCSPGRP: 484728Sbill if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp))) 485728Sbill u.u_error = EFAULT; 486174Sbill break; 487174Sbill 488174Sbill case TIOCGPGRP: 489174Sbill if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp))) 490174Sbill u.u_error = EFAULT; 491174Sbill break; 492174Sbill 493174Sbill /* 494174Sbill * Modify local mode word. 495174Sbill */ 496174Sbill case TIOCLBIS: 497728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 498728Sbill u.u_error = EFAULT; 499728Sbill else 500728Sbill tp->t_local |= temp; 501174Sbill break; 502174Sbill 503174Sbill case TIOCLBIC: 504728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 505728Sbill u.u_error = EFAULT; 506728Sbill else 507728Sbill tp->t_local &= ~temp; 508174Sbill break; 509174Sbill 510174Sbill case TIOCLSET: 511728Sbill if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local))) 512728Sbill u.u_error = EFAULT; 513728Sbill else 514728Sbill tp->t_local = temp; 515174Sbill break; 516174Sbill 517174Sbill case TIOCLGET: 518174Sbill if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local))) 519174Sbill u.u_error = EFAULT; 520174Sbill break; 521174Sbill 522903Sbill /* 523903Sbill * Return number of characters in 524903Sbill * the output. 525903Sbill */ 526213Sbill case TIOCOUTQ: 527213Sbill if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc))) 528213Sbill u.u_error = EFAULT; 529213Sbill break; 530213Sbill 531903Sbill /* 532903Sbill * Simulate typing of a character at the terminal. 533903Sbill */ 534887Sbill case TIOCSTI: 535887Sbill c = fubyte(addr); 536887Sbill if (u.u_uid && u.u_ttyp != tp || c < 0) 537887Sbill u.u_error = EFAULT; 538887Sbill else 539887Sbill (*linesw[tp->t_line].l_rint)(c, tp); 540887Sbill break; 5415573Swnj 5425573Swnj case TIOCSTOP: 5435573Swnj c = spl5(); 5445573Swnj if ((tp->t_state & TS_TTSTOP) == 0) { 5455573Swnj tp->t_state |= TS_TTSTOP; 5465573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 5475573Swnj } 5485573Swnj splx(c); 5495573Swnj break; 5505573Swnj 5515573Swnj case TIOCSTART: 5525573Swnj c = spl5(); 5535573Swnj if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) { 5545573Swnj tp->t_state &= ~TS_TTSTOP; 5555573Swnj tp->t_local &= ~LFLUSHO; 5565573Swnj ttstart(tp); 5575573Swnj } 5585573Swnj splx(c); 5595573Swnj break; 5605573Swnj 561174Sbill /* end of locals */ 562887Sbill 56339Sbill default: 56439Sbill return(0); 56539Sbill } 56639Sbill return(1); 56739Sbill } 5684484Swnj 5694484Swnj ttnread(tp) 5704484Swnj struct tty *tp; 5714484Swnj { 5724484Swnj int nread = 0; 5734484Swnj 5744484Swnj if (tp->t_local & LPENDIN) 5754484Swnj ttypend(tp); 5764484Swnj nread = tp->t_canq.c_cc; 5774484Swnj if (tp->t_flags & (RAW|CBREAK)) 5784484Swnj nread += tp->t_rawq.c_cc; 5794484Swnj return (nread); 5804484Swnj } 5814484Swnj 5825408Swnj ttselect(dev, rw) 5834484Swnj dev_t dev; 5845408Swnj int rw; 5854484Swnj { 5864484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5874484Swnj int nread; 5885408Swnj int s = spl5(); 5894484Swnj 5905408Swnj switch (rw) { 5914484Swnj 5924484Swnj case FREAD: 5934484Swnj nread = ttnread(tp); 5944484Swnj if (nread > 0) 5955408Swnj goto win; 5964938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5975408Swnj tp->t_state |= TS_RCOLL; 5984484Swnj else 5994484Swnj tp->t_rsel = u.u_procp; 6005408Swnj break; 6014484Swnj 6025408Swnj case FWRITE: 6035408Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp)) 6045408Swnj goto win; 6055408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 6065408Swnj tp->t_state |= TS_WCOLL; 6075408Swnj else 6085408Swnj tp->t_wsel = u.u_procp; 6095408Swnj break; 6104484Swnj } 6115408Swnj splx(s); 6125408Swnj return (0); 6135408Swnj win: 6145408Swnj splx(s); 6155408Swnj return (1); 6164484Swnj } 617*7436Skre 618