Date: Sat, 20 Sep 2008 21:19:47 GMT From: Andrew Thompson <thompsa@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 150182 for review Message-ID: <200809202119.m8KLJlHJ097484@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=150182 Change 150182 by thompsa@thompsa_burger on 2008/09/20 21:18:53 Update for the latest TTY hooks. Affected files ... .. //depot/projects/mpsafetty/sys/netgraph/ng_tty.c#3 edit Differences ... ==== //depot/projects/mpsafetty/sys/netgraph/ng_tty.c#3 (text+ko) ==== @@ -77,36 +77,46 @@ #include <netgraph/ng_tty.h> /* Misc defs */ +#define MAX_MBUFQ 3 /* Max number of queued mbufs */ #define NGT_HIWATER 400 /* High water mark on output */ /* Per-node private info */ -struct ngt_sc { - struct tty *tp; /* Terminal device */ - node_p node; /* Netgraph node */ - hook_p hook; /* Netgraph hook */ - short hotchar; /* Hotchar, or -1 if none */ - u_int flags; /* Flags */ +struct ngt_softc { + struct tty *tp; /* Terminal device */ + node_p node; /* Netgraph node */ + hook_p hook; /* Netgraph hook */ + struct ifqueue outq; /* Queue of outgoing data */ + size_t outqlen; /* Number of bytes in outq */ + short hotchar; /* Hotchar, or -1 if none */ + u_int flags; /* Flags */ }; -typedef struct ngt_sc *sc_p; +typedef struct ngt_softc *sc_p; /* Flags */ #define FLG_DEBUG 0x0002 /* Netgraph methods */ -static ng_constructor_t ngt_constructor; -static ng_rcvmsg_t ngt_rcvmsg; -static ng_shutdown_t ngt_shutdown; -static ng_newhook_t ngt_newhook; -static ng_rcvdata_t ngt_rcvdata; -static ng_disconnect_t ngt_disconnect; +static ng_constructor_t ngt_constructor; +static ng_rcvmsg_t ngt_rcvmsg; +static ng_shutdown_t ngt_shutdown; +static ng_newhook_t ngt_newhook; +static ng_rcvdata_t ngt_rcvdata; +static ng_disconnect_t ngt_disconnect; #define ERROUT(x) do { error = (x); goto done; } while (0) -static th_getc_capture_t ngt_getc_capture; +static th_getc_inject_t ngt_getc_inject; +static th_getc_poll_t ngt_getc_poll; +static th_rint_bypass_t ngt_rint_bypass; +static th_rint_poll_t ngt_rint_poll; +static th_close_t ngt_close; -/* XXX Not the right hook, yet! */ static struct ttyhook ngt_hook = { - .th_getc_capture = ngt_getc_capture, + .th_getc_inject = ngt_getc_inject, + .th_getc_poll = ngt_getc_poll, + .th_rint_bypass = ngt_rint_bypass, + .th_rint_poll = ngt_rint_poll, + .th_close = ngt_close, }; /* Netgraph node type descriptor */ @@ -144,6 +154,9 @@ NG_NODE_SET_PRIVATE(node, sc); + mtx_init(&sc->outq.ifq_mtx, "ng_tty node+queue", NULL, MTX_DEF); + IFQ_SET_MAXLEN(&sc->outq, MAX_MBUFQ); + /* Done */ return (0); } @@ -212,89 +225,6 @@ return (0); } -/* XXX Not the right hook, yet! */ -static void -ngt_getc_capture(struct tty *tp, const void *buf, size_t len) -{ - sc_p sc = ttyhook_softc(tp); - node_p node = sc->node; - struct mbuf *m, *mb; - int error = 0, progress = 0, length; - - if (sc->hook == NULL) - return; - - m = m_getm2(NULL, len, M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - if (sc->flags & FLG_DEBUG) - log(LOG_ERR, - "%s: can't get mbuf\n", NG_NODE_NAME(node)); - return; - } - m->m_pkthdr.rcvif = NULL; - - for (mb = m; mb != NULL; mb = mb->m_next) { - length = min(M_TRAILINGSPACE(mb), len - progress); - - memcpy(mtod(m, char *), (const char *)buf + progress, length); - mb->m_len = length; - progress += length; - m->m_pkthdr.len += length; - } - - NG_SEND_DATA_ONLY(error, sc->hook, m); -} - -/* - * Receive incoming data from netgraph system. Put it on our - * output queue and start output if necessary. - */ -static int -ngt_rcvdata(hook_p hook, item_p item) -{ - const sc_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - struct tty *tp = sc->tp; - struct mbuf *m; - char *buf; - int i, len; - - if (hook != sc->hook) - panic(__func__); - - NGI_GET_M(item, m); - NG_FREE_ITEM(item); - - tty_lock(tp); - - /* Driver could have abandoned the TTY in the mean time. */ - if (tty_gone(tp)) { - NG_FREE_M(m); - tty_unlock(tp); - return (ENXIO); - } - - while (m != NULL) { - buf = mtod(m, char *); - len = m->m_len; - - /* - * Deliver data to the TTY. Ignore errors for now, - * because we shouldn't bail out when we're running - * close to the watermarks. - */ - if (ttydisc_can_bypass(tp)) { - ttydisc_rint_bypass(tp, buf, len); - } else { - for (i = 0; i < len; i++) - ttydisc_rint(tp, buf[i], 0); - } - m = m_free(m); - } - ttydisc_rint_done(tp); - tty_unlock(tp); - return (0); -} - /* * Receive control message */ @@ -350,3 +280,139 @@ NG_FREE_MSG(msg); return (error); } + +/* + * Receive incoming data from netgraph system. Put it on our + * output queue and start output if necessary. + */ +static int +ngt_rcvdata(hook_p hook, item_p item) +{ + const sc_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); + struct tty *tp = sc->tp; + struct mbuf *m; + + if (hook != sc->hook) + panic(__func__); + + NGI_GET_M(item, m); + NG_FREE_ITEM(item); + + IF_LOCK(&sc->outq); + if (_IF_QFULL(&sc->outq)) { + _IF_DROP(&sc->outq); + IF_UNLOCK(&sc->outq); + NG_FREE_M(m); + return (ENOBUFS); + } + + _IF_ENQUEUE(&sc->outq, m); + IF_UNLOCK(&sc->outq); + + /* notify the TTY that data is ready */ + tty_lock(tp); + sc->outqlen += m->m_pkthdr.len; + if (!tty_gone(tp)) + ttydevsw_outwakeup(tp); + tty_unlock(tp); + + return (0); +} + +static size_t +ngt_getc_inject(struct tty *tp, void *buf, size_t len) +{ + sc_p sc = ttyhook_softc(tp); + size_t total = 0; + int length; + + while (len) { + struct mbuf *m; + + /* Remove first mbuf from queue */ + IF_DEQUEUE(&sc->outq, m); + if (m == NULL) + break; + + /* Send as much of it as possible */ + while (m != NULL) { + length = min(m->m_len, len); + memcpy((char *)buf + total, mtod(m, char *), length); + + m->m_data += length; + m->m_len -= length; + total += length; + len -= length; + + if (m->m_len > 0) + break; /* device can't take any more */ + m = m_free(m); + } + + /* Put remainder of mbuf chain (if any) back on queue */ + if (m != NULL) { + IF_PREPEND(&sc->outq, m); + break; + } + } + sc->outqlen -= total; + MPASS(sc->outqlen >= 0); + return (total); +} + +static size_t +ngt_getc_poll(struct tty *tp) +{ + sc_p sc = ttyhook_softc(tp); + + return (sc->outqlen); +} + +static size_t +ngt_rint_bypass(struct tty *tp, const void *buf, size_t len) +{ + sc_p sc = ttyhook_softc(tp); + node_p node = sc->node; + struct mbuf *m, *mb; + size_t total = 0; + int error = 0, length; + + if (sc->hook == NULL) + return (0); + + m = m_getm2(NULL, len, M_DONTWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) { + if (sc->flags & FLG_DEBUG) + log(LOG_ERR, + "%s: can't get mbuf\n", NG_NODE_NAME(node)); + return (0); + } + m->m_pkthdr.rcvif = NULL; + + for (mb = m; mb != NULL; mb = mb->m_next) { + length = min(M_TRAILINGSPACE(mb), len - total); + + memcpy(mtod(m, char *), (const char *)buf + total, length); + mb->m_len = length; + total += length; + m->m_pkthdr.len += length; + } + NG_SEND_DATA_ONLY(error, sc->hook, m); + + return (total); +} + +static size_t +ngt_rint_poll(struct tty *tp) +{ + /* XXX We can always accept input, whats a good value? */ + return (MCLBYTES); +} + +static void +ngt_close(struct tty *tp) +{ + /* XXX ??? */ + ttyhook_unregister(tp); +} +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200809202119.m8KLJlHJ097484>