dcons_os.c revision 189752
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 189752 2009-03-13 02:15:49Z imp $
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);
339186876Smarius		if (dg.buf == NULL)
340186876Smarius			return (-1);
341136467Ssimokawa		dcons_init(dg.buf, dg.size, sc);
342136467Ssimokawa	}
343136467Ssimokawa
344136467Ssimokawaok:
345136467Ssimokawa	dcons_buf = dg.buf;
346136467Ssimokawa
347136467Ssimokawa	drv_init = 1;
348136467Ssimokawa
349136467Ssimokawa	return 0;
350136467Ssimokawa}
351136467Ssimokawa
352136467Ssimokawa
353136467Ssimokawastatic int
354136467Ssimokawadcons_attach_port(int port, char *name, int flags)
355136467Ssimokawa{
356136467Ssimokawa	struct dcons_softc *dc;
357136467Ssimokawa	struct tty *tp;
358136467Ssimokawa
359136467Ssimokawa	dc = &sc[port];
360181905Sed	tp = tty_alloc(&dcons_ttydevsw, dc, NULL);
361136467Ssimokawa	dc->flags = flags;
362181905Sed	dc->tty   = tp;
363189752Simp	tty_init_console(tp, 0);
364181905Sed	tty_makedev(tp, NULL, "%s", name);
365136467Ssimokawa	return(0);
366136467Ssimokawa}
367136467Ssimokawa
368136467Ssimokawastatic int
369136467Ssimokawadcons_attach(void)
370136467Ssimokawa{
371136467Ssimokawa	int polltime;
372136467Ssimokawa
373136467Ssimokawa	dcons_attach_port(DCONS_CON, "dcons", 0);
374136467Ssimokawa	dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB);
375185107Sed	callout_init(&dcons_callout, CALLOUT_MPSAFE);
376136467Ssimokawa	polltime = hz / poll_hz;
377136467Ssimokawa	if (polltime < 1)
378136467Ssimokawa		polltime = 1;
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);
406136467Ssimokawa		if (ret == 0) {
407186876Smarius			dcons_attach();
408136467Ssimokawa			dcons_cnprobe(&dcons_consdev);
409136467Ssimokawa			dcons_cninit(&dcons_consdev);
410136467Ssimokawa			cnadd(&dcons_consdev);
411136467Ssimokawa		}
412136467Ssimokawa		break;
413136467Ssimokawa	case MOD_UNLOAD:
414136467Ssimokawa		printf("dcons: unload\n");
415186876Smarius		if (drv_init == 1) {
416186876Smarius			callout_stop(&dcons_callout);
417186876Smarius			cnremove(&dcons_consdev);
418186876Smarius			dcons_detach(DCONS_CON);
419186876Smarius			dcons_detach(DCONS_GDB);
420186876Smarius			dg.buf->magic = 0;
421136467Ssimokawa
422186876Smarius			contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF);
423186876Smarius		}
424136467Ssimokawa
425136467Ssimokawa		break;
426136467Ssimokawa	case MOD_SHUTDOWN:
427170426Ssimokawa#if 0		/* Keep connection after halt */
428136467Ssimokawa		dg.buf->magic = 0;
429170426Ssimokawa#endif
430136467Ssimokawa		break;
431136467Ssimokawa	default:
432136467Ssimokawa		err = EOPNOTSUPP;
433136467Ssimokawa		break;
434136467Ssimokawa	}
435136467Ssimokawa	return(err);
436136467Ssimokawa}
437136467Ssimokawa
438181905Sed#if defined(GDB)
439136467Ssimokawa/* Debugger interface */
440136467Ssimokawa
441136467Ssimokawastatic int
442181905Seddcons_os_getc(struct dcons_softc *dc)
443181905Sed{
444181905Sed	int c;
445181905Sed
446181905Sed	while ((c = dcons_os_checkc(dc)) == -1);
447181905Sed
448181905Sed	return (c & 0xff);
449181905Sed}
450181905Sed
451181905Sedstatic int
452136467Ssimokawadcons_dbg_probe(void)
453136467Ssimokawa{
454170537Ssimokawa	int dcons_gdb;
455170537Ssimokawa
456170537Ssimokawa	if (getenv_int("dcons_gdb", &dcons_gdb) == 0)
457170537Ssimokawa		return (-1);
458170537Ssimokawa	return (dcons_gdb);
459136467Ssimokawa}
460136467Ssimokawa
461136467Ssimokawastatic void
462136467Ssimokawadcons_dbg_init(void)
463136467Ssimokawa{
464136467Ssimokawa}
465136467Ssimokawa
466136467Ssimokawastatic void
467136467Ssimokawadcons_dbg_term(void)
468136467Ssimokawa{
469136467Ssimokawa}
470136467Ssimokawa
471136467Ssimokawastatic void
472136467Ssimokawadcons_dbg_putc(int c)
473136467Ssimokawa{
474136467Ssimokawa	struct dcons_softc *dc = &sc[DCONS_GDB];
475136467Ssimokawa	dcons_os_putc(dc, c);
476136467Ssimokawa}
477136467Ssimokawa
478136467Ssimokawastatic int
479136467Ssimokawadcons_dbg_getc(void)
480136467Ssimokawa{
481136467Ssimokawa	struct dcons_softc *dc = &sc[DCONS_GDB];
482136467Ssimokawa	return (dcons_os_getc(dc));
483136467Ssimokawa}
484136467Ssimokawa#endif
485136467Ssimokawa
486136467SsimokawaDEV_MODULE(dcons, dcons_modevent, NULL);
487136467SsimokawaMODULE_VERSION(dcons, DCONS_VERSION);
488