1*7a8d25c0SNathan Whitehorn /*- 2*7a8d25c0SNathan Whitehorn * Copyright (C) 2011 by Nathan Whitehorn. All rights reserved. 3*7a8d25c0SNathan Whitehorn * 4*7a8d25c0SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 5*7a8d25c0SNathan Whitehorn * modification, are permitted provided that the following conditions 6*7a8d25c0SNathan Whitehorn * are met: 7*7a8d25c0SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 8*7a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 9*7a8d25c0SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 10*7a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 11*7a8d25c0SNathan Whitehorn * documentation and/or other materials provided with the distribution. 12*7a8d25c0SNathan Whitehorn * 13*7a8d25c0SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14*7a8d25c0SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15*7a8d25c0SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16*7a8d25c0SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 17*7a8d25c0SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18*7a8d25c0SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 19*7a8d25c0SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20*7a8d25c0SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 21*7a8d25c0SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22*7a8d25c0SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23*7a8d25c0SNathan Whitehorn */ 24*7a8d25c0SNathan Whitehorn 25*7a8d25c0SNathan Whitehorn #include <sys/cdefs.h> 26*7a8d25c0SNathan Whitehorn __FBSDID("$FreeBSD$"); 27*7a8d25c0SNathan Whitehorn 28*7a8d25c0SNathan Whitehorn #include <sys/param.h> 29*7a8d25c0SNathan Whitehorn #include <sys/kdb.h> 30*7a8d25c0SNathan Whitehorn #include <sys/kernel.h> 31*7a8d25c0SNathan Whitehorn #include <sys/priv.h> 32*7a8d25c0SNathan Whitehorn #include <sys/systm.h> 33*7a8d25c0SNathan Whitehorn #include <sys/module.h> 34*7a8d25c0SNathan Whitehorn #include <sys/types.h> 35*7a8d25c0SNathan Whitehorn #include <sys/conf.h> 36*7a8d25c0SNathan Whitehorn #include <sys/cons.h> 37*7a8d25c0SNathan Whitehorn #include <sys/tty.h> 38*7a8d25c0SNathan Whitehorn #include <machine/bus.h> 39*7a8d25c0SNathan Whitehorn 40*7a8d25c0SNathan Whitehorn #include <dev/ofw/openfirm.h> 41*7a8d25c0SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 42*7a8d25c0SNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 43*7a8d25c0SNathan Whitehorn #include <dev/uart/uart.h> 44*7a8d25c0SNathan Whitehorn #include <dev/uart/uart_cpu.h> 45*7a8d25c0SNathan Whitehorn #include <dev/uart/uart_bus.h> 46*7a8d25c0SNathan Whitehorn 47*7a8d25c0SNathan Whitehorn #include "phyp-hvcall.h" 48*7a8d25c0SNathan Whitehorn #include "uart_if.h" 49*7a8d25c0SNathan Whitehorn 50*7a8d25c0SNathan Whitehorn struct uart_phyp_softc { 51*7a8d25c0SNathan Whitehorn device_t dev; 52*7a8d25c0SNathan Whitehorn phandle_t node; 53*7a8d25c0SNathan Whitehorn int vtermid; 54*7a8d25c0SNathan Whitehorn 55*7a8d25c0SNathan Whitehorn struct tty *tp; 56*7a8d25c0SNathan Whitehorn struct resource *irqres; 57*7a8d25c0SNathan Whitehorn int irqrid; 58*7a8d25c0SNathan Whitehorn struct callout callout; 59*7a8d25c0SNathan Whitehorn void *sc_icookie; 60*7a8d25c0SNathan Whitehorn int polltime; 61*7a8d25c0SNathan Whitehorn 62*7a8d25c0SNathan Whitehorn struct mtx sc_mtx; 63*7a8d25c0SNathan Whitehorn int protocol; 64*7a8d25c0SNathan Whitehorn 65*7a8d25c0SNathan Whitehorn union { 66*7a8d25c0SNathan Whitehorn uint64_t u64[2]; 67*7a8d25c0SNathan Whitehorn char str[16]; 68*7a8d25c0SNathan Whitehorn } phyp_inbuf; 69*7a8d25c0SNathan Whitehorn uint64_t inbuflen; 70*7a8d25c0SNathan Whitehorn uint8_t outseqno; 71*7a8d25c0SNathan Whitehorn }; 72*7a8d25c0SNathan Whitehorn 73*7a8d25c0SNathan Whitehorn static struct uart_phyp_softc *console_sc = NULL; 74*7a8d25c0SNathan Whitehorn #if defined(KDB) 75*7a8d25c0SNathan Whitehorn static int alt_break_state; 76*7a8d25c0SNathan Whitehorn #endif 77*7a8d25c0SNathan Whitehorn 78*7a8d25c0SNathan Whitehorn enum { 79*7a8d25c0SNathan Whitehorn HVTERM1, HVTERMPROT 80*7a8d25c0SNathan Whitehorn }; 81*7a8d25c0SNathan Whitehorn 82*7a8d25c0SNathan Whitehorn #define VS_DATA_PACKET_HEADER 0xff 83*7a8d25c0SNathan Whitehorn #define VS_CONTROL_PACKET_HEADER 0xfe 84*7a8d25c0SNathan Whitehorn #define VSV_SET_MODEM_CTL 0x01 85*7a8d25c0SNathan Whitehorn #define VSV_MODEM_CTL_UPDATE 0x02 86*7a8d25c0SNathan Whitehorn #define VSV_RENEGOTIATE_CONNECTION 0x03 87*7a8d25c0SNathan Whitehorn #define VS_QUERY_PACKET_HEADER 0xfd 88*7a8d25c0SNathan Whitehorn #define VSV_SEND_VERSION_NUMBER 0x01 89*7a8d25c0SNathan Whitehorn #define VSV_SEND_MODEM_CTL_STATUS 0x02 90*7a8d25c0SNathan Whitehorn #define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc 91*7a8d25c0SNathan Whitehorn 92*7a8d25c0SNathan Whitehorn static int uart_phyp_probe(device_t dev); 93*7a8d25c0SNathan Whitehorn static int uart_phyp_attach(device_t dev); 94*7a8d25c0SNathan Whitehorn static void uart_phyp_intr(void *v); 95*7a8d25c0SNathan Whitehorn 96*7a8d25c0SNathan Whitehorn static device_method_t uart_phyp_methods[] = { 97*7a8d25c0SNathan Whitehorn /* Device interface */ 98*7a8d25c0SNathan Whitehorn DEVMETHOD(device_probe, uart_phyp_probe), 99*7a8d25c0SNathan Whitehorn DEVMETHOD(device_attach, uart_phyp_attach), 100*7a8d25c0SNathan Whitehorn 101*7a8d25c0SNathan Whitehorn DEVMETHOD_END 102*7a8d25c0SNathan Whitehorn }; 103*7a8d25c0SNathan Whitehorn 104*7a8d25c0SNathan Whitehorn static driver_t uart_phyp_driver = { 105*7a8d25c0SNathan Whitehorn "uart", 106*7a8d25c0SNathan Whitehorn uart_phyp_methods, 107*7a8d25c0SNathan Whitehorn sizeof(struct uart_phyp_softc), 108*7a8d25c0SNathan Whitehorn }; 109*7a8d25c0SNathan Whitehorn 110*7a8d25c0SNathan Whitehorn DRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0); 111*7a8d25c0SNathan Whitehorn 112*7a8d25c0SNathan Whitehorn static cn_probe_t uart_phyp_cnprobe; 113*7a8d25c0SNathan Whitehorn static cn_init_t uart_phyp_cninit; 114*7a8d25c0SNathan Whitehorn static cn_term_t uart_phyp_cnterm; 115*7a8d25c0SNathan Whitehorn static cn_getc_t uart_phyp_cngetc; 116*7a8d25c0SNathan Whitehorn static cn_putc_t uart_phyp_cnputc; 117*7a8d25c0SNathan Whitehorn static cn_grab_t uart_phyp_cngrab; 118*7a8d25c0SNathan Whitehorn static cn_ungrab_t uart_phyp_cnungrab; 119*7a8d25c0SNathan Whitehorn 120*7a8d25c0SNathan Whitehorn CONSOLE_DRIVER(uart_phyp); 121*7a8d25c0SNathan Whitehorn 122*7a8d25c0SNathan Whitehorn static void uart_phyp_ttyoutwakeup(struct tty *tp); 123*7a8d25c0SNathan Whitehorn 124*7a8d25c0SNathan Whitehorn static struct ttydevsw uart_phyp_tty_class = { 125*7a8d25c0SNathan Whitehorn .tsw_flags = TF_INITLOCK|TF_CALLOUT, 126*7a8d25c0SNathan Whitehorn .tsw_outwakeup = uart_phyp_ttyoutwakeup, 127*7a8d25c0SNathan Whitehorn }; 128*7a8d25c0SNathan Whitehorn 129*7a8d25c0SNathan Whitehorn static int 130*7a8d25c0SNathan Whitehorn uart_phyp_probe_node(struct uart_phyp_softc *sc) 131*7a8d25c0SNathan Whitehorn { 132*7a8d25c0SNathan Whitehorn phandle_t node = sc->node; 133*7a8d25c0SNathan Whitehorn uint32_t reg; 134*7a8d25c0SNathan Whitehorn char buf[64]; 135*7a8d25c0SNathan Whitehorn 136*7a8d25c0SNathan Whitehorn sc->inbuflen = 0; 137*7a8d25c0SNathan Whitehorn sc->outseqno = 0; 138*7a8d25c0SNathan Whitehorn 139*7a8d25c0SNathan Whitehorn if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0) 140*7a8d25c0SNathan Whitehorn return (ENXIO); 141*7a8d25c0SNathan Whitehorn if (strcmp(buf, "vty") != 0) 142*7a8d25c0SNathan Whitehorn return (ENXIO); 143*7a8d25c0SNathan Whitehorn 144*7a8d25c0SNathan Whitehorn if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0) 145*7a8d25c0SNathan Whitehorn return (ENXIO); 146*7a8d25c0SNathan Whitehorn if (strcmp(buf, "serial") != 0) 147*7a8d25c0SNathan Whitehorn return (ENXIO); 148*7a8d25c0SNathan Whitehorn 149*7a8d25c0SNathan Whitehorn reg = -1; 150*7a8d25c0SNathan Whitehorn OF_getprop(node, "reg", ®, sizeof(reg)); 151*7a8d25c0SNathan Whitehorn if (reg == -1) 152*7a8d25c0SNathan Whitehorn return (ENXIO); 153*7a8d25c0SNathan Whitehorn sc->node = node; 154*7a8d25c0SNathan Whitehorn 155*7a8d25c0SNathan Whitehorn if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0) 156*7a8d25c0SNathan Whitehorn return (ENXIO); 157*7a8d25c0SNathan Whitehorn if (strcmp(buf, "hvterm1") == 0) { 158*7a8d25c0SNathan Whitehorn sc->protocol = HVTERM1; 159*7a8d25c0SNathan Whitehorn return (0); 160*7a8d25c0SNathan Whitehorn } else if (strcmp(buf, "hvterm-protocol") == 0) { 161*7a8d25c0SNathan Whitehorn sc->protocol = HVTERMPROT; 162*7a8d25c0SNathan Whitehorn return (0); 163*7a8d25c0SNathan Whitehorn } 164*7a8d25c0SNathan Whitehorn 165*7a8d25c0SNathan Whitehorn return (ENXIO); 166*7a8d25c0SNathan Whitehorn } 167*7a8d25c0SNathan Whitehorn 168*7a8d25c0SNathan Whitehorn static int 169*7a8d25c0SNathan Whitehorn uart_phyp_probe(device_t dev) 170*7a8d25c0SNathan Whitehorn { 171*7a8d25c0SNathan Whitehorn const char *name; 172*7a8d25c0SNathan Whitehorn struct uart_phyp_softc sc; 173*7a8d25c0SNathan Whitehorn int err; 174*7a8d25c0SNathan Whitehorn 175*7a8d25c0SNathan Whitehorn name = ofw_bus_get_name(dev); 176*7a8d25c0SNathan Whitehorn if (name == NULL || strcmp(name, "vty") != 0) 177*7a8d25c0SNathan Whitehorn return (ENXIO); 178*7a8d25c0SNathan Whitehorn 179*7a8d25c0SNathan Whitehorn sc.node = ofw_bus_get_node(dev); 180*7a8d25c0SNathan Whitehorn err = uart_phyp_probe_node(&sc); 181*7a8d25c0SNathan Whitehorn if (err != 0) 182*7a8d25c0SNathan Whitehorn return (err); 183*7a8d25c0SNathan Whitehorn 184*7a8d25c0SNathan Whitehorn device_set_desc(dev, "POWER Hypervisor Virtual Serial Port"); 185*7a8d25c0SNathan Whitehorn 186*7a8d25c0SNathan Whitehorn return (err); 187*7a8d25c0SNathan Whitehorn } 188*7a8d25c0SNathan Whitehorn 189*7a8d25c0SNathan Whitehorn static void 190*7a8d25c0SNathan Whitehorn uart_phyp_cnprobe(struct consdev *cp) 191*7a8d25c0SNathan Whitehorn { 192*7a8d25c0SNathan Whitehorn char buf[64]; 193*7a8d25c0SNathan Whitehorn ihandle_t stdout; 194*7a8d25c0SNathan Whitehorn phandle_t input, opts, chosen; 195*7a8d25c0SNathan Whitehorn static struct uart_phyp_softc sc; 196*7a8d25c0SNathan Whitehorn 197*7a8d25c0SNathan Whitehorn if ((opts = OF_finddevice("/options")) == -1) 198*7a8d25c0SNathan Whitehorn goto fail; 199*7a8d25c0SNathan Whitehorn if ((chosen = OF_finddevice("/chosen")) == -1) 200*7a8d25c0SNathan Whitehorn goto fail; 201*7a8d25c0SNathan Whitehorn 202*7a8d25c0SNathan Whitehorn /* Check if OF has an active stdin/stdout */ 203*7a8d25c0SNathan Whitehorn input = -1; 204*7a8d25c0SNathan Whitehorn if (OF_getprop(chosen, "stdout", &stdout, 205*7a8d25c0SNathan Whitehorn sizeof(stdout)) == sizeof(stdout) && stdout != 0) 206*7a8d25c0SNathan Whitehorn input = OF_instance_to_package(stdout); 207*7a8d25c0SNathan Whitehorn if (input == -1) 208*7a8d25c0SNathan Whitehorn goto fail; 209*7a8d25c0SNathan Whitehorn 210*7a8d25c0SNathan Whitehorn if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) 211*7a8d25c0SNathan Whitehorn goto fail; 212*7a8d25c0SNathan Whitehorn if (strcmp(buf, "serial") != 0) 213*7a8d25c0SNathan Whitehorn goto fail; 214*7a8d25c0SNathan Whitehorn 215*7a8d25c0SNathan Whitehorn sc.node = input; 216*7a8d25c0SNathan Whitehorn if (uart_phyp_probe_node(&sc) != 0) 217*7a8d25c0SNathan Whitehorn goto fail; 218*7a8d25c0SNathan Whitehorn mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET | 219*7a8d25c0SNathan Whitehorn MTX_NOWITNESS); 220*7a8d25c0SNathan Whitehorn 221*7a8d25c0SNathan Whitehorn cp->cn_pri = CN_NORMAL; 222*7a8d25c0SNathan Whitehorn console_sc = ≻ 223*7a8d25c0SNathan Whitehorn return; 224*7a8d25c0SNathan Whitehorn 225*7a8d25c0SNathan Whitehorn fail: 226*7a8d25c0SNathan Whitehorn cp->cn_pri = CN_DEAD; 227*7a8d25c0SNathan Whitehorn return; 228*7a8d25c0SNathan Whitehorn } 229*7a8d25c0SNathan Whitehorn 230*7a8d25c0SNathan Whitehorn static int 231*7a8d25c0SNathan Whitehorn uart_phyp_attach(device_t dev) 232*7a8d25c0SNathan Whitehorn { 233*7a8d25c0SNathan Whitehorn struct uart_phyp_softc *sc; 234*7a8d25c0SNathan Whitehorn int unit; 235*7a8d25c0SNathan Whitehorn 236*7a8d25c0SNathan Whitehorn sc = device_get_softc(dev); 237*7a8d25c0SNathan Whitehorn sc->dev = dev; 238*7a8d25c0SNathan Whitehorn sc->node = ofw_bus_get_node(dev); 239*7a8d25c0SNathan Whitehorn uart_phyp_probe_node(sc); 240*7a8d25c0SNathan Whitehorn 241*7a8d25c0SNathan Whitehorn unit = device_get_unit(dev); 242*7a8d25c0SNathan Whitehorn sc->tp = tty_alloc(&uart_phyp_tty_class, sc); 243*7a8d25c0SNathan Whitehorn mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, 244*7a8d25c0SNathan Whitehorn MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); 245*7a8d25c0SNathan Whitehorn 246*7a8d25c0SNathan Whitehorn if (console_sc != NULL && console_sc->vtermid == sc->vtermid) { 247*7a8d25c0SNathan Whitehorn sc->outseqno = console_sc->outseqno; 248*7a8d25c0SNathan Whitehorn console_sc = sc; 249*7a8d25c0SNathan Whitehorn sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit); 250*7a8d25c0SNathan Whitehorn tty_init_console(sc->tp, 0); 251*7a8d25c0SNathan Whitehorn } 252*7a8d25c0SNathan Whitehorn 253*7a8d25c0SNathan Whitehorn sc->irqrid = 0; 254*7a8d25c0SNathan Whitehorn #ifdef NOTYET 255*7a8d25c0SNathan Whitehorn sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, 256*7a8d25c0SNathan Whitehorn RF_ACTIVE | RF_SHAREABLE); 257*7a8d25c0SNathan Whitehorn #else 258*7a8d25c0SNathan Whitehorn sc->irqres = NULL; 259*7a8d25c0SNathan Whitehorn #endif 260*7a8d25c0SNathan Whitehorn if (sc->irqres != NULL) { 261*7a8d25c0SNathan Whitehorn bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE, 262*7a8d25c0SNathan Whitehorn NULL, uart_phyp_intr, sc, &sc->sc_icookie); 263*7a8d25c0SNathan Whitehorn } else { 264*7a8d25c0SNathan Whitehorn callout_init(&sc->callout, CALLOUT_MPSAFE); 265*7a8d25c0SNathan Whitehorn sc->polltime = hz / 20; 266*7a8d25c0SNathan Whitehorn if (sc->polltime < 1) 267*7a8d25c0SNathan Whitehorn sc->polltime = 1; 268*7a8d25c0SNathan Whitehorn callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc); 269*7a8d25c0SNathan Whitehorn } 270*7a8d25c0SNathan Whitehorn 271*7a8d25c0SNathan Whitehorn tty_makedev(sc->tp, NULL, "u%r", unit); 272*7a8d25c0SNathan Whitehorn 273*7a8d25c0SNathan Whitehorn return (0); 274*7a8d25c0SNathan Whitehorn } 275*7a8d25c0SNathan Whitehorn 276*7a8d25c0SNathan Whitehorn static void 277*7a8d25c0SNathan Whitehorn uart_phyp_cninit(struct consdev *cp) 278*7a8d25c0SNathan Whitehorn { 279*7a8d25c0SNathan Whitehorn 280*7a8d25c0SNathan Whitehorn strcpy(cp->cn_name, "phypcons"); 281*7a8d25c0SNathan Whitehorn } 282*7a8d25c0SNathan Whitehorn 283*7a8d25c0SNathan Whitehorn static void 284*7a8d25c0SNathan Whitehorn uart_phyp_cnterm(struct consdev *cp) 285*7a8d25c0SNathan Whitehorn { 286*7a8d25c0SNathan Whitehorn } 287*7a8d25c0SNathan Whitehorn 288*7a8d25c0SNathan Whitehorn static int 289*7a8d25c0SNathan Whitehorn uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) 290*7a8d25c0SNathan Whitehorn { 291*7a8d25c0SNathan Whitehorn int err; 292*7a8d25c0SNathan Whitehorn 293*7a8d25c0SNathan Whitehorn uart_lock(&sc->sc_mtx); 294*7a8d25c0SNathan Whitehorn if (sc->inbuflen == 0) { 295*7a8d25c0SNathan Whitehorn err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid, 296*7a8d25c0SNathan Whitehorn 0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0], 297*7a8d25c0SNathan Whitehorn &sc->phyp_inbuf.u64[1]); 298*7a8d25c0SNathan Whitehorn if (err != H_SUCCESS) { 299*7a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 300*7a8d25c0SNathan Whitehorn return (-1); 301*7a8d25c0SNathan Whitehorn } 302*7a8d25c0SNathan Whitehorn } 303*7a8d25c0SNathan Whitehorn 304*7a8d25c0SNathan Whitehorn if (sc->inbuflen == 0) { 305*7a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 306*7a8d25c0SNathan Whitehorn return (0); 307*7a8d25c0SNathan Whitehorn } 308*7a8d25c0SNathan Whitehorn 309*7a8d25c0SNathan Whitehorn if (bufsize > sc->inbuflen) 310*7a8d25c0SNathan Whitehorn bufsize = sc->inbuflen; 311*7a8d25c0SNathan Whitehorn memcpy(buffer, sc->phyp_inbuf.str, bufsize); 312*7a8d25c0SNathan Whitehorn sc->inbuflen -= bufsize; 313*7a8d25c0SNathan Whitehorn if (sc->inbuflen > 0) 314*7a8d25c0SNathan Whitehorn memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize], 315*7a8d25c0SNathan Whitehorn sc->inbuflen); 316*7a8d25c0SNathan Whitehorn 317*7a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 318*7a8d25c0SNathan Whitehorn return (bufsize); 319*7a8d25c0SNathan Whitehorn } 320*7a8d25c0SNathan Whitehorn 321*7a8d25c0SNathan Whitehorn static int 322*7a8d25c0SNathan Whitehorn uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) 323*7a8d25c0SNathan Whitehorn { 324*7a8d25c0SNathan Whitehorn uint16_t seqno; 325*7a8d25c0SNathan Whitehorn uint64_t len = 0; 326*7a8d25c0SNathan Whitehorn union { 327*7a8d25c0SNathan Whitehorn uint64_t u64; 328*7a8d25c0SNathan Whitehorn char bytes[8]; 329*7a8d25c0SNathan Whitehorn } cbuf; 330*7a8d25c0SNathan Whitehorn 331*7a8d25c0SNathan Whitehorn uart_lock(&sc->sc_mtx); 332*7a8d25c0SNathan Whitehorn switch (sc->protocol) { 333*7a8d25c0SNathan Whitehorn case HVTERM1: 334*7a8d25c0SNathan Whitehorn if (bufsize > 8) 335*7a8d25c0SNathan Whitehorn bufsize = 8; 336*7a8d25c0SNathan Whitehorn memcpy(&cbuf, buffer, bufsize); 337*7a8d25c0SNathan Whitehorn len = bufsize; 338*7a8d25c0SNathan Whitehorn break; 339*7a8d25c0SNathan Whitehorn case HVTERMPROT: 340*7a8d25c0SNathan Whitehorn if (bufsize > 4) 341*7a8d25c0SNathan Whitehorn bufsize = 4; 342*7a8d25c0SNathan Whitehorn seqno = sc->outseqno++; 343*7a8d25c0SNathan Whitehorn cbuf.bytes[0] = VS_DATA_PACKET_HEADER; 344*7a8d25c0SNathan Whitehorn cbuf.bytes[1] = 4 + bufsize; /* total length */ 345*7a8d25c0SNathan Whitehorn cbuf.bytes[2] = (seqno >> 8) & 0xff; 346*7a8d25c0SNathan Whitehorn cbuf.bytes[3] = seqno & 0xff; 347*7a8d25c0SNathan Whitehorn memcpy(&cbuf.bytes[4], buffer, bufsize); 348*7a8d25c0SNathan Whitehorn len = 4 + bufsize; 349*7a8d25c0SNathan Whitehorn break; 350*7a8d25c0SNathan Whitehorn } 351*7a8d25c0SNathan Whitehorn phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64, 0); 352*7a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 353*7a8d25c0SNathan Whitehorn 354*7a8d25c0SNathan Whitehorn return (bufsize); 355*7a8d25c0SNathan Whitehorn } 356*7a8d25c0SNathan Whitehorn 357*7a8d25c0SNathan Whitehorn static int 358*7a8d25c0SNathan Whitehorn uart_phyp_cngetc(struct consdev *cp) 359*7a8d25c0SNathan Whitehorn { 360*7a8d25c0SNathan Whitehorn unsigned char c; 361*7a8d25c0SNathan Whitehorn int retval; 362*7a8d25c0SNathan Whitehorn 363*7a8d25c0SNathan Whitehorn retval = uart_phyp_get(console_sc, &c, 1); 364*7a8d25c0SNathan Whitehorn if (retval != 1) 365*7a8d25c0SNathan Whitehorn return (-1); 366*7a8d25c0SNathan Whitehorn #if defined(KDB) 367*7a8d25c0SNathan Whitehorn kdb_alt_break(c, &alt_break_state); 368*7a8d25c0SNathan Whitehorn #endif 369*7a8d25c0SNathan Whitehorn 370*7a8d25c0SNathan Whitehorn return (c); 371*7a8d25c0SNathan Whitehorn } 372*7a8d25c0SNathan Whitehorn 373*7a8d25c0SNathan Whitehorn static void 374*7a8d25c0SNathan Whitehorn uart_phyp_cnputc(struct consdev *cp, int c) 375*7a8d25c0SNathan Whitehorn { 376*7a8d25c0SNathan Whitehorn unsigned char ch = c; 377*7a8d25c0SNathan Whitehorn uart_phyp_put(console_sc, &ch, 1); 378*7a8d25c0SNathan Whitehorn } 379*7a8d25c0SNathan Whitehorn 380*7a8d25c0SNathan Whitehorn static void 381*7a8d25c0SNathan Whitehorn uart_phyp_cngrab(struct consdev *cp) 382*7a8d25c0SNathan Whitehorn { 383*7a8d25c0SNathan Whitehorn } 384*7a8d25c0SNathan Whitehorn 385*7a8d25c0SNathan Whitehorn static void 386*7a8d25c0SNathan Whitehorn uart_phyp_cnungrab(struct consdev *cp) 387*7a8d25c0SNathan Whitehorn { 388*7a8d25c0SNathan Whitehorn } 389*7a8d25c0SNathan Whitehorn 390*7a8d25c0SNathan Whitehorn static void 391*7a8d25c0SNathan Whitehorn uart_phyp_ttyoutwakeup(struct tty *tp) 392*7a8d25c0SNathan Whitehorn { 393*7a8d25c0SNathan Whitehorn struct uart_phyp_softc *sc; 394*7a8d25c0SNathan Whitehorn char buffer[8]; 395*7a8d25c0SNathan Whitehorn int len; 396*7a8d25c0SNathan Whitehorn 397*7a8d25c0SNathan Whitehorn sc = tty_softc(tp); 398*7a8d25c0SNathan Whitehorn 399*7a8d25c0SNathan Whitehorn while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0) 400*7a8d25c0SNathan Whitehorn uart_phyp_put(sc, buffer, len); 401*7a8d25c0SNathan Whitehorn } 402*7a8d25c0SNathan Whitehorn 403*7a8d25c0SNathan Whitehorn static void 404*7a8d25c0SNathan Whitehorn uart_phyp_intr(void *v) 405*7a8d25c0SNathan Whitehorn { 406*7a8d25c0SNathan Whitehorn struct uart_phyp_softc *sc = v; 407*7a8d25c0SNathan Whitehorn struct tty *tp = sc->tp; 408*7a8d25c0SNathan Whitehorn unsigned char c; 409*7a8d25c0SNathan Whitehorn int len; 410*7a8d25c0SNathan Whitehorn 411*7a8d25c0SNathan Whitehorn tty_lock(tp); 412*7a8d25c0SNathan Whitehorn while ((len = uart_phyp_get(sc, &c, 1)) > 0) 413*7a8d25c0SNathan Whitehorn ttydisc_rint(tp, c, 0); 414*7a8d25c0SNathan Whitehorn ttydisc_rint_done(tp); 415*7a8d25c0SNathan Whitehorn tty_unlock(tp); 416*7a8d25c0SNathan Whitehorn 417*7a8d25c0SNathan Whitehorn if (sc->irqres == NULL) 418*7a8d25c0SNathan Whitehorn callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc); 419*7a8d25c0SNathan Whitehorn } 420*7a8d25c0SNathan Whitehorn 421