]> git.ozlabs.org Git - ppp.git/blobdiff - ultrix/ppp_tty.c
added prototypes, removed unused variables
[ppp.git] / ultrix / ppp_tty.c
index a1d8af783042932994d5a0fa0e85adbdb3fcaec0..40d6cf2a13d391478a9094bb72861fe4bb0ce65e 100644 (file)
@@ -73,7 +73,7 @@
  * Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
  */
 
-/* $Id: ppp_tty.c,v 1.3 1994/12/08 00:32:59 paulus Exp $ */
+/* $Id: ppp_tty.c,v 1.6 1995/10/27 04:00:10 paulus Exp $ */
 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
 
 #include "ppp.h"
@@ -113,8 +113,7 @@ int pppopen __P((dev_t dev, struct tty *tp));
 int    pppclose __P((struct tty *tp, int flag));
 int    pppread __P((struct tty *tp, struct uio *uio, int flag));
 int    pppwrite __P((struct tty *tp, struct uio *uio, int flag));
-int    ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
-                      struct proc *));
+int    ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag));
 int    pppinput __P((int c, struct tty *tp));
 int    pppstart __P((struct tty *tp));
 
@@ -122,6 +121,7 @@ static u_short      pppfcs __P((u_short fcs, u_char *cp, int len));
 static void    pppasyncstart __P((struct ppp_softc *));
 static void    pppasyncctlp __P((struct ppp_softc *));
 static void    pppasyncrelinq __P((struct ppp_softc *));
+static void    ppp_timeout __P((void *));
 static void    pppgetm __P((struct ppp_softc *sc));
 static void    pppdumpb __P((u_char *b, int l));
 static void    ppplogchar __P((struct ppp_softc *, int));
@@ -161,6 +161,7 @@ static void ppplogchar __P((struct ppp_softc *, int));
 /*
  * Line specific open routine for async tty devices.
  * Attach the given tty to the first available ppp unit.
+ * Called from device open routine or ttioctl.
  */
 /* ARGSUSED */
 int
@@ -175,19 +176,24 @@ pppopen(dev, tp)
     if (!suser())
        return EPERM;
 
+    s = spltty();
+
     if (tp->t_line == PPPDISC) {
        sc = (struct ppp_softc *) tp->t_sc;
-       if (sc != NULL && sc->sc_devp == (void *) tp)
+       if (sc != NULL && sc->sc_devp == (void *) tp) {
+           splx(s);
            return (0);
+       }
     }
 
-    if ((sc = pppalloc(p->p_pid)) == NULL)
+    if ((sc = pppalloc(p->p_pid)) == NULL) {
+       splx(s);
        return ENXIO;
+    }
 
     if (sc->sc_relinq)
        (*sc->sc_relinq)(sc);   /* get previous owner to relinquish the unit */
 
-    s = splimp();
     sc->sc_ilen = 0;
     sc->sc_m = NULL;
     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
@@ -204,13 +210,14 @@ pppopen(dev, tp)
 
     tp->t_sc = (caddr_t) sc;
     ttyflush(tp, FREAD | FWRITE);
-    splx(s);
 
+    splx(s);
     return (0);
 }
 
 /*
- * Line specific close routine.
+ * Line specific close routine, called from device close routine
+ * and from ttioctl.
  * Detach the tty from the ppp unit.
  * Mimics part of ttyclose().
  */
@@ -223,8 +230,8 @@ pppclose(tp, flag)
     struct mbuf *m;
     int s;
 
-    ttywflush(tp);
-    s = splimp();              /* paranoid; splnet probably ok */
+    s = spltty();
+    ttyflush(tp, FREAD|FWRITE);
     tp->t_line = 0;
     sc = (struct ppp_softc *) tp->t_sc;
     if (sc != NULL) {
@@ -247,7 +254,7 @@ pppasyncrelinq(sc)
 {
     int s;
 
-    s = splimp();
+    s = spltty();
     if (sc->sc_outm) {
        m_freem(sc->sc_outm);
        sc->sc_outm = NULL;
@@ -256,6 +263,10 @@ pppasyncrelinq(sc)
        m_freem(sc->sc_m);
        sc->sc_m = NULL;
     }
+    if (sc->sc_flags & SC_TIMEOUT) {
+       untimeout(ppp_timeout, (void *) sc);
+       sc->sc_flags &= ~SC_TIMEOUT;
+    }
     splx(s);
 }
 
@@ -273,22 +284,31 @@ pppread(tp, uio, flag)
     register int s;
     int error = 0;
 
-    if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
-       return 0;               /* end of file */
-    if (sc == NULL || tp != (struct tty *) sc->sc_devp)
+    if (sc == NULL)
        return 0;
-    s = splimp();
-    while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
+    /*
+     * Loop waiting for input, checking that nothing disasterous
+     * happens in the meantime.
+     */
+    s = spltty();
+    for (;;) {
+       if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
+           splx(s);
+           return 0;
+       }
+       if (sc->sc_inq.ifq_head != NULL)
+           break;
+       if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
+           && (tp->t_state & TS_ISOPEN)) {
+           splx(s);
+           return 0;           /* end of file */
+       }
        if (tp->t_state & (TS_ASYNC | TS_NBIO)) {
            splx(s);
            return (EWOULDBLOCK);
        }
        sleep((caddr_t) &tp->t_rawq, TTIPRI);
     }
