]> git.ozlabs.org Git - ppp.git/blobdiff - ultrix/ppp_tty.c
added timeout stuff to kick the transmitter periodically
[ppp.git] / ultrix / ppp_tty.c
index d5e6fda481c93141080a3c9524a531d798ebbee9..09b7769bf863798aff6a60a17684fb1e62fdc421 100644 (file)
@@ -1,5 +1,6 @@
 /*
 /*
- * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
+ * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
+ *            tty devices.
  *
  * Copyright (c) 1989 Carnegie Mellon University.
  * All rights reserved.
  *
  * Copyright (c) 1989 Carnegie Mellon University.
  * All rights reserved.
@@ -72,7 +73,7 @@
  * Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
  */
 
  * Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
  */
 
-/* $Id: ppp_tty.c,v 1.1 1994/11/21 04:50:36 paulus Exp $ */
+/* $Id: ppp_tty.c,v 1.4 1994/12/13 03:30:21 paulus Exp $ */
 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
 
 #include "ppp.h"
 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
 
 #include "ppp.h"
@@ -96,6 +97,7 @@
 #include "../h/systm.h"
 
 #include "../net/net/if.h"
 #include "../h/systm.h"
 
 #include "../net/net/if.h"
+#include "ppp_defs.h"
 
 #ifdef VJC
 #include "../net/netinet/in.h"
 
 #ifdef VJC
 #include "../net/netinet/in.h"
 #include "slcompress.h"
 #endif
 
 #include "slcompress.h"
 #endif
 
-#include "ppp_defs.h"
 #include "if_ppp.h"
 #include "if_pppvar.h"
 
 #include "if_ppp.h"
 #include "if_pppvar.h"
 
@@ -120,6 +121,8 @@ int pppstart __P((struct tty *tp));
 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 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));
 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));
@@ -182,14 +185,12 @@ pppopen(dev, tp)
     if ((sc = pppalloc(p->p_pid)) == NULL)
        return ENXIO;
 
     if ((sc = pppalloc(p->p_pid)) == NULL)
        return ENXIO;
 
-    if (sc->sc_outm != NULL) {
-       m_freem(sc->sc_outm);
-       sc->sc_outm = NULL;
-    }
-       
-    pppgetm(sc);
+    if (sc->sc_relinq)
+       (*sc->sc_relinq)(sc);   /* get previous owner to relinquish the unit */
 
 
+    s = splimp();
     sc->sc_ilen = 0;
     sc->sc_ilen = 0;
+    sc->sc_m = NULL;
     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
     sc->sc_asyncmap[0] = 0xffffffff;
     sc->sc_asyncmap[3] = 0x60000000;
     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
     sc->sc_asyncmap[0] = 0xffffffff;
     sc->sc_asyncmap[3] = 0x60000000;
@@ -197,9 +198,14 @@ pppopen(dev, tp)
     sc->sc_devp = (void *) tp;
     sc->sc_start = pppasyncstart;
     sc->sc_ctlp = pppasyncctlp;
     sc->sc_devp = (void *) tp;
     sc->sc_start = pppasyncstart;
     sc->sc_ctlp = pppasyncctlp;
+    sc->sc_relinq = pppasyncrelinq;
+    sc->sc_outm = NULL;
+    pppgetm(sc);
+    sc->sc_if.if_flags |= IFF_RUNNING;
 
     tp->t_sc = (caddr_t) sc;
     ttyflush(tp, FREAD | FWRITE);
 
     tp->t_sc = (caddr_t) sc;
     ttyflush(tp, FREAD | FWRITE);
+    splx(s);
 
     return (0);
 }
 
     return (0);
 }
@@ -221,14 +227,11 @@ pppclose(tp, flag)
     ttywflush(tp);
     s = splimp();              /* paranoid; splnet probably ok */
     tp->t_line = 0;
     ttywflush(tp);
     s = splimp();              /* paranoid; splnet probably ok */
     tp->t_line = 0;
