dcons_os.c revision 228631
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: head/sys/dev/dcons/dcons_os.c 228631 2011-12-17 15:08:43Z avg $
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
77136467Ssimokawa#ifndef DCONS_BUF_SIZE
78136467Ssimokawa#define DCONS_BUF_SIZE (16*1024)
79136467Ssimokawa#endif
80136467Ssimokawa
81136467Ssimokawa#ifndef DCONS_FORCE_CONSOLE
82136467Ssimokawa#define DCONS_FORCE_CONSOLE	0	/* Mostly for FreeBSD-4/DragonFly */
83136467Ssimokawa#endif
84136467Ssimokawa
85136467Ssimokawa#ifndef KLD_MODULE
86136467Ssimokawastatic char bssbuf[DCONS_BUF_SIZE];	/* buf in bss */
87136467Ssimokawa#endif
88136467Ssimokawa
89136467Ssimokawa/* global data */
90136467Ssimokawastatic struct dcons_global dg;
91136467Ssimokawastruct dcons_global *dcons_conf;
92136467Ssimokawastatic int poll_hz = DCONS_POLL_HZ;
93136467Ssimokawa
94136467Ssimokawastatic struct dcons_softc sc[DCONS_NPORT];
95136467Ssimokawa
96227309Sedstatic SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console");
97136467SsimokawaSYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0,
98136467Ssimokawa				"dcons polling rate");
99136467Ssimokawa
100136467Ssimokawastatic int drv_init = 0;
101136467Ssimokawastatic struct callout dcons_callout;
102136467Ssimokawastruct dcons_buf *dcons_buf;		/* for local dconschat */
103136467Ssimokawa
104136467Ssimokawastatic void	dcons_timeout(void *);
105136467Ssimokawastatic int	dcons_drv_init(int);
106136467Ssimokawa
107136467Ssimokawastatic cn_probe_t	dcons_cnprobe;
108136467Ssimokawastatic cn_init_t	dcons_cninit;
109158959Sphkstatic cn_term_t	dcons_cnterm;
110136467Ssimokawastatic cn_getc_t	dcons_cngetc;
111136467Ssimokawastatic cn_putc_t	dcons_cnputc;
112228631Savgstatic cn_grab_t	dcons_cngrab;
113228631Savgstatic cn_ungrab_t	dcons_cnungrab;
114136467Ssimokawa
115158959SphkCONSOLE_DRIVER(dcons);
116136467Ssimokawa
117181905Sed#if defined(GDB)
118181905Sedstatic gdb_probe_f	dcons_dbg_probe;
119181905Sedstatic gdb_init_f	dcons_dbg_init;
120181905Sedstatic gdb_term_f	dcons_dbg_term;
121181905Sedstatic gdb_getc_f	dcons_dbg_getc;
122181905Sedstatic gdb_putc_f	dcons_dbg_putc;
123136467Ssimokawa
124136467SsimokawaGDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term,
125158950Sphk    dcons_dbg_getc, dcons_dbg_putc);
126136467Ssimokawa
127136467Ssimokawaextern struct gdb_dbgport *gdb_cur;
128136467Ssimokawa#endif
129136467Ssimokawa
130181905Sedstatic tsw_outwakeup_t dcons_outwakeup;
131181905Sed
132181905Sedstatic struct ttydevsw dcons_ttydevsw = {
133181905Sed	.tsw_flags      = TF_NOPREFIX,
134181905Sed	.tsw_outwakeup  = dcons_outwakeup,
135181905Sed};
136181905Sed
137225203Srwatson#if (defined(GDB) || defined(DDB))
138136467Ssimokawastatic int
139136467Ssimokawadcons_check_break(struct dcons_softc *dc, int c)
140136467Ssimokawa{
141181905Sed
142136467Ssimokawa	if (c < 0)
143136467Ssimokawa		return (c);
144136467Ssimokawa
145170017Ssimokawa#ifdef GDB
146225203Srwatson	if ((dc->flags & DC_GDB) != 0 && gdb_cur == &dcons_gdb_dbgport)
147225203Srwatson		kdb_alt_break_gdb(c, &dc->brk_state);
148225203Srwatson	else
149178766Speter#endif
150225203Srwatson		kdb_alt_break(c, &dc->brk_state);
151225203Srwatson
152136467Ssimokawa	return (c);
153136467Ssimokawa}
154136467Ssimokawa#else
155136467Ssimokawa#define	dcons_check_break(dc, c)	(c)
156136467Ssimokawa#endif
157136467Ssimokawa
158136467Ssimokawastatic int
159171867Ssimokawadcons_os_checkc_nopoll(struct dcons_softc *dc)
160136467Ssimokawa{
161136467Ssimokawa	int c;
162136467Ssimokawa
163136467Ssimokawa	if (dg.dma_tag != NULL)
164136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD);
165181905Sed
166136467Ssimokawa	c = dcons_check_break(dc, dcons_checkc(dc));
167136467Ssimokawa
168136467Ssimokawa	if (dg.dma_tag != NULL)
169136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREREAD);
170136467Ssimokawa
171136467Ssimokawa	return (c);
172136467Ssimokawa}
173136467Ssimokawa
174171867Ssimokawastatic int
175171867Ssimokawadcons_os_checkc(struct dcons_softc *dc)
176171867Ssimokawa{
177171867Ssimokawa	EVENTHANDLER_INVOKE(dcons_poll, 0);
178171867Ssimokawa	return (dcons_os_checkc_nopoll(dc));
179171867Ssimokawa}
180171867Ssimokawa
181136467Ssimokawastatic void
182136467Ssimokawadcons_os_putc(struct dcons_softc *dc, int c)
183136467Ssimokawa{
184136467Ssimokawa	if (dg.dma_tag != NULL)
185136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTWRITE);
186136467Ssimokawa
187136467Ssimokawa	dcons_putc(dc, c);
188136467Ssimokawa
189136467Ssimokawa	if (dg.dma_tag != NULL)
190136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE);
191136467Ssimokawa}
192136467Ssimokawa
193136467Ssimokawastatic void
194181905Seddcons_outwakeup(struct tty *tp)
195136467Ssimokawa{
196136467Ssimokawa	struct dcons_softc *dc;
197181905Sed	char ch;
198136467Ssimokawa
199181905Sed	dc = tty_softc(tp);
200136467Ssimokawa
201181905Sed	while (ttydisc_getc(tp, &ch, sizeof ch) != 0)
202181905Sed		dcons_os_putc(dc, ch);
203136467Ssimokawa}
204136467Ssimokawa
205136467Ssimokawastatic void
206136467Ssimokawadcons_timeout(void *v)
207136467Ssimokawa{
208136467Ssimokawa	struct	tty *tp;
209136467Ssimokawa	struct dcons_softc *dc;
210136467Ssimokawa	int i, c, polltime;
211136467Ssimokawa
212136467Ssimokawa	for (i = 0; i < DCONS_NPORT; i ++) {
213136467Ssimokawa		dc = &sc[i];
214181905Sed		tp = dc->tty;
215181905Sed
216181905Sed		tty_lock(tp);
217171867Ssimokawa		while ((c = dcons_os_checkc_nopoll(dc)) != -1)
218181905Sed			ttydisc_rint(tp, c, 0);
219181905Sed		ttydisc_rint_done(tp);
220181905Sed		tty_unlock(tp);
221136467Ssimokawa	}
222136467Ssimokawa	polltime = hz / poll_hz;
223136467Ssimokawa	if (polltime < 1)
224136467Ssimokawa		polltime = 1;
225136467Ssimokawa	callout_reset(&dcons_callout, polltime, dcons_timeout, tp);
226136467Ssimokawa}
227136467Ssimokawa
228136467Ssimokawastatic void
229136467Ssimokawadcons_cnprobe(struct consdev *cp)
230136467Ssimokawa{
231136467Ssimokawa	sprintf(cp->cn_name, "dcons");
232136467Ssimokawa#if DCONS_FORCE_CONSOLE
233136467Ssimokawa	cp->cn_pri = CN_REMOTE;
234136467Ssimokawa#else
235136467Ssimokawa	cp->cn_pri = CN_NORMAL;
236136467Ssimokawa#endif
237136467Ssimokawa}
238136467Ssimokawa
239136467Ssimokawastatic void
240136467Ssimokawadcons_cninit(struct consdev *cp)
241136467Ssimokawa{
242136467Ssimokawa	dcons_drv_init(0);
243181905Sed	cp->cn_arg = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */
244136467Ssimokawa}
245136467Ssimokawa
246158959Sphkstatic void
247158959Sphkdcons_cnterm(struct consdev *cp)
248158959Sphk{
249158959Sphk}
250158959Sphk
251228631Savgstatic void
252228631Savgdcons_cngrab(struct consdev *cp)
253228631Savg{
254228631Savg}
255228631Savg
256228631Savgstatic void
257228631Savgdcons_cnungrab(struct consdev *cp)
258228631Savg{
259228631Savg}
260228631Savg
261136467Ssimokawastatic int
262136467Ssimokawadcons_cngetc(struct consdev *cp)
263136467Ssimokawa{
264136467Ssimokawa	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
265136467Ssimokawa	return (dcons_os_checkc(dc));
266136467Ssimokawa}
267181905Sed
268136467Ssimokawastatic void
269136467Ssimokawadcons_cnputc(struct consdev *cp, int c)
270136467Ssimokawa{
271136467Ssimokawa	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
272136467Ssimokawa	dcons_os_putc(dc, c);
273136467Ssimokawa}
274136467Ssimokawa
275136467Ssimokawastatic int
276136467Ssimokawadcons_drv_init(int stage)
277136467Ssimokawa{
278137013Ssimokawa#if defined(__i386__) || defined(__amd64__)
279136898Ssimokawa	quad_t addr, size;
280136498Ssimokawa#endif
281136467Ssimokawa
282136467Ssimokawa	if (drv_init)
283136467Ssimokawa		return(drv_init);
284136467Ssimokawa
285136467Ssimokawa	drv_init = -1;
286136467Ssimokawa
287136467Ssimokawa	bzero(&dg, sizeof(dg));
288136467Ssimokawa	dcons_conf = &dg;
289136467Ssimokawa	dg.cdev = &dcons_consdev;
290136467Ssimokawa	dg.buf = NULL;
291136467Ssimokawa	dg.size = DCONS_BUF_SIZE;
292136467Ssimokawa
293137013Ssimokawa#if defined(__i386__) || defined(__amd64__)
294136898Ssimokawa	if (getenv_quad("dcons.addr", &addr) > 0 &&
295136898Ssimokawa	    getenv_quad("dcons.size", &size) > 0) {
296137013Ssimokawa#ifdef __i386__
297136898Ssimokawa		vm_paddr_t pa;
298136898Ssimokawa		/*
299136898Ssimokawa		 * Allow read/write access to dcons buffer.
300136898Ssimokawa		 */
301136898Ssimokawa		for (pa = trunc_page(addr); pa < addr + size; pa += PAGE_SIZE)
302136898Ssimokawa			*vtopte(KERNBASE + pa) |= PG_RW;
303136898Ssimokawa		invltlb();
304137013Ssimokawa#endif
305136467Ssimokawa		/* XXX P to V */
306136898Ssimokawa		dg.buf = (struct dcons_buf *)(vm_offset_t)(KERNBASE + addr);
307136467Ssimokawa		dg.size = size;
308136467Ssimokawa		if (dcons_load_buffer(dg.buf, dg.size, sc) < 0)
309136467Ssimokawa			dg.buf = NULL;
310136467Ssimokawa	}
311136467Ssimokawa#endif
312136467Ssimokawa	if (dg.buf != NULL)
313136467Ssimokawa		goto ok;
314136467Ssimokawa
315136467Ssimokawa#ifndef KLD_MODULE
316136467Ssimokawa	if (stage == 0) { /* XXX or cold */
317136467Ssimokawa		/*
318136467Ssimokawa		 * DCONS_FORCE_CONSOLE == 1 and statically linked.
319136467Ssimokawa		 * called from cninit(). can't use contigmalloc yet .
320136467Ssimokawa		 */
321136467Ssimokawa		dg.buf = (struct dcons_buf *) bssbuf;
322136467Ssimokawa		dcons_init(dg.buf, dg.size, sc);
323136467Ssimokawa	} else
324136467Ssimokawa#endif
325136467Ssimokawa	{
326136467Ssimokawa		/*
327136467Ssimokawa		 * DCONS_FORCE_CONSOLE == 0 or kernel module case.
328136467Ssimokawa		 * if the module is loaded after boot,
329136467Ssimokawa		 * bssbuf could be non-continuous.
330136467Ssimokawa		 */
331136467Ssimokawa		dg.buf = (struct dcons_buf *) contigmalloc(dg.size,
332136467Ssimokawa			M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
333186876Smarius		if (dg.buf == NULL)
334186876Smarius			return (-1);
335136467Ssimokawa		dcons_init(dg.buf, dg.size, sc);
336136467Ssimokawa	}
337136467Ssimokawa
338136467Ssimokawaok:
339136467Ssimokawa	dcons_buf = dg.buf;
340136467Ssimokawa
341136467Ssimokawa	drv_init = 1;
342136467Ssimokawa
343136467Ssimokawa	return 0;
344136467Ssimokawa}
345136467Ssimokawa
346136467Ssimokawa
347136467Ssimokawastatic int
348136467Ssimokawadcons_attach_port(int port, char *name, int flags)
349136467Ssimokawa{
350136467Ssimokawa	struct dcons_softc *dc;
351136467Ssimokawa	struct tty *tp;
352136467Ssimokawa
353136467Ssimokawa	dc = &sc[port];
354193018Sed	tp = tty_alloc(&dcons_ttydevsw, dc);
355136467Ssimokawa	dc->flags = flags;
356181905Sed	dc->tty   = tp;
357189752Simp	tty_init_console(tp, 0);
358181905Sed	tty_makedev(tp, NULL, "%s", name);
359136467Ssimokawa	return(0);
360136467Ssimokawa}
361136467Ssimokawa
362136467Ssimokawastatic int
363136467Ssimokawadcons_attach(void)
364136467Ssimokawa{
365136467Ssimokawa	int polltime;
366136467Ssimokawa
367136467Ssimokawa	dcons_attach_port(DCONS_CON, "dcons", 0);
368136467Ssimokawa	dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB);
369185107Sed	callout_init(&dcons_callout, CALLOUT_MPSAFE);
370136467Ssimokawa	polltime = hz / poll_hz;
371136467Ssimokawa	if (polltime < 1)
372136467Ssimokawa		polltime = 1;
373136467Ssimokawa	callout_reset(&dcons_callout, polltime, dcons_timeout, NULL);
374136467Ssimokawa	return(0);
375136467Ssimokawa}
376136467Ssimokawa
377136467Ssimokawastatic int
378136467Ssimokawadcons_detach(int port)
379136467Ssimokawa{
380136467Ssimokawa	struct	tty *tp;
381136467Ssimokawa	struct dcons_softc *dc;
382136467Ssimokawa
383136467Ssimokawa	dc = &sc[port];
384181905Sed	tp = dc->tty;
385136467Ssimokawa
386181905Sed	tty_lock(tp);
387181905Sed	tty_rel_gone(tp);
388136467Ssimokawa
389136467Ssimokawa	return(0);
390136467Ssimokawa}
391136467Ssimokawa
392136467Ssimokawastatic int
393136467Ssimokawadcons_modevent(module_t mode, int type, void *data)
394136467Ssimokawa{
395136467Ssimokawa	int err = 0, ret;
396136467Ssimokawa
397136467Ssimokawa	switch (type) {
398136467Ssimokawa	case MOD_LOAD:
399136467Ssimokawa		ret = dcons_drv_init(1);
400190756Skan		if (ret != -1)
401190756Skan			dcons_attach();
402136467Ssimokawa		if (ret == 0) {
403136467Ssimokawa			dcons_cnprobe(&dcons_consdev);
404136467Ssimokawa			dcons_cninit(&dcons_consdev);
405136467Ssimokawa			cnadd(&dcons_consdev);
406136467Ssimokawa		}
407136467Ssimokawa		break;
408136467Ssimokawa	case MOD_UNLOAD:
409136467Ssimokawa		printf("dcons: unload\n");
410186876Smarius		if (drv_init == 1) {
411186876Smarius			callout_stop(&dcons_callout);
412186876Smarius			cnremove(&dcons_consdev);
413186876Smarius			dcons_detach(DCONS_CON);
414186876Smarius			dcons_detach(DCONS_GDB);
415186876Smarius			dg.buf->magic = 0;
416136467Ssimokawa
417186876Smarius			contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF);
418186876Smarius		}
419136467Ssimokawa
420136467Ssimokawa		break;
421136467Ssimokawa	case MOD_SHUTDOWN:
422170426Ssimokawa#if 0		/* Keep connection after halt */
423136467Ssimokawa		dg.buf->magic = 0;
424170426Ssimokawa#endif
425136467Ssimokawa		break;
426136467Ssimokawa	default:
427136467Ssimokawa		err = EOPNOTSUPP;
428136467Ssimokawa		break;
429136467Ssimokawa	}
430136467Ssimokawa	return(err);
431136467Ssimokawa}
432136467Ssimokawa
433181905Sed#if defined(GDB)
434136467Ssimokawa/* Debugger interface */
435136467Ssimokawa
436136467Ssimokawastatic int
437181905Seddcons_os_getc(struct dcons_softc *dc)
438181905Sed{
439181905Sed	int c;
440181905Sed
441181905Sed	while ((c = dcons_os_checkc(dc)) == -1);
442181905Sed
443181905Sed	return (c & 0xff);
444181905Sed}
445181905Sed
446181905Sedstatic int
447136467Ssimokawadcons_dbg_probe(void)
448136467Ssimokawa{
449170537Ssimokawa	int dcons_gdb;
450170537Ssimokawa
451170537Ssimokawa	if (getenv_int("dcons_gdb", &dcons_gdb) == 0)
452170537Ssimokawa		return (-1);
453170537Ssimokawa	return (dcons_gdb);
454136467Ssimokawa}
455136467Ssimokawa
456136467Ssimokawastatic void
457136467Ssimokawadcons_dbg_init(void)
458136467Ssimokawa{
459136467Ssimokawa}
460136467Ssimokawa
461136467Ssimokawastatic void
462136467Ssimokawadcons_dbg_term(void)
463136467Ssimokawa{
464136467Ssimokawa}
465136467Ssimokawa
466136467Ssimokawastatic void
467136467Ssimokawadcons_dbg_putc(int c)
468136467Ssimokawa{
469136467Ssimokawa	struct dcons_softc *dc = &sc[DCONS_GDB];
470136467Ssimokawa	dcons_os_putc(dc, c);
471136467Ssimokawa}
472136467Ssimokawa
473136467Ssimokawastatic int
474136467Ssimokawadcons_dbg_getc(void)
475136467Ssimokawa{
476136467Ssimokawa	struct dcons_softc *dc = &sc[DCONS_GDB];
477136467Ssimokawa	return (dcons_os_getc(dc));
478136467Ssimokawa}
479136467Ssimokawa#endif
480136467Ssimokawa
481136467SsimokawaDEV_MODULE(dcons, dcons_modevent, NULL);
482136467SsimokawaMODULE_VERSION(dcons, DCONS_VERSION);
483