17a8d25c0SNathan Whitehorn /*- 27a8d25c0SNathan Whitehorn * Copyright (C) 2011 by Nathan Whitehorn. All rights reserved. 37a8d25c0SNathan Whitehorn * 47a8d25c0SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 57a8d25c0SNathan Whitehorn * modification, are permitted provided that the following conditions 67a8d25c0SNathan Whitehorn * are met: 77a8d25c0SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 87a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 97a8d25c0SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 107a8d25c0SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 117a8d25c0SNathan Whitehorn * documentation and/or other materials provided with the distribution. 127a8d25c0SNathan Whitehorn * 137a8d25c0SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 147a8d25c0SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 157a8d25c0SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 167a8d25c0SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 177a8d25c0SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 187a8d25c0SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 197a8d25c0SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 207a8d25c0SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 217a8d25c0SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 227a8d25c0SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 237a8d25c0SNathan Whitehorn */ 247a8d25c0SNathan Whitehorn 257a8d25c0SNathan Whitehorn #include <sys/cdefs.h> 267a8d25c0SNathan Whitehorn __FBSDID("$FreeBSD$"); 277a8d25c0SNathan Whitehorn 287a8d25c0SNathan Whitehorn #include <sys/param.h> 297a8d25c0SNathan Whitehorn #include <sys/kdb.h> 307a8d25c0SNathan Whitehorn #include <sys/kernel.h> 317a8d25c0SNathan Whitehorn #include <sys/priv.h> 327a8d25c0SNathan Whitehorn #include <sys/systm.h> 337a8d25c0SNathan Whitehorn #include <sys/module.h> 347a8d25c0SNathan Whitehorn #include <sys/types.h> 357a8d25c0SNathan Whitehorn #include <sys/conf.h> 367a8d25c0SNathan Whitehorn #include <sys/cons.h> 377a8d25c0SNathan Whitehorn #include <sys/tty.h> 387a8d25c0SNathan Whitehorn #include <machine/bus.h> 397a8d25c0SNathan Whitehorn 407a8d25c0SNathan Whitehorn #include <dev/ofw/openfirm.h> 417a8d25c0SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 427a8d25c0SNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 437a8d25c0SNathan Whitehorn #include <dev/uart/uart.h> 447a8d25c0SNathan Whitehorn #include <dev/uart/uart_cpu.h> 457a8d25c0SNathan Whitehorn #include <dev/uart/uart_bus.h> 467a8d25c0SNathan Whitehorn 477a8d25c0SNathan Whitehorn #include "phyp-hvcall.h" 487a8d25c0SNathan Whitehorn #include "uart_if.h" 497a8d25c0SNathan Whitehorn 507a8d25c0SNathan Whitehorn struct uart_phyp_softc { 517a8d25c0SNathan Whitehorn device_t dev; 527a8d25c0SNathan Whitehorn phandle_t node; 537a8d25c0SNathan Whitehorn int vtermid; 547a8d25c0SNathan Whitehorn 557a8d25c0SNathan Whitehorn struct tty *tp; 567a8d25c0SNathan Whitehorn struct resource *irqres; 577a8d25c0SNathan Whitehorn int irqrid; 587a8d25c0SNathan Whitehorn struct callout callout; 597a8d25c0SNathan Whitehorn void *sc_icookie; 607a8d25c0SNathan Whitehorn int polltime; 617a8d25c0SNathan Whitehorn 627a8d25c0SNathan Whitehorn struct mtx sc_mtx; 637a8d25c0SNathan Whitehorn int protocol; 647a8d25c0SNathan Whitehorn 657a8d25c0SNathan Whitehorn union { 667a8d25c0SNathan Whitehorn uint64_t u64[2]; 677a8d25c0SNathan Whitehorn char str[16]; 687a8d25c0SNathan Whitehorn } phyp_inbuf; 697a8d25c0SNathan Whitehorn uint64_t inbuflen; 707a8d25c0SNathan Whitehorn uint8_t outseqno; 717a8d25c0SNathan Whitehorn }; 727a8d25c0SNathan Whitehorn 737a8d25c0SNathan Whitehorn static struct uart_phyp_softc *console_sc = NULL; 747a8d25c0SNathan Whitehorn #if defined(KDB) 757a8d25c0SNathan Whitehorn static int alt_break_state; 767a8d25c0SNathan Whitehorn #endif 777a8d25c0SNathan Whitehorn 787a8d25c0SNathan Whitehorn enum { 797a8d25c0SNathan Whitehorn HVTERM1, HVTERMPROT 807a8d25c0SNathan Whitehorn }; 817a8d25c0SNathan Whitehorn 827a8d25c0SNathan Whitehorn #define VS_DATA_PACKET_HEADER 0xff 837a8d25c0SNathan Whitehorn #define VS_CONTROL_PACKET_HEADER 0xfe 847a8d25c0SNathan Whitehorn #define VSV_SET_MODEM_CTL 0x01 857a8d25c0SNathan Whitehorn #define VSV_MODEM_CTL_UPDATE 0x02 867a8d25c0SNathan Whitehorn #define VSV_RENEGOTIATE_CONNECTION 0x03 877a8d25c0SNathan Whitehorn #define VS_QUERY_PACKET_HEADER 0xfd 887a8d25c0SNathan Whitehorn #define VSV_SEND_VERSION_NUMBER 0x01 897a8d25c0SNathan Whitehorn #define VSV_SEND_MODEM_CTL_STATUS 0x02 907a8d25c0SNathan Whitehorn #define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc 917a8d25c0SNathan Whitehorn 927a8d25c0SNathan Whitehorn static int uart_phyp_probe(device_t dev); 937a8d25c0SNathan Whitehorn static int uart_phyp_attach(device_t dev); 947a8d25c0SNathan Whitehorn static void uart_phyp_intr(void *v); 957a8d25c0SNathan Whitehorn 967a8d25c0SNathan Whitehorn static device_method_t uart_phyp_methods[] = { 977a8d25c0SNathan Whitehorn /* Device interface */ 987a8d25c0SNathan Whitehorn DEVMETHOD(device_probe, uart_phyp_probe), 997a8d25c0SNathan Whitehorn DEVMETHOD(device_attach, uart_phyp_attach), 1007a8d25c0SNathan Whitehorn 1017a8d25c0SNathan Whitehorn DEVMETHOD_END 1027a8d25c0SNathan Whitehorn }; 1037a8d25c0SNathan Whitehorn 1047a8d25c0SNathan Whitehorn static driver_t uart_phyp_driver = { 1057a8d25c0SNathan Whitehorn "uart", 1067a8d25c0SNathan Whitehorn uart_phyp_methods, 1077a8d25c0SNathan Whitehorn sizeof(struct uart_phyp_softc), 1087a8d25c0SNathan Whitehorn }; 1097a8d25c0SNathan Whitehorn 1107a8d25c0SNathan Whitehorn DRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0); 1117a8d25c0SNathan Whitehorn 1127a8d25c0SNathan Whitehorn static cn_probe_t uart_phyp_cnprobe; 1137a8d25c0SNathan Whitehorn static cn_init_t uart_phyp_cninit; 1147a8d25c0SNathan Whitehorn static cn_term_t uart_phyp_cnterm; 1157a8d25c0SNathan Whitehorn static cn_getc_t uart_phyp_cngetc; 1167a8d25c0SNathan Whitehorn static cn_putc_t uart_phyp_cnputc; 1177a8d25c0SNathan Whitehorn static cn_grab_t uart_phyp_cngrab; 1187a8d25c0SNathan Whitehorn static cn_ungrab_t uart_phyp_cnungrab; 1197a8d25c0SNathan Whitehorn 1207a8d25c0SNathan Whitehorn CONSOLE_DRIVER(uart_phyp); 1217a8d25c0SNathan Whitehorn 1227a8d25c0SNathan Whitehorn static void uart_phyp_ttyoutwakeup(struct tty *tp); 1237a8d25c0SNathan Whitehorn 1247a8d25c0SNathan Whitehorn static struct ttydevsw uart_phyp_tty_class = { 1257a8d25c0SNathan Whitehorn .tsw_flags = TF_INITLOCK|TF_CALLOUT, 1267a8d25c0SNathan Whitehorn .tsw_outwakeup = uart_phyp_ttyoutwakeup, 1277a8d25c0SNathan Whitehorn }; 1287a8d25c0SNathan Whitehorn 1297a8d25c0SNathan Whitehorn static int 1307a8d25c0SNathan Whitehorn uart_phyp_probe_node(struct uart_phyp_softc *sc) 1317a8d25c0SNathan Whitehorn { 1327a8d25c0SNathan Whitehorn phandle_t node = sc->node; 1337a8d25c0SNathan Whitehorn uint32_t reg; 1347a8d25c0SNathan Whitehorn char buf[64]; 1357a8d25c0SNathan Whitehorn 1367a8d25c0SNathan Whitehorn sc->inbuflen = 0; 1377a8d25c0SNathan Whitehorn sc->outseqno = 0; 1387a8d25c0SNathan Whitehorn 1397a8d25c0SNathan Whitehorn if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0) 1407a8d25c0SNathan Whitehorn return (ENXIO); 1417a8d25c0SNathan Whitehorn if (strcmp(buf, "vty") != 0) 1427a8d25c0SNathan Whitehorn return (ENXIO); 1437a8d25c0SNathan Whitehorn 1447a8d25c0SNathan Whitehorn if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0) 1457a8d25c0SNathan Whitehorn return (ENXIO); 1467a8d25c0SNathan Whitehorn if (strcmp(buf, "serial") != 0) 1477a8d25c0SNathan Whitehorn return (ENXIO); 1487a8d25c0SNathan Whitehorn 1497a8d25c0SNathan Whitehorn reg = -1; 1507a8d25c0SNathan Whitehorn OF_getprop(node, "reg", ®, sizeof(reg)); 1517a8d25c0SNathan Whitehorn if (reg == -1) 1527a8d25c0SNathan Whitehorn return (ENXIO); 153145341e9SNathan Whitehorn sc->vtermid = reg; 1547a8d25c0SNathan Whitehorn sc->node = node; 1557a8d25c0SNathan Whitehorn 1567a8d25c0SNathan Whitehorn if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0) 1577a8d25c0SNathan Whitehorn return (ENXIO); 1587a8d25c0SNathan Whitehorn if (strcmp(buf, "hvterm1") == 0) { 1597a8d25c0SNathan Whitehorn sc->protocol = HVTERM1; 1607a8d25c0SNathan Whitehorn return (0); 1617a8d25c0SNathan Whitehorn } else if (strcmp(buf, "hvterm-protocol") == 0) { 1627a8d25c0SNathan Whitehorn sc->protocol = HVTERMPROT; 1637a8d25c0SNathan Whitehorn return (0); 1647a8d25c0SNathan Whitehorn } 1657a8d25c0SNathan Whitehorn 1667a8d25c0SNathan Whitehorn return (ENXIO); 1677a8d25c0SNathan Whitehorn } 1687a8d25c0SNathan Whitehorn 1697a8d25c0SNathan Whitehorn static int 1707a8d25c0SNathan Whitehorn uart_phyp_probe(device_t dev) 1717a8d25c0SNathan Whitehorn { 1727a8d25c0SNathan Whitehorn const char *name; 1737a8d25c0SNathan Whitehorn struct uart_phyp_softc sc; 1747a8d25c0SNathan Whitehorn int err; 1757a8d25c0SNathan Whitehorn 1767a8d25c0SNathan Whitehorn name = ofw_bus_get_name(dev); 1777a8d25c0SNathan Whitehorn if (name == NULL || strcmp(name, "vty") != 0) 1787a8d25c0SNathan Whitehorn return (ENXIO); 1797a8d25c0SNathan Whitehorn 1807a8d25c0SNathan Whitehorn sc.node = ofw_bus_get_node(dev); 1817a8d25c0SNathan Whitehorn err = uart_phyp_probe_node(&sc); 1827a8d25c0SNathan Whitehorn if (err != 0) 1837a8d25c0SNathan Whitehorn return (err); 1847a8d25c0SNathan Whitehorn 1857a8d25c0SNathan Whitehorn device_set_desc(dev, "POWER Hypervisor Virtual Serial Port"); 1867a8d25c0SNathan Whitehorn 1877a8d25c0SNathan Whitehorn return (err); 1887a8d25c0SNathan Whitehorn } 1897a8d25c0SNathan Whitehorn 1907a8d25c0SNathan Whitehorn static void 1917a8d25c0SNathan Whitehorn uart_phyp_cnprobe(struct consdev *cp) 1927a8d25c0SNathan Whitehorn { 1937a8d25c0SNathan Whitehorn char buf[64]; 1947a8d25c0SNathan Whitehorn ihandle_t stdout; 1957a8d25c0SNathan Whitehorn phandle_t input, opts, chosen; 1967a8d25c0SNathan Whitehorn static struct uart_phyp_softc sc; 1977a8d25c0SNathan Whitehorn 1987a8d25c0SNathan Whitehorn if ((opts = OF_finddevice("/options")) == -1) 1997a8d25c0SNathan Whitehorn goto fail; 2007a8d25c0SNathan Whitehorn if ((chosen = OF_finddevice("/chosen")) == -1) 2017a8d25c0SNathan Whitehorn goto fail; 2027a8d25c0SNathan Whitehorn 2037a8d25c0SNathan Whitehorn /* Check if OF has an active stdin/stdout */ 2047a8d25c0SNathan Whitehorn input = -1; 2057a8d25c0SNathan Whitehorn if (OF_getprop(chosen, "stdout", &stdout, 2067a8d25c0SNathan Whitehorn sizeof(stdout)) == sizeof(stdout) && stdout != 0) 2077a8d25c0SNathan Whitehorn input = OF_instance_to_package(stdout); 2087a8d25c0SNathan Whitehorn if (input == -1) 2097a8d25c0SNathan Whitehorn goto fail; 2107a8d25c0SNathan Whitehorn 2117a8d25c0SNathan Whitehorn if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) 2127a8d25c0SNathan Whitehorn goto fail; 2137a8d25c0SNathan Whitehorn if (strcmp(buf, "serial") != 0) 2147a8d25c0SNathan Whitehorn goto fail; 2157a8d25c0SNathan Whitehorn 2167a8d25c0SNathan Whitehorn sc.node = input; 2177a8d25c0SNathan Whitehorn if (uart_phyp_probe_node(&sc) != 0) 2187a8d25c0SNathan Whitehorn goto fail; 2197a8d25c0SNathan Whitehorn mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET | 2207a8d25c0SNathan Whitehorn MTX_NOWITNESS); 2217a8d25c0SNathan Whitehorn 2227a8d25c0SNathan Whitehorn cp->cn_pri = CN_NORMAL; 2237a8d25c0SNathan Whitehorn console_sc = ≻ 2247a8d25c0SNathan Whitehorn return; 2257a8d25c0SNathan Whitehorn 2267a8d25c0SNathan Whitehorn fail: 2277a8d25c0SNathan Whitehorn cp->cn_pri = CN_DEAD; 2287a8d25c0SNathan Whitehorn return; 2297a8d25c0SNathan Whitehorn } 2307a8d25c0SNathan Whitehorn 2317a8d25c0SNathan Whitehorn static int 2327a8d25c0SNathan Whitehorn uart_phyp_attach(device_t dev) 2337a8d25c0SNathan Whitehorn { 2347a8d25c0SNathan Whitehorn struct uart_phyp_softc *sc; 2357a8d25c0SNathan Whitehorn int unit; 2367a8d25c0SNathan Whitehorn 2377a8d25c0SNathan Whitehorn sc = device_get_softc(dev); 2387a8d25c0SNathan Whitehorn sc->dev = dev; 2397a8d25c0SNathan Whitehorn sc->node = ofw_bus_get_node(dev); 2407a8d25c0SNathan Whitehorn uart_phyp_probe_node(sc); 2417a8d25c0SNathan Whitehorn 2427a8d25c0SNathan Whitehorn unit = device_get_unit(dev); 2437a8d25c0SNathan Whitehorn sc->tp = tty_alloc(&uart_phyp_tty_class, sc); 2447a8d25c0SNathan Whitehorn mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, 2457a8d25c0SNathan Whitehorn MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); 2467a8d25c0SNathan Whitehorn 2477a8d25c0SNathan Whitehorn if (console_sc != NULL && console_sc->vtermid == sc->vtermid) { 2487a8d25c0SNathan Whitehorn sc->outseqno = console_sc->outseqno; 2497a8d25c0SNathan Whitehorn console_sc = sc; 2507a8d25c0SNathan Whitehorn sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit); 2517a8d25c0SNathan Whitehorn tty_init_console(sc->tp, 0); 2527a8d25c0SNathan Whitehorn } 2537a8d25c0SNathan Whitehorn 2547a8d25c0SNathan Whitehorn sc->irqrid = 0; 2557a8d25c0SNathan Whitehorn sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, 2567a8d25c0SNathan Whitehorn RF_ACTIVE | RF_SHAREABLE); 2577a8d25c0SNathan Whitehorn if (sc->irqres != NULL) { 2587a8d25c0SNathan Whitehorn bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE, 2597a8d25c0SNathan Whitehorn NULL, uart_phyp_intr, sc, &sc->sc_icookie); 2607a8d25c0SNathan Whitehorn } else { 2617a8d25c0SNathan Whitehorn callout_init(&sc->callout, CALLOUT_MPSAFE); 2627a8d25c0SNathan Whitehorn sc->polltime = hz / 20; 2637a8d25c0SNathan Whitehorn if (sc->polltime < 1) 2647a8d25c0SNathan Whitehorn sc->polltime = 1; 2657a8d25c0SNathan Whitehorn callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc); 2667a8d25c0SNathan Whitehorn } 2677a8d25c0SNathan Whitehorn 2687a8d25c0SNathan Whitehorn tty_makedev(sc->tp, NULL, "u%r", unit); 2697a8d25c0SNathan Whitehorn 2707a8d25c0SNathan Whitehorn return (0); 2717a8d25c0SNathan Whitehorn } 2727a8d25c0SNathan Whitehorn 2737a8d25c0SNathan Whitehorn static void 2747a8d25c0SNathan Whitehorn uart_phyp_cninit(struct consdev *cp) 2757a8d25c0SNathan Whitehorn { 2767a8d25c0SNathan Whitehorn 2777a8d25c0SNathan Whitehorn strcpy(cp->cn_name, "phypcons"); 2787a8d25c0SNathan Whitehorn } 2797a8d25c0SNathan Whitehorn 2807a8d25c0SNathan Whitehorn static void 2817a8d25c0SNathan Whitehorn uart_phyp_cnterm(struct consdev *cp) 2827a8d25c0SNathan Whitehorn { 2837a8d25c0SNathan Whitehorn } 2847a8d25c0SNathan Whitehorn 2857a8d25c0SNathan Whitehorn static int 2867a8d25c0SNathan Whitehorn uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) 2877a8d25c0SNathan Whitehorn { 2887a8d25c0SNathan Whitehorn int err; 289*90653c1cSAndreas Tobler int hdr = 0; 2907a8d25c0SNathan Whitehorn 2917a8d25c0SNathan Whitehorn uart_lock(&sc->sc_mtx); 2927a8d25c0SNathan Whitehorn if (sc->inbuflen == 0) { 2937a8d25c0SNathan Whitehorn err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid, 2947a8d25c0SNathan Whitehorn 0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0], 2957a8d25c0SNathan Whitehorn &sc->phyp_inbuf.u64[1]); 2967a8d25c0SNathan Whitehorn if (err != H_SUCCESS) { 2977a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 2987a8d25c0SNathan Whitehorn return (-1); 2997a8d25c0SNathan Whitehorn } 300*90653c1cSAndreas Tobler hdr = 1; 3017a8d25c0SNathan Whitehorn } 3027a8d25c0SNathan Whitehorn 3037a8d25c0SNathan Whitehorn if (sc->inbuflen == 0) { 3047a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 3057a8d25c0SNathan Whitehorn return (0); 3067a8d25c0SNathan Whitehorn } 3077a8d25c0SNathan Whitehorn 3087a8d25c0SNathan Whitehorn if (bufsize > sc->inbuflen) 3097a8d25c0SNathan Whitehorn bufsize = sc->inbuflen; 310*90653c1cSAndreas Tobler 311*90653c1cSAndreas Tobler if ((sc->protocol == HVTERMPROT) && (hdr == 1)) { 312*90653c1cSAndreas Tobler sc->inbuflen = sc->inbuflen - 4; 313*90653c1cSAndreas Tobler /* The VTERM protocol has a 4 byte header, skip it here. */ 314*90653c1cSAndreas Tobler memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4], 315*90653c1cSAndreas Tobler sc->inbuflen); 316*90653c1cSAndreas Tobler } 317*90653c1cSAndreas Tobler 3187a8d25c0SNathan Whitehorn memcpy(buffer, sc->phyp_inbuf.str, bufsize); 3197a8d25c0SNathan Whitehorn sc->inbuflen -= bufsize; 3207a8d25c0SNathan Whitehorn if (sc->inbuflen > 0) 3217a8d25c0SNathan Whitehorn memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize], 3227a8d25c0SNathan Whitehorn sc->inbuflen); 3237a8d25c0SNathan Whitehorn 3247a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 3257a8d25c0SNathan Whitehorn return (bufsize); 3267a8d25c0SNathan Whitehorn } 3277a8d25c0SNathan Whitehorn 3287a8d25c0SNathan Whitehorn static int 3297a8d25c0SNathan Whitehorn uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) 3307a8d25c0SNathan Whitehorn { 3317a8d25c0SNathan Whitehorn uint16_t seqno; 3327a8d25c0SNathan Whitehorn uint64_t len = 0; 333*90653c1cSAndreas Tobler int err; 334*90653c1cSAndreas Tobler 3357a8d25c0SNathan Whitehorn union { 336*90653c1cSAndreas Tobler uint64_t u64[2]; 337*90653c1cSAndreas Tobler char bytes[16]; 3387a8d25c0SNathan Whitehorn } cbuf; 3397a8d25c0SNathan Whitehorn 3407a8d25c0SNathan Whitehorn uart_lock(&sc->sc_mtx); 3417a8d25c0SNathan Whitehorn switch (sc->protocol) { 3427a8d25c0SNathan Whitehorn case HVTERM1: 343*90653c1cSAndreas Tobler if (bufsize > 16) 344*90653c1cSAndreas Tobler bufsize = 16; 3457a8d25c0SNathan Whitehorn memcpy(&cbuf, buffer, bufsize); 3467a8d25c0SNathan Whitehorn len = bufsize; 3477a8d25c0SNathan Whitehorn break; 3487a8d25c0SNathan Whitehorn case HVTERMPROT: 349*90653c1cSAndreas Tobler if (bufsize > 12) 350*90653c1cSAndreas Tobler bufsize = 12; 3517a8d25c0SNathan Whitehorn seqno = sc->outseqno++; 3527a8d25c0SNathan Whitehorn cbuf.bytes[0] = VS_DATA_PACKET_HEADER; 353*90653c1cSAndreas Tobler cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */ 3547a8d25c0SNathan Whitehorn cbuf.bytes[2] = (seqno >> 8) & 0xff; 3557a8d25c0SNathan Whitehorn cbuf.bytes[3] = seqno & 0xff; 3567a8d25c0SNathan Whitehorn memcpy(&cbuf.bytes[4], buffer, bufsize); 3577a8d25c0SNathan Whitehorn len = 4 + bufsize; 3587a8d25c0SNathan Whitehorn break; 3597a8d25c0SNathan Whitehorn } 360*90653c1cSAndreas Tobler 361*90653c1cSAndreas Tobler do { 362*90653c1cSAndreas Tobler err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64[0], 363*90653c1cSAndreas Tobler cbuf.u64[1]); 364*90653c1cSAndreas Tobler DELAY(100); 365*90653c1cSAndreas Tobler } while (err == H_BUSY); 366*90653c1cSAndreas Tobler 3677a8d25c0SNathan Whitehorn uart_unlock(&sc->sc_mtx); 3687a8d25c0SNathan Whitehorn 3697a8d25c0SNathan Whitehorn return (bufsize); 3707a8d25c0SNathan Whitehorn } 3717a8d25c0SNathan Whitehorn 3727a8d25c0SNathan Whitehorn static int 3737a8d25c0SNathan Whitehorn uart_phyp_cngetc(struct consdev *cp) 3747a8d25c0SNathan Whitehorn { 3757a8d25c0SNathan Whitehorn unsigned char c; 3767a8d25c0SNathan Whitehorn int retval; 3777a8d25c0SNathan Whitehorn 3787a8d25c0SNathan Whitehorn retval = uart_phyp_get(console_sc, &c, 1); 3797a8d25c0SNathan Whitehorn if (retval != 1) 3807a8d25c0SNathan Whitehorn return (-1); 3817a8d25c0SNathan Whitehorn #if defined(KDB) 3827a8d25c0SNathan Whitehorn kdb_alt_break(c, &alt_break_state); 3837a8d25c0SNathan Whitehorn #endif 3847a8d25c0SNathan Whitehorn 3857a8d25c0SNathan Whitehorn return (c); 3867a8d25c0SNathan Whitehorn } 3877a8d25c0SNathan Whitehorn 3887a8d25c0SNathan Whitehorn static void 3897a8d25c0SNathan Whitehorn uart_phyp_cnputc(struct consdev *cp, int c) 3907a8d25c0SNathan Whitehorn { 3917a8d25c0SNathan Whitehorn unsigned char ch = c; 3927a8d25c0SNathan Whitehorn uart_phyp_put(console_sc, &ch, 1); 3937a8d25c0SNathan Whitehorn } 3947a8d25c0SNathan Whitehorn 3957a8d25c0SNathan Whitehorn static void 3967a8d25c0SNathan Whitehorn uart_phyp_cngrab(struct consdev *cp) 3977a8d25c0SNathan Whitehorn { 3987a8d25c0SNathan Whitehorn } 3997a8d25c0SNathan Whitehorn 4007a8d25c0SNathan Whitehorn static void 4017a8d25c0SNathan Whitehorn uart_phyp_cnungrab(struct consdev *cp) 4027a8d25c0SNathan Whitehorn { 4037a8d25c0SNathan Whitehorn } 4047a8d25c0SNathan Whitehorn 4057a8d25c0SNathan Whitehorn static void 4067a8d25c0SNathan Whitehorn uart_phyp_ttyoutwakeup(struct tty *tp) 4077a8d25c0SNathan Whitehorn { 4087a8d25c0SNathan Whitehorn struct uart_phyp_softc *sc; 4097a8d25c0SNathan Whitehorn char buffer[8]; 4107a8d25c0SNathan Whitehorn int len; 4117a8d25c0SNathan Whitehorn 4127a8d25c0SNathan Whitehorn sc = tty_softc(tp); 4137a8d25c0SNathan Whitehorn 4147a8d25c0SNathan Whitehorn while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0) 4157a8d25c0SNathan Whitehorn uart_phyp_put(sc, buffer, len); 4167a8d25c0SNathan Whitehorn } 4177a8d25c0SNathan Whitehorn 4187a8d25c0SNathan Whitehorn static void 4197a8d25c0SNathan Whitehorn uart_phyp_intr(void *v) 4207a8d25c0SNathan Whitehorn { 4217a8d25c0SNathan Whitehorn struct uart_phyp_softc *sc = v; 4227a8d25c0SNathan Whitehorn struct tty *tp = sc->tp; 4237a8d25c0SNathan Whitehorn unsigned char c; 4247a8d25c0SNathan Whitehorn int len; 4257a8d25c0SNathan Whitehorn 4267a8d25c0SNathan Whitehorn tty_lock(tp); 4277a8d25c0SNathan Whitehorn while ((len = uart_phyp_get(sc, &c, 1)) > 0) 4287a8d25c0SNathan Whitehorn ttydisc_rint(tp, c, 0); 4297a8d25c0SNathan Whitehorn ttydisc_rint_done(tp); 4307a8d25c0SNathan Whitehorn tty_unlock(tp); 4317a8d25c0SNathan Whitehorn 4327a8d25c0SNathan Whitehorn if (sc->irqres == NULL) 4337a8d25c0SNathan Whitehorn callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc); 4347a8d25c0SNathan Whitehorn } 4357a8d25c0SNathan Whitehorn 436