diff options
Diffstat (limited to 'sys/dev/dcons')
-rw-r--r-- | sys/dev/dcons/dcons.c | 713 | ||||
-rw-r--r-- | sys/dev/dcons/dcons.h | 21 | ||||
-rw-r--r-- | sys/dev/dcons/dcons_crom.c | 9 | ||||
-rw-r--r-- | sys/dev/dcons/dcons_os.c | 746 | ||||
-rw-r--r-- | sys/dev/dcons/dcons_os.h | 44 |
5 files changed, 883 insertions, 650 deletions
diff --git a/sys/dev/dcons/dcons.c b/sys/dev/dcons/dcons.c index 284a3b0..b48a504 100644 --- a/sys/dev/dcons/dcons.c +++ b/sys/dev/dcons/dcons.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 + * Copyright (C) 2003,2004 * Hidetoshi Shimokawa. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,387 +36,42 @@ */ #include <sys/param.h> -#if __FreeBSD_version >= 502122 -#include <sys/kdb.h> -#include <gdb/gdb.h> -#endif -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/systm.h> -#include <sys/types.h> -#include <sys/conf.h> -#include <sys/cons.h> -#include <sys/consio.h> -#include <sys/tty.h> -#include <sys/malloc.h> -#include <sys/proc.h> -#include <sys/ucred.h> - -#include <machine/bus.h> -#ifdef __DragonFly__ +#if defined(__DragonFly__) || defined(_BOOT) #include "dcons.h" #else #include <dev/dcons/dcons.h> #endif -#include <ddb/ddb.h> -#include <sys/reboot.h> - -#include <sys/sysctl.h> - -#include "opt_ddb.h" -#include "opt_comconsole.h" -#include "opt_dcons.h" - -#ifndef DCONS_POLL_HZ -#define DCONS_POLL_HZ 100 -#endif - -#ifndef DCONS_BUF_SIZE -#define DCONS_BUF_SIZE (16*1024) -#endif - -#ifndef DCONS_FORCE_CONSOLE -#define DCONS_FORCE_CONSOLE 0 /* Mostly for FreeBSD-4/DragonFly */ -#endif - -#ifndef DCONS_FORCE_GDB -#define DCONS_FORCE_GDB 1 -#endif - -#if __FreeBSD_version >= 500101 -#define CONS_NODEV 1 -#if __FreeBSD_version < 502122 -static struct consdev gdbconsdev; -#endif -#endif - -static d_open_t dcons_open; -static d_close_t dcons_close; -#if defined(__DragonFly__) || __FreeBSD_version < 500104 -static d_ioctl_t dcons_ioctl; -#endif - -static struct cdevsw dcons_cdevsw = { -#ifdef __DragonFly__ -#define CDEV_MAJOR 184 - "dcons", CDEV_MAJOR, D_TTY, NULL, 0, - dcons_open, dcons_close, ttyread, ttywrite, dcons_ioctl, - ttypoll, nommap, nostrategy, nodump, nopsize, -#elif __FreeBSD_version >= 500104 - .d_version = D_VERSION, - .d_open = dcons_open, - .d_close = dcons_close, - .d_name = "dcons", - .d_flags = D_TTY | D_NEEDGIANT, -#else -#define CDEV_MAJOR 184 - /* open */ dcons_open, - /* close */ dcons_close, - /* read */ ttyread, - /* write */ ttywrite, - /* ioctl */ dcons_ioctl, - /* poll */ ttypoll, - /* mmap */ nommap, - /* strategy */ nostrategy, - /* name */ "dcons", - /* major */ CDEV_MAJOR, - /* dump */ nodump, - /* psize */ nopsize, - /* flags */ D_TTY, -#endif -}; - -#ifndef KLD_MODULE -static char bssbuf[DCONS_BUF_SIZE]; /* buf in bss */ -#endif - -/* global data */ -static struct dcons_global dg; -struct dcons_global *dcons_conf; -static int poll_hz = DCONS_POLL_HZ; - -SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console"); -SYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0, - "dcons polling rate"); - -static int drv_init = 0; -static struct callout dcons_callout; -struct dcons_buf *dcons_buf; /* for local dconschat */ - -#ifdef __DragonFly__ -#define DEV dev_t -#define THREAD d_thread_t -#elif __FreeBSD_version < 500000 -#define DEV dev_t -#define THREAD struct proc -#else -#define DEV struct cdev * -#define THREAD struct thread -#endif - -/* per device data */ -static struct dcons_softc { - DEV dev; - struct dcons_ch o, i; - int brk_state; -#define DC_GDB 1 - int flags; -} sc[DCONS_NPORT]; -static void dcons_tty_start(struct tty *); -static int dcons_tty_param(struct tty *, struct termios *); -static void dcons_timeout(void *); -static int dcons_drv_init(int); -static int dcons_getc(struct dcons_softc *); -static int dcons_checkc(struct dcons_softc *); -static void dcons_putc(struct dcons_softc *, int); - -static cn_probe_t dcons_cnprobe; -static cn_init_t dcons_cninit; -static cn_getc_t dcons_cngetc; -static cn_checkc_t dcons_cncheckc; -static cn_putc_t dcons_cnputc; - -CONS_DRIVER(dcons, dcons_cnprobe, dcons_cninit, NULL, dcons_cngetc, - dcons_cncheckc, dcons_cnputc, NULL); - -#if __FreeBSD_version >= 502122 -static gdb_probe_f dcons_dbg_probe; -static gdb_init_f dcons_dbg_init; -static gdb_term_f dcons_dbg_term; -static gdb_getc_f dcons_dbg_getc; -static gdb_checkc_f dcons_dbg_checkc; -static gdb_putc_f dcons_dbg_putc; - -GDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term, - dcons_dbg_checkc, dcons_dbg_getc, dcons_dbg_putc); - -extern struct gdb_dbgport *gdb_cur; -#endif - -static int -dcons_open(DEV dev, int flag, int mode, THREAD *td) -{ - struct tty *tp; - int unit, error, s; - - unit = minor(dev); - if (unit != 0) - return (ENXIO); - - tp = dev->si_tty = ttymalloc(dev->si_tty); - tp->t_oproc = dcons_tty_start; - tp->t_param = dcons_tty_param; - tp->t_stop = nottystop; - tp->t_dev = dev; - - error = 0; - - s = spltty(); - if ((tp->t_state & TS_ISOPEN) == 0) { - tp->t_state |= TS_CARR_ON; - ttychars(tp); - tp->t_iflag = TTYDEF_IFLAG; - tp->t_oflag = TTYDEF_OFLAG; - tp->t_cflag = TTYDEF_CFLAG|CLOCAL; - tp->t_lflag = TTYDEF_LFLAG; - tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; - ttsetwater(tp); - } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { - splx(s); - return (EBUSY); - } - splx(s); - -#if __FreeBSD_version < 502113 - error = (*linesw[tp->t_line].l_open)(dev, tp); -#else - error = ttyld_open(tp, dev); -#endif - - return (error); -} - -static int -dcons_close(DEV dev, int flag, int mode, THREAD *td) +int +dcons_ischar(struct dcons_softc *dc) { - int unit; - struct tty *tp; - - unit = minor(dev); - if (unit != 0) - return (ENXIO); - - tp = dev->si_tty; - if (tp->t_state & TS_ISOPEN) { -#if __FreeBSD_version < 502113 - (*linesw[tp->t_line].l_close)(tp, flag); - ttyclose(tp); -#else - ttyld_close(tp, flag); - tty_close(tp); -#endif - } - - return (0); -} - -#if defined(__DragonFly__) || __FreeBSD_version < 500104 -static int -dcons_ioctl(DEV dev, u_long cmd, caddr_t data, int flag, THREAD *td) -{ - int unit; - struct tty *tp; - int error; - - unit = minor(dev); - if (unit != 0) - return (ENXIO); - - tp = dev->si_tty; - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); - if (error != ENOIOCTL) - return (error); - - error = ttioctl(tp, cmd, data, flag); - if (error != ENOIOCTL) - return (error); - - return (ENOTTY); -} -#endif - -static int -dcons_tty_param(struct tty *tp, struct termios *t) -{ - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = t->c_cflag; - return 0; -} - -static void -dcons_tty_start(struct tty *tp) -{ - struct dcons_softc *dc; - int s; - - dc = (struct dcons_softc *)tp->t_dev->si_drv1; - s = spltty(); - if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - return; - } - - tp->t_state |= TS_BUSY; - while (tp->t_outq.c_cc != 0) - dcons_putc(dc, getc(&tp->t_outq)); - tp->t_state &= ~TS_BUSY; + u_int32_t ptr, pos, gen, next_gen; + struct dcons_ch *ch; - ttwwakeup(tp); - splx(s); -} + ch = &dc->i; -static void -dcons_timeout(void *v) -{ - struct tty *tp; - struct dcons_softc *dc; - int i, c, polltime; + ptr = ntohl(*ch->ptr); + gen = ptr >> DCONS_GEN_SHIFT; + pos = ptr & DCONS_POS_MASK; + if (gen == ch->gen && pos == ch->pos) + return (0); - for (i = 0; i < DCONS_NPORT; i ++) { - dc = &sc[i]; - tp = dc->dev->si_tty; - while ((c = dcons_checkc(dc)) != -1) - if (tp->t_state & TS_ISOPEN) -#if __FreeBSD_version < 502113 - (*linesw[tp->t_line].l_rint)(c, tp); -#else - ttyld_rint(tp, c); -#endif + next_gen = DCONS_NEXT_GEN(ch->gen); + /* XXX sanity check */ + if ((gen != ch->gen && gen != next_gen) + || (gen == ch->gen && pos < ch->pos)) { + /* generation skipped !! */ + /* XXX discard */ + ch->gen = gen; + ch->pos = pos; + return (0); } - polltime = hz / poll_hz; - if (polltime < 1) - polltime = 1; - callout_reset(&dcons_callout, polltime, dcons_timeout, tp); -} - -static void -dcons_cnprobe(struct consdev *cp) -{ -#ifdef __DragonFly__ - cp->cn_dev = make_dev(&dcons_cdevsw, DCONS_CON, - UID_ROOT, GID_WHEEL, 0600, "dcons"); -#elif __FreeBSD_version >= 501109 - sprintf(cp->cn_name, "dcons"); -#else - cp->cn_dev = makedev(CDEV_MAJOR, DCONS_CON); -#endif -#if DCONS_FORCE_CONSOLE - cp->cn_pri = CN_REMOTE; -#else - cp->cn_pri = CN_NORMAL; -#endif -} - -static void -dcons_cninit(struct consdev *cp) -{ - dcons_drv_init(0); -#if CONS_NODEV - cp->cn_arg -#else - cp->cn_dev->si_drv1 -#endif - = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */ -} - -#if CONS_NODEV -static int -dcons_cngetc(struct consdev *cp) -{ - return(dcons_getc((struct dcons_softc *)cp->cn_arg)); -} -static int -dcons_cncheckc(struct consdev *cp) -{ - return(dcons_checkc((struct dcons_softc *)cp->cn_arg)); -} -static void -dcons_cnputc(struct consdev *cp, int c) -{ - dcons_putc((struct dcons_softc *)cp->cn_arg, c); -} -#else -static int -dcons_cngetc(DEV dev) -{ - return(dcons_getc((struct dcons_softc *)dev->si_drv1)); -} -static int -dcons_cncheckc(DEV dev) -{ - return(dcons_checkc((struct dcons_softc *)dev->si_drv1)); -} -static void -dcons_cnputc(DEV dev, int c) -{ - dcons_putc((struct dcons_softc *)dev->si_drv1, c); -} -#endif - -static int -dcons_getc(struct dcons_softc *dc) -{ - int c; - while ((c = dcons_checkc(dc)) == -1); - - return (c & 0xff); + return (1); } -static int +int dcons_checkc(struct dcons_softc *dc) { unsigned char c; @@ -425,8 +80,6 @@ dcons_checkc(struct dcons_softc *dc) ch = &dc->i; - if (dg.dma_tag != NULL) - bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD); ptr = ntohl(*ch->ptr); gen = ptr >> DCONS_GEN_SHIFT; pos = ptr & DCONS_POS_MASK; @@ -451,45 +104,10 @@ dcons_checkc(struct dcons_softc *dc) ch->pos = 0; } -#if __FreeBSD_version >= 502122 -#if KDB && ALT_BREAK_TO_DEBUGGER - if (kdb_alt_break(c, &dc->brk_state)) { - if ((dc->flags & DC_GDB) != 0) { - if (gdb_cur == &dcons_gdb_dbgport) { - kdb_dbbe_select("gdb"); - breakpoint(); - } - } else - breakpoint(); - } -#endif -#else -#if DDB && ALT_BREAK_TO_DEBUGGER - switch (dc->brk_state) { - case STATE1: - if (c == KEY_TILDE) - dc->brk_state = STATE2; - else - dc->brk_state = STATE0; - break; - case STATE2: - dc->brk_state = STATE0; - if (c == KEY_CTRLB) { -#if DCONS_FORCE_GDB - if (dc->flags & DC_GDB) - boothowto |= RB_GDB; -#endif - breakpoint(); - } - } - if (c == KEY_CR) - dc->brk_state = STATE1; -#endif -#endif return (c); } -static void +void dcons_putc(struct dcons_softc *dc, int c) { struct dcons_ch *ch; @@ -503,12 +121,11 @@ dcons_putc(struct dcons_softc *dc, int c) ch->pos = 0; } *ch->ptr = DCONS_MAKE_PTR(ch); - if (dg.dma_tag != NULL) - bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE); } static int -dcons_init_port(int port, int offset, int size) +dcons_init_port(int port, int offset, int size, struct dcons_buf *buf, + struct dcons_softc *sc) { int osize; struct dcons_softc *dc; @@ -519,259 +136,71 @@ dcons_init_port(int port, int offset, int size) dc->o.size = osize; dc->i.size = size - osize; - dc->o.buf = (char *)dg.buf + offset; + dc->o.buf = (char *)buf + offset; dc->i.buf = dc->o.buf + osize; dc->o.gen = dc->i.gen = 0; dc->o.pos = dc->i.pos = 0; - dc->o.ptr = &dg.buf->optr[port]; - dc->i.ptr = &dg.buf->iptr[port]; + dc->o.ptr = &buf->optr[port]; + dc->i.ptr = &buf->iptr[port]; dc->brk_state = STATE0; - dg.buf->osize[port] = htonl(osize); - dg.buf->isize[port] = htonl(size - osize); - dg.buf->ooffset[port] = htonl(offset); - dg.buf->ioffset[port] = htonl(offset + osize); - dg.buf->optr[port] = DCONS_MAKE_PTR(&dc->o); - dg.buf->iptr[port] = DCONS_MAKE_PTR(&dc->i); + buf->osize[port] = htonl(osize); + buf->isize[port] = htonl(size - osize); + buf->ooffset[port] = htonl(offset); + buf->ioffset[port] = htonl(offset + osize); + buf->optr[port] = DCONS_MAKE_PTR(&dc->o); + buf->iptr[port] = DCONS_MAKE_PTR(&dc->i); return(0); } -static int -dcons_drv_init(int stage) -{ - int size, size0, offset; - - if (drv_init) - return(drv_init); - - drv_init = -1; - - bzero(&dg, sizeof(dg)); - dcons_conf = &dg; - dg.cdev = &dcons_consdev; - dg.size = DCONS_BUF_SIZE; - -#ifndef KLD_MODULE - if (stage == 0) /* XXX or cold */ - /* - * DCONS_FORCE_CONSOLE == 1 and statically linked. - * called from cninit(). can't use contigmalloc yet . - */ - dg.buf = (struct dcons_buf *) bssbuf; - else -#endif - /* - * DCONS_FORCE_CONSOLE == 0 or kernel module case. - * if the module is loaded after boot, - * bssbuf could be non-continuous. - */ - dg.buf = (struct dcons_buf *) contigmalloc(dg.size, - M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul); - - dcons_buf = dg.buf; - offset = DCONS_HEADER_SIZE; - size = (dg.size - offset); - size0 = size * 3 / 4; - - dcons_init_port(0, offset, size0); - offset += size0; - dcons_init_port(1, offset, size - size0); - dg.buf->version = htonl(DCONS_VERSION); - dg.buf->magic = ntohl(DCONS_MAGIC); - -#if __FreeBSD_version < 502122 -#if DDB && DCONS_FORCE_GDB -#if CONS_NODEV - gdbconsdev.cn_arg = (void *)&sc[DCONS_GDB]; -#if __FreeBSD_version >= 501109 - sprintf(gdbconsdev.cn_name, "dgdb"); -#endif - gdb_arg = &gdbconsdev; -#elif defined(__DragonFly__) - gdbdev = make_dev(&dcons_cdevsw, DCONS_GDB, - UID_ROOT, GID_WHEEL, 0600, "dgdb"); -#else - gdbdev = makedev(CDEV_MAJOR, DCONS_GDB); -#endif - gdb_getc = dcons_cngetc; - gdb_putc = dcons_cnputc; -#endif -#endif - drv_init = 1; - - return 0; -} - - -static int -dcons_attach_port(int port, char *name, int flags) +int +dcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc) { + int port, s; struct dcons_softc *dc; - struct tty *tp; - - dc = &sc[port]; - dc->flags = flags; - dc->dev = make_dev(&dcons_cdevsw, port, - UID_ROOT, GID_WHEEL, 0600, name); - tp = ttymalloc(NULL); - - dc->dev->si_drv1 = (void *)dc; - dc->dev->si_tty = tp; - - tp->t_oproc = dcons_tty_start; - tp->t_param = dcons_tty_param; - tp->t_stop = nottystop; - tp->t_dev = dc->dev; - - return(0); -} -static int -dcons_attach(void) -{ - int polltime; - -#ifdef __DragonFly__ - cdevsw_add(&dcons_cdevsw, -1, 0); -#endif - dcons_attach_port(DCONS_CON, "dcons", 0); - dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB); -#if __FreeBSD_version < 500000 - callout_init(&dcons_callout); -#else - callout_init(&dcons_callout, 0); -#endif - polltime = hz / poll_hz; - if (polltime < 1) - polltime = 1; - callout_reset(&dcons_callout, polltime, dcons_timeout, NULL); - return(0); -} - -static int -dcons_detach(int port) -{ - struct tty *tp; - struct dcons_softc *dc; - - dc = &sc[port]; - - tp = dc->dev->si_tty; - - if (tp->t_state & TS_ISOPEN) { - printf("dcons: still opened\n"); -#if __FreeBSD_version < 502113 - (*linesw[tp->t_line].l_close)(tp, 0); - tp->t_gen++; - ttyclose(tp); - ttwakeup(tp); - ttwwakeup(tp); -#else - ttyld_close(tp, 0); - tty_close(tp); -#endif - } - /* XXX - * must wait until all device are closed. - */ -#ifdef __DragonFly__ - tsleep((void *)dc, 0, "dcodtc", hz/4); -#else - tsleep((void *)dc, PWAIT, "dcodtc", hz/4); -#endif - destroy_dev(dc->dev); - - return(0); -} - - -/* cnXXX works only for FreeBSD-5 */ -static int -dcons_modevent(module_t mode, int type, void *data) -{ - int err = 0, ret; - - switch (type) { - case MOD_LOAD: - ret = dcons_drv_init(1); - dcons_attach(); -#if __FreeBSD_version >= 500000 - if (ret == 0) { - dcons_cnprobe(&dcons_consdev); - dcons_cninit(&dcons_consdev); - cnadd(&dcons_consdev); - } -#endif - break; - case MOD_UNLOAD: - printf("dcons: unload\n"); - callout_stop(&dcons_callout); -#if __FreeBSD_version < 502122 -#if DDB && DCONS_FORCE_GDB -#if CONS_NODEV - gdb_arg = NULL; -#else - gdbdev = NULL; -#endif -#endif -#endif -#if __FreeBSD_version >= 500000 - cnremove(&dcons_consdev); -#endif - dcons_detach(DCONS_CON); - dcons_detach(DCONS_GDB); - dg.buf->magic = 0; + if (buf->version != htonl(DCONS_VERSION)) + return (-1); - contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF); + s = DCONS_HEADER_SIZE; + for (port = 0; port < DCONS_NPORT; port ++) { + dc = &sc[port]; + dc->o.size = ntohl(buf->osize[port]); + dc->i.size = ntohl(buf->isize[port]); + dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]); + dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]); + dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT; + dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT; + dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK; + dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK; + dc->o.ptr = &buf->optr[port]; + dc->i.ptr = &buf->iptr[port]; + dc->brk_state = STATE0; - break; - case MOD_SHUTDOWN: - dg.buf->magic = 0; - break; - default: - err = EOPNOTSUPP; - break; + s += dc->o.size + dc->i.size; } - return(err); -} - -#if __FreeBSD_version >= 502122 -/* Debugger interface */ -static int -dcons_dbg_probe(void) -{ - return(DCONS_FORCE_GDB); -} + /* sanity check */ + if (s > size) + return (-1); -static void -dcons_dbg_init(void) -{ -} + buf->magic = ntohl(DCONS_MAGIC); -static void -dcons_dbg_term(void) -{ + return (0); } -static void -dcons_dbg_putc(int c) +void +dcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc) { - dcons_putc(&sc[DCONS_GDB], c); -} + int size0, size1, offset; -static int -dcons_dbg_checkc(void) -{ - return (dcons_checkc(&sc[DCONS_GDB])); -} + offset = DCONS_HEADER_SIZE; + size0 = (size - offset); + size1 = size0 * 3 / 4; /* console port buffer */ -static int -dcons_dbg_getc(void) -{ - return (dcons_getc(&sc[DCONS_GDB])); + dcons_init_port(0, offset, size1, buf, sc); + offset += size1; + dcons_init_port(1, offset, size0 - size1, buf, sc); + buf->version = htonl(DCONS_VERSION); + buf->magic = ntohl(DCONS_MAGIC); } -#endif - -DEV_MODULE(dcons, dcons_modevent, NULL); -MODULE_VERSION(dcons, DCONS_VERSION); diff --git a/sys/dev/dcons/dcons.h b/sys/dev/dcons/dcons.h index 6c25ee1..5fdc820 100644 --- a/sys/dev/dcons/dcons.h +++ b/sys/dev/dcons/dcons.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 + * Copyright (C) 2002-2004 * Hidetoshi Shimokawa. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -90,12 +90,17 @@ struct dcons_ch { #define STATE2 2 #ifdef _KERNEL -struct dcons_global { - struct consdev *cdev; - struct dcons_buf *buf; - size_t size; - bus_dma_tag_t dma_tag; - bus_dmamap_t dma_map; +struct dcons_softc { + struct dcons_ch o, i; + int brk_state; +#define DC_GDB 1 + int flags; + void *dev; }; -extern struct dcons_global *dcons_conf; + +int dcons_checkc(struct dcons_softc *); +int dcons_ischar(struct dcons_softc *); +void dcons_putc(struct dcons_softc *, int); +int dcons_load_buffer(struct dcons_buf *, int, struct dcons_softc *); +void dcons_init(struct dcons_buf *, int, struct dcons_softc *); #endif diff --git a/sys/dev/dcons/dcons_crom.c b/sys/dev/dcons/dcons_crom.c index f2518fd..32ae15a 100644 --- a/sys/dev/dcons/dcons_crom.c +++ b/sys/dev/dcons/dcons_crom.c @@ -46,10 +46,19 @@ #include <sys/bus.h> #include <machine/bus.h> +#ifdef __DragonFly__ +#include <bus/firewire/firewire.h> +#include <bus/firewire/firewirereg.h> +#include <bus/firewire/iec13213.h> +#include "dcons.h" +#include "dcons_os.h" +#else #include <dev/firewire/firewire.h> #include <dev/firewire/firewirereg.h> #include <dev/firewire/iec13213.h> #include <dev/dcons/dcons.h> +#include <dev/dcons/dcons_os.h> +#endif #include <sys/cons.h> diff --git a/sys/dev/dcons/dcons_os.c b/sys/dev/dcons/dcons_os.c new file mode 100644 index 0000000..7347336 --- /dev/null +++ b/sys/dev/dcons/dcons_os.c @@ -0,0 +1,746 @@ +/* + * Copyright (C) 2003,2004 + * Hidetoshi Shimokawa. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Hidetoshi Shimokawa. + * + * 4. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#if __FreeBSD_version >= 502122 +#include <sys/kdb.h> +#include <gdb/gdb.h> +#endif +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/conf.h> +#include <sys/cons.h> +#include <sys/consio.h> +#include <sys/tty.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/ucred.h> + +#include <machine/bus.h> + +#ifdef __DragonFly__ +#include "dcons.h" +#include "dcons_os.h" +#else +#include <dev/dcons/dcons.h> +#include <dev/dcons/dcons_os.h> +#endif + +#include <ddb/ddb.h> +#include <sys/reboot.h> + +#include <sys/sysctl.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + +#include "opt_ddb.h" +#include "opt_comconsole.h" +#include "opt_dcons.h" + +#ifndef DCONS_POLL_HZ +#define DCONS_POLL_HZ 100 +#endif + +#ifndef DCONS_BUF_SIZE +#define DCONS_BUF_SIZE (16*1024) +#endif + +#ifndef DCONS_FORCE_CONSOLE +#define DCONS_FORCE_CONSOLE 0 /* Mostly for FreeBSD-4/DragonFly */ +#endif + +#ifndef DCONS_FORCE_GDB +#define DCONS_FORCE_GDB 1 +#endif + +#if __FreeBSD_version >= 500101 +#define CONS_NODEV 1 +#if __FreeBSD_version < 502122 +static struct consdev gdbconsdev; +#endif +#endif + +static d_open_t dcons_open; +static d_close_t dcons_close; +#if defined(__DragonFly__) || __FreeBSD_version < 500104 +static d_ioctl_t dcons_ioctl; +#endif + +static struct cdevsw dcons_cdevsw = { +#ifdef __DragonFly__ +#define CDEV_MAJOR 184 + "dcons", CDEV_MAJOR, D_TTY, NULL, 0, + dcons_open, dcons_close, ttyread, ttywrite, dcons_ioctl, + ttypoll, nommap, nostrategy, nodump, nopsize, +#elif __FreeBSD_version >= 500104 + .d_version = D_VERSION, + .d_open = dcons_open, + .d_close = dcons_close, + .d_name = "dcons", + .d_flags = D_TTY | D_NEEDGIANT, +#else +#define CDEV_MAJOR 184 + /* open */ dcons_open, + /* close */ dcons_close, + /* read */ ttyread, + /* write */ ttywrite, + /* ioctl */ dcons_ioctl, + /* poll */ ttypoll, + /* mmap */ nommap, + /* strategy */ nostrategy, + /* name */ "dcons", + /* major */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ D_TTY, +#endif +}; + +#ifndef KLD_MODULE +static char bssbuf[DCONS_BUF_SIZE]; /* buf in bss */ +#endif + +/* global data */ +static struct dcons_global dg; +struct dcons_global *dcons_conf; +static int poll_hz = DCONS_POLL_HZ; + +static struct dcons_softc sc[DCONS_NPORT]; + +SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console"); +SYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0, + "dcons polling rate"); + +static int drv_init = 0; +static struct callout dcons_callout; +struct dcons_buf *dcons_buf; /* for local dconschat */ + +#ifdef __DragonFly__ +#define DEV dev_t +#define THREAD d_thread_t +#elif __FreeBSD_version < 500000 +#define DEV dev_t +#define THREAD struct proc +#else +#define DEV struct cdev * +#define THREAD struct thread +#endif + + +static void dcons_tty_start(struct tty *); +static int dcons_tty_param(struct tty *, struct termios *); +static void dcons_timeout(void *); +static int dcons_drv_init(int); + +static cn_probe_t dcons_cnprobe; +static cn_init_t dcons_cninit; +static cn_getc_t dcons_cngetc; +static cn_checkc_t dcons_cncheckc; +static cn_putc_t dcons_cnputc; + +CONS_DRIVER(dcons, dcons_cnprobe, dcons_cninit, NULL, dcons_cngetc, + dcons_cncheckc, dcons_cnputc, NULL); + +#if __FreeBSD_version >= 502122 +static gdb_probe_f dcons_dbg_probe; +static gdb_init_f dcons_dbg_init; +static gdb_term_f dcons_dbg_term; +static gdb_getc_f dcons_dbg_getc; +static gdb_checkc_f dcons_dbg_checkc; +static gdb_putc_f dcons_dbg_putc; + +GDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term, + dcons_dbg_checkc, dcons_dbg_getc, dcons_dbg_putc); + +extern struct gdb_dbgport *gdb_cur; +#endif + +#if (KDB || DDB) && ALT_BREAK_TO_DEBUGGER +static int +dcons_check_break(struct dcons_softc *dc, int c) +{ + if (c < 0) + return (c); + +#if __FreeBSD_version >= 502122 + if (kdb_alt_break(c, &dc->brk_state)) { + if ((dc->flags & DC_GDB) != 0) { + if (gdb_cur == &dcons_gdb_dbgport) { + kdb_dbbe_select("gdb"); + breakpoint(); + } + } else + breakpoint(); + } +#else + switch (dc->brk_state) { + case STATE1: + if (c == KEY_TILDE) + dc->brk_state = STATE2; + else + dc->brk_state = STATE0; + break; + case STATE2: + dc->brk_state = STATE0; + if (c == KEY_CTRLB) { +#if DCONS_FORCE_GDB + if (dc->flags & DC_GDB) + boothowto |= RB_GDB; +#endif + breakpoint(); + } + } + if (c == KEY_CR) + dc->brk_state = STATE1; +#endif + return (c); +} +#else +#define dcons_check_break(dc, c) (c) +#endif + +static int +dcons_os_checkc(struct dcons_softc *dc) +{ + int c; + + if (dg.dma_tag != NULL) + bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD); + + c = dcons_check_break(dc, dcons_checkc(dc)); + + if (dg.dma_tag != NULL) + bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREREAD); + + return (c); +} + +static int +dcons_os_getc(struct dcons_softc *dc) +{ + int c; + + while ((c = dcons_os_checkc(dc)) == -1); + + return (c & 0xff); +} + +static void +dcons_os_putc(struct dcons_softc *dc, int c) +{ + if (dg.dma_tag != NULL) + bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTWRITE); + + dcons_putc(dc, c); + + if (dg.dma_tag != NULL) + bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE); +} +static int +dcons_open(DEV dev, int flag, int mode, THREAD *td) +{ + struct tty *tp; + int unit, error, s; + + unit = minor(dev); + if (unit != 0) + return (ENXIO); + + tp = dev->si_tty = ttymalloc(dev->si_tty); + tp->t_oproc = dcons_tty_start; + tp->t_param = dcons_tty_param; + tp->t_stop = nottystop; + tp->t_dev = dev; + + error = 0; + + s = spltty(); + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_CARR_ON; + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG|CLOCAL; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; + ttsetwater(tp); + } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { + splx(s); + return (EBUSY); + } + splx(s); + +#if __FreeBSD_version < 502113 + error = (*linesw[tp->t_line].l_open)(dev, tp); +#else + error = ttyld_open(tp, dev); +#endif + + return (error); +} + +static int +dcons_close(DEV dev, int flag, int mode, THREAD *td) +{ + int unit; + struct tty *tp; + + unit = minor(dev); + if (unit != 0) + return (ENXIO); + + tp = dev->si_tty; + if (tp->t_state & TS_ISOPEN) { +#if __FreeBSD_version < 502113 + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); +#else + ttyld_close(tp, flag); + tty_close(tp); +#endif + } + + return (0); +} + +#if defined(__DragonFly__) || __FreeBSD_version < 500104 +static int +dcons_ioctl(DEV dev, u_long cmd, caddr_t data, int flag, THREAD *td) +{ + int unit; + struct tty *tp; + int error; + + unit = minor(dev); + if (unit != 0) + return (ENXIO); + + tp = dev->si_tty; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); + if (error != ENOIOCTL) + return (error); + + error = ttioctl(tp, cmd, data, flag); + if (error != ENOIOCTL) + return (error); + + return (ENOTTY); +} +#endif + +static int +dcons_tty_param(struct tty *tp, struct termios *t) +{ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + return 0; +} + +static void +dcons_tty_start(struct tty *tp) +{ + struct dcons_softc *dc; + int s; + + dc = (struct dcons_softc *)tp->t_dev->si_drv1; + s = spltty(); + if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { + ttwwakeup(tp); + return; + } + + tp->t_state |= TS_BUSY; + while (tp->t_outq.c_cc != 0) + dcons_os_putc(dc, getc(&tp->t_outq)); + tp->t_state &= ~TS_BUSY; + + ttwwakeup(tp); + splx(s); +} + +static void +dcons_timeout(void *v) +{ + struct tty *tp; + struct dcons_softc *dc; + int i, c, polltime; + + for (i = 0; i < DCONS_NPORT; i ++) { + dc = &sc[i]; + tp = ((DEV)dc->dev)->si_tty; + while ((c = dcons_os_checkc(dc)) != -1) + if (tp->t_state & TS_ISOPEN) +#if __FreeBSD_version < 502113 + (*linesw[tp->t_line].l_rint)(c, tp); +#else + ttyld_rint(tp, c); +#endif + } + polltime = hz / poll_hz; + if (polltime < 1) + polltime = 1; + callout_reset(&dcons_callout, polltime, dcons_timeout, tp); +} + +static void +dcons_cnprobe(struct consdev *cp) +{ +#ifdef __DragonFly__ + cp->cn_dev = make_dev(&dcons_cdevsw, DCONS_CON, + UID_ROOT, GID_WHEEL, 0600, "dcons"); +#elif __FreeBSD_version >= 501109 + sprintf(cp->cn_name, "dcons"); +#else + cp->cn_dev = makedev(CDEV_MAJOR, DCONS_CON); +#endif +#if DCONS_FORCE_CONSOLE + cp->cn_pri = CN_REMOTE; +#else + cp->cn_pri = CN_NORMAL; +#endif +} + +static void +dcons_cninit(struct consdev *cp) +{ + dcons_drv_init(0); +#if CONS_NODEV + cp->cn_arg +#else + cp->cn_dev->si_drv1 +#endif + = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */ +} + +#if CONS_NODEV +static int +dcons_cngetc(struct consdev *cp) +{ + struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg; + return (dcons_os_getc(dc)); +} +static int +dcons_cncheckc(struct consdev *cp) +{ + struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg; + return (dcons_os_checkc(dc)); +} +static void +dcons_cnputc(struct consdev *cp, int c) +{ + struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg; + dcons_os_putc(dc, c); +} +#else +static int +dcons_cngetc(DEV dev) +{ + struct dcons_softc *dc = (struct dcons_softc *)dev->si_drv1; + return (dcons_os_getc(dc)); +} +static int +dcons_cncheckc(DEV dev) +{ + struct dcons_softc *dc = (struct dcons_softc *)dev->si_drv1; + return (dcons_os_checkc(dc)); +} +static void +dcons_cnputc(DEV dev, int c) +{ + struct dcons_softc *dc = (struct dcons_softc *)dev->si_drv1; + dcons_os_putc(dc, c); +} +#endif + +static int +dcons_drv_init(int stage) +{ + int addr, size; + + if (drv_init) + return(drv_init); + + drv_init = -1; + + bzero(&dg, sizeof(dg)); + dcons_conf = &dg; + dg.cdev = &dcons_consdev; + dg.buf = NULL; + dg.size = DCONS_BUF_SIZE; + +#ifdef __i386__ + if (getenv_int("dcons.addr", &addr) > 0 && + getenv_int("dcons.size", &size) > 0) { + /* XXX P to V */ + dg.buf = (struct dcons_buf *)(KERNBASE + addr); + dg.size = size; + if (dcons_load_buffer(dg.buf, dg.size, sc) < 0) + dg.buf = NULL; + } +#endif + if (dg.buf != NULL) + goto ok; + +#ifndef KLD_MODULE + if (stage == 0) { /* XXX or cold */ + /* + * DCONS_FORCE_CONSOLE == 1 and statically linked. + * called from cninit(). can't use contigmalloc yet . + */ + dg.buf = (struct dcons_buf *) bssbuf; + dcons_init(dg.buf, dg.size, sc); + } else +#endif + { + /* + * DCONS_FORCE_CONSOLE == 0 or kernel module case. + * if the module is loaded after boot, + * bssbuf could be non-continuous. + */ + dg.buf = (struct dcons_buf *) contigmalloc(dg.size, + M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul); + dcons_init(dg.buf, dg.size, sc); + } + +ok: + dcons_buf = dg.buf; + +#if __FreeBSD_version < 502122 +#if DDB && DCONS_FORCE_GDB +#if CONS_NODEV + gdbconsdev.cn_arg = (void *)&sc[DCONS_GDB]; +#if __FreeBSD_version >= 501109 + sprintf(gdbconsdev.cn_name, "dgdb"); +#endif + gdb_arg = &gdbconsdev; +#elif defined(__DragonFly__) + gdbdev = make_dev(&dcons_cdevsw, DCONS_GDB, + UID_ROOT, GID_WHEEL, 0600, "dgdb"); +#else + gdbdev = makedev(CDEV_MAJOR, DCONS_GDB); +#endif + gdb_getc = dcons_cngetc; + gdb_putc = dcons_cnputc; +#endif +#endif + drv_init = 1; + + return 0; +} + + +static int +dcons_attach_port(int port, char *name, int flags) +{ + struct dcons_softc *dc; + struct tty *tp; + DEV dev; + + dc = &sc[port]; + dc->flags = flags; + dev = make_dev(&dcons_cdevsw, port, + UID_ROOT, GID_WHEEL, 0600, name); + dc->dev = (void *)dev; + tp = ttymalloc(NULL); + + dev->si_drv1 = (void *)dc; + dev->si_tty = tp; + + tp->t_oproc = dcons_tty_start; + tp->t_param = dcons_tty_param; + tp->t_stop = nottystop; + tp->t_dev = dc->dev; + + return(0); +} + +static int +dcons_attach(void) +{ + int polltime; + +#ifdef __DragonFly__ + cdevsw_add(&dcons_cdevsw, -1, 0); +#endif + dcons_attach_port(DCONS_CON, "dcons", 0); + dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB); +#if __FreeBSD_version < 500000 + callout_init(&dcons_callout); +#else + callout_init(&dcons_callout, 0); +#endif + polltime = hz / poll_hz; + if (polltime < 1) + polltime = 1; + callout_reset(&dcons_callout, polltime, dcons_timeout, NULL); + return(0); +} + +static int +dcons_detach(int port) +{ + struct tty *tp; + struct dcons_softc *dc; + + dc = &sc[port]; + + tp = ((DEV)dc->dev)->si_tty; + + if (tp->t_state & TS_ISOPEN) { + printf("dcons: still opened\n"); +#if __FreeBSD_version < 502113 + (*linesw[tp->t_line].l_close)(tp, 0); + tp->t_gen++; + ttyclose(tp); + ttwakeup(tp); + ttwwakeup(tp); +#else + ttyld_close(tp, 0); + tty_close(tp); +#endif + } + /* XXX + * must wait until all device are closed. + */ +#ifdef __DragonFly__ + tsleep((void *)dc, 0, "dcodtc", hz/4); +#else + tsleep((void *)dc, PWAIT, "dcodtc", hz/4); +#endif + destroy_dev(dc->dev); + + return(0); +} + + +/* cnXXX works only for FreeBSD-5 */ +static int +dcons_modevent(module_t mode, int type, void *data) +{ + int err = 0, ret; + + switch (type) { + case MOD_LOAD: + ret = dcons_drv_init(1); + dcons_attach(); +#if __FreeBSD_version >= 500000 + if (ret == 0) { + dcons_cnprobe(&dcons_consdev); + dcons_cninit(&dcons_consdev); + cnadd(&dcons_consdev); + } +#endif + break; + case MOD_UNLOAD: + printf("dcons: unload\n"); + callout_stop(&dcons_callout); +#if __FreeBSD_version < 502122 +#if DDB && DCONS_FORCE_GDB +#if CONS_NODEV + gdb_arg = NULL; +#else + gdbdev = NULL; +#endif +#endif +#endif +#if __FreeBSD_version >= 500000 + cnremove(&dcons_consdev); +#endif + dcons_detach(DCONS_CON); + dcons_detach(DCONS_GDB); + dg.buf->magic = 0; + + contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF); + + break; + case MOD_SHUTDOWN: + dg.buf->magic = 0; + break; + default: + err = EOPNOTSUPP; + break; + } + return(err); +} + +#if __FreeBSD_version >= 502122 +/* Debugger interface */ + +static int +dcons_dbg_probe(void) +{ + return(DCONS_FORCE_GDB); +} + +static void +dcons_dbg_init(void) +{ +} + +static void +dcons_dbg_term(void) +{ +} + +static void +dcons_dbg_putc(int c) +{ + struct dcons_softc *dc = &sc[DCONS_GDB]; + dcons_os_putc(dc, c); +} + +static int +dcons_dbg_checkc(void) +{ + struct dcons_softc *dc = &sc[DCONS_GDB]; + return (dcons_os_checkc(dc)); +} + +static int +dcons_dbg_getc(void) +{ + struct dcons_softc *dc = &sc[DCONS_GDB]; + return (dcons_os_getc(dc)); +} +#endif + +DEV_MODULE(dcons, dcons_modevent, NULL); +MODULE_VERSION(dcons, DCONS_VERSION); diff --git a/sys/dev/dcons/dcons_os.h b/sys/dev/dcons/dcons_os.h new file mode 100644 index 0000000..f88738b --- /dev/null +++ b/sys/dev/dcons/dcons_os.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002-2004 + * Hidetoshi Shimokawa. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Hidetoshi Shimokawa. + * + * 4. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +struct dcons_global { + struct consdev *cdev; + struct dcons_buf *buf; + size_t size; + bus_dma_tag_t dma_tag; + bus_dmamap_t dma_map; +}; +extern struct dcons_global *dcons_conf; |