-    if (tp->t_line != PPPDISC) {
-       splx(s);
-       return (-1);
-    }
 
     /* Pull place-holder byte out of canonical queue */
     getc(&tp->t_canq);
@@ -469,7 +489,7 @@ pppfcs(fcs, cp, len)
 
 /*
  * This gets called from pppoutput when a new packet is
- * put on a queue.
+ * put on a queue, at splnet.
  */
 static void
 pppasyncstart(sc)
@@ -478,30 +498,34 @@ pppasyncstart(sc)
     register struct tty *tp = (struct tty *) sc->sc_devp;
     int s;
 
-    s = splimp();
+    s = spltty();
     pppstart(tp);
     splx(s);
 }
 
 /*
  * This gets called when a received packet is placed on
- * the inq.
+ * the inq, at splnet.
  */
 static void
 pppasyncctlp(sc)
     struct ppp_softc *sc;
 {
     struct tty *tp;
+    int s;
 
     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
+    s = spltty();
     tp = (struct tty *) sc->sc_devp;
     putc(0, &tp->t_canq);
     ttwakeup(tp);
+    splx(s);
 }
 
 /*
  * Start output on async tty interface.  Get another datagram
  * to send from the interface queue and start sending it.
+ * Called at spltty or higher.
  */
 int
 pppstart(tp)
@@ -511,30 +535,18 @@ pppstart(tp)
     register struct mbuf *m;
     register int len;
     register u_char *start, *stop, *cp;
-    int n, s, ndone, done;
+    int n, s, ndone, done, idle;
     struct mbuf *m2;
 
-    if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
-       /* sorry, I can't talk now */
-       return;
-    }
-    if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
-       (*tp->t_oproc)(tp);
-       return;
-    }
-
-    for (;;) {
-       /*
-        * If there is more in the output queue, just send it now.
-        * We are being called in lieu of ttstart and must do what
-        * it would.
-        */
-       if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
+    if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
+       || sc == NULL || tp != (struct tty *) sc->sc_devp) {
+       if (tp->t_oproc != NULL)
            (*tp->t_oproc)(tp);
-           if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
-               return;
-       }
+       return 0;
+    }
 
+    idle = 0;
+    while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
        /*
         * See if we have an existing packet partly sent.
         * If not, get a new packet and start sending it.
@@ -546,9 +558,8 @@ pppstart(tp)
             */
            m = ppp_dequeue(sc);
            if (m == NULL) {
-               if (tp->t_oproc != NULL)
-                   (*tp->t_oproc)(tp);
-               return;
+               idle = 1;
+               break;
            }
 
            /*
@@ -604,6 +615,7 @@ pppstart(tp)
                    len--;
                }
            }
+
            /*
             * If we didn't empty this mbuf, remember where we're up to.
             * If we emptied the last mbuf, try to add the FCS and closing
@@ -645,31 +657,70 @@ pppstart(tp)
                            unputc(&tp->t_outq);
                        break;
                    }
+               sc->sc_bytessent += q - endseq;
            }
 
            if (!done) {
                m->m_off += m->m_len - len;
                m->m_len = len;
-               sc->sc_outm = m;
-               if (tp->t_oproc != NULL)
-                   (*tp->t_oproc)(tp);
-               return;         /* can't do any more at the moment */
+               break;
            }
 
            /* Finished with this mbuf; free it and move on. */
            MFREE(m, m2);
-           if (m2 == NULL)
-               break;
-
            m = m2;
