PERFORCE change 150182 for review
Andrew Thompson
thompsa at FreeBSD.org
Sat Sep 20 21:19:48 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=150182
Change 150182 by thompsa at 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);
+}
+
More information about the p4-projects
mailing list