⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppp_tty.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous * 	       tty devices. * * Copyright (c) 1989 Carnegie Mellon University. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by Carnegie Mellon University.  The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Drew D. Perkins * Carnegie Mellon University * 4910 Forbes Ave. * Pittsburgh, PA 15213 * (412) 268-8576 * ddp@andrew.cmu.edu * * Based on: *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89 * * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley.  The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Serial Line interface * * Rick Adams * Center for Seismic Studies * 1300 N 17th Street, Suite 1450 * Arlington, Virginia 22209 * (703)276-7900 * rick@seismo.ARPA * seismo!rick * * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). * Converted to 4.3BSD Beta by Chris Torek. * Other changes made at Berkeley, based in part on code by Kirk Smith. * * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) * Added VJ tcp header compression; more unified ioctls * * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). * Cleaned up a lot of the mbuf-related code to fix bugs that * caused system crashes and packet corruption.  Changed pppstart * so that it doesn't just give up with a "collision" if the whole * packet doesn't fit in the output ring buffer. * * Added priority queueing for interactive IP packets, following * the model of if_sl.c, plus hooks for bpf. * Paul Mackerras (paulus@cs.anu.edu.au). *//* $Id: ppp_tty.c,v 1.3.2.1 2004/01/30 14:43:05 joel Exp $ *//* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp *//* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */#include "ppp.h"#if NPPP > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/file.h>#include <sys/kernel.h>#include <net/if.h>#include <net/if_types.h>#ifdef VJC#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <net/pppcompress.h>#endif#include <rtems.h>#include <rtems/libio.h>#include <sys/ttycom.h>#include <termios.h>#include <rtems/termiostypes.h>#ifdef PPP_FILTER#include <net/bpf.h>#endif#include <net/ppp_defs.h>#include <net/if_ppp.h>#include <net/if_pppvar.h>void	pppasyncattach __P((void));int     pppopen __P((struct rtems_termios_tty *tty));int     pppclose __P((struct rtems_termios_tty *tty));int     pppread __P((struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args));int     pppwrite __P((struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args));int     ppptioctl __P((struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args));int     pppinput __P((int c, struct rtems_termios_tty *tty));int     pppstart __P((struct rtems_termios_tty *tp));u_short pppfcs __P((u_short fcs, u_char *cp, int len));void    pppallocmbuf __P((struct ppp_softc *sc, struct mbuf **mp));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 pppdumpb __P((u_char *b, int l)); *//*static void ppplogchar __P((struct ppp_softc *, int)); *//* * Some useful mbuf macros not in mbuf.h. */#define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)#define M_DATASTART(m)	\	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)#define M_DATASIZE(m)	\	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)/* * We steal two bits in the mbuf m_flags, to mark high-priority packets * for output, and received packets following lost/corrupted packets. */#define M_HIGHPRI	0x2000	/* output packet for sc_fastq */#define M_ERRMARK	0x4000	/* steal a bit in mbuf m_flags *//* * Does c need to be escaped? */#define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))/* * Procedures for using an async tty interface for PPP. *//* This is a FreeBSD-2.0 kernel. */#define CCOUNT(rb)      (((rb).Size+(rb).Head-(rb).Tail) % (rb).Size)#define FCOUNT(rb)      ((rb).Size-CCOUNT(rb)-1)#define PPP_LOWAT	100	/* Process more output when < LOWAT on queue */#define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que *//* * Define the PPP line discipline. */static struct linesw pppdisc = {	pppopen, pppclose, pppread, pppwrite,	pppinput, pppstart, ppptioctl, NULL};voidpppasyncattach(){    linesw[PPPDISC] = pppdisc;}TEXT_SET(pseudo_set, pppasyncattach);/* * 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 */intpppopen(struct rtems_termios_tty *tty){    int                        i;    register struct ppp_softc *sc;    struct mbuf *m = (struct mbuf *)0;    extern int termios_baud_to_number(int);    if (tty->t_line == PPPDISC) {	sc = (struct ppp_softc *)tty->t_sc;	if (sc != NULL && sc->sc_devp == (void *)tty) {	    return (0);	}    }    if ((sc = pppalloc(1)) == NULL) {	return ENXIO;    }    if (sc->sc_relinq)	(*sc->sc_relinq)(sc);	/* get previous owner to relinquish the unit */    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;    sc->sc_rasyncmap = 0;    sc->sc_devp = tty;    sc->sc_start = pppasyncstart;    sc->sc_ctlp = pppasyncctlp;    sc->sc_relinq = pppasyncrelinq;    sc->sc_outm = NULL;    sc->sc_outmc = NULL;        /* preallocate mbufs for free queue */    rtems_bsdnet_semaphore_obtain();    for (i=0; i<NUM_MBUFQ; i++) {      pppallocmbuf(sc, &m);      if ( i == 0 ) {        /* use first mbuf for rx iterrupt handling */        sc->sc_m = m;      }      else {        /* enqueue mbuf for later use */        IF_ENQUEUE(&sc->sc_freeq, m);      }      m = (struct mbuf *)0;    }    rtems_bsdnet_semaphore_release();    /* initialize values */    sc->sc_if.if_flags |= IFF_RUNNING;    sc->sc_if.if_baudrate =	termios_baud_to_number(tty->termios.c_cflag & CBAUD);    tty->t_sc = (void *)sc;    return ( RTEMS_SUCCESSFUL );}/* * Line specific close routine, called from device close routine * and from ttioctl. * Detach the tty from the ppp unit. * Mimics part of ttyclose(). */intpppclose(struct rtems_termios_tty *tty){    register struct ppp_softc *sc;    tty->t_line = 0;    sc = (struct ppp_softc *)tty->t_sc;    if (sc != NULL) {	tty->t_sc = NULL;	if (tty == (struct rtems_termios_tty *)sc->sc_devp) {            rtems_bsdnet_semaphore_obtain();	    pppasyncrelinq(sc);	    pppdealloc(sc);            rtems_bsdnet_semaphore_release();	}    }    return ( RTEMS_SUCCESSFUL );}/* * Relinquish the interface unit to another device. */static voidpppasyncrelinq(sc)    struct ppp_softc *sc;{#ifdef XXX_XXX    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;    }#endif}/* * Line specific (tty) read routine. */intpppread(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args){    rtems_status_code            status  = RTEMS_UNSATISFIED;    int                          count   = 0;    int                          maximum = rw_args->count;    char                        *buffer  = rw_args->buffer;    register struct ppp_softc   *sc      = (struct ppp_softc *)tty->t_sc;    struct mbuf                 *m;    struct mbuf                 *m0;    u_char                      *p;    if (sc == NULL) {        return 0;    }    /*     * Loop waiting for input, checking that nothing disasterous     * happens in the meantime.     */    if (tty != (struct rtems_termios_tty *)sc->sc_devp || tty->t_line != PPPDISC) {        return ( status );    }    if (sc->sc_inq.ifq_head == NULL) {      return ( status );    }    /* Get the packet from the input queue */    rtems_bsdnet_semaphore_obtain();    IF_DEQUEUE(&sc->sc_inq, m0);    /* loop over mbuf chain */    m = m0;    while (( m != NULL ) && ( m->m_len > 0 ) && ( count+m->m_len < maximum )) {      /* copy data into buffer */      p = mtod(m, u_char *);      memcpy(buffer, p, m->m_len);      memset(p, 0, m->m_len);      count  += m->m_len;      buffer += m->m_len;      /* increment loop index */      m = m->m_next;    }    /* free mbuf chain */    m_freem(m0);    rtems_bsdnet_semaphore_release();    /* update return values */    rw_args->bytes_moved = count;    if ( count >= 0 ) {      status = RTEMS_SUCCESSFUL;    }    /* check to see if queue is empty */    if (sc->sc_inq.ifq_head != NULL) {      /* queue is not empty - post another event to ourself */      rtems_event_send(sc->sc_pppdtask, PPPD_EVENT);    }    return ( status );}/* * Line specific (tty) write routine. */intpppwrite(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args){    struct sockaddr               dst;    int                           n;    int                           len;    int                           maximum    = rw_args->count;    char                         *out_buffer = rw_args->buffer;     register struct ppp_softc    *sc         = (struct ppp_softc *)tty->t_sc;    struct mbuf                  *m;    struct mbuf                  *m0;    struct mbuf                 **mp;    rtems_bsdnet_semaphore_obtain();    for (mp = &m0; maximum; mp = &m->m_next) {	MGET(m, M_WAIT, MT_DATA);	if ((*mp = m) == NULL) {	    m_freem(m0);	    return (ENOBUFS);	}	m->m_len = 0;	if (maximum >= MCLBYTES / 2) {	    MCLGET(m, M_DONTWAIT);        }	len = M_TRAILINGSPACE(m);	if (len > maximum) {          memcpy(mtod(m, u_char *),out_buffer,maximum);          m->m_len = maximum;          maximum  = 0;        }        else {          memcpy(mtod(m, u_char *),out_buffer,len);          m->m_len    = len;          maximum    -= len;          out_buffer += len;        }    }    dst.sa_family = AF_UNSPEC;    bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);    m0->m_data += PPP_HDRLEN;    m0->m_len  -= PPP_HDRLEN;    n = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);    rtems_bsdnet_semaphore_release();    return ( n );}/* * Line specific (tty) ioctl routine. * This discipline requires that tty device drivers call * the line specific l_ioctl routine from their ioctl routines. *//* ARGSUSED */intppptioctl(struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args){/*    int                 i;	*/    int                 error = RTEMS_SUCCESSFUL;    int                 cmd   = args->command;    caddr_t             data  = args->buffer;    struct ppp_softc   *sc    = tty->t_sc;    switch (cmd) {    case RTEMS_IO_GET_ATTRIBUTES:    case RTEMS_IO_SET_ATTRIBUTES:    case RTEMS_IO_TCDRAIN:    case RTEMS_IO_SNDWAKEUP:    case RTEMS_IO_RCVWAKEUP:    case TIOCGETD:    case TIOCSETD:        error = rtems_termios_ioctl(args);	break;    case PPPIOCSASYNCMAP:	sc->sc_asyncmap[0] = *(u_int *)data;	break;    case PPPIOCGASYNCMAP:	*(u_int *)data = sc->sc_asyncmap[0];	break;    case PPPIOCSRASYNCMAP:	sc->sc_rasyncmap = *(u_int *)data;	break;    case PPPIOCGRASYNCMAP:	*(u_int *)data = sc->sc_rasyncmap;	break;    case PPPIOCSXASYNCMAP:	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 */	break;    case PPPIOCGXASYNCMAP:	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));	break;    default:        rtems_bsdnet_semaphore_obtain();	error = pppioctl(sc, cmd, data, 0, NULL);        rtems_bsdnet_semaphore_release();    }    return error;}/*

⌨️ 快捷键说明

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