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
This commit is contained in:
Andreas Tobler 2013-11-26 05:26:10 +00:00
parent 4b48ea6ab2
commit 90653c1c5c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=258615

View File

@ -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);