PERFORCE change 150512 for review

Andrew Thompson thompsa at FreeBSD.org
Fri Sep 26 17:29:57 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=150512

Change 150512 by thompsa at thompsa_burger on 2008/09/26 17:29:13

	Add in a custom rint routine, we should buffer the input intil the
	hotchar is seen. In most cases this will be the PPP framing char of
	0x7e.

Affected files ...

.. //depot/projects/mpsafetty/sys/netgraph/ng_tty.c#7 edit

Differences ...

==== //depot/projects/mpsafetty/sys/netgraph/ng_tty.c#7 (text+ko) ====

@@ -87,6 +87,7 @@
 	hook_p		hook;		/* Netgraph hook */
 	struct ifqueue	outq;		/* Queue of outgoing data */
 	size_t		outqlen;	/* Number of bytes in outq */
+	struct mbuf	*m;		/* Incoming non-bypass data buffer */
 	short		hotchar;	/* Hotchar, or -1 if none */
 	u_int		flags;		/* Flags */
 };
@@ -110,6 +111,7 @@
 
 static th_getc_inject_t		ngt_getc_inject;
 static th_getc_poll_t		ngt_getc_poll;
+static th_rint_t		ngt_rint;
 static th_rint_bypass_t		ngt_rint_bypass;
 static th_rint_poll_t		ngt_rint_poll;
 static th_close_t		ngt_close;
@@ -117,7 +119,8 @@
 static struct ttyhook ngt_hook = {
 	.th_getc_inject = ngt_getc_inject,
 	.th_getc_poll = ngt_getc_poll,
-	.th_rint_bypass	= ngt_rint_bypass,
+	.th_rint = ngt_rint,
+	.th_rint_bypass = ngt_rint_bypass,
 	.th_rint_poll = ngt_rint_poll,
 	.th_close = ngt_close,
 };
@@ -401,6 +404,12 @@
 	return (sc->outqlen);
 }
 
+/*
+ * Optimised TTY input.
+ *
+ * We get a buffer pointer to hopefully a complete data frame. Do not check for
+ * the hotchar, just pass it on.
+ */
 static size_t
 ngt_rint_bypass(struct tty *tp, const void *buf, size_t len)
 {
@@ -410,6 +419,8 @@
 	size_t total = 0;
 	int error = 0, length;
 
+	tty_lock_assert(tp, MA_OWNED);
+
 	if (sc->hook == NULL)
 		return (0);
 
@@ -430,11 +441,75 @@
 		total += length;
 		m->m_pkthdr.len += length;
 	}
+	if (sc->m != NULL) {
+		/*
+		 * Odd, we have changed from non-bypass to bypass. It is
+		 * unlikely but not impossible, flush the data first.
+		 */
+		sc->m->m_data = sc->m->m_pktdat;
+		NG_SEND_DATA_ONLY(error, sc->hook, sc->m);
+		sc->m = NULL;
+	}
 	NG_SEND_DATA_ONLY(error, sc->hook, m);
 
 	return (total);
 }
 
+/*
+ * Receive data coming from the device one char at a time, when it is not in
+ * bypass mode.
+ */
+static int
+ngt_rint(struct tty *tp, char c, int flags)
+{
+	sc_p sc = ttyhook_softc(tp);
+	node_p node = sc->node;
+	struct mbuf *m;
+	int error = 0;
+
+	tty_lock_assert(tp, MA_OWNED);
+
+	if (sc->hook == NULL)
+		return (0);
+
+	if (flags != 0) {
+		/* framing error or overrun on this char */
+		if (sc->flags & FLG_DEBUG)
+			log(LOG_DEBUG, "%s: line error %x\n",
+			    NG_NODE_NAME(node), flags);
+		return (0);
+	}
+
+	/* Get a new header mbuf if we need one */
+	if (!(m = sc->m)) {
+		MGETHDR(m, M_DONTWAIT, MT_DATA);
+		if (!m) {
+			if (sc->flags & FLG_DEBUG)
+				log(LOG_ERR,
+				    "%s: can't get mbuf\n", NG_NODE_NAME(node));
+			return (ENOBUFS);
+		}
+		m->m_len = m->m_pkthdr.len = 0;
+		m->m_pkthdr.rcvif = NULL;
+		sc->m = m;
+	}
+
+	/* Add char to mbuf */
+	*mtod(m, u_char *) = c;
+	m->m_data++;
+	m->m_len++;
+	m->m_pkthdr.len++;
+
+	/* Ship off mbuf if it's time */
+	if (sc->hotchar == -1 || c == sc->hotchar || m->m_len >= MHLEN) {
+		m->m_data = m->m_pktdat;
+		sc->m = NULL;
+		NG_SEND_DATA_ONLY(error, sc->hook, m);	/* Will queue */
+	}
+
+	return (error);
+}
+
 static size_t
 ngt_rint_poll(struct tty *tp)
 {


More information about the p4-projects mailing list