2 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
5 * Copyright (c) 1989 Carnegie Mellon University.
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by Carnegie Mellon University. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 * Carnegie Mellon University
23 * Pittsburgh, PA 15213
28 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
30 * Copyright (c) 1987 Regents of the University of California.
31 * All rights reserved.
33 * Redistribution and use in source and binary forms are permitted
34 * provided that the above copyright notice and this paragraph are
35 * duplicated in all such forms and that any documentation,
36 * advertising materials, and other materials related to such
37 * distribution and use acknowledge that the software was developed
38 * by the University of California, Berkeley. The name of the
39 * University may not be used to endorse or promote products derived
40 * from this software without specific prior written permission.
41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
42 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
43 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
45 * Serial Line interface
48 * Center for Seismic Studies
49 * 1300 N 17th Street, Suite 1450
50 * Arlington, Virginia 22209
55 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
56 * Converted to 4.3BSD Beta by Chris Torek.
57 * Other changes made at Berkeley, based in part on code by Kirk Smith.
59 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
60 * Added VJ tcp header compression; more unified ioctls
62 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
63 * Cleaned up a lot of the mbuf-related code to fix bugs that
64 * caused system crashes and packet corruption. Changed pppstart
65 * so that it doesn't just give up with a "collision" if the whole
66 * packet doesn't fit in the output ring buffer.
68 * Added priority queueing for interactive IP packets, following
69 * the model of if_sl.c, plus hooks for bpf.
70 * Paul Mackerras (paulus@cs.anu.edu.au).
73 /* $Id: ppp_tty.c,v 1.36 1998/06/07 17:12:07 dfr Exp $ */
78 #include "opt_ppp.h" /* XXX for ppp_defs.h */
80 #define VJC /* XXX for ppp_defs.h */
82 #include <sys/param.h>
83 #include <sys/systm.h>
86 #include <sys/dkstat.h>
87 #include <sys/socket.h>
88 #include <sys/fcntl.h>
94 * XXX stop <sys/vnode.h> from including <vnode_if.h>. <vnode_if.h> doesn't
95 * exist if we are an LKM.
98 # include <sys/vnode.h>
102 #include <i386/isa/intr_machdep.h>
108 #include <net/if_ppp.h>
109 #include <net/if_pppvar.h>
111 static int pppopen __P((dev_t dev, struct tty *tp));
112 static int pppclose __P((struct tty *tp, int flag));
113 static int pppread __P((struct tty *tp, struct uio *uio, int flag));
114 static int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
115 static int ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
117 static int pppinput __P((int c, struct tty *tp));
118 static int pppstart __P((struct tty *tp));
120 static u_short pppfcs __P((u_short fcs, u_char *cp, int len));
121 static void pppasyncstart __P((struct ppp_softc *));
122 static void pppasyncctlp __P((struct ppp_softc *));
123 static void pppasyncrelinq __P((struct ppp_softc *));
124 static void pppasyncsetmtu __P((struct ppp_softc *));
125 static void ppp_timeout __P((void *));
126 static void pppgetm __P((struct ppp_softc *sc));
127 static void ppplogchar __P((struct ppp_softc *, int));
129 /* XXX called from if_ppp.c - layering violation */
130 void pppasyncattach __P((void *));
133 * Some useful mbuf macros not in mbuf.h.
135 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
137 #define M_DATASTART(m) \
138 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
139 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
141 #define M_DATASIZE(m) \
142 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
143 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
146 * Does c need to be escaped?
148 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
151 * Procedures for using an async tty interface for PPP.
154 /* This is a FreeBSD-2.X kernel. */
155 #define CCOUNT(q) ((q)->c_cc)
156 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
157 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
160 * Define the PPP line discipline.
163 static struct linesw pppdisc = {
164 pppopen, pppclose, pppread, pppwrite,
165 ppptioctl, pppinput, pppstart, ttymodem,
170 pppasyncattach(dummy)
179 * Make sure that the soft net "engine" cannot run while spltty code is
180 * active. The if_ppp.c code can walk down into b_to_q etc, and it is
181 * bad if the tty system was in the middle of another b_to_q...
183 tty_imask |= softnet_imask; /* spltty() block spl[soft]net() */
184 net_imask |= softtty_imask; /* splimp() block splsofttty() */
185 net_imask |= tty_imask; /* splimp() block spltty() */
190 printf("new masks: bio %x, tty %x, net %x\n",
191 bio_imask, tty_imask, net_imask);
194 /* register line discipline */
195 linesw[PPPDISC] = pppdisc;
199 * Line specific open routine for async tty devices.
200 * Attach the given tty to the first available ppp unit.
201 * Called from device open routine or ttioctl() at >= splsofttty()
207 register struct tty *tp;
209 struct proc *p = curproc; /* XXX */
210 register struct ppp_softc *sc;
213 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
218 if (tp->t_line == PPPDISC) {
219 sc = (struct ppp_softc *) tp->t_sc;
220 if (sc != NULL && sc->sc_devp == (void *) tp) {
226 if ((sc = pppalloc(p->p_pid)) == NULL) {
232 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
236 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
237 sc->sc_asyncmap[0] = 0xffffffff;
238 sc->sc_asyncmap[3] = 0x60000000;
239 sc->sc_rasyncmap = 0;
240 sc->sc_devp = (void *) tp;
241 sc->sc_start = pppasyncstart;
242 sc->sc_ctlp = pppasyncctlp;
243 sc->sc_relinq = pppasyncrelinq;
244 sc->sc_setmtu = pppasyncsetmtu;
247 sc->sc_if.if_flags |= IFF_RUNNING;
248 getmicrotime(&sc->sc_if.if_lastchange);
249 sc->sc_if.if_baudrate = tp->t_ospeed;
251 tp->t_sc = (caddr_t) sc;
252 ttyflush(tp, FREAD | FWRITE);
255 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
256 * allocation helps avoid the need for select and/or FIONREAD.
257 * We also pass 1 byte tokens through t_canq...
259 clist_alloc_cblocks(&tp->t_canq, 1, 1);
260 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
261 sc->sc_if.if_mtu + PPP_HIWAT);
262 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
270 * Line specific close routine, called from device close routine
271 * and from ttioctl at >= splsofttty().
272 * Detach the tty from the ppp unit.
273 * Mimics part of ttyclose().
280 register struct ppp_softc *sc;
284 ttyflush(tp, FREAD | FWRITE);
285 clist_free_cblocks(&tp->t_canq);
286 clist_free_cblocks(&tp->t_outq);
288 sc = (struct ppp_softc *) tp->t_sc;
291 if (tp == (struct tty *) sc->sc_devp) {
301 * Relinquish the interface unit to another device.
305 struct ppp_softc *sc;
311 m_freem(sc->sc_outm);
318 if (sc->sc_flags & SC_TIMEOUT) {
319 untimeout(ppp_timeout, (void *) sc, sc->sc_ch);
320 sc->sc_flags &= ~SC_TIMEOUT;
326 * This gets called from the upper layer to notify a mtu change
330 register struct ppp_softc *sc;
332 register struct tty *tp = (struct tty *) sc->sc_devp;
337 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
338 sc->sc_if.if_mtu + PPP_HIWAT);
343 * Line specific (tty) read routine.
344 * called at zero spl from the device driver in the response to user-level
345 * reads on the tty file descriptor (ie: pppd).
348 pppread(tp, uio, flag)
349 register struct tty *tp;
353 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
361 * Loop waiting for input, checking that nothing disasterous
362 * happens in the meantime.
366 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
370 if (sc->sc_inq.ifq_head != NULL)
372 if ((tp->t_state & TS_CONNECTED) == 0) {
374 return 0; /* end of file */
376 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
378 return (EWOULDBLOCK);
380 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
387 /* Pull place-holder byte out of canonical queue */
390 /* Get the packet from the input queue */
391 IF_DEQUEUE(&sc->sc_inq, m0);
394 for (m = m0; m && uio->uio_resid; m = m->m_next)
395 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
402 * Line specific (tty) write routine.
403 * called at zero spl from the device driver in the response to user-level
404 * writes on the tty file descriptor (ie: pppd).
407 pppwrite(tp, uio, flag)
408 register struct tty *tp;
412 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
413 struct mbuf *m, *m0, **mp;
417 if ((tp->t_state & TS_CONNECTED) == 0)
418 return 0; /* wrote 0 bytes */
419 if (tp->t_line != PPPDISC)
421 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
423 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
424 uio->uio_resid < PPP_HDRLEN)
428 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
429 MGET(m, M_WAIT, MT_DATA);
430 if ((*mp = m) == NULL) {
436 if (uio->uio_resid >= MCLBYTES / 2)
437 MCLGET(m, M_DONTWAIT);
438 len = M_TRAILINGSPACE(m);
439 if (len > uio->uio_resid)
440 len = uio->uio_resid;
441 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
448 dst.sa_family = AF_UNSPEC;
449 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
450 m0->m_data += PPP_HDRLEN;
451 m0->m_len -= PPP_HDRLEN;
453 /* call the upper layer to "transmit" it... */
454 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
460 * Line specific (tty) ioctl routine.
461 * This discipline requires that tty device drivers call
462 * the line specific l_ioctl routine from their ioctl routines.
466 ppptioctl(tp, cmd, data, flag, p)
473 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
476 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
481 case PPPIOCSASYNCMAP:
482 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
484 sc->sc_asyncmap[0] = *(u_int *)data;
487 case PPPIOCGASYNCMAP:
488 *(u_int *)data = sc->sc_asyncmap[0];
491 case PPPIOCSRASYNCMAP:
492 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
494 sc->sc_rasyncmap = *(u_int *)data;
497 case PPPIOCGRASYNCMAP:
498 *(u_int *)data = sc->sc_rasyncmap;
501 case PPPIOCSXASYNCMAP:
502 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
505 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
506 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
507 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
508 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
512 case PPPIOCGXASYNCMAP:
513 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
517 error = pppioctl(sc, cmd, data, flag, p);
518 if (error == 0 && cmd == PPPIOCSMRU)
526 * FCS lookup table as calculated by genfcstab.
528 static u_short fcstab[256] = {
529 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
530 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
531 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
532 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
533 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
534 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
535 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
536 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
537 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
538 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
539 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
540 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
541 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
542 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
543 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
544 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
545 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
546 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
547 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
548 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
549 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
550 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
551 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
552 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
553 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
554 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
555 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
556 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
557 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
558 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
559 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
560 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
564 * Calculate a new FCS given the current FCS and the new data.
567 pppfcs(u_short fcs, u_char *cp, int len)
570 fcs = PPP_FCS(fcs, *cp++);
575 * This gets called at splsoftnet from if_ppp.c at various times
576 * when there is data ready to be sent.
580 register struct ppp_softc *sc;
582 register struct tty *tp = (struct tty *) sc->sc_devp;
583 register struct mbuf *m;
585 register u_char *start, *stop, *cp;
586 int n, ndone, done, idle;
591 /* XXX assumes atomic access to *tp although we're not at spltty(). */
592 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
594 * See if we have an existing packet partly sent.
595 * If not, get a new packet and start sending it.
600 * Get another packet to be sent.
609 * The extra PPP_FLAG will start up a new packet, and thus
610 * will flush any accumulated garbage. We do this whenever
611 * the line may have been idle for some time.
614 if (CCOUNT(&tp->t_outq) == 0) {
615 ++sc->sc_stats.ppp_obytes;
616 (void) putc(PPP_FLAG, &tp->t_outq);
619 /* Calculate the FCS for the first mbuf's worth. */
620 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
621 getmicrotime(&sc->sc_if.if_lastchange);
625 start = mtod(m, u_char *);
630 * Find out how many bytes in the string we can
631 * handle without doing something special.
633 for (cp = start; cp < stop; cp++)
638 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
639 ndone = n - b_to_q(start, n, &tp->t_outq);
642 sc->sc_stats.ppp_obytes += ndone;
645 break; /* packet doesn't fit */
648 * If there are characters left in the mbuf,
649 * the first one must be special.
650 * Put it out in a different form.
654 if (putc(PPP_ESCAPE, &tp->t_outq)) {
658 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
659 (void) unputc(&tp->t_outq);
664 sc->sc_stats.ppp_obytes += 2;
671 * If we didn't empty this mbuf, remember where we're up to.
672 * If we emptied the last mbuf, try to add the FCS and closing
673 * flag, and if we can't, leave sc_outm pointing to m, but with
674 * m->m_len == 0, to remind us to output the FCS and flag later.
677 if (done && m->m_next == NULL) {
683 * We may have to escape the bytes in the FCS.
686 c = ~sc->sc_outfcs & 0xFF;
689 *p++ = c ^ PPP_TRANS;
692 c = (~sc->sc_outfcs >> 8) & 0xFF;
695 *p++ = c ^ PPP_TRANS;
701 * Try to output the FCS and flag. If the bytes
702 * don't all fit, back out.
705 for (q = endseq; q < p; ++q)
706 if (putc(*q, &tp->t_outq)) {
708 for (; q > endseq; --q)
714 sc->sc_stats.ppp_obytes += q - endseq;
718 /* remember where we got to */
724 /* Finished with this mbuf; free it and move on. */
728 /* Finished a packet */
731 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
735 * If m == NULL, we have finished a packet.
736 * If m != NULL, we've either done as much work this time
737 * as we need to, or else we've filled up the output queue.
744 /* Call pppstart to start output again if necessary. */
749 * This timeout is needed for operation on a pseudo-tty,
750 * because the pty code doesn't call pppstart after it has
751 * drained the t_outq.
753 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
754 sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
755 sc->sc_flags |= SC_TIMEOUT;
762 * This gets called when a received packet is placed on
763 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
767 struct ppp_softc *sc;
772 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
774 tp = (struct tty *) sc->sc_devp;
775 putc(0, &tp->t_canq);
781 * Start output on async tty interface. If the transmit queue
782 * has drained sufficiently, arrange for pppasyncstart to be
783 * called later at splsoftnet.
784 * Called at spltty or higher.
788 register struct tty *tp;
790 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
793 * Call output process whether or not there is any output.
794 * We are being called in lieu of ttstart and must do what it would.
796 if (tp->t_oproc != NULL)
800 * If the transmit queue has drained and the tty has not hung up
801 * or been disconnected from the ppp unit, then tell if_ppp.c that
802 * we need more output.
804 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
805 && !((tp->t_state & TS_CONNECTED) == 0)
806 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
814 * Timeout routine - try to start some more output.
820 struct ppp_softc *sc = (struct ppp_softc *) x;
821 struct tty *tp = (struct tty *) sc->sc_devp;
825 sc->sc_flags &= ~SC_TIMEOUT;
831 * Allocate enough mbuf to handle current MRU.
835 register struct ppp_softc *sc;
837 struct mbuf *m, **mp;
841 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
842 if ((m = *mp) == NULL) {
843 MGETHDR(m, M_DONTWAIT, MT_DATA);
847 MCLGET(m, M_DONTWAIT);
849 len -= M_DATASIZE(m);
855 * tty interface receiver interrupt.
857 static unsigned paritytab[8] = {
858 0x96696996, 0x69969669, 0x69969669, 0x96696996,
859 0x69969669, 0x96696996, 0x96696996, 0x69969669
863 * Called when character is available from device driver.
864 * Only guaranteed to be at splsofttty() or spltty()
865 * This is safe to be called while the upper half's netisr is preempted.
870 register struct tty *tp;
872 register struct ppp_softc *sc;
876 sc = (struct ppp_softc *) tp->t_sc;
877 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
881 ++sc->sc_stats.ppp_ibytes;
883 if ((tp->t_state & TS_CONNECTED) == 0) {
884 if (sc->sc_flags & SC_DEBUG)
885 printf("ppp%d: no carrier\n", sc->sc_if.if_unit);
889 if (c & TTY_ERRORMASK) {
890 /* framing error or overrun on this char - abort packet */
891 if (sc->sc_flags & SC_DEBUG)
892 printf("ppp%d: line error %x\n", sc->sc_if.if_unit,
900 * Handle software flow control of output.
902 if (tp->t_iflag & IXON) {
903 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
904 if ((tp->t_state & TS_TTSTOP) == 0) {
905 tp->t_state |= TS_TTSTOP;
906 (*cdevsw[major(tp->t_dev)]->d_stop)(tp, 0);
910 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
911 tp->t_state &= ~TS_TTSTOP;
912 if (tp->t_oproc != NULL)
920 sc->sc_flags |= SC_RCV_B7_1;
922 sc->sc_flags |= SC_RCV_B7_0;
923 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
924 sc->sc_flags |= SC_RCV_ODDP;
926 sc->sc_flags |= SC_RCV_EVNP;
929 if (sc->sc_flags & SC_LOG_RAWIN)
936 if (sc->sc_rawin_count > 0)
940 * If SC_ESCAPED is set, then we've seen the packet
941 * abort sequence "}~".
943 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
944 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
946 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
947 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
948 if (sc->sc_flags & SC_DEBUG)
949 printf("ppp%d: bad fcs %x, pkt len %d\n",
950 sc->sc_if.if_unit, sc->sc_fcs, ilen);
951 sc->sc_if.if_ierrors++;
952 sc->sc_stats.ppp_ierrors++;
954 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
959 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
961 if (sc->sc_flags & SC_DEBUG)
962 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
964 sc->sc_if.if_ierrors++;
965 sc->sc_stats.ppp_ierrors++;
966 sc->sc_flags |= SC_PKTLOST;
973 * Remove FCS trailer. Somewhat painful...
976 if (--sc->sc_mc->m_len == 0) {
977 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
983 /* excise this mbuf chain */
985 sc->sc_m = sc->sc_mc->m_next;
986 sc->sc_mc->m_next = NULL;
988 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
989 if (sc->sc_flags & SC_PKTLOST) {
991 sc->sc_flags &= ~SC_PKTLOST;
999 if (sc->sc_flags & SC_FLUSH) {
1000 if (sc->sc_flags & SC_LOG_FLUSH)
1005 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
1009 if (sc->sc_flags & SC_ESCAPED) {
1010 sc->sc_flags &= ~SC_ESCAPED;
1012 } else if (c == PPP_ESCAPE) {
1013 sc->sc_flags |= SC_ESCAPED;
1020 * Initialize buffer on first octet received.
1021 * First octet could be address or protocol (when compressing
1023 * Second octet is control.
1024 * Third octet is first or second (when compressing protocol)
1025 * octet of protocol.
1026 * Fourth octet is second octet of protocol.
1028 if (sc->sc_ilen == 0) {
1029 /* reset the first input mbuf */
1030 if (sc->sc_m == NULL) {
1032 if (sc->sc_m == NULL) {
1033 if (sc->sc_flags & SC_DEBUG)
1034 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1040 m->m_data = M_DATASTART(sc->sc_m);
1042 sc->sc_mp = mtod(m, char *);
1043 sc->sc_fcs = PPP_INITFCS;
1044 if (c != PPP_ALLSTATIONS) {
1045 if (sc->sc_flags & SC_REJ_COMP_AC) {
1046 if (sc->sc_flags & SC_DEBUG)
1047 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1048 sc->sc_if.if_unit, c);
1051 *sc->sc_mp++ = PPP_ALLSTATIONS;
1052 *sc->sc_mp++ = PPP_UI;
1057 if (sc->sc_ilen == 1 && c != PPP_UI) {
1058 if (sc->sc_flags & SC_DEBUG)
1059 printf("ppp%d: missing UI (0x3), got 0x%x\n",
1060 sc->sc_if.if_unit, c);
1063 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1064 /* a compressed protocol */
1069 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1070 if (sc->sc_flags & SC_DEBUG)
1071 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1072 (sc->sc_mp[-1] << 8) + c);
1076 /* packet beyond configured mru? */
1077 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1078 if (sc->sc_flags & SC_DEBUG)
1079 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1083 /* is this mbuf full? */
1085 if (M_TRAILINGSPACE(m) <= 0) {
1086 if (m->m_next == NULL) {
1088 if (m->m_next == NULL) {
1089 if (sc->sc_flags & SC_DEBUG)
1090 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1094 sc->sc_mc = m = m->m_next;
1096 m->m_data = M_DATASTART(m);
1097 sc->sc_mp = mtod(m, char *);
1102 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1106 if (!(sc->sc_flags & SC_FLUSH)) {
1108 sc->sc_if.if_ierrors++;
1109 sc->sc_stats.ppp_ierrors++;
1110 sc->sc_flags |= SC_FLUSH;
1112 if (sc->sc_flags & SC_LOG_FLUSH)
1118 #define MAX_DUMP_BYTES 128
1122 struct ppp_softc *sc;
1126 sc->sc_rawin[sc->sc_rawin_count++] = c;
1127 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1128 || (c < 0 && sc->sc_rawin_count > 0)) {
1129 printf("ppp%d input: %*D", sc->sc_if.if_unit,
1130 sc->sc_rawin_count, sc->sc_rawin, " ");
1131 sc->sc_rawin_count = 0;
1135 #endif /* NPPP > 0 */