dcons_os.c revision 247005
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 247005 2013-02-19 18:22:25Z mav $ 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