X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=ultrix%2Fppp_tty.c;h=40d6cf2a13d391478a9094bb72861fe4bb0ce65e;hp=a1d8af783042932994d5a0fa0e85adbdb3fcaec0;hb=0f4ddcb519d4c9cf0c0ca59fc4723aeb6e9e17d0;hpb=a471bdc20d7f993fc126b765c8c3dacbc902fa68 diff --git a/ultrix/ppp_tty.c b/ultrix/ppp_tty.c index a1d8af7..40d6cf2 100644 --- a/ultrix/ppp_tty.c +++ b/ultrix/ppp_tty.c @@ -73,7 +73,7 @@ * Robert Olsson 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