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