diff options
author | andreast <andreast@FreeBSD.org> | 2013-11-26 05:26:10 +0000 |
---|---|---|
committer | andreast <andreast@FreeBSD.org> | 2013-11-26 05:26:10 +0000 |
commit | b6e7868243c5dbb84690a1975b85f817cb88a34c (patch) | |
tree | 9bb994ed5494955bcfe995ab0b52e1b471fcaa3c /sys | |
parent | fbf25c0508965f67dc1302f75b1c5022c1217d91 (diff) | |
download | FreeBSD-src-b6e7868243c5dbb84690a1975b85f817cb88a34c.zip FreeBSD-src-b6e7868243c5dbb84690a1975b85f817cb88a34c.tar.gz |
Take care to handle the full 16 byte buffer in the get/put routines. Also,
skip the VTERM header once when receiving data from the hypervisor call when
we have a HVTERMPROT connection.
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/powerpc/pseries/phyp_console.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/sys/powerpc/pseries/phyp_console.c b/sys/powerpc/pseries/phyp_console.c index a72fe80..2434697 100644 --- a/sys/powerpc/pseries/phyp_console.c +++ b/sys/powerpc/pseries/phyp_console.c @@ -286,6 +286,7 @@ static int uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) { int err; + int hdr = 0; uart_lock(&sc->sc_mtx); if (sc->inbuflen == 0) { @@ -296,6 +297,7 @@ uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) uart_unlock(&sc->sc_mtx); return (-1); } + hdr = 1; } if (sc->inbuflen == 0) { @@ -305,6 +307,14 @@ uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) if (bufsize > sc->inbuflen) bufsize = sc->inbuflen; + + if ((sc->protocol == HVTERMPROT) && (hdr == 1)) { + sc->inbuflen = sc->inbuflen - 4; + /* The VTERM protocol has a 4 byte header, skip it here. */ + memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4], + sc->inbuflen); + } + memcpy(buffer, sc->phyp_inbuf.str, bufsize); sc->inbuflen -= bufsize; if (sc->inbuflen > 0) @@ -320,32 +330,40 @@ uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) { uint16_t seqno; uint64_t len = 0; + int err; + union { - uint64_t u64; - char bytes[8]; + uint64_t u64[2]; + char bytes[16]; } cbuf; uart_lock(&sc->sc_mtx); switch (sc->protocol) { case HVTERM1: - if (bufsize > 8) - bufsize = 8; + if (bufsize > 16) + bufsize = 16; memcpy(&cbuf, buffer, bufsize); len = bufsize; break; case HVTERMPROT: - if (bufsize > 4) - bufsize = 4; + if (bufsize > 12) + bufsize = 12; seqno = sc->outseqno++; cbuf.bytes[0] = VS_DATA_PACKET_HEADER; - cbuf.bytes[1] = 4 + bufsize; /* total length */ + cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */ cbuf.bytes[2] = (seqno >> 8) & 0xff; cbuf.bytes[3] = seqno & 0xff; memcpy(&cbuf.bytes[4], buffer, bufsize); len = 4 + bufsize; break; } - phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64, 0); + + do { + err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64[0], + cbuf.u64[1]); + DELAY(100); + } while (err == H_BUSY); + uart_unlock(&sc->sc_mtx); return (bufsize); |