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