* 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.5 1995/05/02 02:48:32 paulus Exp $ */
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
#include "ppp.h"
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));
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);
}
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;
+ /*
+ * Loop waiting for input, checking that nothing disasterous
+ * happens in the meantime.
+ */
s = splimp();
- while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
+ 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);
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.
*/
m = ppp_dequeue(sc);
if (m == NULL) {
- if (tp->t_oproc != NULL)
- (*tp->t_oproc)(tp);
- return;
+ idle = 1;
+ break;
}
/*
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
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 = splimp();
+ sc->sc_flags &= ~SC_TIMEOUT;
+ pppstart(tp);
+ splx(s);
}
/*
{
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++;
+ ++tk_nin;
+ ++sc->sc_bytesrcvd;
c &= 0xff;
} else
sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
splx(s);
- return;
+ return 0;
}
if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
sc->sc_flags |= SC_PKTLOST;
}
splx(s);
- return;
+ return 0;
}
/*
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) {
} else if (c == PPP_ESCAPE) {
sc->sc_flags |= SC_ESCAPED;
splx(s);
- return;
+ return 0;
}
/*
*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)) {
ppplogchar(sc, c);
}
splx(s);
+ return 0;
}
#define MAX_DUMP_BYTES 128