+           if (m == NULL) {
+               /* Finished a packet */
+               sc->sc_if.if_opackets++;
+               break;
+           }
            sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
        }
 
-       /* Finished a packet */
-       sc->sc_outm = NULL;
-       sc->sc_bytessent++;     /* account for closing flag */
-       sc->sc_if.if_opackets++;
+       /*
+        * Here we have either finished a packet (m == NULL)
+        * or filled up the output queue (m != NULL).
+        */
+       sc->sc_outm = m;
+       if (m)
+           break;
     }
+
+    /*
+     * If there is stuff in the output queue, send it now.
+     * We are being called in lieu of ttstart and must do what it would.
+     */
+    if (tp->t_oproc != NULL)
+       (*tp->t_oproc)(tp);
+
+    /*
+     * This timeout is needed for operation on a pseudo-tty,
+     * because the pty code doesn't call pppstart after it has
+     * drained the t_outq.
+     */
+    if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
+       timeout(ppp_timeout, (void *) sc, 1);
+       sc->sc_flags |= SC_TIMEOUT;
+    }
+
+    return 0;
+}
+
+/*
+ * Timeout routine - try to start some more output.
+ */
+static void
+ppp_timeout(x)
+    void *x;
+{
+    struct ppp_softc *sc = (struct ppp_softc *) x;
+    struct tty *tp = (struct tty *) sc->sc_devp;
+    int s;
+
+    s = spltty();
+    sc->sc_flags &= ~SC_TIMEOUT;
+    pppstart(tp);
+    splx(s);
 }
 
 /*
@@ -683,7 +734,7 @@ pppgetm(sc)
     int len;
     int s;
 
-    s = splimp();
+    s = spltty();
     mp = &sc->sc_m;
     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
        if ((m = *mp) == NULL) {
@@ -714,19 +765,35 @@ pppinput(c, tp)
 {
     register struct ppp_softc *sc;
     struct mbuf *m;
-    int ilen;
+    int ilen, s;
     extern int tk_nin;
 
-    tk_nin++;
     sc = (struct ppp_softc *) tp->t_sc;
     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
-       return;
+       return 0;
 
-    s = spltty();
-    sc->sc_bytesrcvd++;
+    s = spltty();              /* should be unnecessary */
+    ++tk_nin;
+    ++sc->sc_bytesrcvd;
 
     c &= 0xff;
 
+    if (sc->sc_flags & SC_XONXOFF) {
+       if (c == XOFF) {
+           if ((tp->t_state & TS_TTSTOP) == 0) {
+               tp->t_state |= TS_TTSTOP;
+               (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
+           }
+           return 0;
+       }
+       if (c == XON) {
+           tp->t_state &= ~TS_TTSTOP;
+           if (tp->t_oproc != NULL)
+               (*tp->t_oproc)(tp);
+           return 0;
+       }
+    }
+
     if (c & 0x80)
        sc->sc_flags |= SC_RCV_B7_1;
     else
@@ -761,7 +828,7 @@ pppinput(c, tp)
            } else
                sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
            splx(s);
-           return;
+           return 0;
        }
 
        if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
@@ -772,7 +839,7 @@ pppinput(c, tp)
                sc->sc_flags |= SC_PKTLOST;
            }
            splx(s);
-           return;
+           return 0;
        }
 
        /*
@@ -796,19 +863,19 @@ pppinput(c, tp)
 
        pppgetm(sc);
        splx(s);
-       return;
+       return 0;
     }
 
     if (sc->sc_flags & SC_FLUSH) {
        if (sc->sc_flags & SC_LOG_FLUSH)
            ppplogchar(sc, c);
        splx(s);
-       return;
+       return 0;
     }
 
     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
        splx(s);
-       return;
+       return 0;
     }
 
     if (sc->sc_flags & SC_ESCAPED) {
@@ -817,7 +884,7 @@ pppinput(c, tp)
     } else if (c == PPP_ESCAPE) {
        sc->sc_flags |= SC_ESCAPED;
        splx(s);
-       return;
+       return 0;
     }
 
     /*
@@ -905,7 +972,7 @@ pppinput(c, tp)
     *sc->sc_mp++ = c;
     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
     splx(s);
-    return;
+    return 0;
 
  flush:
     if (!(sc->sc_flags & SC_FLUSH)) {
@@ -915,6 +982,7 @@ pppinput(c, tp)
            ppplogchar(sc, c);
     }
     splx(s);
+    return 0;
 }
 
 #define MAX_DUMP_BYTES 128