early non-blocking stuff
[unix-history] / usr / src / sys / kern / tty.c
index d33a8e5..901e6c5 100644 (file)
@@ -1,4 +1,4 @@
-/*     tty.c   3.17    %G%     */
+/*     tty.c   4.15    82/01/14        */
 
 /*
  * TTY subroutines common to more than one line discipline
 
 /*
  * TTY subroutines common to more than one line discipline
@@ -9,7 +9,6 @@
 #include "../h/user.h"
 #include "../h/tty.h"
 #include "../h/proc.h"
 #include "../h/user.h"
 #include "../h/tty.h"
 #include "../h/proc.h"
-#include "../h/mx.h"
 #include "../h/inode.h"
 #include "../h/file.h"
 #include "../h/reg.h"
 #include "../h/inode.h"
 #include "../h/file.h"
 #include "../h/reg.h"
 
 char   partab[];
 
 
 char   partab[];
 
-/*
- * When running dz's using only SAE (silo alarm) on input
- * it is necessary to call dzrint() at clock interrupt time.
- * This is unsafe unless spl5()s in tty code are changed to
- * spl6()s to block clock interrupts.  Note that the dh driver
- * currently in use works the same way as the dz, even though
- * we could try to more intelligently manage its silo.
- * Thus don't take this out if you have no dz's unless you
- * change clock.c and dhtimer().
- */
-#define        spl5    spl6
-
 /*
  * Input mapping table-- if an entry is non-zero, when the
  * corresponding character is typed preceded by "\" the escape
 /*
  * Input mapping table-- if an entry is non-zero, when the
  * corresponding character is typed preceded by "\" the escape
@@ -57,6 +44,11 @@ char maptab[] ={
        'X','Y','Z',000,000,000,000,000,
 };
 
        'X','Y','Z',000,000,000,000,000,
 };
 
+short  tthiwat[16] =
+   { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
+short  ttlowat[16] =
+   {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
+
 #define        OBUFSIZ 100
 
 /*
 #define        OBUFSIZ 100
 
 /*
@@ -81,9 +73,6 @@ register struct tty *tp;
        tlun.t_flushc = CTRL(o);
        tlun.t_werasc = CTRL(w);
        tlun.t_lnextc = CTRL(v);
        tlun.t_flushc = CTRL(o);
        tlun.t_werasc = CTRL(w);
        tlun.t_lnextc = CTRL(v);
-       tlun.t_lintr = CTRL(c);
-       tlun.t_lerase = CTRL(h);
-       tlun.t_lkill = CTRL(u);
        tp->t_local = 0;
        tp->t_lstate = 0;
 /* end local */
        tp->t_local = 0;
        tp->t_lstate = 0;
 /* end local */
@@ -93,13 +82,13 @@ register struct tty *tp;
  * Wait for output to drain, then flush input waiting.
  */
 wflushtty(tp)
  * Wait for output to drain, then flush input waiting.
  */
 wflushtty(tp)
-register struct tty *tp;
+       register struct tty *tp;
 {
 
        (void) spl5();
 {
 
        (void) spl5();
-       while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
+       while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON) {
                (*tp->t_oproc)(tp);
                (*tp->t_oproc)(tp);
-               tp->t_state |= ASLEEP;
+               tp->t_state |= TS_ASLEEP;
                sleep((caddr_t)&tp->t_outq, TTOPRI);
        }
        flushtty(tp, FREAD|FWRITE);
                sleep((caddr_t)&tp->t_outq, TTOPRI);
        }
        flushtty(tp, FREAD|FWRITE);