-    sc = (struct ppp_softc *)tp->t_sc;
+    sc = (struct ppp_softc *) tp->t_sc;
     if (sc != NULL) {
        tp->t_sc = NULL;
        if (tp == (struct tty *) sc->sc_devp) {
     if (sc != NULL) {
        tp->t_sc = NULL;
        if (tp == (struct tty *) sc->sc_devp) {
-           m_freem(sc->sc_outm);
-           sc->sc_outm = NULL;
-           m_freem(sc->sc_m);
-           sc->sc_m = NULL;
+           pppasyncrelinq(sc);
            pppdealloc(sc);
        }
     }
            pppdealloc(sc);
        }
     }
@@ -236,6 +239,31 @@ pppclose(tp, flag)
     return 0;
 }
 
     return 0;
 }
 
+/*
+ * Relinquish the interface unit to another device.
+ */
+static void
+pppasyncrelinq(sc)
+    struct ppp_softc *sc;
+{
+    int s;
+
+    s = splimp();
+    if (sc->sc_outm) {
+       m_freem(sc->sc_outm);
+       sc->sc_outm = NULL;
+    }
+    if (sc->sc_m) {
+       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);
+}
+
 /*
  * Line specific (tty) read routine.
  */
 /*
  * Line specific (tty) read routine.
  */
@@ -322,7 +350,7 @@ pppwrite(tp, uio, flag)
        m->m_len = len;
     }
     dst.sa_family = AF_UNSPEC;
        m->m_len = len;
     }
     dst.sa_family = AF_UNSPEC;
-    *(u_int32_t *)dst.sa_data = *mtod(m0, u_int32_t *);
+    bcopy(mtod(m0, caddr_t), dst.sa_data, PPP_HDRLEN);
     m0->m_off += PPP_HDRLEN;
     m0->m_len -= PPP_HDRLEN;
     return (pppoutput(&sc->sc_if, m0, &dst));
     m0->m_off += PPP_HDRLEN;
     m0->m_len -= PPP_HDRLEN;
     return (pppoutput(&sc->sc_if, m0, &dst));
@@ -341,7 +369,7 @@ ppptioctl(tp, cmd, data, flag)
     int cmd, flag;
 {
     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
     int cmd, flag;
 {
     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
-    int error;
+    int error, s;
 
     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
        return -1;
 
     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
        return -1;
@@ -371,10 +399,12 @@ ppptioctl(tp, cmd, data, flag)
     case PPPIOCSXASYNCMAP:
        if (!suser())
            return EPERM;
     case PPPIOCSXASYNCMAP:
        if (!suser())
            return EPERM;
+       s = spltty();
        bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
        sc->sc_asyncmap[1] = 0;             /* mustn't escape 0x20 - 0x3f */
        sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
        sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
        bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
        sc->sc_asyncmap[1] = 0;             /* mustn't escape 0x20 - 0x3f */
        sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
        sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
+       splx(s);
        break;
 
     case PPPIOCGXASYNCMAP:
        break;
 
     case PPPIOCGXASYNCMAP:
@@ -451,8 +481,11 @@ pppasyncstart(sc)
     register struct ppp_softc *sc;
 {
     register struct tty *tp = (struct tty *) sc->sc_devp;
     register struct ppp_softc *sc;
 {
     register struct tty *tp = (struct tty *) sc->sc_devp;
+    int s;
 
 
+    s = splimp();
     pppstart(tp);
     pppstart(tp);
+    splx(s);
 }
 
 /*
 }
 
 /*
@@ -483,30 +516,18 @@ pppstart(tp)
     register struct mbuf *m;
     register int len;
     register u_char *start, *stop, *cp;
     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;
 
     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);
+    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);
        return;
     }
 
        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) {
-           (*tp->t_oproc)(tp);
-           if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
-               return;
-       }
-
+    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.
        /*
         * See if we have an existing packet partly sent.
         * If not, get a new packet and start sending it.
@@ -517,8 +538,10 @@ pppstart(tp)
             * Get another packet to be sent.
             */
            m = ppp_dequeue(sc);
             * Get another packet to be sent.
             */
            m = ppp_dequeue(sc);
-           if (m == NULL)
-               return;
+           if (m == NULL) {
+               idle = 1;
+               break;
+           }
 
            /*
             * The extra PPP_FLAG will start up a new packet, and thus
 
            /*
             * The extra PPP_FLAG will start up a new packet, and thus
@@ -573,6 +596,7 @@ pppstart(tp)
                    len--;
                }
            }
                    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
            /*
             * 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
@@ -614,33 +638,70 @@ pppstart(tp)
                            unputc(&tp->t_outq);
                        break;
                    }
                            unputc(&tp->t_outq);
                        break;
                    }
+               sc->sc_bytessent += q - endseq;
            }
 
            if (!done) {
                m->m_off += m->m_len - len;
                m->m_len = len;
            }
 
            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);
            }
 
            /* Finished with this mbuf; free it and move on. */
            MFREE(m, m2);
-           if (m2 == NULL)
-               break;
-
            m = m2;
            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);
        }
 
            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;
     }
 }
 
     }
 }
 
