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