1139749Simp/*-
2136467Ssimokawa * Copyright (C) 2003,2004
3136467Ssimokawa * 	Hidetoshi Shimokawa. All rights reserved.
4181905Sed *
5136467Ssimokawa * Redistribution and use in source and binary forms, with or without
6136467Ssimokawa * modification, are permitted provided that the following conditions
7136467Ssimokawa * are met:
8136467Ssimokawa * 1. Redistributions of source code must retain the above copyright
9136467Ssimokawa *    notice, this list of conditions and the following disclaimer.
10136467Ssimokawa * 2. Redistributions in binary form must reproduce the above copyright
11136467Ssimokawa *    notice, this list of conditions and the following disclaimer in the
12136467Ssimokawa *    documentation and/or other materials provided with the distribution.
13136467Ssimokawa * 3. All advertising materials mentioning features or use of this software
14136467Ssimokawa *    must display the following acknowledgement:
15136467Ssimokawa *
16136467Ssimokawa *	This product includes software developed by Hidetoshi Shimokawa.
17136467Ssimokawa *
18136467Ssimokawa * 4. Neither the name of the author nor the names of its contributors
19136467Ssimokawa *    may be used to endorse or promote products derived from this software
20136467Ssimokawa *    without specific prior written permission.
21181905Sed *
22136467Ssimokawa * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23136467Ssimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24136467Ssimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25136467Ssimokawa * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26136467Ssimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27136467Ssimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28136467Ssimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29136467Ssimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30136467Ssimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31136467Ssimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32136467Ssimokawa * SUCH DAMAGE.
33181905Sed *
34136467Ssimokawa * $FreeBSD$
35136467Ssimokawa */
36136467Ssimokawa
37136467Ssimokawa#include <sys/param.h>
38136467Ssimokawa#include <sys/kdb.h>
39136467Ssimokawa#include <gdb/gdb.h>
40136467Ssimokawa#include <sys/kernel.h>
41136467Ssimokawa#include <sys/module.h>
42136467Ssimokawa#include <sys/systm.h>
43136467Ssimokawa#include <sys/types.h>
44136467Ssimokawa#include <sys/conf.h>
45136467Ssimokawa#include <sys/cons.h>
46136467Ssimokawa#include <sys/consio.h>
47136467Ssimokawa#include <sys/tty.h>
48136467Ssimokawa#include <sys/malloc.h>
49164033Srwatson#include <sys/priv.h>
50136467Ssimokawa#include <sys/proc.h>
51136467Ssimokawa#include <sys/ucred.h>
52136467Ssimokawa
53136467Ssimokawa#include <machine/bus.h>
54136467Ssimokawa
55136467Ssimokawa#include <dev/dcons/dcons.h>
56136467Ssimokawa#include <dev/dcons/dcons_os.h>
57136467Ssimokawa
58136467Ssimokawa#include <ddb/ddb.h>
59136467Ssimokawa#include <sys/reboot.h>
60136467Ssimokawa
61136467Ssimokawa#include <sys/sysctl.h>
62136467Ssimokawa
63136467Ssimokawa#include <vm/vm.h>
64136467Ssimokawa#include <vm/vm_param.h>
65136467Ssimokawa#include <vm/pmap.h>
66136467Ssimokawa
67136467Ssimokawa#include "opt_dcons.h"
68170017Ssimokawa#include "opt_kdb.h"
69170017Ssimokawa#include "opt_gdb.h"
70170017Ssimokawa#include "opt_ddb.h"
71136467Ssimokawa
72170017Ssimokawa
73136467Ssimokawa#ifndef DCONS_POLL_HZ
74190771Sed#define DCONS_POLL_HZ	25
75136467Ssimokawa#endif
76136467Ssimokawa
77247005Smav#ifndef DCONS_POLL_IDLE
78247005Smav#define DCONS_POLL_IDLE	256
79247005Smav#endif
80247005Smav
81136467Ssimokawa#ifndef DCONS_BUF_SIZE
82136467Ssimokawa#define DCONS_BUF_SIZE (16*1024)
83136467Ssimokawa#endif
84136467Ssimokawa
85136467Ssimokawa#ifndef DCONS_FORCE_CONSOLE
86136467Ssimokawa#define DCONS_FORCE_CONSOLE	0	/* Mostly for FreeBSD-4/DragonFly */
87136467Ssimokawa#endif
88136467Ssimokawa
89136467Ssimokawa#ifndef KLD_MODULE
90136467Ssimokawastatic char bssbuf[DCONS_BUF_SIZE];	/* buf in bss */
91136467Ssimokawa#endif
92136467Ssimokawa
93136467Ssimokawa/* global data */
94136467Ssimokawastatic struct dcons_global dg;
95136467Ssimokawastruct dcons_global *dcons_conf;
96136467Ssimokawastatic int poll_hz = DCONS_POLL_HZ;
97247005Smavstatic u_int poll_idle = DCONS_POLL_HZ * DCONS_POLL_IDLE;
98136467Ssimokawa
99136467Ssimokawastatic struct dcons_softc sc[DCONS_NPORT];
100136467Ssimokawa
101227309Sedstatic SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console");
102136467SsimokawaSYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0,
103136467Ssimokawa				"dcons polling rate");
104136467Ssimokawa
105136467Ssimokawastatic int drv_init = 0;
106136467Ssimokawastatic struct callout dcons_callout;
107136467Ssimokawastruct dcons_buf *dcons_buf;		/* for local dconschat */
108136467Ssimokawa
109136467Ssimokawastatic void	dcons_timeout(void *);
110136467Ssimokawastatic int	dcons_drv_init(int);
111136467Ssimokawa
112136467Ssimokawastatic cn_probe_t	dcons_cnprobe;
113136467Ssimokawastatic cn_init_t	dcons_cninit;
114158959Sphkstatic cn_term_t	dcons_cnterm;
115136467Ssimokawastatic cn_getc_t	dcons_cngetc;
116136467Ssimokawastatic cn_putc_t	dcons_cnputc;
117228631Savgstatic cn_grab_t	dcons_cngrab;
118228631Savgstatic cn_ungrab_t	dcons_cnungrab;
119136467Ssimokawa
120158959SphkCONSOLE_DRIVER(dcons);
121136467Ssimokawa
122181905Sed#if defined(GDB)
123181905Sedstatic gdb_probe_f	dcons_dbg_probe;
124181905Sedstatic gdb_init_f	dcons_dbg_init;
125181905Sedstatic gdb_term_f	dcons_dbg_term;
126181905Sedstatic gdb_getc_f	dcons_dbg_getc;
127181905Sedstatic gdb_putc_f	dcons_dbg_putc;
128136467Ssimokawa
129136467SsimokawaGDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term,
130158950Sphk    dcons_dbg_getc, dcons_dbg_putc);
131136467Ssimokawa
132136467Ssimokawaextern struct gdb_dbgport *gdb_cur;
133136467Ssimokawa#endif
134136467Ssimokawa
135181905Sedstatic tsw_outwakeup_t dcons_outwakeup;
136181905Sed
137181905Sedstatic struct ttydevsw dcons_ttydevsw = {
138181905Sed	.tsw_flags      = TF_NOPREFIX,
139181905Sed	.tsw_outwakeup  = dcons_outwakeup,
140181905Sed};
141181905Sed
142225203Srwatson#if (defined(GDB) || defined(DDB))
143136467Ssimokawastatic int
144136467Ssimokawadcons_check_break(struct dcons_softc *dc, int c)
145136467Ssimokawa{
146181905Sed
147136467Ssimokawa	if (c < 0)
148136467Ssimokawa		return (c);
149136467Ssimokawa
150170017Ssimokawa#ifdef GDB
151225203Srwatson	if ((dc->flags & DC_GDB) != 0 && gdb_cur == &dcons_gdb_dbgport)
152225203Srwatson		kdb_alt_break_gdb(c, &dc->brk_state);
153225203Srwatson	else
154178766Speter#endif
155225203Srwatson		kdb_alt_break(c, &dc->brk_state);
156225203Srwatson
157136467Ssimokawa	return (c);
158136467Ssimokawa}
159136467Ssimokawa#else
160136467Ssimokawa#define	dcons_check_break(dc, c)	(c)
161136467Ssimokawa#endif
162136467Ssimokawa
163136467Ssimokawastatic int
164171867Ssimokawadcons_os_checkc_nopoll(struct dcons_softc *dc)
165136467Ssimokawa{
166136467Ssimokawa	int c;
167136467Ssimokawa
168136467Ssimokawa	if (dg.dma_tag != NULL)
169136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD);
170181905Sed
171136467Ssimokawa	c = dcons_check_break(dc, dcons_checkc(dc));
172136467Ssimokawa
173136467Ssimokawa	if (dg.dma_tag != NULL)
174136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREREAD);
175136467Ssimokawa
176136467Ssimokawa	return (c);
177136467Ssimokawa}
178136467Ssimokawa
179171867Ssimokawastatic int
180171867Ssimokawadcons_os_checkc(struct dcons_softc *dc)
181171867Ssimokawa{
182171867Ssimokawa	EVENTHANDLER_INVOKE(dcons_poll, 0);
183171867Ssimokawa	return (dcons_os_checkc_nopoll(dc));
184171867Ssimokawa}
185171867Ssimokawa
186136467Ssimokawastatic void
187136467Ssimokawadcons_os_putc(struct dcons_softc *dc, int c)
188136467Ssimokawa{
189136467Ssimokawa	if (dg.dma_tag != NULL)
190136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTWRITE);
191136467Ssimokawa
192136467Ssimokawa	dcons_putc(dc, c);
193136467Ssimokawa
194136467Ssimokawa	if (dg.dma_tag != NULL)
195136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE);
196136467Ssimokawa}
197136467Ssimokawa
198136467Ssimokawastatic void
199181905Seddcons_outwakeup(struct tty *tp)
200136467Ssimokawa{
201136467Ssimokawa	struct dcons_softc *dc;
202181905Sed	char ch;
203136467Ssimokawa
204181905Sed	dc = tty_softc(tp);
205136467Ssimokawa
206181905Sed	while (ttydisc_getc(tp, &ch, sizeof ch) != 0)
207181905Sed		dcons_os_putc(dc, ch);
208136467Ssimokawa}
209136467Ssimokawa
210136467Ssimokawastatic void
211136467Ssimokawadcons_timeout(void *v)
212136467Ssimokawa{
213136467Ssimokawa	struct	tty *tp;
214136467Ssimokawa	struct dcons_softc *dc;
215136467Ssimokawa	int i, c, polltime;
216136467Ssimokawa
217136467Ssimokawa	for (i = 0; i < DCONS_NPORT; i ++) {
218136467Ssimokawa		dc = &sc[i];
219181905Sed		tp = dc->tty;
220181905Sed
221181905Sed		tty_lock(tp);
222247005Smav		while ((c = dcons_os_checkc_nopoll(dc)) != -1) {
223181905Sed			ttydisc_rint(tp, c, 0);
224247005Smav			poll_idle = 0;
225247005Smav		}
226181905Sed		ttydisc_rint_done(tp);
227181905Sed		tty_unlock(tp);
228136467Ssimokawa	}
229247005Smav	poll_idle++;
230247005Smav	polltime = hz;
231247005Smav	if (poll_idle <= (poll_hz * DCONS_POLL_IDLE))
232247005Smav		polltime /= poll_hz;
233136467Ssimokawa	callout_reset(&dcons_callout, polltime, dcons_timeout, tp);
234136467Ssimokawa}
235136467Ssimokawa
236136467Ssimokawastatic void
237136467Ssimokawadcons_cnprobe(struct consdev *cp)
238136467Ssimokawa{
239136467Ssimokawa	sprintf(cp->cn_name, "dcons");
240136467Ssimokawa#if DCONS_FORCE_CONSOLE
241136467Ssimokawa	cp->cn_pri = CN_REMOTE;
242136467Ssimokawa#else
243136467Ssimokawa	cp->cn_pri = CN_NORMAL;
244136467Ssimokawa#endif
245136467Ssimokawa}
246136467Ssimokawa
247136467Ssimokawastatic void
248136467Ssimokawadcons_cninit(struct consdev *cp)
249136467Ssimokawa{
250136467Ssimokawa	dcons_drv_init(0);
251181905Sed	cp->cn_arg = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */
252136467Ssimokawa}
253136467Ssimokawa
254158959Sphkstatic void
255158959Sphkdcons_cnterm(struct consdev *cp)
256158959Sphk{
257158959Sphk}
258158959Sphk
259228631Savgstatic void
260228631Savgdcons_cngrab(struct consdev *cp)
261228631Savg{
262228631Savg}
263228631Savg
264228631Savgstatic void
265228631Savgdcons_cnungrab(struct consdev *cp)
266228631Savg{
267228631Savg}
268228631Savg
269136467Ssimokawastatic int
270136467Ssimokawadcons_cngetc(struct consdev *cp)
271136467Ssimokawa{
272136467Ssimokawa	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
273136467Ssimokawa	return (dcons_os_checkc(dc));
274136467Ssimokawa}
275181905Sed
276136467Ssimokawastatic void
277136467Ssimokawadcons_cnputc(struct consdev *cp, int c)
278136467Ssimokawa{
279136467Ssimokawa	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
280136467Ssimokawa	dcons_os_putc(dc, c);
281136467Ssimokawa}
282136467Ssimokawa
283136467Ssimokawastatic int
284136467Ssimokawadcons_drv_init(int stage)
285136467Ssimokawa{
286137013Ssimokawa#if defined(__i386__) || defined(__amd64__)
287136898Ssimokawa	quad_t addr, size;
288136498Ssimokawa#endif
289136467Ssimokawa
290136467Ssimokawa	if (drv_init)
291136467Ssimokawa		return(drv_init);
292136467Ssimokawa
293136467Ssimokawa	drv_init = -1;
294136467Ssimokawa
295136467Ssimokawa	bzero(&dg, sizeof(dg));
296136467Ssimokawa	dcons_conf = &dg;
297136467Ssimokawa	dg.cdev = &dcons_consdev;
298136467Ssimokawa	dg.buf = NULL;
299136467Ssimokawa	dg.size = DCONS_BUF_SIZE;
300136467Ssimokawa
301137013Ssimokawa#if defined(__i386__) || defined(__amd64__)
302136898Ssimokawa	if (getenv_quad("dcons.addr", &addr) > 0 &&
303136898Ssimokawa	    getenv_quad("dcons.size", &size) > 0) {
304137013Ssimokawa#ifdef __i386__
305136898Ssimokawa		vm_paddr_t pa;
306136898Ssimokawa		/*
307136898Ssimokawa		 * Allow read/write access to dcons buffer.
308136898Ssimokawa		 */
309136898Ssimokawa		for (pa = trunc_page(addr); pa < addr + size; pa += PAGE_SIZE)
310136898Ssimokawa			*vtopte(KERNBASE + pa) |= PG_RW;
311136898Ssimokawa		invltlb();
312137013Ssimokawa#endif
313136467Ssimokawa		/* XXX P to V */
314136898Ssimokawa		dg.buf = (struct dcons_buf *)(vm_offset_t)(KERNBASE + addr);
315136467Ssimokawa		dg.size = size;
316136467Ssimokawa		if (dcons_load_buffer(dg.buf, dg.size, sc) < 0)
317136467Ssimokawa			dg.buf = NULL;
318136467Ssimokawa	}
319136467Ssimokawa#endif
320136467Ssimokawa	if (dg.buf != NULL)
321136467Ssimokawa		goto ok;
322136467Ssimokawa
323136467Ssimokawa#ifndef KLD_MODULE
324136467Ssimokawa	if (stage == 0) { /* XXX or cold */
325136467Ssimokawa		/*
326136467Ssimokawa		 * DCONS_FORCE_CONSOLE == 1 and statically linked.
327136467Ssimokawa		 * called from cninit(). can't use contigmalloc yet .
328136467Ssimokawa		 */
329136467Ssimokawa		dg.buf = (struct dcons_buf *) bssbuf;
330136467Ssimokawa		dcons_init(dg.buf, dg.size, sc);
331136467Ssimokawa	} else
332136467Ssimokawa#endif
333136467Ssimokawa	{
334136467Ssimokawa		/*
335136467Ssimokawa		 * DCONS_FORCE_CONSOLE == 0 or kernel module case.
336136467Ssimokawa		 * if the module is loaded after boot,
337136467Ssimokawa		 * bssbuf could be non-continuous.
338136467Ssimokawa		 */
339136467Ssimokawa		dg.buf = (struct dcons_buf *) contigmalloc(dg.size,
340136467Ssimokawa			M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
341186876Smarius		if (dg.buf == NULL)
342186876Smarius			return (-1);
343136467Ssimokawa		dcons_init(dg.buf, dg.size, sc);
344136467Ssimokawa	}
345136467Ssimokawa
346136467Ssimokawaok:
347136467Ssimokawa	dcons_buf = dg.buf;
348136467Ssimokawa
349136467Ssimokawa	drv_init = 1;
350136467Ssimokawa
351136467Ssimokawa	return 0;
352136467Ssimokawa}
353136467Ssimokawa
354136467Ssimokawa
355136467Ssimokawastatic int
356136467Ssimokawadcons_attach_port(int port, char *name, int flags)
357136467Ssimokawa{
358136467Ssimokawa	struct dcons_softc *dc;
359136467Ssimokawa	struct tty *tp;
360136467Ssimokawa
361136467Ssimokawa	dc = &sc[port];
362193018Sed	tp = tty_alloc(&dcons_ttydevsw, dc);
363136467Ssimokawa	dc->flags = flags;
364181905Sed	dc->tty   = tp;
365189752Simp	tty_init_console(tp, 0);
366181905Sed	tty_makedev(tp, NULL, "%s", name);
367136467Ssimokawa	return(0);
368136467Ssimokawa}
369136467Ssimokawa
370136467Ssimokawastatic int
371136467Ssimokawadcons_attach(void)
372136467Ssimokawa{
373136467Ssimokawa	int polltime;
374136467Ssimokawa
375136467Ssimokawa	dcons_attach_port(DCONS_CON, "dcons", 0);
376136467Ssimokawa	dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB);
377185107Sed	callout_init(&dcons_callout, CALLOUT_MPSAFE);
378136467Ssimokawa	polltime = hz / poll_hz;
379136467Ssimokawa	callout_reset(&dcons_callout, polltime, dcons_timeout, NULL);
380136467Ssimokawa	return(0);
381136467Ssimokawa}
382136467Ssimokawa
383136467Ssimokawastatic int
384136467Ssimokawadcons_detach(int port)
385136467Ssimokawa{
386136467Ssimokawa	struct	tty *tp;
387136467Ssimokawa	struct dcons_softc *dc;
388136467Ssimokawa
389136467Ssimokawa	dc = &sc[port];
390181905Sed	tp = dc->tty;
391136467Ssimokawa
392181905Sed	tty_lock(tp);
393181905Sed	tty_rel_gone(tp);
394136467Ssimokawa
395136467Ssimokawa	return(0);
396136467Ssimokawa}
397136467Ssimokawa
398136467Ssimokawastatic int
399136467Ssimokawadcons_modevent(module_t mode, int type, void *data)
400136467Ssimokawa{
401136467Ssimokawa	int err = 0, ret;
402136467Ssimokawa
403136467Ssimokawa	switch (type) {
404136467Ssimokawa	case MOD_LOAD:
405136467Ssimokawa		ret = dcons_drv_init(1);
406190756Skan		if (ret != -1)
407190756Skan			dcons_attach();
408136467Ssimokawa		if (ret == 0) {
409136467Ssimokawa			dcons_cnprobe(&dcons_consdev);
410136467Ssimokawa			dcons_cninit(&dcons_consdev);
411136467Ssimokawa			cnadd(&dcons_consdev);
412136467Ssimokawa		}
413136467Ssimokawa		break;
414136467Ssimokawa	case MOD_UNLOAD:
415136467Ssimokawa		printf("dcons: unload\n");
416186876Smarius		if (drv_init == 1) {
417186876Smarius			callout_stop(&dcons_callout);
418186876Smarius			cnremove(&dcons_consdev);
419186876Smarius			dcons_detach(DCONS_CON);
420186876Smarius			dcons_detach(DCONS_GDB);
421186876Smarius			dg.buf->magic = 0;
422136467Ssimokawa
423186876Smarius			contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF);
424186876Smarius		}
425136467Ssimokawa
426136467Ssimokawa		break;
427136467Ssimokawa	case MOD_SHUTDOWN:
428170426Ssimokawa#if 0		/* Keep connection after halt */
429136467Ssimokawa		dg.buf->magic = 0;
430170426Ssimokawa#endif
431136467Ssimokawa		break;
432136467Ssimokawa	default:
433136467Ssimokawa		err = EOPNOTSUPP;
434136467Ssimokawa		break;
435136467Ssimokawa	}
436136467Ssimokawa	return(err);
437136467Ssimokawa}
438136467Ssimokawa
439181905Sed#if defined(GDB)
440136467Ssimokawa/* Debugger interface */
441136467Ssimokawa
442136467Ssimokawastatic int
443181905Seddcons_os_getc(struct dcons_softc *dc)
444181905Sed{
445181905Sed	int c;
446181905Sed
447181905Sed	while ((c = dcons_os_checkc(dc)) == -1);
448181905Sed
449181905Sed	return (c & 0xff);
450181905Sed}
451181905Sed
452181905Sedstatic int
453136467Ssimokawadcons_dbg_probe(void)
454136467Ssimokawa{
455170537Ssimokawa	int dcons_gdb;
456170537Ssimokawa
457170537Ssimokawa	if (getenv_int("dcons_gdb", &dcons_gdb) == 0)
458170537Ssimokawa		return (-1);
459170537Ssimokawa	return (dcons_gdb);
460136467Ssimokawa}
461136467Ssimokawa
462136467Ssimokawastatic void
463136467Ssimokawadcons_dbg_init(void)
464136467Ssimokawa{
465136467Ssimokawa}
466136467Ssimokawa
467136467Ssimokawastatic void
468136467Ssimokawadcons_dbg_term(void)
469136467Ssimokawa{
470136467Ssimokawa}
471136467Ssimokawa
472136467Ssimokawastatic void
473136467Ssimokawadcons_dbg_putc(int c)
474136467Ssimokawa{
475136467Ssimokawa	struct dcons_softc *dc = &sc[DCONS_GDB];
476136467Ssimokawa	dcons_os_putc(dc, c);
477136467Ssimokawa}
478136467Ssimokawa
479136467Ssimokawastatic int
480136467Ssimokawadcons_dbg_getc(void)
481136467Ssimokawa{
482136467Ssimokawa	struct dcons_softc *dc = &sc[DCONS_GDB];
483136467Ssimokawa	return (dcons_os_getc(dc));
484136467Ssimokawa}
485136467Ssimokawa#endif
486136467Ssimokawa
487136467SsimokawaDEV_MODULE(dcons, dcons_modevent, NULL);
488136467SsimokawaMODULE_VERSION(dcons, DCONS_VERSION);
489