+/*
+ * 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 = splimp();
+    sc->sc_flags &= ~SC_TIMEOUT;
+    pppstart(tp);
+    splx(s);
+}
+
 /*
  * Allocate enough mbuf to handle current MRU.
  */
 /*
  * Allocate enough mbuf to handle current MRU.
  */
@@ -683,14 +744,16 @@ pppinput(c, tp)
 {
     register struct ppp_softc *sc;
     struct mbuf *m;
 {
     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;
 
     sc = (struct ppp_softc *) tp->t_sc;
     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
        return;
 
-    sc->sc_bytesrcvd++;
+    s = spltty();
+    ++tk_nin;
+    ++sc->sc_bytesrcvd;
 
     c &= 0xff;
 
 
     c &= 0xff;
 
@@ -727,6 +790,7 @@ pppinput(c, tp)
                sc->sc_if.if_ierrors++;
            } else
                sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
                sc->sc_if.if_ierrors++;
            } else
                sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
+           splx(s);
            return;
        }
 
            return;
        }
 
@@ -737,6 +801,7 @@ pppinput(c, tp)
                sc->sc_if.if_ierrors++;
                sc->sc_flags |= SC_PKTLOST;
            }
                sc->sc_if.if_ierrors++;
                sc->sc_flags |= SC_PKTLOST;
            }
+           splx(s);
            return;
        }
 
            return;
        }
 
@@ -760,23 +825,28 @@ pppinput(c, tp)
        sc->sc_flags &= ~SC_PKTLOST;
 
        pppgetm(sc);
        sc->sc_flags &= ~SC_PKTLOST;
 
        pppgetm(sc);
+       splx(s);
        return;
     }
 
     if (sc->sc_flags & SC_FLUSH) {
        if (sc->sc_flags & SC_LOG_FLUSH)
            ppplogchar(sc, c);
        return;
     }
 
     if (sc->sc_flags & SC_FLUSH) {
        if (sc->sc_flags & SC_LOG_FLUSH)
            ppplogchar(sc, c);
+       splx(s);
        return;
     }
 
        return;
     }
 
-    if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
+    if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
+       splx(s);
        return;
        return;
+    }
 
     if (sc->sc_flags & SC_ESCAPED) {
        sc->sc_flags &= ~SC_ESCAPED;
        c ^= PPP_TRANS;
     } else if (c == PPP_ESCAPE) {
        sc->sc_flags |= SC_ESCAPED;
 
     if (sc->sc_flags & SC_ESCAPED) {
        sc->sc_flags &= ~SC_ESCAPED;
        c ^= PPP_TRANS;
     } else if (c == PPP_ESCAPE) {
        sc->sc_flags |= SC_ESCAPED;
+       splx(s);
        return;
     }
 
        return;
     }
 
@@ -864,6 +934,7 @@ pppinput(c, tp)
     ++m->m_len;
     *sc->sc_mp++ = c;
     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
     ++m->m_len;
     *sc->sc_mp++ = c;
     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
+    splx(s);
     return;
 
  flush:
     return;
 
  flush:
@@ -873,6 +944,7 @@ pppinput(c, tp)
        if (sc->sc_flags & SC_LOG_FLUSH)
            ppplogchar(sc, c);
     }
        if (sc->sc_flags & SC_LOG_FLUSH)
            ppplogchar(sc, c);
     }
+    splx(s);
 }
 
 #define MAX_DUMP_BYTES 128
 }
 
 #define MAX_DUMP_BYTES 128