dcons_os.c revision 181905
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 181905 2008-08-20 08:31:58Z ed $
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_comconsole.h"
68136467Ssimokawa#include "opt_dcons.h"
69170017Ssimokawa#include "opt_kdb.h"
70170017Ssimokawa#include "opt_gdb.h"
71170017Ssimokawa#include "opt_ddb.h"
72136467Ssimokawa
73170017Ssimokawa
74136467Ssimokawa#ifndef DCONS_POLL_HZ
75136467Ssimokawa#define DCONS_POLL_HZ	100
76136467Ssimokawa#endif
77136467Ssimokawa
78136467Ssimokawa#ifndef DCONS_BUF_SIZE
79136467Ssimokawa#define DCONS_BUF_SIZE (16*1024)
80136467Ssimokawa#endif
81136467Ssimokawa
82136467Ssimokawa#ifndef DCONS_FORCE_CONSOLE
83136467Ssimokawa#define DCONS_FORCE_CONSOLE	0	/* Mostly for FreeBSD-4/DragonFly */
84136467Ssimokawa#endif
85136467Ssimokawa
86136467Ssimokawa#ifndef KLD_MODULE
87136467Ssimokawastatic char bssbuf[DCONS_BUF_SIZE];	/* buf in bss */
88136467Ssimokawa#endif
89136467Ssimokawa
90136467Ssimokawa/* global data */
91136467Ssimokawastatic struct dcons_global dg;
92136467Ssimokawastruct dcons_global *dcons_conf;
93136467Ssimokawastatic int poll_hz = DCONS_POLL_HZ;
94136467Ssimokawa
95136467Ssimokawastatic struct dcons_softc sc[DCONS_NPORT];
96136467Ssimokawa
97136467SsimokawaSYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console");
98136467SsimokawaSYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0,
99136467Ssimokawa				"dcons polling rate");
100136467Ssimokawa
101136467Ssimokawastatic int drv_init = 0;
102136467Ssimokawastatic struct callout dcons_callout;
103136467Ssimokawastruct dcons_buf *dcons_buf;		/* for local dconschat */
104136467Ssimokawa
105136467Ssimokawastatic void	dcons_timeout(void *);
106136467Ssimokawastatic int	dcons_drv_init(int);
107136467Ssimokawa
108136467Ssimokawastatic cn_probe_t	dcons_cnprobe;
109136467Ssimokawastatic cn_init_t	dcons_cninit;
110158959Sphkstatic cn_term_t	dcons_cnterm;
111136467Ssimokawastatic cn_getc_t	dcons_cngetc;
112136467Ssimokawastatic cn_putc_t	dcons_cnputc;
113136467Ssimokawa
114158959SphkCONSOLE_DRIVER(dcons);
115136467Ssimokawa
116181905Sed#if defined(GDB)
117181905Sedstatic gdb_probe_f	dcons_dbg_probe;
118181905Sedstatic gdb_init_f	dcons_dbg_init;
119181905Sedstatic gdb_term_f	dcons_dbg_term;
120181905Sedstatic gdb_getc_f	dcons_dbg_getc;
121181905Sedstatic gdb_putc_f	dcons_dbg_putc;
122136467Ssimokawa
123136467SsimokawaGDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term,
124158950Sphk    dcons_dbg_getc, dcons_dbg_putc);
125136467Ssimokawa
126136467Ssimokawaextern struct gdb_dbgport *gdb_cur;
127136467Ssimokawa#endif
128136467Ssimokawa
129181905Sedstatic tsw_outwakeup_t dcons_outwakeup;
130181905Sed
131181905Sedstatic struct ttydevsw dcons_ttydevsw = {
132181905Sed	.tsw_flags      = TF_NOPREFIX,
133181905Sed	.tsw_outwakeup  = dcons_outwakeup,
134181905Sed};
135181905Sed
136170017Ssimokawa#if (defined(GDB) || defined(DDB)) && defined(ALT_BREAK_TO_DEBUGGER)
137136467Ssimokawastatic int
138136467Ssimokawadcons_check_break(struct dcons_softc *dc, int c)
139136467Ssimokawa{
140178766Speter	int kdb_brk;
141181905Sed
142136467Ssimokawa	if (c < 0)
143136467Ssimokawa		return (c);
144136467Ssimokawa
145178766Speter	if ((kdb_brk = kdb_alt_break(c, &dc->brk_state)) != 0) {
146178766Speter		switch (kdb_brk) {
147178766Speter		case KDB_REQ_DEBUGGER:
148178766Speter			if ((dc->flags & DC_GDB) != 0) {
149170017Ssimokawa#ifdef GDB
150178766Speter				if (gdb_cur == &dcons_gdb_dbgport) {
151178766Speter					kdb_dbbe_select("gdb");
152178766Speter					kdb_enter(KDB_WHY_BREAK,
153178766Speter					    "Break sequence on dcons gdb port");
154178766Speter				}
155178766Speter#endif
156178766Speter			} else
157174898Srwatson				kdb_enter(KDB_WHY_BREAK,
158178766Speter				    "Break sequence on dcons console port");
159178766Speter			break;
160178766Speter		case KDB_REQ_PANIC:
161178766Speter			kdb_panic("Panic sequence on dcons console port");
162178766Speter			break;
163178771Speter		case KDB_REQ_REBOOT:
164178766Speter			kdb_reboot();
165178766Speter			break;
166178766Speter		}
167136467Ssimokawa	}
168136467Ssimokawa	return (c);
169136467Ssimokawa}
170136467Ssimokawa#else
171136467Ssimokawa#define	dcons_check_break(dc, c)	(c)
172136467Ssimokawa#endif
173136467Ssimokawa
174136467Ssimokawastatic int
175171867Ssimokawadcons_os_checkc_nopoll(struct dcons_softc *dc)
176136467Ssimokawa{
177136467Ssimokawa	int c;
178136467Ssimokawa
179136467Ssimokawa	if (dg.dma_tag != NULL)
180136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD);
181181905Sed
182136467Ssimokawa	c = dcons_check_break(dc, dcons_checkc(dc));
183136467Ssimokawa
184136467Ssimokawa	if (dg.dma_tag != NULL)
185136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREREAD);
186136467Ssimokawa
187136467Ssimokawa	return (c);
188136467Ssimokawa}
189136467Ssimokawa
190171867Ssimokawastatic int
191171867Ssimokawadcons_os_checkc(struct dcons_softc *dc)
192171867Ssimokawa{
193171867Ssimokawa	EVENTHANDLER_INVOKE(dcons_poll, 0);
194171867Ssimokawa	return (dcons_os_checkc_nopoll(dc));
195171867Ssimokawa}
196171867Ssimokawa
197136467Ssimokawastatic void
198136467Ssimokawadcons_os_putc(struct dcons_softc *dc, int c)
199136467Ssimokawa{
200136467Ssimokawa	if (dg.dma_tag != NULL)
201136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTWRITE);
202136467Ssimokawa
203136467Ssimokawa	dcons_putc(dc, c);
204136467Ssimokawa
205136467Ssimokawa	if (dg.dma_tag != NULL)
206136467Ssimokawa		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE);
207136467Ssimokawa}
208136467Ssimokawa
209136467Ssimokawastatic void
210181905Seddcons_outwakeup(struct tty *tp)
211136467Ssimokawa{
212136467Ssimokawa	struct dcons_softc *dc;
213181905Sed	char ch;
214136467Ssimokawa
215181905Sed	dc = tty_softc(tp);
216136467Ssimokawa
217181905Sed	while (ttydisc_getc(tp, &ch, sizeof ch) != 0)
218181905Sed		dcons_os_putc(dc, ch);
219136467Ssimokawa}
220136467Ssimokawa
221136467Ssimokawastatic void
222136467Ssimokawadcons_timeout(void *v)
223136467Ssimokawa{
224136467Ssimokawa	struct	tty *tp;
225136467Ssimokawa	struct dcons_softc *dc;
226136467Ssimokawa	int i, c, polltime;
227136467Ssimokawa
228136467Ssimokawa	for (i = 0; i < DCONS_NPORT; i ++) {
229136467Ssimokawa		dc = &sc[i];
230181905Sed		tp = dc->tty;
231181905Sed
232181905Sed		tty_lock(tp);
233171867Ssimokawa		while ((c = dcons_os_checkc_nopoll(dc)) != -1)
234181905Sed			ttydisc_rint(tp, c, 0);
235181905Sed		ttydisc_rint_done(tp);
236181905Sed		tty_unlock(tp);
237136467Ssimokawa	}
238136467Ssimokawa	polltime = hz / poll_hz;
239136467Ssimokawa	if (polltime < 1)
240136467Ssimokawa		polltime = 1;
241136467Ssimokawa	callout_reset(&dcons_callout, polltime, dcons_timeout, tp);
242136467Ssimokawa}
243136467Ssimokawa
244136467Ssimokawastatic void
245136467Ssimokawadcons_cnprobe(struct consdev *cp)
246136467Ssimokawa{
247136467Ssimokawa	sprintf(cp->cn_name, "dcons");
248136467Ssimokawa#if DCONS_FORCE_CONSOLE
249136467Ssimokawa	cp->cn_pri = CN_REMOTE;
250136467Ssimokawa#else
251136467Ssimokawa	cp->cn_pri = CN_NORMAL;
252136467Ssimokawa#endif
253136467Ssimokawa}
254136467Ssimokawa
255136467Ssimokawastatic void
256136467Ssimokawadcons_cninit(struct consdev *cp)
257136467Ssimokawa{
258136467Ssimokawa	dcons_drv_init(0);
259181905Sed	cp->cn_arg = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */
260136467Ssimokawa}
261136467Ssimokawa
262158959Sphkstatic void
263158959Sphkdcons_cnterm(struct consdev *cp)
264158959Sphk{
265158959Sphk}
266158959Sphk
267136467Ssimokawastatic int
268136467Ssimokawadcons_cngetc(struct consdev *cp)
269136467Ssimokawa{
270136467Ssimokawa	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
271136467Ssimokawa	return (dcons_os_checkc(dc));
272136467Ssimokawa}
273181905Sed
274136467Ssimokawastatic void
275136467Ssimokawadcons_cnputc(struct consdev *cp, int c)
276136467Ssimokawa{
277136467Ssimokawa	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
278136467Ssimokawa	dcons_os_putc(dc, c);
279136467Ssimokawa}
280136467Ssimokawa
281136467Ssimokawastatic int
282136467Ssimokawadcons_drv_init(int stage)
283136467Ssimokawa{
284137013Ssimokawa#if defined(__i386__) || defined(__amd64__)
285136898Ssimokawa	quad_t addr, size;
286136498Ssimokawa#endif
287136467Ssimokawa
288136467Ssimokawa	if (drv_init)
289136467Ssimokawa		return(drv_init);
290136467Ssimokawa
291136467Ssimokawa	drv_init = -1;
292136467Ssimokawa
293136467Ssimokawa	bzero(&dg, sizeof(dg));
294136467Ssimokawa	dcons_conf = &dg;
295136467Ssimokawa	dg.cdev = &dcons_consdev;
296136467Ssimokawa	dg.buf = NULL;
297136467Ssimokawa	dg.size = DCONS_BUF_SIZE;
298136467Ssimokawa
299137013Ssimokawa#if defined(__i386__) || defined(__amd64__)
300136898Ssimokawa	if (getenv_quad("dcons.addr", &addr) > 0 &&
301136898Ssimokawa	    getenv_quad("dcons.size", &size) > 0) {
302137013Ssimokawa#ifdef __i386__
303136898Ssimokawa		vm_paddr_t pa;
304136898Ssimokawa		/*
305136898Ssimokawa		 * Allow read/write access to dcons buffer.
306136898Ssimokawa		 */
307136898Ssimokawa		for (pa = trunc_page(addr); pa < addr + size; pa += PAGE_SIZE)
308136898Ssimokawa			*vtopte(KERNBASE + pa) |= PG_RW;
309136898Ssimokawa		invltlb();
310137013Ssimokawa#endif
311136467Ssimokawa		/* XXX P to V */
312136898Ssimokawa		dg.buf = (struct dcons_buf *)(vm_offset_t)(KERNBASE + addr);
313136467Ssimokawa		dg.size = size;
314136467Ssimokawa		if (dcons_load_buffer(dg.buf, dg.size, sc) < 0)
315136467Ssimokawa			dg.buf = NULL;
316136467Ssimokawa	}
317136467Ssimokawa#endif
318136467Ssimokawa	if (dg.buf != NULL)
319136467Ssimokawa		goto ok;
320136467Ssimokawa
321136467Ssimokawa#ifndef KLD_MODULE
322136467Ssimokawa	if (stage == 0) { /* XXX or cold */
323136467Ssimokawa		/*
324136467Ssimokawa		 * DCONS_FORCE_CONSOLE == 1 and statically linked.
325136467Ssimokawa		 * called from cninit(). can't use contigmalloc yet .
326136467Ssimokawa		 */
327136467Ssimokawa		dg.buf = (struct dcons_buf *) bssbuf;
328136467Ssimokawa		dcons_init(dg.buf, dg.size, sc);
329136467Ssimokawa	} else
330136467Ssimokawa#endif
331136467Ssimokawa	{
332136467Ssimokawa		/*
333136467Ssimokawa		 * DCONS_FORCE_CONSOLE == 0 or kernel module case.
334136467Ssimokawa		 * if the module is loaded after boot,
335136467Ssimokawa		 * bssbuf could be non-continuous.
336136467Ssimokawa		 */
337136467Ssimokawa		dg.buf = (struct dcons_buf *) contigmalloc(dg.size,
338136467Ssimokawa			M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
339136467Ssimokawa		dcons_init(dg.buf, dg.size, sc);
340136467Ssimokawa	}
341136467Ssimokawa
342136467Ssimokawaok:
343136467Ssimokawa	dcons_buf = dg.buf;
344136467Ssimokawa
345136467Ssimokawa	drv_init = 1;
346136467Ssimokawa
347136467Ssimokawa	return 0;
348136467Ssimokawa}
349136467Ssimokawa
350136467Ssimokawa
351136467Ssimokawastatic int
352136467Ssimokawadcons_attach_port(int port, char *name, int flags)
353136467Ssimokawa{
354136467Ssimokawa	struct dcons_softc *dc;
355136467Ssimokawa	struct tty *tp;
356136467Ssimokawa
357136467Ssimokawa	dc = &sc[port];
358181905Sed	tp = tty_alloc(&dcons_ttydevsw, dc, NULL);
359136467Ssimokawa	dc->flags = flags;
360181905Sed	dc->tty   = tp;
361181905Sed	tty_makedev(tp, NULL, "%s", name);
362136467Ssimokawa	return(0);
363136467Ssimokawa}
364136467Ssimokawa
365136467Ssimokawastatic int
366136467Ssimokawadcons_attach(void)
367136467Ssimokawa{
368136467Ssimokawa	int polltime;
369136467Ssimokawa
370136467Ssimokawa	dcons_attach_port(DCONS_CON, "dcons", 0);
371136467Ssimokawa	dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB);
372136467Ssimokawa	callout_init(&dcons_callout, 0);
373136467Ssimokawa	polltime = hz / poll_hz;
374136467Ssimokawa	if (polltime < 1)
375136467Ssimokawa		polltime = 1;
376136467Ssimokawa	callout_reset(&dcons_callout, polltime, dcons_timeout, NULL);
377136467Ssimokawa	return(0);
378136467Ssimokawa}
379136467Ssimokawa
380136467Ssimokawastatic int
381136467Ssimokawadcons_detach(int port)
382136467Ssimokawa{
383136467Ssimokawa	struct	tty *tp;
384136467Ssimokawa	struct dcons_softc *dc;
385136467Ssimokawa
386136467Ssimokawa	dc = &sc[port];
387181905Sed	tp = dc->tty;
388136467Ssimokawa
389181905Sed	tty_lock(tp);
390181905Sed	tty_rel_gone(tp);
391136467Ssimokawa
392136467Ssimokawa	return(0);
393136467Ssimokawa}
394136467Ssimokawa
395136467Ssimokawastatic int
396136467Ssimokawadcons_modevent(module_t mode, int type, void *data)
397136467Ssimokawa{
398136467Ssimokawa	int err = 0, ret;
399136467Ssimokawa
400136467Ssimokawa	switch (type) {
401136467Ssimokawa	case MOD_LOAD:
402136467Ssimokawa		ret = dcons_drv_init(1);
403136467Ssimokawa		dcons_attach();
404136467Ssimokawa		if (ret == 0) {
405136467Ssimokawa			dcons_cnprobe(&dcons_consdev);
406136467Ssimokawa			dcons_cninit(&dcons_consdev);
407136467Ssimokawa			cnadd(&dcons_consdev);
408136467Ssimokawa		}
409136467Ssimokawa		break;
410136467Ssimokawa	case MOD_UNLOAD:
411136467Ssimokawa		printf("dcons: unload\n");
412136467Ssimokawa		callout_stop(&dcons_callout);
413136467Ssimokawa		cnremove(&dcons_consdev);
414136467Ssimokawa		dcons_detach(DCONS_CON);
415136467Ssimokawa		dcons_detach(DCONS_GDB);
416136467Ssimokawa		dg.buf->magic = 0;
417136467Ssimokawa
418136467Ssimokawa		contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF);
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