@@ -114,8 +103,6 @@ register struct tty *tp;
 {
        register s;
 
 {
        register s;
 
-       if (tp->t_line == NETLDISC)
-               return;
        s = spl6();
        if (rw & FREAD) {
                while (getc(&tp->t_canq) >= 0)
        s = spl6();
        if (rw & FREAD) {
                while (getc(&tp->t_canq) >= 0)
@@ -124,7 +111,7 @@ register struct tty *tp;
        }
        if (rw & FWRITE) {
                wakeup((caddr_t)&tp->t_outq);
        }
        if (rw & FWRITE) {
                wakeup((caddr_t)&tp->t_outq);
-               tp->t_state &= ~TTSTOP;
+               tp->t_state &= ~TS_TTSTOP;
                (*cdevsw[major(tp->t_dev)].d_stop)(tp);
                while (getc(&tp->t_outq) >= 0)
                        ;
                (*cdevsw[major(tp->t_dev)].d_stop)(tp);
                while (getc(&tp->t_outq) >= 0)
                        ;
@@ -150,11 +137,11 @@ register struct tty *tp;
        x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
        if (tp->t_rawq.c_cc > TTYHOG) {
                flushtty(tp, FREAD|FWRITE);
        x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
        if (tp->t_rawq.c_cc > TTYHOG) {
                flushtty(tp, FREAD|FWRITE);
-               tp->t_state &= ~TBLOCK;
+               tp->t_state &= ~TS_TBLOCK;
        }
        if (x >= TTYHOG/2) {
                if (putc(tun.t_stopc, &tp->t_outq)==0) {
        }
        if (x >= TTYHOG/2) {
                if (putc(tun.t_stopc, &tp->t_outq)==0) {
-                       tp->t_state |= TBLOCK;
+                       tp->t_state |= TS_TBLOCK;
                        tp->t_char++;
                        ttstart(tp);
                }
                        tp->t_char++;
                        ttstart(tp);
                }
@@ -171,7 +158,11 @@ ttrstrt(tp)
 register struct tty *tp;
 {
 
 register struct tty *tp;
 {
 
-       tp->t_state &= ~TIMEOUT;
+       if (tp == 0) {
+               printf("ttrstrt: arg was 0!\n");
+               return;
+       }
+       tp->t_state &= ~TS_TIMEOUT;
        ttstart(tp);
 }
 
        ttstart(tp);
 }
 
@@ -187,7 +178,7 @@ register struct tty *tp;
        register s;
 
        s = spl5();
        register s;
 
        s = spl5();
-       if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
+       if((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0)
                (*tp->t_oproc)(tp);
        splx(s);
 }
                (*tp->t_oproc)(tp);
        splx(s);
 }
@@ -195,10 +186,12 @@ register struct tty *tp;
 /*
  * Common code for tty ioctls.
  */
 /*
  * Common code for tty ioctls.
  */
-ttioctl(com, tp, addr, dev, flag)
+/*ARGSUSED*/
+ttioctl(tp, com, addr, flag)
 register struct tty *tp;
 caddr_t addr;
 {
 register struct tty *tp;
 caddr_t addr;
 {
+       int dev;
        unsigned t;
        struct sgttyb iocb;
        struct clist tq;
        unsigned t;
        struct sgttyb iocb;
        struct clist tq;
@@ -206,6 +199,16 @@ caddr_t addr;
        register c;
        int temp;
 
        register c;
        int temp;
 
+       /*
+        * This is especially so that isatty() will
+        * fail when carrier is gone.
+        */
+       if ((tp->t_state&TS_CARR_ON) == 0) {
+               u.u_error = EBADF;
+               return (1);
+       }
+
+       dev = tp->t_dev;
        /*
         * If the ioctl involves modification,
         * insist on being able to write the device,
        /*
         * If the ioctl involves modification,
         * insist on being able to write the device,
@@ -213,7 +216,9 @@ caddr_t addr;
         */
        switch(com) {
 
         */
        switch(com) {
 
-       case TIOCHPCL:
+       case TIOCSETD:
+       case TIOCSETP:
+       case TIOCSETN:
        case TIOCFLUSH:
        case TIOCSETC:
        case TIOCSLTC:
        case TIOCFLUSH:
        case TIOCSETC:
        case TIOCSLTC:
@@ -222,10 +227,12 @@ caddr_t addr;
        case TIOCLBIC:
        case TIOCLSET:
        case TIOCSTI:
        case TIOCLBIC:
        case TIOCLSET:
        case TIOCSTI:
+/* this is reasonable, but impractical... 
                if ((flag & FWRITE) == 0) {
                        u.u_error = EBADF;
                        return (1);
                }
                if ((flag & FWRITE) == 0) {
                        u.u_error = EBADF;
                        return (1);
                }
+ */
                while (tp->t_line == NTTYDISC &&
                   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
                   (u.u_procp->p_flag&SVFORK) == 0 &&
                while (tp->t_line == NTTYDISC &&
                   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
                   (u.u_procp->p_flag&SVFORK) == 0 &&
@@ -274,17 +281,6 @@ caddr_t addr;
                (void) spl0();
                break;
 
                (void) spl0();
                break;
 
-       /*
-        * Prevent more opens on channel
-        */
-       case TIOCEXCL:
-               tp->t_state |= XCLUDE;
-               break;
-
-       case TIOCNXCL:
-               tp->t_state &= ~XCLUDE;
-               break;
-
        /*
         * Set new parameters
         */
        /*
         * Set new parameters
         */
@@ -295,39 +291,29 @@ caddr_t addr;
                        return(1);
                }
                (void) spl5();
                        return(1);
                }
                (void) spl5();
-               if (tp->t_line == 0) {
-                       if (com == TIOCSETP)
-                               wflushtty(tp);
-                       while (canon(tp)>=0) 
-                               ;
-               } else if (tp->t_line == NTTYDISC) {
-                       if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
-                           com == TIOCSETP)
-                               wflushtty(tp);
-                       else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
-                               if (iocb.sg_flags & CBREAK) {
-                                       catq(&tp->t_rawq, &tp->t_canq);
-                                       tq = tp->t_rawq;
-                                       tp->t_rawq = tp->t_canq;
-                                       tp->t_canq = tq;
-                               } else {
-                                       tp->t_local |= LPENDIN;
-                                       if (tp->t_canq.c_cc)
-                                               panic("ioccom canq");
-                                       if (tp->t_chan)
-                                               (void) sdata(tp->t_chan);
-                                       else
-                                               wakeup((caddr_t)&tp->t_rawq);
-                               }
+               if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
+                   com == TIOCSETP)
+                       wflushtty(tp);
+               else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
+                       if (iocb.sg_flags & CBREAK) {
+                               catq(&tp->t_rawq, &tp->t_canq);
+                               tq = tp->t_rawq;
+                               tp->t_rawq = tp->t_canq;
+                               tp->t_canq = tq;
+                       } else {
+                               tp->t_local |= LPENDIN;
+                               ttwakeup(tp);
                        }
                }
                        }
                }
-               if ((tp->t_state&SPEEDS)==0) {
-                       tp->t_ispeed = iocb.sg_ispeed;
-                       tp->t_ospeed = iocb.sg_ospeed;
-               }
+               tp->t_ispeed = iocb.sg_ispeed;
+               tp->t_ospeed = iocb.sg_ospeed;
                tp->t_erase = iocb.sg_erase;
                tp->t_kill = iocb.sg_kill;
                tp->t_flags = iocb.sg_flags;
                tp->t_erase = iocb.sg_erase;
                tp->t_kill = iocb.sg_kill;
                tp->t_flags = iocb.sg_flags;
+               if (tp->t_flags & RAW) {
+                       tp->t_state &= ~TS_TTSTOP;
+                       ttstart(tp);
+               }
                (void) spl0();
                break;
 
                (void) spl0();
                break;
 
@@ -348,21 +334,33 @@ caddr_t addr;
         * Hang up line on last close
         */
        case TIOCHPCL:
         * Hang up line on last close
         */
        case TIOCHPCL:
-               tp->t_state |= HUPCLS;
+               tp->t_state |= TS_HUPCLS;
                break;
 
                break;
 
-       case TIOCFLUSH:
-               flushtty(tp, FREAD|FWRITE);
+       case TIOCFLUSH: {
+               int flags;
+               if (addr == 0)
+                       flags = FREAD|FWRITE;
+               else if (copyin(addr, (caddr_t)&flags, sizeof (flags))) {
+                       u.u_error = EFAULT;
+                       return(1);
+               }
+               flushtty(tp, flags);
                break;
                break;
+       }
 
 
-       /*
-        * Ioctl entries to line discipline
-        */
-       case DIOCSETP:
-       case DIOCGETP:
-               if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr))
-                       u.u_error = ENOTTY;
+       case FIONBIO: {
+               int nbio;
+               if (copyin(addr, (caddr_t)&nbio, sizeof (nbio))) {
+                       u.u_error = EFAULT;
+                       return(1);
+               }
+               if (nbio)
+                       tp->t_state |= TS_NBIO;
+               else
+                       tp->t_state &= ~TS_NBIO;
                break;
                break;
+       }
 
        /*
         * Set and fetch special characters
 
        /*
         * Set and fetch special characters
@@ -395,28 +393,7 @@ caddr_t addr;
         * Return number of characters immediately available.
         */
        case FIONREAD: {
         * Return number of characters immediately available.
         */
        case FIONREAD: {
-               off_t nread;
-
-               switch (tp->t_line) {
-
-               case NETLDISC:
-                       nread = tp->t_rec ? tp->t_inbuf : 0;
-                       break;
-
-               case 0:
-                       (void) spl5();
-                       while (canon(tp)>=0)
-                               ;
-                       (void) spl0();
-                       /* fall into ... */
-
-               case NTTYDISC:
-                       nread = tp->t_canq.c_cc;
-                       if (tp->t_flags & (RAW|CBREAK))
-                               nread += tp->t_rawq.c_cc;
-                       break;
-
-               }
+               off_t nread = ttnread(tp);
                if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
                        u.u_error = EFAULT;
                break;
                if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
                        u.u_error = EFAULT;
                break;
@@ -490,3 +467,53 @@ caddr_t addr;
        }
        return(1);
 }
        }
        return(1);
 }
+
+ttnread(tp)
+       struct tty *tp;
+{
+       int nread = 0;
+
+       if (tp->t_local & LPENDIN)
+               ttypend(tp);
+       nread = tp->t_canq.c_cc;
+       if (tp->t_flags & (RAW|CBREAK))
+               nread += tp->t_rawq.c_cc;
+       return (nread);
+}
+
+ttselect(dev, rw)
+       dev_t dev;
+       int rw;
+{
+       register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
+       int nread;
+       int s = spl5();
+
+       switch (rw) {
+
+       case FREAD:
+               nread = ttnread(tp);
+               if (nread > 0)
+                       goto win;
+               if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
+                       tp->t_state |= TS_RCOLL;
+               else
+                       tp->t_rsel = u.u_procp;
+               break;
+
+       case FWRITE:
+               if (tp->t_outq.c_cc <= TTLOWAT(tp))
+                       goto win;
+printf("wsel block\n");
+               if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
+                       tp->t_state |= TS_WCOLL;
+               else
+                       tp->t_wsel = u.u_procp;
+               break;
+       }
+       splx(s);
+       return (0);
+win:
+       splx(s);
+       return (1);
+}