Remove confusing and incorrect comment inherited from patchkit days.
[unix-history] / sys / kern / tty.c
index 002180b..1a79702 100644 (file)
@@ -32,7 +32,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)tty.c 7.44 (Berkeley) 5/28/91
  * SUCH DAMAGE.
  *
  *     from: @(#)tty.c 7.44 (Berkeley) 5/28/91
- *     $Id: tty.c,v 1.7 1993/11/08 19:15:00 ache Exp $
+ *     $Id: tty.c,v 1.14 1994/01/11 18:09:36 ache Exp $
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -49,6 +49,7 @@
 #include "kernel.h"
 #include "vnode.h"
 #include "syslog.h"
 #include "kernel.h"
 #include "vnode.h"
 #include "syslog.h"
+#include "signalvar.h"
 
 #include "vm/vm.h"
 
 
 #include "vm/vm.h"
 
 static int proc_compare __P((struct proc *p1, struct proc *p2));
 
 /* symbolic sleep message strings */
 static int proc_compare __P((struct proc *p1, struct proc *p2));
 
 /* symbolic sleep message strings */
-char ttyin[] = "ttyin";
-char ttyout[] = "ttyout";
-char ttopen[] = "ttyopn";
-char ttclos[] = "ttycls";
-char ttybg[] = "ttybg";
-char ttybuf[] = "ttybuf";
+const char ttyin[] = "ttyin";
+const char ttyout[] = "ttyout";
+const char ttopen[] = "ttyopn";
+const char ttclos[] = "ttycls";
+const char ttybg[] = "ttybg";
+const char ttybuf[] = "ttybuf";
 
 /*
  * Table giving parity for characters and indicating
 
 /*
  * Table giving parity for characters and indicating
@@ -158,6 +159,7 @@ extern struct tty *constty;         /* temporary virtual console */
 #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \
        (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)
 
 #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \
        (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)
 
+void
 ttychars(tp)
        struct tty *tp;
 {
 ttychars(tp)
        struct tty *tp;
 {
@@ -168,6 +170,7 @@ ttychars(tp)
 /*
  * Flush tty after output has drained.
  */
 /*
  * Flush tty after output has drained.
  */
+int
 ttywflush(tp)
        struct tty *tp;
 {
 ttywflush(tp)
        struct tty *tp;
 {
@@ -181,6 +184,7 @@ ttywflush(tp)
 /*
  * Wait for output to drain.
  */
 /*
  * Wait for output to drain.
  */
+int
 ttywait(tp)
        register struct tty *tp;
 {
 ttywait(tp)
        register struct tty *tp;
 {
@@ -190,9 +194,14 @@ ttywait(tp)
            (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 
            tp->t_oproc) {
                (*tp->t_oproc)(tp);
            (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 
            tp->t_oproc) {
                (*tp->t_oproc)(tp);
-               tp->t_state |= TS_ASLEEP;
-               if (error = ttysleep(tp, (caddr_t)&tp->t_out, 
-                   TTOPRI | PCATCH, ttyout, 0))
+               if ((RB_LEN(&tp->t_out) || tp->t_state&TS_BUSY) &&
+                   (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL)) {
+                       tp->t_state |= TS_ASLEEP;
+                       if (error = ttysleep(tp, (caddr_t)&tp->t_out,
+                           TTOPRI | PCATCH, ttyout, 0))
+                               break;
+               }
+               else
                        break;
        }
        splx(s);
                        break;
        }
        splx(s);
@@ -208,10 +217,12 @@ ttywait(tp)
  * Flush TTY read and/or write queues,
  * notifying anyone waiting.
  */
  * Flush TTY read and/or write queues,
  * notifying anyone waiting.
  */
+void
 ttyflush(tp, rw)
        register struct tty *tp;
 ttyflush(tp, rw)
        register struct tty *tp;
+       int rw;
 {
 {
-       register s;
+       register int s;
 
        s = spltty();
        if (rw & FWRITE)
 
        s = spltty();
        if (rw & FWRITE)
@@ -269,6 +280,7 @@ ttyflush(tp, rw)
  * driver.
  */
 /* static void */
  * driver.
  */
 /* static void */
+void
 ttyblock(tp)
        struct tty *tp;
 {
 ttyblock(tp)
        struct tty *tp;
 {
@@ -289,7 +301,7 @@ ttyblock(tp)
  * off our input flow control bits and propagate the change to the driver.
  */
 /* static */
  * off our input flow control bits and propagate the change to the driver.
  */
 /* static */
-int
+void
 ttyunblock(tp)
        struct tty *tp;
 {
 ttyunblock(tp)
        struct tty *tp;
 {
@@ -302,6 +314,7 @@ ttyunblock(tp)
        ttstart(tp);
 }
 
        ttstart(tp);
 }
 
+void
 ttstart(tp)
        struct tty *tp;
 {
 ttstart(tp)
        struct tty *tp;
 {
@@ -310,6 +323,7 @@ ttstart(tp)
                (*tp->t_oproc)(tp);
 }
 
                (*tp->t_oproc)(tp);
 }
 
+void
 ttrstrt(tp)                            /* XXX */
        struct tty *tp;
 {
 ttrstrt(tp)                            /* XXX */
        struct tty *tp;
 {
@@ -330,9 +344,12 @@ ttrstrt(tp)                                /* XXX */
  * and/or reject any of these ioctl commands.
  */
 /*ARGSUSED*/
  * and/or reject any of these ioctl commands.
  */
 /*ARGSUSED*/
+int
 ttioctl(tp, com, data, flag)
        register struct tty *tp;
 ttioctl(tp, com, data, flag)
        register struct tty *tp;
+       int com;
        caddr_t data;
        caddr_t data;
+       int flag;
 {
        register struct proc *p = curproc;              /* XXX */
        extern int nldisp;
 {
        register struct proc *p = curproc;              /* XXX */
        extern int nldisp;
@@ -395,9 +412,9 @@ ttioctl(tp, com, data, flag)
                if (t != tp->t_line) {
                        s = spltty();
                        (*linesw[tp->t_line].l_close)(tp, flag);
                if (t != tp->t_line) {
                        s = spltty();
                        (*linesw[tp->t_line].l_close)(tp, flag);
-                       error = (*linesw[t].l_open)(dev, tp);
+                       error = (*linesw[t].l_open)(dev, tp, 0);
                        if (error) {
                        if (error) {
-                               (void)(*linesw[tp->t_line].l_open)(dev, tp);
+                               (void)(*linesw[tp->t_line].l_open)(dev, tp, 0);
                                splx(s);
                                return (error);
                        }
                                splx(s);
                                return (error);
                        }
@@ -636,6 +653,7 @@ ttioctl(tp, com, data, flag)
        return (0);
 }
 
        return (0);
 }
 
+int
 ttnread(tp)
        struct tty *tp;
 {
 ttnread(tp)
        struct tty *tp;
 {
@@ -649,6 +667,7 @@ ttnread(tp)
        return (nread);
 }
 
        return (nread);
 }
 
+int
 ttselect(dev, rw, p)
        dev_t dev;
        int rw;
 ttselect(dev, rw, p)
        dev_t dev;
        int rw;
@@ -691,9 +710,11 @@ win:
 /*
  * Initial open of tty, or (re)entry to standard tty line discipline.
  */
 /*
  * Initial open of tty, or (re)entry to standard tty line discipline.
  */
-ttyopen(dev, tp)
+int
+ttyopen(dev, tp, dummy)
        dev_t dev;
        register struct tty *tp;
        dev_t dev;
        register struct tty *tp;
+       int dummy;
 {
 
        tp->t_dev = dev;
 {
 
        tp->t_dev = dev;
@@ -712,6 +733,7 @@ ttyopen(dev, tp)
 /*
  * "close" a line discipline
  */
 /*
  * "close" a line discipline
  */
+void
 ttylclose(tp, flag)
        struct tty *tp;
        int flag;
 ttylclose(tp, flag)
        struct tty *tp;
        int flag;
@@ -728,6 +750,7 @@ ttylclose(tp, flag)
  * bumping generation number so that pending read/write calls
  * can detect recycling of the tty.
  */
  * bumping generation number so that pending read/write calls
  * can detect recycling of the tty.
  */
+int
 ttyclose(tp)
        register struct tty *tp;
 {
 ttyclose(tp)
        register struct tty *tp;
 {
@@ -746,8 +769,10 @@ ttyclose(tp)
  * Flag indicates new state of carrier.
  * Returns 0 if the line should be turned off, otherwise 1.
  */
  * Flag indicates new state of carrier.
  * Returns 0 if the line should be turned off, otherwise 1.
  */
+int
 ttymodem(tp, flag)
        register struct tty *tp;
 ttymodem(tp, flag)
        register struct tty *tp;
+       int flag;
 {
 
        if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) {
 {
 
        if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) {
@@ -786,6 +811,7 @@ ttymodem(tp, flag)
  * Default modem control routine (for other line disciplines).
  * Return argument flag, to turn off device on carrier drop.
  */
  * Default modem control routine (for other line disciplines).
  * Return argument flag, to turn off device on carrier drop.
  */
+int
 nullmodem(tp, flag)
        register struct tty *tp;
        int flag;
 nullmodem(tp, flag)
        register struct tty *tp;
        int flag;
@@ -808,6 +834,7 @@ nullmodem(tp, flag)
  * reinput pending characters after state switch
  * call at spltty().
  */
  * reinput pending characters after state switch
  * call at spltty().
  */
+void
 ttypend(tp)
        register struct tty *tp;
 {
 ttypend(tp)
        register struct tty *tp;
 {
@@ -829,8 +856,9 @@ ttypend(tp)
 /*
  * Process input of a single character received on a tty.
  */
 /*
  * Process input of a single character received on a tty.
  */
+void
 ttyinput(c, tp)
 ttyinput(c, tp)
-       register c;
+       register int c;
        register struct tty *tp;
 {
        register int iflag = tp->t_iflag;
        register struct tty *tp;
 {
        register int iflag = tp->t_iflag;
@@ -1151,8 +1179,9 @@ startoutput:
  * Returns < 0 if putc succeeds, otherwise returns char to resend.
  * Must be recursive.
  */
  * Returns < 0 if putc succeeds, otherwise returns char to resend.
  * Must be recursive.
  */
+int
 ttyoutput(c, tp)
 ttyoutput(c, tp)
-       register c;
+       register int c;
        register struct tty *tp;
 {
        register int col;
        register struct tty *tp;
 {
        register int col;
@@ -1251,16 +1280,18 @@ ttyoutput(c, tp)
 /*
  * Process a read call on a tty device.
  */
 /*
  * Process a read call on a tty device.
  */
+int
 ttread(tp, uio, flag)
        register struct tty *tp;
        struct uio *uio;
 ttread(tp, uio, flag)
        register struct tty *tp;
        struct uio *uio;
+       int flag;
 {
        register struct ringb *qp;
        register int c;
        register long lflag;
        register u_char *cc = tp->t_cc;
        register struct proc *p = curproc;
 {
        register struct ringb *qp;
        register int c;
        register long lflag;
        register u_char *cc = tp->t_cc;
        register struct proc *p = curproc;
-       int s, first, error = 0;
+       int s, first, error = 0, not_enough, rblen;
 
 loop:
        lflag = tp->t_lflag;
 
 loop:
        lflag = tp->t_lflag;
@@ -1268,14 +1299,17 @@ loop:
        /*
         * take pending input first 
         */
        /*
         * take pending input first 
         */
-       if (lflag&PENDIN)
+       if (lflag&PENDIN) {
                ttypend(tp);
                ttypend(tp);
-       splx(s);
+               splx(s);        /* reduce latency */
+               s = spltty();
+       }
 
        /*
         * Hang process if it's in the background.
         */
        if (isbackground(p, tp)) {
 
        /*
         * Hang process if it's in the background.
         */
        if (isbackground(p, tp)) {
+               splx(s);
                if ((p->p_sigignore & sigmask(SIGTTIN)) ||
                   (p->p_sigmask & sigmask(SIGTTIN)) ||
                    p->p_flag&SPPWAIT || p->p_pgrp->pg_jobc == 0)
                if ((p->p_sigignore & sigmask(SIGTTIN)) ||
                   (p->p_sigmask & sigmask(SIGTTIN)) ||
                    p->p_flag&SPPWAIT || p->p_pgrp->pg_jobc == 0)
@@ -1292,14 +1326,15 @@ loop:
         * else use the raw queue.
         */
        qp = lflag&ICANON ? &tp->t_can : &tp->t_raw;
         * else use the raw queue.
         */
        qp = lflag&ICANON ? &tp->t_can : &tp->t_raw;
+       not_enough = lflag&ICANON ? 0 : (int) cc[VMIN] - 1;
+       rblen = RB_LEN(qp);
 
        /*
         * If there is no input, sleep on rawq
         * awaiting hardware receipt and notification.
         * If we have data, we don't need to check for carrier.
         */
 
        /*
         * If there is no input, sleep on rawq
         * awaiting hardware receipt and notification.
         * If we have data, we don't need to check for carrier.
         */
-       s = spltty();
-       if (RB_LEN(qp) <= 0) {
+       if (rblen == 0 || rblen <= not_enough) {
                int carrier;
 
                carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL);
                int carrier;
 
                carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL);
@@ -1307,10 +1342,14 @@ loop:
                        splx(s);
                        return (0);     /* EOF */
                }
                        splx(s);
                        return (0);     /* EOF */
                }
-               if (flag & IO_NDELAY) {
+               if ((flag&IO_NDELAY) || not_enough < 0) {
                        splx(s);
                        return (EWOULDBLOCK);
                }
                        splx(s);
                        return (EWOULDBLOCK);
                }
+               /*
+                * XXX: needs some extention here,
+                * now always acts like cc[VTIME] == 0 (inactive)
+                */
                error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH,
                    carrier ? ttyin : ttopen, 0);
                splx(s);
                error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH,
                    carrier ? ttyin : ttopen, 0);
                splx(s);
@@ -1318,13 +1357,45 @@ loop:
                        return (error);
                goto loop;
        }
                        return (error);
                goto loop;
        }
-       splx(s);
 
        /*
         * Input present, check for input mapping and processing.
         */
        first = 1;
 
        /*
         * Input present, check for input mapping and processing.
         */
        first = 1;
-       while ((c = getc(qp)) >= 0) {
+       if (lflag & (ICANON | ISIG))
+               goto slowcase;
+       for (;;) {
+               int rcc;
+
+               rcc = RB_CONTIGGET(qp);
+               if (rcc > uio->uio_resid)
+                       rcc = uio->uio_resid;
+               if (rcc <= 0) {
+                       if (first) {
+                               /* queue got flushed (can't happen) */
+                               splx(s);
+                               goto loop;
+                       }
+                       break;
+               }
+               error = uiomove(qp->rb_hd, rcc, uio);
+               if (error)
+                       splx(s);
+               qp->rb_hd = RB_ROLLOVER(qp, qp->rb_hd + rcc);
+               splx(s);
+               s = spltty();
+               first = 0;
+       }
+       goto out;
+slowcase:
+       for (;;) {
+               c = getc(qp);
+               splx(s);
+               if (c < 0) {
+                       if (first)
+                               goto loop;
+                       break;
+               }
                /*
                 * delayed suspend (^Y)
                 */
                /*
                 * delayed suspend (^Y)
                 */
@@ -1357,16 +1428,21 @@ loop:
                 */
                if (lflag&ICANON && ttbreakc(c))
                        break;
                 */
                if (lflag&ICANON && ttbreakc(c))
                        break;
+               s = spltty();
                first = 0;
        }
                first = 0;
        }
+       s = spltty();
+
        /*
         * Look to unblock input now that (presumably)
         * the input queue has gone down.
         */
        /*
         * Look to unblock input now that (presumably)
         * the input queue has gone down.
         */
+out:
        if (tp->t_state & (TS_TBLOCK | TS_HW_IFLOW)
            && INPUT_LEN(tp) <= I_LOW_WATER)
                ttyunblock(tp);
 
        if (tp->t_state & (TS_TBLOCK | TS_HW_IFLOW)
            && INPUT_LEN(tp) <= I_LOW_WATER)
                ttyunblock(tp);
 
+       splx(s);
        return (error);
 }
 
        return (error);
 }
 
@@ -1378,12 +1454,12 @@ loop:
  * Sleeps here are not interruptible, but we return prematurely
  * if new signals come in.
  */
  * Sleeps here are not interruptible, but we return prematurely
  * if new signals come in.
  */
+int
 ttycheckoutq(tp, wait)
        register struct tty *tp;
        int wait;
 {
        int hiwat, s, oldsig;
 ttycheckoutq(tp, wait)
        register struct tty *tp;
        int wait;
 {
        int hiwat, s, oldsig;
-       extern int wakeup();
 
        hiwat = tp->t_hiwat;
        s = spltty();
 
        hiwat = tp->t_hiwat;
        s = spltty();
@@ -1398,7 +1474,8 @@ ttycheckoutq(tp, wait)
                                splx(s);
                                return (0);
                        }
                                splx(s);
                                return (0);
                        }
-                       timeout(wakeup, (caddr_t)&tp->t_out, hz);
+                       timeout((timeout_func_t)wakeup, (caddr_t)&tp->t_out,
+                               hz); /* XXX */
                        tp->t_state |= TS_ASLEEP;
                        tsleep((caddr_t)&tp->t_out, PZERO - 1, "ttchout", 0);
                }
                        tp->t_state |= TS_ASLEEP;
                        tsleep((caddr_t)&tp->t_out, PZERO - 1, "ttchout", 0);
                }
@@ -1409,11 +1486,13 @@ ttycheckoutq(tp, wait)
 /*
  * Process a write call on a tty device.
  */
 /*
  * Process a write call on a tty device.
  */
+int
 ttwrite(tp, uio, flag)
        register struct tty *tp;
        register struct uio *uio;
 ttwrite(tp, uio, flag)
        register struct tty *tp;
        register struct uio *uio;
+       int flag;
 {
 {
-       register char *cp;
+       register char *cp = 0;
        register int cc = 0, ce;
        register struct proc *p = curproc;
        int i, hiwat, cnt, error, s;
        register int cc = 0, ce;
        register struct proc *p = curproc;
        int i, hiwat, cnt, error, s;
@@ -1611,8 +1690,9 @@ ovhiwat:
  * Rubout one character from the rawq of tp
  * as cleanly as possible.
  */
  * Rubout one character from the rawq of tp
  * as cleanly as possible.
  */
+void
 ttyrub(c, tp)
 ttyrub(c, tp)
-       register c;
+       register int c;
        register struct tty *tp;
 {
        char *cp;
        register struct tty *tp;
 {
        char *cp;
@@ -1699,6 +1779,7 @@ ttyrub(c, tp)
  * Crt back over cnt chars perhaps
  * erasing them.
  */
  * Crt back over cnt chars perhaps
  * erasing them.
  */
+void
 ttyrubo(tp, cnt)
        register struct tty *tp;
        int cnt;
 ttyrubo(tp, cnt)
        register struct tty *tp;
        int cnt;
@@ -1712,6 +1793,7 @@ ttyrubo(tp, cnt)
  * Reprint the rawq line.
  * We assume c_cc has already been checked.
  */
  * Reprint the rawq line.
  * We assume c_cc has already been checked.
  */
+void
 ttyretype(tp)
        register struct tty *tp;
 {
 ttyretype(tp)
        register struct tty *tp;
 {
@@ -1739,8 +1821,9 @@ ttyretype(tp)
 /*
  * Echo a typed character to the terminal.
  */
 /*
  * Echo a typed character to the terminal.
  */
+void
 ttyecho(c, tp)
 ttyecho(c, tp)
-       register c;
+       register int c;
        register struct tty *tp;
 {
        if ((tp->t_state & TS_CNTTB) == 0)
        register struct tty *tp;
 {
        if ((tp->t_state & TS_CNTTB) == 0)
@@ -1770,6 +1853,7 @@ ttyecho(c, tp)
 /*
  * send string cp to tp
  */
 /*
  * send string cp to tp
  */
+void
 ttyoutstr(cp, tp)
        register char *cp;
        register struct tty *tp;
 ttyoutstr(cp, tp)
        register char *cp;
        register struct tty *tp;
@@ -1783,6 +1867,7 @@ ttyoutstr(cp, tp)
 /*
  * Wake up any readers on a tty.
  */
 /*
  * Wake up any readers on a tty.
  */
+void
 ttwakeup(tp)
        register struct tty *tp;
 {
 ttwakeup(tp)
        register struct tty *tp;
 {
@@ -1801,7 +1886,9 @@ ttwakeup(tp)
  * Look up a code for a specified speed in a conversion table;
  * used by drivers to map software speed values to hardware parameters.
  */
  * Look up a code for a specified speed in a conversion table;
  * used by drivers to map software speed values to hardware parameters.
  */
+int
 ttspeedtab(speed, table)
 ttspeedtab(speed, table)
+       int speed;
        register struct speedtab *table;
 {
 
        register struct speedtab *table;
 {
 
@@ -1818,6 +1905,7 @@ ttspeedtab(speed, table)
  * from hi to low water.
  * 
  */
  * from hi to low water.
  * 
  */
+void
 ttsetwater(tp)
        struct tty *tp;
 {
 ttsetwater(tp)
        struct tty *tp;
 {
@@ -1835,6 +1923,7 @@ ttsetwater(tp)
 /*
  * Report on state of foreground process group.
  */
 /*
  * Report on state of foreground process group.
  */
+void
 ttyinfo(tp)
        register struct tty *tp;
 {
 ttyinfo(tp)
        register struct tty *tp;
 {
@@ -1888,7 +1977,7 @@ ttyinfo(tp)
                /* Print percentage cpu, resident set size. */
                tmp = pick->p_pctcpu * 10000 + FSCALE / 2 >> FSHIFT;
                ttyprintf(tp, "%d%% %dk\n",
                /* Print percentage cpu, resident set size. */
                tmp = pick->p_pctcpu * 10000 + FSCALE / 2 >> FSHIFT;
                ttyprintf(tp, "%d%% %dk\n",
-                  tmp / 100, pgtok(pick->p_vmspace->vm_rssize));
+                  tmp / 100, pgtok(pick->p_vmspace->vm_pmap.pm_stats.resident_count));
        }
        tp->t_rocount = 0;      /* so pending input will be retyped if BS */
 }
        }
        tp->t_rocount = 0;      /* so pending input will be retyped if BS */
 }
@@ -1972,6 +2061,7 @@ proc_compare(p1, p2)
 /*
  * Output char to tty; console putchar style.
  */
 /*
  * Output char to tty; console putchar style.
  */
+int
 tputchar(c, tp)
        int c;
        struct tty *tp;
 tputchar(c, tp)
        int c;
        struct tty *tp;
@@ -1996,11 +2086,12 @@ tputchar(c, tp)
  * reported by tsleep.  If the tty is revoked, restarting a pending
  * call will redo validation done at the start of the call.
  */
  * reported by tsleep.  If the tty is revoked, restarting a pending
  * call will redo validation done at the start of the call.
  */
+int
 ttysleep(tp, chan, pri, wmesg, timo)
        struct tty *tp;
        caddr_t chan;
        int pri;
 ttysleep(tp, chan, pri, wmesg, timo)
        struct tty *tp;
        caddr_t chan;
        int pri;
-       char *wmesg;
+       const char *wmesg;
        int timo;
 {
        int error;
        int timo;
 {
        int error;