xref: /freebsd/sys/powerpc/pseries/phyp_console.c (revision 7a8d25c037129dff84a10b804e27aa9f25454fce)
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", &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 = &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