ppp_io.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,145 行 · 第 1/2 页

C
1,145
字号
                           &nb, &len);        s = splsoftnet();        pppasyncstart( sc );        splx(s);    }        return 0;}#endif//==========================================================================/* * This gets called at splsoftnet from if_ppp.c at various times * when there is data ready to be sent. */static voidpppasyncstart(sc)    register struct ppp_softc *sc;{    register struct tty *tp = (struct tty *) sc->sc_devp;    register struct mbuf *m;    register int len;    register u_char *start, *stop, *cp;    int n, ndone, done, idle;    struct mbuf *m2;    int s;    idle = 0;    while (1) {        	/*	 * See if we have an existing packet partly sent.	 * If not, get a new packet and start sending it.	 */	m = sc->sc_outm;	if (m == NULL) {	    /*	     * Get another packet to be sent.	     */	    m = ppp_dequeue(sc);	    if (m == NULL) {		idle = 1;		break;	    }	    /* Calculate the FCS for the first mbuf's worth. */	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);	    getmicrotime(&sc->sc_if.if_lastchange);	}	for (;;) {	    start = mtod(m, u_char *);	    len = m->m_len;	    stop = start + len;	    while (len > 0) {		/*		 * Find out how many bytes in the string we can		 * handle without doing something special.		 */		for (cp = start; cp < stop; cp++)		    if (ESCAPE_P(*cp))			break;		n = cp - start;		if (n) {#ifndef __ECOS        		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */		    ndone = n - b_to_q(start, n, &tp->t_outq);#else                    ndone = 0;//                    db_printf("send: data %d\n",ndone);//                    db_dump_buf(start,ndone);                    {                        cyg_serial_buf_info_t info;                        cyg_uint32 ilen = sizeof(info);                        if( cyg_io_get_config( tp->t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &info, &ilen ) == 0 )                        {                            ndone = info.tx_bufsize-info.tx_count;                            if( ndone > n )                                ndone = n;                            cyg_io_write( tp->t_handle, start, &ndone);                        }                    }#endif		    len -= ndone;		    start += ndone;		    sc->sc_stats.ppp_obytes += ndone;		    if (ndone < n)			break;	/* packet doesn't fit */		}		/*		 * If there are characters left in the mbuf,		 * the first one must be special.		 * Put it out in a different form.		 */		if (len) {		    s = spltty();#ifndef __ECOS        		    if (putc(PPP_ESCAPE, &tp->t_outq)) {			splx(s);			break;		    }		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {			(void) unputc(&tp->t_outq);			splx(s);			break;		    }#else                    {                        cyg_serial_buf_info_t info;                        cyg_uint32 ilen = sizeof(info);                        if( cyg_io_get_config( tp->t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &info, &ilen ) == 0 &&                            info.tx_bufsize-info.tx_count >= 2 )                        {                            char buf[2];                            int blen = 2;                            buf[0] = PPP_ESCAPE;                            buf[1] = *start ^ PPP_TRANS;                            if( cyg_io_write( tp->t_handle, buf, &blen) != 0 ) {                                splx(s);                                break;                            }                        }                        else                        {                            splx(s);                            break;                        }                    }#endif		    splx(s);		    sc->sc_stats.ppp_obytes += 2;		    start++;		    len--;                } // if( len )            } // while (len > 0)	    /*	     * 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	     * flag, and if we can't, leave sc_outm pointing to m, but with	     * m->m_len == 0, to remind us to output the FCS and flag later.	     */	    done = len == 0;	    if (done && m->m_next == NULL) {		u_char *p, *q;		int c;		u_char endseq[8];		/*		 * We may have to escape the bytes in the FCS.		 */		p = endseq;		c = ~sc->sc_outfcs & 0xFF;		if (ESCAPE_P(c)) {		    *p++ = PPP_ESCAPE;		    *p++ = c ^ PPP_TRANS;		} else		    *p++ = c;		c = (~sc->sc_outfcs >> 8) & 0xFF;		if (ESCAPE_P(c)) {		    *p++ = PPP_ESCAPE;		    *p++ = c ^ PPP_TRANS;		} else		    *p++ = c;		*p++ = PPP_FLAG;		/*		 * Try to output the FCS and flag.  If the bytes		 * don't all fit, back out.		 */		s = spltty();#ifndef __ECOS		for (q = endseq; q < p; ++q)		    if (putc(*q, &tp->t_outq)) {			done = 0;			for (; q > endseq; --q)			    unputc(&tp->t_outq);			break;		    }#else                {                    int elen = p-endseq;                    cyg_serial_buf_info_t info;                    cyg_uint32 ilen = sizeof(info);                    q = p;                    if( (cyg_io_get_config( tp->t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &info, &ilen ) == 0) &&                        ((info.tx_bufsize-info.tx_count) >= elen) )                    {                        if( cyg_io_write( tp->t_handle, endseq, &elen) != 0 ) {                            done = 0;                        }                    }                    else                    {                        done = 0;                    }                }#endif		splx(s);		if (done)		    sc->sc_stats.ppp_obytes += q - endseq;            } // if (done && m->m_next == NULL)	    if (!done) {		/* remember where we got to */		m->m_data = start;		m->m_len = len;		break;	    }	    /* Finished with this mbuf; free it and move on. */	    MFREE(m, m2);	    m = m2;	    if (m == NULL) {		/* Finished a packet */		break;	    }	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);        } // for(;;)	/*	 * If m == NULL, we have finished a packet.	 * If m != NULL, we've either done as much work this time	 * as we need to, or else we've filled up the output queue.	 */	sc->sc_outm = m;	if (m)	    break;    }#ifndef __ECOS            /* Call pppstart to start output again if necessary. */    s = spltty();    pppstart(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) {	sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);	sc->sc_flags |= SC_TIMEOUT;    }        splx(s);#else    s = spltty();    if( sc->sc_outm != NULL &&        cyg_thread_self() != tp->tx_thread )    {        cyg_semaphore_post( &tp->tx_sem );    }        splx(s);    #endif    }//==========================================================================/* * This gets called when a received packet is placed on * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read(). */static voidpppasyncctlp(sc)    struct ppp_softc *sc;{    struct tty *tp;    int s;    s = spltty();    tp = (struct tty *) sc->sc_devp;        tp->pppd_wakeup = 1;    if( tp->pppd_thread != cyg_thread_self() )        cyg_thread_release( tp->pppd_thread );    splx(s);}//==========================================================================/* * Allocate enough mbuf to handle current MRU. */static voidpppgetm(sc)    register struct ppp_softc *sc;{    struct mbuf *m, **mp;    int len;    mp = &sc->sc_m;    for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){	if ((m = *mp) == NULL) {	    MGETHDR(m, M_DONTWAIT, MT_DATA);	    if (m == NULL)		break;	    *mp = m;	    MCLGET(m, M_DONTWAIT);	}	len -= M_DATASIZE(m);	mp = &m->m_next;    }}//==========================================================================/* * tty interface receiver interrupt. */static unsigned paritytab[8] = {    0x96696996, 0x69969669, 0x69969669, 0x96696996,    0x69969669, 0x96696996, 0x96696996, 0x69969669};/* * Called when character is available from device driver. * Only guaranteed to be at splsofttty() or spltty() * This is safe to be called while the upper half's netisr is preempted. */intcyg_ppp_pppinput(c, tp)    int c;    register struct tty *tp;{    register struct ppp_softc *sc;    struct mbuf *m;    int ilen, s;    sc = (struct ppp_softc *) tp->t_sc;    if (sc == NULL || tp != (struct tty *) sc->sc_devp)	return 0;//    ++tk_nin;    ++sc->sc_stats.ppp_ibytes;    s = spltty();    if (c & 0x80)	sc->sc_flags |= SC_RCV_B7_1;    else	sc->sc_flags |= SC_RCV_B7_0;    if (paritytab[c >> 5] & (1 << (c & 0x1F)))	sc->sc_flags |= SC_RCV_ODDP;    else	sc->sc_flags |= SC_RCV_EVNP;    splx(s);    if (sc->sc_flags & SC_LOG_RAWIN)	ppplogchar(sc, c);    if (c == PPP_FLAG) {	ilen = sc->sc_ilen;	sc->sc_ilen = 0;	if (sc->sc_rawin_count > 0) 	    ppplogchar(sc, -1);	/*	 * If SC_ESCAPED is set, then we've seen the packet	 * abort sequence "}~".	 */	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {	    s = spltty();	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){#if 1		if (sc->sc_flags & SC_DEBUG)		    diag_printf("ppp%d: bad fcs %x, pkt len %d\n",                                sc->sc_if.if_unit, sc->sc_fcs, ilen);#endif		sc->sc_if.if_ierrors++;		sc->sc_stats.ppp_ierrors++;	    } else		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);	    splx(s);	    return 0;	}	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {	    if (ilen) {		if (sc->sc_flags & SC_DEBUG)		    diag_printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);		s = spltty();		sc->sc_if.if_ierrors++;		sc->sc_stats.ppp_ierrors++;		sc->sc_flags |= SC_PKTLOST;		splx(s);	    }	    return 0;	}	/*	 * Remove FCS trailer.  Somewhat painful...	 */	ilen -= 2;	if (--sc->sc_mc->m_len == 0) {	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)		;	    sc->sc_mc = m;	}	sc->sc_mc->m_len--;	/* excise this mbuf chain */	m = sc->sc_m;	sc->sc_m = sc->sc_mc->m_next;	sc->sc_mc->m_next = NULL;	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);	if (sc->sc_flags & SC_PKTLOST) {	    s = spltty();	    sc->sc_flags &= ~SC_PKTLOST;	    splx(s);	}	pppgetm(sc);	return 0;    }    if (sc->sc_flags & SC_FLUSH) {	if (sc->sc_flags & SC_LOG_FLUSH)	    ppplogchar(sc, c);	return 0;    }    if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))	return 0;    s = spltty();    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 0;    }    splx(s);    /*     * Initialize buffer on first octet received.     * First octet could be address or protocol (when compressing     * address/control).     * Second octet is control.     * Third octet is first or second (when compressing protocol)     * octet of protocol.     * Fourth octet is second octet of protocol.     */    if (sc->sc_ilen == 0) {	/* reset the first input mbuf */	if (sc->sc_m == NULL) {	    pppgetm(sc);	    if (sc->sc_m == NULL) {		if (sc->sc_flags & SC_DEBUG)		    diag_printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);		goto flush;	    }	}	m = sc->sc_m;	m->m_len = 0;	m->m_data = M_DATASTART(sc->sc_m);	sc->sc_mc = m;	sc->sc_mp = mtod(m, char *);	sc->sc_fcs = PPP_INITFCS;	if (c != PPP_ALLSTATIONS) {	    if (sc->sc_flags & SC_REJ_COMP_AC) {		if (sc->sc_flags & SC_DEBUG)		    diag_printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",			   sc->sc_if.if_unit, c);		goto flush;	    }	    *sc->sc_mp++ = PPP_ALLSTATIONS;	    *sc->sc_mp++ = PPP_UI;	    sc->sc_ilen += 2;	    m->m_len += 2;	}    }    if (sc->sc_ilen == 1 && c != PPP_UI) {	if (sc->sc_flags & SC_DEBUG)	    diag_printf("ppp%d: missing UI (0x3), got 0x%x\n",		   sc->sc_if.if_unit, c);	goto flush;    }    if (sc->sc_ilen == 2 && (c & 1) == 1) {	/* a compressed protocol */	*sc->sc_mp++ = 0;	sc->sc_ilen++;	sc->sc_mc->m_len++;    }    if (sc->sc_ilen == 3 && (c & 1) == 0) {	if (sc->sc_flags & SC_DEBUG)	    diag_printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,                        (sc->sc_mp[-1] << 8) + c);	goto flush;    }    /* packet beyond configured mru? */    if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {	if (sc->sc_flags & SC_DEBUG)	    diag_printf("ppp%d: packet too big\n", sc->sc_if.if_unit);	goto flush;    }    /* is this mbuf full? */    m = sc->sc_mc;    if (M_TRAILINGSPACE(m) <= 0) {	if (m->m_next == NULL) {	    pppgetm(sc);	    if (m->m_next == NULL) {		if (sc->sc_flags & SC_DEBUG)		    diag_printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);		goto flush;	    }	}	sc->sc_mc = m = m->m_next;	m->m_len = 0;	m->m_data = M_DATASTART(m);	sc->sc_mp = mtod(m, char *);    }    ++m->m_len;    *sc->sc_mp++ = c;    sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);    return 0; flush:    if (!(sc->sc_flags & SC_FLUSH)) {	s = spltty();	sc->sc_if.if_ierrors++;	sc->sc_stats.ppp_ierrors++;	sc->sc_flags |= SC_FLUSH;	splx(s);	if (sc->sc_flags & SC_LOG_FLUSH)	    ppplogchar(sc, c);    }    return 0;}//==========================================================================#define MAX_DUMP_BYTES	128static voidppplogchar(sc, c)    struct ppp_softc *sc;    int c;{    if (c >= 0)	sc->sc_rawin[sc->sc_rawin_count++] = c;    if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)	|| (c < 0 && sc->sc_rawin_count > 0)) {        diag_printf("ppp%d input:\n");        diag_vdump_buf_with_offset( diag_printf, sc->sc_rawin, sc->sc_rawin_count, sc->sc_rawin );	sc->sc_rawin_count = 0;    }}//==========================================================================// End of ppp_io.c

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?