1255643Snwhitehorn/*-
2255643Snwhitehorn * Copyright (C) 2011 by Nathan Whitehorn. All rights reserved.
3255643Snwhitehorn *
4255643Snwhitehorn * Redistribution and use in source and binary forms, with or without
5255643Snwhitehorn * modification, are permitted provided that the following conditions
6255643Snwhitehorn * are met:
7255643Snwhitehorn * 1. Redistributions of source code must retain the above copyright
8255643Snwhitehorn *    notice, this list of conditions and the following disclaimer.
9255643Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
10255643Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
11255643Snwhitehorn *    documentation and/or other materials provided with the distribution.
12255643Snwhitehorn *
13255643Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14255643Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15255643Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16255643Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17255643Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
18255643Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
19255643Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20255643Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
21255643Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22255643Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23255643Snwhitehorn */
24255643Snwhitehorn
25255643Snwhitehorn#include <sys/cdefs.h>
26255643Snwhitehorn__FBSDID("$FreeBSD: releng/10.3/sys/powerpc/pseries/phyp_console.c 266019 2014-05-14 14:08:45Z ian $");
27255643Snwhitehorn
28255643Snwhitehorn#include <sys/param.h>
29255643Snwhitehorn#include <sys/kdb.h>
30255643Snwhitehorn#include <sys/kernel.h>
31255643Snwhitehorn#include <sys/priv.h>
32255643Snwhitehorn#include <sys/systm.h>
33255643Snwhitehorn#include <sys/module.h>
34255643Snwhitehorn#include <sys/types.h>
35255643Snwhitehorn#include <sys/conf.h>
36255643Snwhitehorn#include <sys/cons.h>
37255643Snwhitehorn#include <sys/tty.h>
38255643Snwhitehorn#include <machine/bus.h>
39255643Snwhitehorn
40255643Snwhitehorn#include <dev/ofw/openfirm.h>
41255643Snwhitehorn#include <dev/ofw/ofw_bus.h>
42255643Snwhitehorn#include <dev/ofw/ofw_bus_subr.h>
43255643Snwhitehorn#include <dev/uart/uart.h>
44255643Snwhitehorn#include <dev/uart/uart_cpu.h>
45255643Snwhitehorn#include <dev/uart/uart_bus.h>
46255643Snwhitehorn
47255643Snwhitehorn#include "phyp-hvcall.h"
48255643Snwhitehorn#include "uart_if.h"
49255643Snwhitehorn
50255643Snwhitehornstruct uart_phyp_softc {
51255643Snwhitehorn	device_t dev;
52255643Snwhitehorn	phandle_t node;
53255643Snwhitehorn	int vtermid;
54255643Snwhitehorn
55255643Snwhitehorn	struct tty *tp;
56255643Snwhitehorn	struct resource *irqres;
57255643Snwhitehorn	int irqrid;
58255643Snwhitehorn	struct callout callout;
59255643Snwhitehorn	void *sc_icookie;
60255643Snwhitehorn	int polltime;
61255643Snwhitehorn
62255643Snwhitehorn	struct mtx sc_mtx;
63255643Snwhitehorn	int protocol;
64255643Snwhitehorn
65255643Snwhitehorn	union {
66255643Snwhitehorn		uint64_t u64[2];
67255643Snwhitehorn		char str[16];
68255643Snwhitehorn	} phyp_inbuf;
69255643Snwhitehorn	uint64_t inbuflen;
70255643Snwhitehorn	uint8_t outseqno;
71255643Snwhitehorn};
72255643Snwhitehorn
73255643Snwhitehornstatic struct uart_phyp_softc	*console_sc = NULL;
74255643Snwhitehorn#if defined(KDB)
75255643Snwhitehornstatic int			alt_break_state;
76255643Snwhitehorn#endif
77255643Snwhitehorn
78255643Snwhitehornenum {
79255643Snwhitehorn	HVTERM1, HVTERMPROT
80255643Snwhitehorn};
81255643Snwhitehorn
82255643Snwhitehorn#define VS_DATA_PACKET_HEADER		0xff
83255643Snwhitehorn#define VS_CONTROL_PACKET_HEADER	0xfe
84255643Snwhitehorn#define  VSV_SET_MODEM_CTL		0x01
85255643Snwhitehorn#define  VSV_MODEM_CTL_UPDATE		0x02
86255643Snwhitehorn#define  VSV_RENEGOTIATE_CONNECTION	0x03
87255643Snwhitehorn#define VS_QUERY_PACKET_HEADER		0xfd
88255643Snwhitehorn#define  VSV_SEND_VERSION_NUMBER	0x01
89255643Snwhitehorn#define  VSV_SEND_MODEM_CTL_STATUS	0x02
90255643Snwhitehorn#define VS_QUERY_RESPONSE_PACKET_HEADER	0xfc
91255643Snwhitehorn
92255643Snwhitehornstatic int uart_phyp_probe(device_t dev);
93255643Snwhitehornstatic int uart_phyp_attach(device_t dev);
94255643Snwhitehornstatic void uart_phyp_intr(void *v);
95255643Snwhitehorn
96255643Snwhitehornstatic device_method_t uart_phyp_methods[] = {
97255643Snwhitehorn	/* Device interface */
98255643Snwhitehorn	DEVMETHOD(device_probe,		uart_phyp_probe),
99255643Snwhitehorn	DEVMETHOD(device_attach,	uart_phyp_attach),
100255643Snwhitehorn
101255643Snwhitehorn	DEVMETHOD_END
102255643Snwhitehorn};
103255643Snwhitehorn
104255643Snwhitehornstatic driver_t uart_phyp_driver = {
105255643Snwhitehorn	"uart",
106255643Snwhitehorn	uart_phyp_methods,
107255643Snwhitehorn	sizeof(struct uart_phyp_softc),
108255643Snwhitehorn};
109255643Snwhitehorn
110255643SnwhitehornDRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0);
111255643Snwhitehorn
112255643Snwhitehornstatic cn_probe_t uart_phyp_cnprobe;
113255643Snwhitehornstatic cn_init_t uart_phyp_cninit;
114255643Snwhitehornstatic cn_term_t uart_phyp_cnterm;
115255643Snwhitehornstatic cn_getc_t uart_phyp_cngetc;
116255643Snwhitehornstatic cn_putc_t uart_phyp_cnputc;
117255643Snwhitehornstatic cn_grab_t uart_phyp_cngrab;
118255643Snwhitehornstatic cn_ungrab_t uart_phyp_cnungrab;
119255643Snwhitehorn
120255643SnwhitehornCONSOLE_DRIVER(uart_phyp);
121255643Snwhitehorn
122255643Snwhitehornstatic void uart_phyp_ttyoutwakeup(struct tty *tp);
123255643Snwhitehorn
124255643Snwhitehornstatic struct ttydevsw uart_phyp_tty_class = {
125255643Snwhitehorn	.tsw_flags	= TF_INITLOCK|TF_CALLOUT,
126255643Snwhitehorn	.tsw_outwakeup	= uart_phyp_ttyoutwakeup,
127255643Snwhitehorn};
128255643Snwhitehorn
129255643Snwhitehornstatic int
130255643Snwhitehornuart_phyp_probe_node(struct uart_phyp_softc *sc)
131255643Snwhitehorn{
132255643Snwhitehorn	phandle_t node = sc->node;
133255643Snwhitehorn	uint32_t reg;
134255643Snwhitehorn	char buf[64];
135255643Snwhitehorn
136255643Snwhitehorn	sc->inbuflen = 0;
137255643Snwhitehorn	sc->outseqno = 0;
138255643Snwhitehorn
139255643Snwhitehorn	if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0)
140255643Snwhitehorn		return (ENXIO);
141255643Snwhitehorn	if (strcmp(buf, "vty") != 0)
142255643Snwhitehorn		return (ENXIO);
143255643Snwhitehorn
144255643Snwhitehorn	if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0)
145255643Snwhitehorn		return (ENXIO);
146255643Snwhitehorn	if (strcmp(buf, "serial") != 0)
147255643Snwhitehorn		return (ENXIO);
148255643Snwhitehorn
149255643Snwhitehorn	reg = -1;
150255643Snwhitehorn	OF_getprop(node, "reg", &reg, sizeof(reg));
151255643Snwhitehorn	if (reg == -1)
152255643Snwhitehorn		return (ENXIO);
153255895Snwhitehorn	sc->vtermid = reg;
154255643Snwhitehorn	sc->node = node;
155255643Snwhitehorn
156255643Snwhitehorn	if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0)
157255643Snwhitehorn		return (ENXIO);
158255643Snwhitehorn	if (strcmp(buf, "hvterm1") == 0) {
159255643Snwhitehorn		sc->protocol = HVTERM1;
160255643Snwhitehorn		return (0);
161255643Snwhitehorn	} else if (strcmp(buf, "hvterm-protocol") == 0) {
162255643Snwhitehorn		sc->protocol = HVTERMPROT;
163255643Snwhitehorn		return (0);
164255643Snwhitehorn	}
165255643Snwhitehorn
166255643Snwhitehorn	return (ENXIO);
167255643Snwhitehorn}
168255643Snwhitehorn
169255643Snwhitehornstatic int
170255643Snwhitehornuart_phyp_probe(device_t dev)
171255643Snwhitehorn{
172255643Snwhitehorn	const char *name;
173255643Snwhitehorn	struct uart_phyp_softc sc;
174255643Snwhitehorn	int err;
175255643Snwhitehorn
176255643Snwhitehorn	name = ofw_bus_get_name(dev);
177255643Snwhitehorn	if (name == NULL || strcmp(name, "vty") != 0)
178255643Snwhitehorn		return (ENXIO);
179255643Snwhitehorn
180255643Snwhitehorn	sc.node = ofw_bus_get_node(dev);
181255643Snwhitehorn	err = uart_phyp_probe_node(&sc);
182255643Snwhitehorn	if (err != 0)
183255643Snwhitehorn		return (err);
184255643Snwhitehorn
185255643Snwhitehorn	device_set_desc(dev, "POWER Hypervisor Virtual Serial Port");
186255643Snwhitehorn
187255643Snwhitehorn	return (err);
188255643Snwhitehorn}
189255643Snwhitehorn
190255643Snwhitehornstatic void
191255643Snwhitehornuart_phyp_cnprobe(struct consdev *cp)
192255643Snwhitehorn{
193255643Snwhitehorn	char buf[64];
194255643Snwhitehorn	ihandle_t stdout;
195266019Sian	phandle_t input, chosen;
196255643Snwhitehorn	static struct uart_phyp_softc sc;
197255643Snwhitehorn
198255643Snwhitehorn	if ((chosen = OF_finddevice("/chosen")) == -1)
199255643Snwhitehorn		goto fail;
200255643Snwhitehorn
201255643Snwhitehorn	/* Check if OF has an active stdin/stdout */
202255643Snwhitehorn	input = -1;
203255643Snwhitehorn	if (OF_getprop(chosen, "stdout", &stdout,
204255643Snwhitehorn	    sizeof(stdout)) == sizeof(stdout) && stdout != 0)
205255643Snwhitehorn		input = OF_instance_to_package(stdout);
206255643Snwhitehorn	if (input == -1)
207255643Snwhitehorn		goto fail;
208255643Snwhitehorn
209255643Snwhitehorn	if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1)
210255643Snwhitehorn		goto fail;
211255643Snwhitehorn	if (strcmp(buf, "serial") != 0)
212255643Snwhitehorn		goto fail;
213255643Snwhitehorn
214255643Snwhitehorn	sc.node = input;
215255643Snwhitehorn	if (uart_phyp_probe_node(&sc) != 0)
216255643Snwhitehorn		goto fail;
217255643Snwhitehorn	mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET |
218255643Snwhitehorn	    MTX_NOWITNESS);
219255643Snwhitehorn
220255643Snwhitehorn	cp->cn_pri = CN_NORMAL;
221255643Snwhitehorn	console_sc = &sc;
222255643Snwhitehorn	return;
223255643Snwhitehorn
224255643Snwhitehornfail:
225255643Snwhitehorn	cp->cn_pri = CN_DEAD;
226255643Snwhitehorn	return;
227255643Snwhitehorn}
228255643Snwhitehorn
229255643Snwhitehornstatic int
230255643Snwhitehornuart_phyp_attach(device_t dev)
231255643Snwhitehorn{
232255643Snwhitehorn	struct uart_phyp_softc *sc;
233255643Snwhitehorn	int unit;
234255643Snwhitehorn
235255643Snwhitehorn	sc = device_get_softc(dev);
236255643Snwhitehorn	sc->dev = dev;
237255643Snwhitehorn	sc->node = ofw_bus_get_node(dev);
238255643Snwhitehorn	uart_phyp_probe_node(sc);
239255643Snwhitehorn
240255643Snwhitehorn	unit = device_get_unit(dev);
241255643Snwhitehorn	sc->tp = tty_alloc(&uart_phyp_tty_class, sc);
242255643Snwhitehorn	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL,
243255643Snwhitehorn	    MTX_SPIN | MTX_QUIET | MTX_NOWITNESS);
244255643Snwhitehorn
245255643Snwhitehorn	if (console_sc != NULL && console_sc->vtermid == sc->vtermid) {
246255643Snwhitehorn		sc->outseqno = console_sc->outseqno;
247255643Snwhitehorn		console_sc = sc;
248255643Snwhitehorn		sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit);
249255643Snwhitehorn		tty_init_console(sc->tp, 0);
250255643Snwhitehorn	}
251255643Snwhitehorn
252255643Snwhitehorn	sc->irqrid = 0;
253255643Snwhitehorn	sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid,
254255643Snwhitehorn	    RF_ACTIVE | RF_SHAREABLE);
255255643Snwhitehorn	if (sc->irqres != NULL) {
256255643Snwhitehorn		bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE,
257255643Snwhitehorn		    NULL, uart_phyp_intr, sc, &sc->sc_icookie);
258255643Snwhitehorn	} else {
259255643Snwhitehorn		callout_init(&sc->callout, CALLOUT_MPSAFE);
260255643Snwhitehorn		sc->polltime = hz / 20;
261255643Snwhitehorn		if (sc->polltime < 1)
262255643Snwhitehorn			sc->polltime = 1;
263255643Snwhitehorn		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
264255643Snwhitehorn	}
265255643Snwhitehorn
266255643Snwhitehorn	tty_makedev(sc->tp, NULL, "u%r", unit);
267255643Snwhitehorn
268255643Snwhitehorn	return (0);
269255643Snwhitehorn}
270255643Snwhitehorn
271255643Snwhitehornstatic void
272255643Snwhitehornuart_phyp_cninit(struct consdev *cp)
273255643Snwhitehorn{
274255643Snwhitehorn
275255643Snwhitehorn	strcpy(cp->cn_name, "phypcons");
276255643Snwhitehorn}
277255643Snwhitehorn
278255643Snwhitehornstatic void
279255643Snwhitehornuart_phyp_cnterm(struct consdev *cp)
280255643Snwhitehorn{
281255643Snwhitehorn}
282255643Snwhitehorn
283255643Snwhitehornstatic int
284255643Snwhitehornuart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
285255643Snwhitehorn{
286255643Snwhitehorn	int err;
287259230Sandreast	int hdr = 0;
288255643Snwhitehorn
289255643Snwhitehorn	uart_lock(&sc->sc_mtx);
290255643Snwhitehorn	if (sc->inbuflen == 0) {
291255643Snwhitehorn		err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid,
292255643Snwhitehorn		    0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0],
293255643Snwhitehorn		    &sc->phyp_inbuf.u64[1]);
294255643Snwhitehorn		if (err != H_SUCCESS) {
295255643Snwhitehorn			uart_unlock(&sc->sc_mtx);
296255643Snwhitehorn			return (-1);
297255643Snwhitehorn		}
298259230Sandreast		hdr = 1;
299255643Snwhitehorn	}
300255643Snwhitehorn
301255643Snwhitehorn	if (sc->inbuflen == 0) {
302255643Snwhitehorn		uart_unlock(&sc->sc_mtx);
303255643Snwhitehorn		return (0);
304255643Snwhitehorn	}
305255643Snwhitehorn
306255643Snwhitehorn	if (bufsize > sc->inbuflen)
307255643Snwhitehorn		bufsize = sc->inbuflen;
308259230Sandreast
309259230Sandreast	if ((sc->protocol == HVTERMPROT) && (hdr == 1)) {
310259230Sandreast		sc->inbuflen = sc->inbuflen - 4;
311259230Sandreast		/* The VTERM protocol has a 4 byte header, skip it here. */
312259230Sandreast		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4],
313259230Sandreast		    sc->inbuflen);
314259230Sandreast	}
315259230Sandreast
316255643Snwhitehorn	memcpy(buffer, sc->phyp_inbuf.str, bufsize);
317255643Snwhitehorn	sc->inbuflen -= bufsize;
318255643Snwhitehorn	if (sc->inbuflen > 0)
319255643Snwhitehorn		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize],
320255643Snwhitehorn		    sc->inbuflen);
321255643Snwhitehorn
322255643Snwhitehorn	uart_unlock(&sc->sc_mtx);
323255643Snwhitehorn	return (bufsize);
324255643Snwhitehorn}
325255643Snwhitehorn
326255643Snwhitehornstatic int
327255643Snwhitehornuart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
328255643Snwhitehorn{
329255643Snwhitehorn	uint16_t seqno;
330255643Snwhitehorn	uint64_t len = 0;
331259230Sandreast	int	err;
332259230Sandreast
333255643Snwhitehorn	union {
334259230Sandreast		uint64_t u64[2];
335259230Sandreast		char bytes[16];
336255643Snwhitehorn	} cbuf;
337255643Snwhitehorn
338255643Snwhitehorn	uart_lock(&sc->sc_mtx);
339255643Snwhitehorn	switch (sc->protocol) {
340255643Snwhitehorn	case HVTERM1:
341259230Sandreast		if (bufsize > 16)
342259230Sandreast			bufsize = 16;
343255643Snwhitehorn		memcpy(&cbuf, buffer, bufsize);
344255643Snwhitehorn		len = bufsize;
345255643Snwhitehorn		break;
346255643Snwhitehorn	case HVTERMPROT:
347259230Sandreast		if (bufsize > 12)
348259230Sandreast			bufsize = 12;
349255643Snwhitehorn		seqno = sc->outseqno++;
350255643Snwhitehorn		cbuf.bytes[0] = VS_DATA_PACKET_HEADER;
351259230Sandreast		cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */
352255643Snwhitehorn		cbuf.bytes[2] = (seqno >> 8) & 0xff;
353255643Snwhitehorn		cbuf.bytes[3] = seqno & 0xff;
354255643Snwhitehorn		memcpy(&cbuf.bytes[4], buffer, bufsize);
355255643Snwhitehorn		len = 4 + bufsize;
356255643Snwhitehorn		break;
357255643Snwhitehorn	}
358259230Sandreast
359259230Sandreast	do {
360259230Sandreast	    err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64[0],
361259230Sandreast			    cbuf.u64[1]);
362259230Sandreast		DELAY(100);
363259230Sandreast	} while (err == H_BUSY);
364259230Sandreast
365255643Snwhitehorn	uart_unlock(&sc->sc_mtx);
366255643Snwhitehorn
367255643Snwhitehorn	return (bufsize);
368255643Snwhitehorn}
369255643Snwhitehorn
370255643Snwhitehornstatic int
371255643Snwhitehornuart_phyp_cngetc(struct consdev *cp)
372255643Snwhitehorn{
373255643Snwhitehorn	unsigned char c;
374255643Snwhitehorn	int retval;
375255643Snwhitehorn
376255643Snwhitehorn	retval = uart_phyp_get(console_sc, &c, 1);
377255643Snwhitehorn	if (retval != 1)
378255643Snwhitehorn		return (-1);
379255643Snwhitehorn#if defined(KDB)
380255643Snwhitehorn	kdb_alt_break(c, &alt_break_state);
381255643Snwhitehorn#endif
382255643Snwhitehorn
383255643Snwhitehorn	return (c);
384255643Snwhitehorn}
385255643Snwhitehorn
386255643Snwhitehornstatic void
387255643Snwhitehornuart_phyp_cnputc(struct consdev *cp, int c)
388255643Snwhitehorn{
389255643Snwhitehorn	unsigned char ch = c;
390255643Snwhitehorn	uart_phyp_put(console_sc, &ch, 1);
391255643Snwhitehorn}
392255643Snwhitehorn
393255643Snwhitehornstatic void
394255643Snwhitehornuart_phyp_cngrab(struct consdev *cp)
395255643Snwhitehorn{
396255643Snwhitehorn}
397255643Snwhitehorn
398255643Snwhitehornstatic void
399255643Snwhitehornuart_phyp_cnungrab(struct consdev *cp)
400255643Snwhitehorn{
401255643Snwhitehorn}
402255643Snwhitehorn
403255643Snwhitehornstatic void
404255643Snwhitehornuart_phyp_ttyoutwakeup(struct tty *tp)
405255643Snwhitehorn{
406255643Snwhitehorn	struct uart_phyp_softc *sc;
407255643Snwhitehorn	char buffer[8];
408255643Snwhitehorn	int len;
409255643Snwhitehorn
410255643Snwhitehorn	sc = tty_softc(tp);
411255643Snwhitehorn
412255643Snwhitehorn	while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0)
413255643Snwhitehorn		uart_phyp_put(sc, buffer, len);
414255643Snwhitehorn}
415255643Snwhitehorn
416255643Snwhitehornstatic void
417255643Snwhitehornuart_phyp_intr(void *v)
418255643Snwhitehorn{
419255643Snwhitehorn	struct uart_phyp_softc *sc = v;
420255643Snwhitehorn	struct tty *tp = sc->tp;
421255643Snwhitehorn	unsigned char c;
422255643Snwhitehorn	int len;
423255643Snwhitehorn
424255643Snwhitehorn	tty_lock(tp);
425255643Snwhitehorn	while ((len = uart_phyp_get(sc, &c, 1)) > 0)
426255643Snwhitehorn		ttydisc_rint(tp, c, 0);
427255643Snwhitehorn	ttydisc_rint_done(tp);
428255643Snwhitehorn	tty_unlock(tp);
429255643Snwhitehorn
430255643Snwhitehorn	if (sc->irqres == NULL)
431255643Snwhitehorn		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
432255643Snwhitehorn}
433255643Snwhitehorn
434