1869093b1SHidetoshi Shimokawa /* 2869093b1SHidetoshi Shimokawa * Copyright (C) 2003 3869093b1SHidetoshi Shimokawa * Hidetoshi Shimokawa. All rights reserved. 4869093b1SHidetoshi Shimokawa * 5869093b1SHidetoshi Shimokawa * Redistribution and use in source and binary forms, with or without 6869093b1SHidetoshi Shimokawa * modification, are permitted provided that the following conditions 7869093b1SHidetoshi Shimokawa * are met: 8869093b1SHidetoshi Shimokawa * 1. Redistributions of source code must retain the above copyright 9869093b1SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer. 10869093b1SHidetoshi Shimokawa * 2. Redistributions in binary form must reproduce the above copyright 11869093b1SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer in the 12869093b1SHidetoshi Shimokawa * documentation and/or other materials provided with the distribution. 13869093b1SHidetoshi Shimokawa * 3. All advertising materials mentioning features or use of this software 14869093b1SHidetoshi Shimokawa * must display the following acknowledgement: 15869093b1SHidetoshi Shimokawa * 16869093b1SHidetoshi Shimokawa * This product includes software developed by Hidetoshi Shimokawa. 17869093b1SHidetoshi Shimokawa * 18869093b1SHidetoshi Shimokawa * 4. Neither the name of the author nor the names of its contributors 19869093b1SHidetoshi Shimokawa * may be used to endorse or promote products derived from this software 20869093b1SHidetoshi Shimokawa * without specific prior written permission. 21869093b1SHidetoshi Shimokawa * 22869093b1SHidetoshi Shimokawa * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23869093b1SHidetoshi Shimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24869093b1SHidetoshi Shimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25869093b1SHidetoshi Shimokawa * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26869093b1SHidetoshi Shimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27869093b1SHidetoshi Shimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28869093b1SHidetoshi Shimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29869093b1SHidetoshi Shimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30869093b1SHidetoshi Shimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31869093b1SHidetoshi Shimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32869093b1SHidetoshi Shimokawa * SUCH DAMAGE. 33869093b1SHidetoshi Shimokawa * 34869093b1SHidetoshi Shimokawa * $Id: dcons.c,v 1.65 2003/10/24 03:24:55 simokawa Exp $ 35869093b1SHidetoshi Shimokawa * $FreeBSD$ 36869093b1SHidetoshi Shimokawa */ 37869093b1SHidetoshi Shimokawa 38869093b1SHidetoshi Shimokawa #include <sys/param.h> 3920021e6aSHidetoshi Shimokawa #if __FreeBSD_version >= 502122 40ed9c21cdSMarcel Moolenaar #include <sys/kdb.h> 4120021e6aSHidetoshi Shimokawa #include <gdb/gdb.h> 4220021e6aSHidetoshi Shimokawa #endif 43869093b1SHidetoshi Shimokawa #include <sys/kernel.h> 44fe12f24bSPoul-Henning Kamp #include <sys/module.h> 45869093b1SHidetoshi Shimokawa #include <sys/systm.h> 46869093b1SHidetoshi Shimokawa #include <sys/types.h> 47869093b1SHidetoshi Shimokawa #include <sys/conf.h> 48869093b1SHidetoshi Shimokawa #include <sys/cons.h> 49869093b1SHidetoshi Shimokawa #include <sys/consio.h> 50869093b1SHidetoshi Shimokawa #include <sys/tty.h> 51869093b1SHidetoshi Shimokawa #include <sys/malloc.h> 52869093b1SHidetoshi Shimokawa #include <sys/proc.h> 53869093b1SHidetoshi Shimokawa #include <sys/ucred.h> 54869093b1SHidetoshi Shimokawa 55869093b1SHidetoshi Shimokawa #include <machine/bus.h> 56869093b1SHidetoshi Shimokawa 575a11c2d9SHidetoshi Shimokawa #ifdef __DragonFly__ 585a11c2d9SHidetoshi Shimokawa #include "dcons.h" 595a11c2d9SHidetoshi Shimokawa #else 60869093b1SHidetoshi Shimokawa #include <dev/dcons/dcons.h> 615a11c2d9SHidetoshi Shimokawa #endif 62869093b1SHidetoshi Shimokawa 63869093b1SHidetoshi Shimokawa #include <ddb/ddb.h> 64869093b1SHidetoshi Shimokawa #include <sys/reboot.h> 65869093b1SHidetoshi Shimokawa 66869093b1SHidetoshi Shimokawa #include <sys/sysctl.h> 67869093b1SHidetoshi Shimokawa 68869093b1SHidetoshi Shimokawa #include "opt_ddb.h" 69869093b1SHidetoshi Shimokawa #include "opt_comconsole.h" 70869093b1SHidetoshi Shimokawa #include "opt_dcons.h" 71869093b1SHidetoshi Shimokawa 72869093b1SHidetoshi Shimokawa #ifndef DCONS_POLL_HZ 73869093b1SHidetoshi Shimokawa #define DCONS_POLL_HZ 100 74869093b1SHidetoshi Shimokawa #endif 75869093b1SHidetoshi Shimokawa 76869093b1SHidetoshi Shimokawa #ifndef DCONS_BUF_SIZE 77869093b1SHidetoshi Shimokawa #define DCONS_BUF_SIZE (16*1024) 78869093b1SHidetoshi Shimokawa #endif 79869093b1SHidetoshi Shimokawa 80869093b1SHidetoshi Shimokawa #ifndef DCONS_FORCE_CONSOLE 815a11c2d9SHidetoshi Shimokawa #define DCONS_FORCE_CONSOLE 0 /* Mostly for FreeBSD-4/DragonFly */ 82869093b1SHidetoshi Shimokawa #endif 83869093b1SHidetoshi Shimokawa 8420021e6aSHidetoshi Shimokawa #ifndef DCONS_FORCE_GDB 8520021e6aSHidetoshi Shimokawa #define DCONS_FORCE_GDB 1 8620021e6aSHidetoshi Shimokawa #endif 8720021e6aSHidetoshi Shimokawa 88869093b1SHidetoshi Shimokawa #if __FreeBSD_version >= 500101 8920021e6aSHidetoshi Shimokawa #define CONS_NODEV 1 9020021e6aSHidetoshi Shimokawa #if __FreeBSD_version < 502122 9120021e6aSHidetoshi Shimokawa static struct consdev gdbconsdev; 9220021e6aSHidetoshi Shimokawa #endif 93869093b1SHidetoshi Shimokawa #endif 94869093b1SHidetoshi Shimokawa 95869093b1SHidetoshi Shimokawa static d_open_t dcons_open; 96869093b1SHidetoshi Shimokawa static d_close_t dcons_close; 975a11c2d9SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500104 985a11c2d9SHidetoshi Shimokawa static d_ioctl_t dcons_ioctl; 995a11c2d9SHidetoshi Shimokawa #endif 100869093b1SHidetoshi Shimokawa 101869093b1SHidetoshi Shimokawa static struct cdevsw dcons_cdevsw = { 1025a11c2d9SHidetoshi Shimokawa #ifdef __DragonFly__ 1035a11c2d9SHidetoshi Shimokawa #define CDEV_MAJOR 184 1045a11c2d9SHidetoshi Shimokawa "dcons", CDEV_MAJOR, D_TTY, NULL, 0, 1055a11c2d9SHidetoshi Shimokawa dcons_open, dcons_close, ttyread, ttywrite, dcons_ioctl, 1065a11c2d9SHidetoshi Shimokawa ttypoll, nommap, nostrategy, nodump, nopsize, 1075a11c2d9SHidetoshi Shimokawa #elif __FreeBSD_version >= 500104 108dc08ffecSPoul-Henning Kamp .d_version = D_VERSION, 109869093b1SHidetoshi Shimokawa .d_open = dcons_open, 110869093b1SHidetoshi Shimokawa .d_close = dcons_close, 111869093b1SHidetoshi Shimokawa .d_name = "dcons", 112dc08ffecSPoul-Henning Kamp .d_flags = D_TTY | D_NEEDGIANT, 113869093b1SHidetoshi Shimokawa #else 1145a11c2d9SHidetoshi Shimokawa #define CDEV_MAJOR 184 115869093b1SHidetoshi Shimokawa /* open */ dcons_open, 116869093b1SHidetoshi Shimokawa /* close */ dcons_close, 117869093b1SHidetoshi Shimokawa /* read */ ttyread, 118869093b1SHidetoshi Shimokawa /* write */ ttywrite, 119869093b1SHidetoshi Shimokawa /* ioctl */ dcons_ioctl, 120869093b1SHidetoshi Shimokawa /* poll */ ttypoll, 121869093b1SHidetoshi Shimokawa /* mmap */ nommap, 122869093b1SHidetoshi Shimokawa /* strategy */ nostrategy, 123869093b1SHidetoshi Shimokawa /* name */ "dcons", 124869093b1SHidetoshi Shimokawa /* major */ CDEV_MAJOR, 125869093b1SHidetoshi Shimokawa /* dump */ nodump, 126869093b1SHidetoshi Shimokawa /* psize */ nopsize, 1275a11c2d9SHidetoshi Shimokawa /* flags */ D_TTY, 128869093b1SHidetoshi Shimokawa #endif 129869093b1SHidetoshi Shimokawa }; 130869093b1SHidetoshi Shimokawa 131869093b1SHidetoshi Shimokawa #ifndef KLD_MODULE 132869093b1SHidetoshi Shimokawa static char bssbuf[DCONS_BUF_SIZE]; /* buf in bss */ 133869093b1SHidetoshi Shimokawa #endif 134869093b1SHidetoshi Shimokawa 13519b3bba3SHidetoshi Shimokawa /* global data */ 13619b3bba3SHidetoshi Shimokawa static struct dcons_global dg; 13719b3bba3SHidetoshi Shimokawa struct dcons_global *dcons_conf; 138869093b1SHidetoshi Shimokawa static int poll_hz = DCONS_POLL_HZ; 13919b3bba3SHidetoshi Shimokawa 140869093b1SHidetoshi Shimokawa SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console"); 141869093b1SHidetoshi Shimokawa SYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0, 142869093b1SHidetoshi Shimokawa "dcons polling rate"); 143869093b1SHidetoshi Shimokawa 144869093b1SHidetoshi Shimokawa static int drv_init = 0; 145869093b1SHidetoshi Shimokawa static struct callout dcons_callout; 14619b3bba3SHidetoshi Shimokawa struct dcons_buf *dcons_buf; /* for local dconschat */ 147869093b1SHidetoshi Shimokawa 1485a11c2d9SHidetoshi Shimokawa #ifdef __DragonFly__ 1495a11c2d9SHidetoshi Shimokawa #define DEV dev_t 1505a11c2d9SHidetoshi Shimokawa #define THREAD d_thread_t 1515a11c2d9SHidetoshi Shimokawa #elif __FreeBSD_version < 500000 1525a11c2d9SHidetoshi Shimokawa #define DEV dev_t 1535a11c2d9SHidetoshi Shimokawa #define THREAD struct proc 1545a11c2d9SHidetoshi Shimokawa #else 1555a11c2d9SHidetoshi Shimokawa #define DEV struct cdev * 1565a11c2d9SHidetoshi Shimokawa #define THREAD struct thread 1575a11c2d9SHidetoshi Shimokawa #endif 1585a11c2d9SHidetoshi Shimokawa 159869093b1SHidetoshi Shimokawa /* per device data */ 160869093b1SHidetoshi Shimokawa static struct dcons_softc { 1615a11c2d9SHidetoshi Shimokawa DEV dev; 162869093b1SHidetoshi Shimokawa struct dcons_ch o, i; 163869093b1SHidetoshi Shimokawa int brk_state; 16420021e6aSHidetoshi Shimokawa #define DC_GDB 1 165869093b1SHidetoshi Shimokawa int flags; 166869093b1SHidetoshi Shimokawa } sc[DCONS_NPORT]; 167869093b1SHidetoshi Shimokawa static void dcons_tty_start(struct tty *); 168869093b1SHidetoshi Shimokawa static int dcons_tty_param(struct tty *, struct termios *); 169869093b1SHidetoshi Shimokawa static void dcons_timeout(void *); 170869093b1SHidetoshi Shimokawa static int dcons_drv_init(int); 171869093b1SHidetoshi Shimokawa static int dcons_getc(struct dcons_softc *); 172869093b1SHidetoshi Shimokawa static int dcons_checkc(struct dcons_softc *); 173869093b1SHidetoshi Shimokawa static void dcons_putc(struct dcons_softc *, int); 174869093b1SHidetoshi Shimokawa 175869093b1SHidetoshi Shimokawa static cn_probe_t dcons_cnprobe; 176869093b1SHidetoshi Shimokawa static cn_init_t dcons_cninit; 177869093b1SHidetoshi Shimokawa static cn_getc_t dcons_cngetc; 178869093b1SHidetoshi Shimokawa static cn_checkc_t dcons_cncheckc; 179869093b1SHidetoshi Shimokawa static cn_putc_t dcons_cnputc; 180869093b1SHidetoshi Shimokawa 181869093b1SHidetoshi Shimokawa CONS_DRIVER(dcons, dcons_cnprobe, dcons_cninit, NULL, dcons_cngetc, 182869093b1SHidetoshi Shimokawa dcons_cncheckc, dcons_cnputc, NULL); 183869093b1SHidetoshi Shimokawa 18420021e6aSHidetoshi Shimokawa #if __FreeBSD_version >= 502122 18520021e6aSHidetoshi Shimokawa static gdb_probe_f dcons_dbg_probe; 18620021e6aSHidetoshi Shimokawa static gdb_init_f dcons_dbg_init; 18720021e6aSHidetoshi Shimokawa static gdb_term_f dcons_dbg_term; 18820021e6aSHidetoshi Shimokawa static gdb_getc_f dcons_dbg_getc; 18920021e6aSHidetoshi Shimokawa static gdb_checkc_f dcons_dbg_checkc; 19020021e6aSHidetoshi Shimokawa static gdb_putc_f dcons_dbg_putc; 19120021e6aSHidetoshi Shimokawa 19220021e6aSHidetoshi Shimokawa GDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term, 19320021e6aSHidetoshi Shimokawa dcons_dbg_checkc, dcons_dbg_getc, dcons_dbg_putc); 19420021e6aSHidetoshi Shimokawa 19520021e6aSHidetoshi Shimokawa extern struct gdb_dbgport *gdb_cur; 19620021e6aSHidetoshi Shimokawa #endif 19720021e6aSHidetoshi Shimokawa 198869093b1SHidetoshi Shimokawa static int 1995a11c2d9SHidetoshi Shimokawa dcons_open(DEV dev, int flag, int mode, THREAD *td) 200869093b1SHidetoshi Shimokawa { 201869093b1SHidetoshi Shimokawa struct tty *tp; 202869093b1SHidetoshi Shimokawa int unit, error, s; 203869093b1SHidetoshi Shimokawa 204869093b1SHidetoshi Shimokawa unit = minor(dev); 205869093b1SHidetoshi Shimokawa if (unit != 0) 206869093b1SHidetoshi Shimokawa return (ENXIO); 207869093b1SHidetoshi Shimokawa 208869093b1SHidetoshi Shimokawa tp = dev->si_tty = ttymalloc(dev->si_tty); 209869093b1SHidetoshi Shimokawa tp->t_oproc = dcons_tty_start; 210869093b1SHidetoshi Shimokawa tp->t_param = dcons_tty_param; 211869093b1SHidetoshi Shimokawa tp->t_stop = nottystop; 212869093b1SHidetoshi Shimokawa tp->t_dev = dev; 213869093b1SHidetoshi Shimokawa 214869093b1SHidetoshi Shimokawa error = 0; 215869093b1SHidetoshi Shimokawa 216869093b1SHidetoshi Shimokawa s = spltty(); 217869093b1SHidetoshi Shimokawa if ((tp->t_state & TS_ISOPEN) == 0) { 218869093b1SHidetoshi Shimokawa tp->t_state |= TS_CARR_ON; 219869093b1SHidetoshi Shimokawa ttychars(tp); 220869093b1SHidetoshi Shimokawa tp->t_iflag = TTYDEF_IFLAG; 221869093b1SHidetoshi Shimokawa tp->t_oflag = TTYDEF_OFLAG; 222869093b1SHidetoshi Shimokawa tp->t_cflag = TTYDEF_CFLAG|CLOCAL; 223869093b1SHidetoshi Shimokawa tp->t_lflag = TTYDEF_LFLAG; 224869093b1SHidetoshi Shimokawa tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 225869093b1SHidetoshi Shimokawa ttsetwater(tp); 226869093b1SHidetoshi Shimokawa } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { 227869093b1SHidetoshi Shimokawa splx(s); 228869093b1SHidetoshi Shimokawa return (EBUSY); 229869093b1SHidetoshi Shimokawa } 230869093b1SHidetoshi Shimokawa splx(s); 231869093b1SHidetoshi Shimokawa 2325a11c2d9SHidetoshi Shimokawa #if __FreeBSD_version < 502113 2335a11c2d9SHidetoshi Shimokawa error = (*linesw[tp->t_line].l_open)(dev, tp); 2345a11c2d9SHidetoshi Shimokawa #else 2352140d01bSPoul-Henning Kamp error = ttyld_open(tp, dev); 2365a11c2d9SHidetoshi Shimokawa #endif 237869093b1SHidetoshi Shimokawa 238869093b1SHidetoshi Shimokawa return (error); 239869093b1SHidetoshi Shimokawa } 240869093b1SHidetoshi Shimokawa 241869093b1SHidetoshi Shimokawa static int 2425a11c2d9SHidetoshi Shimokawa dcons_close(DEV dev, int flag, int mode, THREAD *td) 243869093b1SHidetoshi Shimokawa { 244869093b1SHidetoshi Shimokawa int unit; 245869093b1SHidetoshi Shimokawa struct tty *tp; 246869093b1SHidetoshi Shimokawa 247869093b1SHidetoshi Shimokawa unit = minor(dev); 248869093b1SHidetoshi Shimokawa if (unit != 0) 249869093b1SHidetoshi Shimokawa return (ENXIO); 250869093b1SHidetoshi Shimokawa 251869093b1SHidetoshi Shimokawa tp = dev->si_tty; 252869093b1SHidetoshi Shimokawa if (tp->t_state & TS_ISOPEN) { 2535a11c2d9SHidetoshi Shimokawa #if __FreeBSD_version < 502113 2545a11c2d9SHidetoshi Shimokawa (*linesw[tp->t_line].l_close)(tp, flag); 2555a11c2d9SHidetoshi Shimokawa ttyclose(tp); 2565a11c2d9SHidetoshi Shimokawa #else 2572140d01bSPoul-Henning Kamp ttyld_close(tp, flag); 258672c05d4SPoul-Henning Kamp tty_close(tp); 2595a11c2d9SHidetoshi Shimokawa #endif 260869093b1SHidetoshi Shimokawa } 261869093b1SHidetoshi Shimokawa 262869093b1SHidetoshi Shimokawa return (0); 263869093b1SHidetoshi Shimokawa } 264869093b1SHidetoshi Shimokawa 2655a11c2d9SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500104 2665a11c2d9SHidetoshi Shimokawa static int 2675a11c2d9SHidetoshi Shimokawa dcons_ioctl(DEV dev, u_long cmd, caddr_t data, int flag, THREAD *td) 2685a11c2d9SHidetoshi Shimokawa { 2695a11c2d9SHidetoshi Shimokawa int unit; 2705a11c2d9SHidetoshi Shimokawa struct tty *tp; 2715a11c2d9SHidetoshi Shimokawa int error; 2725a11c2d9SHidetoshi Shimokawa 2735a11c2d9SHidetoshi Shimokawa unit = minor(dev); 2745a11c2d9SHidetoshi Shimokawa if (unit != 0) 2755a11c2d9SHidetoshi Shimokawa return (ENXIO); 2765a11c2d9SHidetoshi Shimokawa 2775a11c2d9SHidetoshi Shimokawa tp = dev->si_tty; 2785a11c2d9SHidetoshi Shimokawa error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 2795a11c2d9SHidetoshi Shimokawa if (error != ENOIOCTL) 2805a11c2d9SHidetoshi Shimokawa return (error); 2815a11c2d9SHidetoshi Shimokawa 2825a11c2d9SHidetoshi Shimokawa error = ttioctl(tp, cmd, data, flag); 2835a11c2d9SHidetoshi Shimokawa if (error != ENOIOCTL) 2845a11c2d9SHidetoshi Shimokawa return (error); 2855a11c2d9SHidetoshi Shimokawa 2865a11c2d9SHidetoshi Shimokawa return (ENOTTY); 2875a11c2d9SHidetoshi Shimokawa } 2885a11c2d9SHidetoshi Shimokawa #endif 2895a11c2d9SHidetoshi Shimokawa 290869093b1SHidetoshi Shimokawa static int 291869093b1SHidetoshi Shimokawa dcons_tty_param(struct tty *tp, struct termios *t) 292869093b1SHidetoshi Shimokawa { 293869093b1SHidetoshi Shimokawa tp->t_ispeed = t->c_ispeed; 294869093b1SHidetoshi Shimokawa tp->t_ospeed = t->c_ospeed; 295869093b1SHidetoshi Shimokawa tp->t_cflag = t->c_cflag; 296869093b1SHidetoshi Shimokawa return 0; 297869093b1SHidetoshi Shimokawa } 298869093b1SHidetoshi Shimokawa 299869093b1SHidetoshi Shimokawa static void 300869093b1SHidetoshi Shimokawa dcons_tty_start(struct tty *tp) 301869093b1SHidetoshi Shimokawa { 302869093b1SHidetoshi Shimokawa struct dcons_softc *dc; 303869093b1SHidetoshi Shimokawa int s; 304869093b1SHidetoshi Shimokawa 305869093b1SHidetoshi Shimokawa dc = (struct dcons_softc *)tp->t_dev->si_drv1; 306869093b1SHidetoshi Shimokawa s = spltty(); 307869093b1SHidetoshi Shimokawa if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 308869093b1SHidetoshi Shimokawa ttwwakeup(tp); 309869093b1SHidetoshi Shimokawa return; 310869093b1SHidetoshi Shimokawa } 311869093b1SHidetoshi Shimokawa 312869093b1SHidetoshi Shimokawa tp->t_state |= TS_BUSY; 313869093b1SHidetoshi Shimokawa while (tp->t_outq.c_cc != 0) 314869093b1SHidetoshi Shimokawa dcons_putc(dc, getc(&tp->t_outq)); 315869093b1SHidetoshi Shimokawa tp->t_state &= ~TS_BUSY; 316869093b1SHidetoshi Shimokawa 317869093b1SHidetoshi Shimokawa ttwwakeup(tp); 318869093b1SHidetoshi Shimokawa splx(s); 319869093b1SHidetoshi Shimokawa } 320869093b1SHidetoshi Shimokawa 321869093b1SHidetoshi Shimokawa static void 322869093b1SHidetoshi Shimokawa dcons_timeout(void *v) 323869093b1SHidetoshi Shimokawa { 324869093b1SHidetoshi Shimokawa struct tty *tp; 325869093b1SHidetoshi Shimokawa struct dcons_softc *dc; 326869093b1SHidetoshi Shimokawa int i, c, polltime; 327869093b1SHidetoshi Shimokawa 328869093b1SHidetoshi Shimokawa for (i = 0; i < DCONS_NPORT; i ++) { 329869093b1SHidetoshi Shimokawa dc = &sc[i]; 330869093b1SHidetoshi Shimokawa tp = dc->dev->si_tty; 331869093b1SHidetoshi Shimokawa while ((c = dcons_checkc(dc)) != -1) 332869093b1SHidetoshi Shimokawa if (tp->t_state & TS_ISOPEN) 3335a11c2d9SHidetoshi Shimokawa #if __FreeBSD_version < 502113 3345a11c2d9SHidetoshi Shimokawa (*linesw[tp->t_line].l_rint)(c, tp); 3355a11c2d9SHidetoshi Shimokawa #else 3362140d01bSPoul-Henning Kamp ttyld_rint(tp, c); 3375a11c2d9SHidetoshi Shimokawa #endif 338869093b1SHidetoshi Shimokawa } 339869093b1SHidetoshi Shimokawa polltime = hz / poll_hz; 340869093b1SHidetoshi Shimokawa if (polltime < 1) 341869093b1SHidetoshi Shimokawa polltime = 1; 342869093b1SHidetoshi Shimokawa callout_reset(&dcons_callout, polltime, dcons_timeout, tp); 343869093b1SHidetoshi Shimokawa } 344869093b1SHidetoshi Shimokawa 345869093b1SHidetoshi Shimokawa static void 346869093b1SHidetoshi Shimokawa dcons_cnprobe(struct consdev *cp) 347869093b1SHidetoshi Shimokawa { 3485a11c2d9SHidetoshi Shimokawa #ifdef __DragonFly__ 3495a11c2d9SHidetoshi Shimokawa cp->cn_dev = make_dev(&dcons_cdevsw, DCONS_CON, 3505a11c2d9SHidetoshi Shimokawa UID_ROOT, GID_WHEEL, 0600, "dcons"); 3515a11c2d9SHidetoshi Shimokawa #elif __FreeBSD_version >= 501109 352869093b1SHidetoshi Shimokawa sprintf(cp->cn_name, "dcons"); 353869093b1SHidetoshi Shimokawa #else 354869093b1SHidetoshi Shimokawa cp->cn_dev = makedev(CDEV_MAJOR, DCONS_CON); 355869093b1SHidetoshi Shimokawa #endif 356869093b1SHidetoshi Shimokawa #if DCONS_FORCE_CONSOLE 357869093b1SHidetoshi Shimokawa cp->cn_pri = CN_REMOTE; 358869093b1SHidetoshi Shimokawa #else 359869093b1SHidetoshi Shimokawa cp->cn_pri = CN_NORMAL; 360869093b1SHidetoshi Shimokawa #endif 361869093b1SHidetoshi Shimokawa } 362869093b1SHidetoshi Shimokawa 363869093b1SHidetoshi Shimokawa static void 364869093b1SHidetoshi Shimokawa dcons_cninit(struct consdev *cp) 365869093b1SHidetoshi Shimokawa { 366869093b1SHidetoshi Shimokawa dcons_drv_init(0); 367869093b1SHidetoshi Shimokawa #if CONS_NODEV 368869093b1SHidetoshi Shimokawa cp->cn_arg 369869093b1SHidetoshi Shimokawa #else 370869093b1SHidetoshi Shimokawa cp->cn_dev->si_drv1 371869093b1SHidetoshi Shimokawa #endif 372869093b1SHidetoshi Shimokawa = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */ 373869093b1SHidetoshi Shimokawa } 374869093b1SHidetoshi Shimokawa 375869093b1SHidetoshi Shimokawa #if CONS_NODEV 376869093b1SHidetoshi Shimokawa static int 377869093b1SHidetoshi Shimokawa dcons_cngetc(struct consdev *cp) 378869093b1SHidetoshi Shimokawa { 379869093b1SHidetoshi Shimokawa return(dcons_getc((struct dcons_softc *)cp->cn_arg)); 380869093b1SHidetoshi Shimokawa } 381869093b1SHidetoshi Shimokawa static int 382869093b1SHidetoshi Shimokawa dcons_cncheckc(struct consdev *cp) 383869093b1SHidetoshi Shimokawa { 384869093b1SHidetoshi Shimokawa return(dcons_checkc((struct dcons_softc *)cp->cn_arg)); 385869093b1SHidetoshi Shimokawa } 386869093b1SHidetoshi Shimokawa static void 387869093b1SHidetoshi Shimokawa dcons_cnputc(struct consdev *cp, int c) 388869093b1SHidetoshi Shimokawa { 389869093b1SHidetoshi Shimokawa dcons_putc((struct dcons_softc *)cp->cn_arg, c); 390869093b1SHidetoshi Shimokawa } 391869093b1SHidetoshi Shimokawa #else 392869093b1SHidetoshi Shimokawa static int 3935a11c2d9SHidetoshi Shimokawa dcons_cngetc(DEV dev) 394869093b1SHidetoshi Shimokawa { 395869093b1SHidetoshi Shimokawa return(dcons_getc((struct dcons_softc *)dev->si_drv1)); 396869093b1SHidetoshi Shimokawa } 397869093b1SHidetoshi Shimokawa static int 3985a11c2d9SHidetoshi Shimokawa dcons_cncheckc(DEV dev) 399869093b1SHidetoshi Shimokawa { 400869093b1SHidetoshi Shimokawa return(dcons_checkc((struct dcons_softc *)dev->si_drv1)); 401869093b1SHidetoshi Shimokawa } 402869093b1SHidetoshi Shimokawa static void 4035a11c2d9SHidetoshi Shimokawa dcons_cnputc(DEV dev, int c) 404869093b1SHidetoshi Shimokawa { 405869093b1SHidetoshi Shimokawa dcons_putc((struct dcons_softc *)dev->si_drv1, c); 406869093b1SHidetoshi Shimokawa } 407869093b1SHidetoshi Shimokawa #endif 408869093b1SHidetoshi Shimokawa 409869093b1SHidetoshi Shimokawa static int 410869093b1SHidetoshi Shimokawa dcons_getc(struct dcons_softc *dc) 411869093b1SHidetoshi Shimokawa { 412869093b1SHidetoshi Shimokawa int c; 413869093b1SHidetoshi Shimokawa 414869093b1SHidetoshi Shimokawa while ((c = dcons_checkc(dc)) == -1); 415869093b1SHidetoshi Shimokawa 416869093b1SHidetoshi Shimokawa return (c & 0xff); 417869093b1SHidetoshi Shimokawa } 418869093b1SHidetoshi Shimokawa 419869093b1SHidetoshi Shimokawa static int 420869093b1SHidetoshi Shimokawa dcons_checkc(struct dcons_softc *dc) 421869093b1SHidetoshi Shimokawa { 422869093b1SHidetoshi Shimokawa unsigned char c; 423869093b1SHidetoshi Shimokawa u_int32_t ptr, pos, gen, next_gen; 424869093b1SHidetoshi Shimokawa struct dcons_ch *ch; 425869093b1SHidetoshi Shimokawa 426869093b1SHidetoshi Shimokawa ch = &dc->i; 427869093b1SHidetoshi Shimokawa 42819b3bba3SHidetoshi Shimokawa if (dg.dma_tag != NULL) 42919b3bba3SHidetoshi Shimokawa bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD); 430869093b1SHidetoshi Shimokawa ptr = ntohl(*ch->ptr); 431869093b1SHidetoshi Shimokawa gen = ptr >> DCONS_GEN_SHIFT; 432869093b1SHidetoshi Shimokawa pos = ptr & DCONS_POS_MASK; 433869093b1SHidetoshi Shimokawa if (gen == ch->gen && pos == ch->pos) 434869093b1SHidetoshi Shimokawa return (-1); 435869093b1SHidetoshi Shimokawa 436869093b1SHidetoshi Shimokawa next_gen = DCONS_NEXT_GEN(ch->gen); 437869093b1SHidetoshi Shimokawa /* XXX sanity check */ 438869093b1SHidetoshi Shimokawa if ((gen != ch->gen && gen != next_gen) 439869093b1SHidetoshi Shimokawa || (gen == ch->gen && pos < ch->pos)) { 440869093b1SHidetoshi Shimokawa /* generation skipped !! */ 441869093b1SHidetoshi Shimokawa /* XXX discard */ 442869093b1SHidetoshi Shimokawa ch->gen = gen; 443869093b1SHidetoshi Shimokawa ch->pos = pos; 444869093b1SHidetoshi Shimokawa return (-1); 445869093b1SHidetoshi Shimokawa } 446869093b1SHidetoshi Shimokawa 447869093b1SHidetoshi Shimokawa c = ch->buf[ch->pos]; 448869093b1SHidetoshi Shimokawa ch->pos ++; 449869093b1SHidetoshi Shimokawa if (ch->pos >= ch->size) { 450869093b1SHidetoshi Shimokawa ch->gen = next_gen; 451869093b1SHidetoshi Shimokawa ch->pos = 0; 452869093b1SHidetoshi Shimokawa } 453869093b1SHidetoshi Shimokawa 45420021e6aSHidetoshi Shimokawa #if __FreeBSD_version >= 502122 455ed9c21cdSMarcel Moolenaar #if KDB && ALT_BREAK_TO_DEBUGGER 45620021e6aSHidetoshi Shimokawa if (kdb_alt_break(c, &dc->brk_state)) { 45720021e6aSHidetoshi Shimokawa if ((dc->flags & DC_GDB) != 0) { 45820021e6aSHidetoshi Shimokawa if (gdb_cur == &dcons_gdb_dbgport) { 45920021e6aSHidetoshi Shimokawa kdb_dbbe_select("gdb"); 460869093b1SHidetoshi Shimokawa breakpoint(); 46120021e6aSHidetoshi Shimokawa } 46220021e6aSHidetoshi Shimokawa } else 46320021e6aSHidetoshi Shimokawa breakpoint(); 46420021e6aSHidetoshi Shimokawa } 46520021e6aSHidetoshi Shimokawa #endif 46620021e6aSHidetoshi Shimokawa #else 46720021e6aSHidetoshi Shimokawa #if DDB && ALT_BREAK_TO_DEBUGGER 46820021e6aSHidetoshi Shimokawa switch (dc->brk_state) { 46920021e6aSHidetoshi Shimokawa case STATE1: 47020021e6aSHidetoshi Shimokawa if (c == KEY_TILDE) 47120021e6aSHidetoshi Shimokawa dc->brk_state = STATE2; 47220021e6aSHidetoshi Shimokawa else 47320021e6aSHidetoshi Shimokawa dc->brk_state = STATE0; 47420021e6aSHidetoshi Shimokawa break; 47520021e6aSHidetoshi Shimokawa case STATE2: 47620021e6aSHidetoshi Shimokawa dc->brk_state = STATE0; 47720021e6aSHidetoshi Shimokawa if (c == KEY_CTRLB) { 47820021e6aSHidetoshi Shimokawa #if DCONS_FORCE_GDB 47920021e6aSHidetoshi Shimokawa if (dc->flags & DC_GDB) 48020021e6aSHidetoshi Shimokawa boothowto |= RB_GDB; 48120021e6aSHidetoshi Shimokawa #endif 48220021e6aSHidetoshi Shimokawa breakpoint(); 48320021e6aSHidetoshi Shimokawa } 48420021e6aSHidetoshi Shimokawa } 48520021e6aSHidetoshi Shimokawa if (c == KEY_CR) 48620021e6aSHidetoshi Shimokawa dc->brk_state = STATE1; 48720021e6aSHidetoshi Shimokawa #endif 488869093b1SHidetoshi Shimokawa #endif 489869093b1SHidetoshi Shimokawa return (c); 490869093b1SHidetoshi Shimokawa } 491869093b1SHidetoshi Shimokawa 492869093b1SHidetoshi Shimokawa static void 493869093b1SHidetoshi Shimokawa dcons_putc(struct dcons_softc *dc, int c) 494869093b1SHidetoshi Shimokawa { 495869093b1SHidetoshi Shimokawa struct dcons_ch *ch; 496869093b1SHidetoshi Shimokawa 497869093b1SHidetoshi Shimokawa ch = &dc->o; 498869093b1SHidetoshi Shimokawa 499869093b1SHidetoshi Shimokawa ch->buf[ch->pos] = c; 500869093b1SHidetoshi Shimokawa ch->pos ++; 501869093b1SHidetoshi Shimokawa if (ch->pos >= ch->size) { 502869093b1SHidetoshi Shimokawa ch->gen = DCONS_NEXT_GEN(ch->gen); 503869093b1SHidetoshi Shimokawa ch->pos = 0; 504869093b1SHidetoshi Shimokawa } 505869093b1SHidetoshi Shimokawa *ch->ptr = DCONS_MAKE_PTR(ch); 50619b3bba3SHidetoshi Shimokawa if (dg.dma_tag != NULL) 50719b3bba3SHidetoshi Shimokawa bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE); 508869093b1SHidetoshi Shimokawa } 509869093b1SHidetoshi Shimokawa 510869093b1SHidetoshi Shimokawa static int 511869093b1SHidetoshi Shimokawa dcons_init_port(int port, int offset, int size) 512869093b1SHidetoshi Shimokawa { 513869093b1SHidetoshi Shimokawa int osize; 514869093b1SHidetoshi Shimokawa struct dcons_softc *dc; 515869093b1SHidetoshi Shimokawa 516869093b1SHidetoshi Shimokawa dc = &sc[port]; 517869093b1SHidetoshi Shimokawa 518869093b1SHidetoshi Shimokawa osize = size * 3 / 4; 519869093b1SHidetoshi Shimokawa 520869093b1SHidetoshi Shimokawa dc->o.size = osize; 521869093b1SHidetoshi Shimokawa dc->i.size = size - osize; 52219b3bba3SHidetoshi Shimokawa dc->o.buf = (char *)dg.buf + offset; 523869093b1SHidetoshi Shimokawa dc->i.buf = dc->o.buf + osize; 524869093b1SHidetoshi Shimokawa dc->o.gen = dc->i.gen = 0; 525869093b1SHidetoshi Shimokawa dc->o.pos = dc->i.pos = 0; 52619b3bba3SHidetoshi Shimokawa dc->o.ptr = &dg.buf->optr[port]; 52719b3bba3SHidetoshi Shimokawa dc->i.ptr = &dg.buf->iptr[port]; 528869093b1SHidetoshi Shimokawa dc->brk_state = STATE0; 52919b3bba3SHidetoshi Shimokawa dg.buf->osize[port] = htonl(osize); 53019b3bba3SHidetoshi Shimokawa dg.buf->isize[port] = htonl(size - osize); 53119b3bba3SHidetoshi Shimokawa dg.buf->ooffset[port] = htonl(offset); 53219b3bba3SHidetoshi Shimokawa dg.buf->ioffset[port] = htonl(offset + osize); 53319b3bba3SHidetoshi Shimokawa dg.buf->optr[port] = DCONS_MAKE_PTR(&dc->o); 53419b3bba3SHidetoshi Shimokawa dg.buf->iptr[port] = DCONS_MAKE_PTR(&dc->i); 535869093b1SHidetoshi Shimokawa 536869093b1SHidetoshi Shimokawa return(0); 537869093b1SHidetoshi Shimokawa } 538869093b1SHidetoshi Shimokawa 539869093b1SHidetoshi Shimokawa static int 540869093b1SHidetoshi Shimokawa dcons_drv_init(int stage) 541869093b1SHidetoshi Shimokawa { 542869093b1SHidetoshi Shimokawa int size, size0, offset; 543869093b1SHidetoshi Shimokawa 544869093b1SHidetoshi Shimokawa if (drv_init) 545869093b1SHidetoshi Shimokawa return(drv_init); 546869093b1SHidetoshi Shimokawa 547869093b1SHidetoshi Shimokawa drv_init = -1; 548869093b1SHidetoshi Shimokawa 54919b3bba3SHidetoshi Shimokawa bzero(&dg, sizeof(dg)); 55019b3bba3SHidetoshi Shimokawa dcons_conf = &dg; 55119b3bba3SHidetoshi Shimokawa dg.cdev = &dcons_consdev; 55219b3bba3SHidetoshi Shimokawa dg.size = DCONS_BUF_SIZE; 553869093b1SHidetoshi Shimokawa 554869093b1SHidetoshi Shimokawa #ifndef KLD_MODULE 555869093b1SHidetoshi Shimokawa if (stage == 0) /* XXX or cold */ 556869093b1SHidetoshi Shimokawa /* 557869093b1SHidetoshi Shimokawa * DCONS_FORCE_CONSOLE == 1 and statically linked. 558869093b1SHidetoshi Shimokawa * called from cninit(). can't use contigmalloc yet . 559869093b1SHidetoshi Shimokawa */ 56019b3bba3SHidetoshi Shimokawa dg.buf = (struct dcons_buf *) bssbuf; 561869093b1SHidetoshi Shimokawa else 562869093b1SHidetoshi Shimokawa #endif 563869093b1SHidetoshi Shimokawa /* 564869093b1SHidetoshi Shimokawa * DCONS_FORCE_CONSOLE == 0 or kernel module case. 565869093b1SHidetoshi Shimokawa * if the module is loaded after boot, 56619b3bba3SHidetoshi Shimokawa * bssbuf could be non-continuous. 567869093b1SHidetoshi Shimokawa */ 56819b3bba3SHidetoshi Shimokawa dg.buf = (struct dcons_buf *) contigmalloc(dg.size, 569869093b1SHidetoshi Shimokawa M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul); 570869093b1SHidetoshi Shimokawa 57119b3bba3SHidetoshi Shimokawa dcons_buf = dg.buf; 572869093b1SHidetoshi Shimokawa offset = DCONS_HEADER_SIZE; 57319b3bba3SHidetoshi Shimokawa size = (dg.size - offset); 574869093b1SHidetoshi Shimokawa size0 = size * 3 / 4; 575869093b1SHidetoshi Shimokawa 576869093b1SHidetoshi Shimokawa dcons_init_port(0, offset, size0); 577869093b1SHidetoshi Shimokawa offset += size0; 578869093b1SHidetoshi Shimokawa dcons_init_port(1, offset, size - size0); 57919b3bba3SHidetoshi Shimokawa dg.buf->version = htonl(DCONS_VERSION); 58019b3bba3SHidetoshi Shimokawa dg.buf->magic = ntohl(DCONS_MAGIC); 58120021e6aSHidetoshi Shimokawa 58220021e6aSHidetoshi Shimokawa #if __FreeBSD_version < 502122 58320021e6aSHidetoshi Shimokawa #if DDB && DCONS_FORCE_GDB 58420021e6aSHidetoshi Shimokawa #if CONS_NODEV 58520021e6aSHidetoshi Shimokawa gdbconsdev.cn_arg = (void *)&sc[DCONS_GDB]; 58620021e6aSHidetoshi Shimokawa #if __FreeBSD_version >= 501109 58720021e6aSHidetoshi Shimokawa sprintf(gdbconsdev.cn_name, "dgdb"); 58820021e6aSHidetoshi Shimokawa #endif 58920021e6aSHidetoshi Shimokawa gdb_arg = &gdbconsdev; 5905a11c2d9SHidetoshi Shimokawa #elif defined(__DragonFly__) 5915a11c2d9SHidetoshi Shimokawa gdbdev = make_dev(&dcons_cdevsw, DCONS_GDB, 5925a11c2d9SHidetoshi Shimokawa UID_ROOT, GID_WHEEL, 0600, "dgdb"); 59320021e6aSHidetoshi Shimokawa #else 59420021e6aSHidetoshi Shimokawa gdbdev = makedev(CDEV_MAJOR, DCONS_GDB); 59520021e6aSHidetoshi Shimokawa #endif 59620021e6aSHidetoshi Shimokawa gdb_getc = dcons_cngetc; 59720021e6aSHidetoshi Shimokawa gdb_putc = dcons_cnputc; 59820021e6aSHidetoshi Shimokawa #endif 59920021e6aSHidetoshi Shimokawa #endif 600869093b1SHidetoshi Shimokawa drv_init = 1; 601869093b1SHidetoshi Shimokawa 602869093b1SHidetoshi Shimokawa return 0; 603869093b1SHidetoshi Shimokawa } 604869093b1SHidetoshi Shimokawa 605869093b1SHidetoshi Shimokawa 606869093b1SHidetoshi Shimokawa static int 607869093b1SHidetoshi Shimokawa dcons_attach_port(int port, char *name, int flags) 608869093b1SHidetoshi Shimokawa { 609869093b1SHidetoshi Shimokawa struct dcons_softc *dc; 610869093b1SHidetoshi Shimokawa struct tty *tp; 611869093b1SHidetoshi Shimokawa 612869093b1SHidetoshi Shimokawa dc = &sc[port]; 613869093b1SHidetoshi Shimokawa dc->flags = flags; 614869093b1SHidetoshi Shimokawa dc->dev = make_dev(&dcons_cdevsw, port, 615869093b1SHidetoshi Shimokawa UID_ROOT, GID_WHEEL, 0600, name); 616869093b1SHidetoshi Shimokawa tp = ttymalloc(NULL); 617869093b1SHidetoshi Shimokawa 618869093b1SHidetoshi Shimokawa dc->dev->si_drv1 = (void *)dc; 619869093b1SHidetoshi Shimokawa dc->dev->si_tty = tp; 620869093b1SHidetoshi Shimokawa 621869093b1SHidetoshi Shimokawa tp->t_oproc = dcons_tty_start; 622869093b1SHidetoshi Shimokawa tp->t_param = dcons_tty_param; 623869093b1SHidetoshi Shimokawa tp->t_stop = nottystop; 624869093b1SHidetoshi Shimokawa tp->t_dev = dc->dev; 625869093b1SHidetoshi Shimokawa 626869093b1SHidetoshi Shimokawa return(0); 627869093b1SHidetoshi Shimokawa } 628869093b1SHidetoshi Shimokawa 629869093b1SHidetoshi Shimokawa static int 630869093b1SHidetoshi Shimokawa dcons_attach(void) 631869093b1SHidetoshi Shimokawa { 632869093b1SHidetoshi Shimokawa int polltime; 633869093b1SHidetoshi Shimokawa 6345a11c2d9SHidetoshi Shimokawa #ifdef __DragonFly__ 6355a11c2d9SHidetoshi Shimokawa cdevsw_add(&dcons_cdevsw, -1, 0); 6365a11c2d9SHidetoshi Shimokawa #endif 637869093b1SHidetoshi Shimokawa dcons_attach_port(DCONS_CON, "dcons", 0); 63820021e6aSHidetoshi Shimokawa dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB); 639869093b1SHidetoshi Shimokawa #if __FreeBSD_version < 500000 640869093b1SHidetoshi Shimokawa callout_init(&dcons_callout); 641869093b1SHidetoshi Shimokawa #else 642869093b1SHidetoshi Shimokawa callout_init(&dcons_callout, 0); 643869093b1SHidetoshi Shimokawa #endif 644869093b1SHidetoshi Shimokawa polltime = hz / poll_hz; 645869093b1SHidetoshi Shimokawa if (polltime < 1) 646869093b1SHidetoshi Shimokawa polltime = 1; 647869093b1SHidetoshi Shimokawa callout_reset(&dcons_callout, polltime, dcons_timeout, NULL); 648869093b1SHidetoshi Shimokawa return(0); 649869093b1SHidetoshi Shimokawa } 650869093b1SHidetoshi Shimokawa 651869093b1SHidetoshi Shimokawa static int 652869093b1SHidetoshi Shimokawa dcons_detach(int port) 653869093b1SHidetoshi Shimokawa { 654869093b1SHidetoshi Shimokawa struct tty *tp; 655869093b1SHidetoshi Shimokawa struct dcons_softc *dc; 656869093b1SHidetoshi Shimokawa 657869093b1SHidetoshi Shimokawa dc = &sc[port]; 658869093b1SHidetoshi Shimokawa 659869093b1SHidetoshi Shimokawa tp = dc->dev->si_tty; 660869093b1SHidetoshi Shimokawa 661869093b1SHidetoshi Shimokawa if (tp->t_state & TS_ISOPEN) { 662869093b1SHidetoshi Shimokawa printf("dcons: still opened\n"); 6635a11c2d9SHidetoshi Shimokawa #if __FreeBSD_version < 502113 6645a11c2d9SHidetoshi Shimokawa (*linesw[tp->t_line].l_close)(tp, 0); 6655a11c2d9SHidetoshi Shimokawa tp->t_gen++; 6665a11c2d9SHidetoshi Shimokawa ttyclose(tp); 6675a11c2d9SHidetoshi Shimokawa ttwakeup(tp); 6685a11c2d9SHidetoshi Shimokawa ttwwakeup(tp); 6695a11c2d9SHidetoshi Shimokawa #else 6702140d01bSPoul-Henning Kamp ttyld_close(tp, 0); 671672c05d4SPoul-Henning Kamp tty_close(tp); 6725a11c2d9SHidetoshi Shimokawa #endif 673869093b1SHidetoshi Shimokawa } 674869093b1SHidetoshi Shimokawa /* XXX 675869093b1SHidetoshi Shimokawa * must wait until all device are closed. 676869093b1SHidetoshi Shimokawa */ 6775a11c2d9SHidetoshi Shimokawa #ifdef __DragonFly__ 6785a11c2d9SHidetoshi Shimokawa tsleep((void *)dc, 0, "dcodtc", hz/4); 6795a11c2d9SHidetoshi Shimokawa #else 680869093b1SHidetoshi Shimokawa tsleep((void *)dc, PWAIT, "dcodtc", hz/4); 6815a11c2d9SHidetoshi Shimokawa #endif 682869093b1SHidetoshi Shimokawa destroy_dev(dc->dev); 683869093b1SHidetoshi Shimokawa 684869093b1SHidetoshi Shimokawa return(0); 685869093b1SHidetoshi Shimokawa } 686869093b1SHidetoshi Shimokawa 687869093b1SHidetoshi Shimokawa 688869093b1SHidetoshi Shimokawa /* cnXXX works only for FreeBSD-5 */ 689869093b1SHidetoshi Shimokawa static int 690869093b1SHidetoshi Shimokawa dcons_modevent(module_t mode, int type, void *data) 691869093b1SHidetoshi Shimokawa { 692869093b1SHidetoshi Shimokawa int err = 0, ret; 693869093b1SHidetoshi Shimokawa 694869093b1SHidetoshi Shimokawa switch (type) { 695869093b1SHidetoshi Shimokawa case MOD_LOAD: 696869093b1SHidetoshi Shimokawa ret = dcons_drv_init(1); 697869093b1SHidetoshi Shimokawa dcons_attach(); 698869093b1SHidetoshi Shimokawa #if __FreeBSD_version >= 500000 699869093b1SHidetoshi Shimokawa if (ret == 0) { 700869093b1SHidetoshi Shimokawa dcons_cnprobe(&dcons_consdev); 701869093b1SHidetoshi Shimokawa dcons_cninit(&dcons_consdev); 702869093b1SHidetoshi Shimokawa cnadd(&dcons_consdev); 703869093b1SHidetoshi Shimokawa } 704869093b1SHidetoshi Shimokawa #endif 705869093b1SHidetoshi Shimokawa break; 706869093b1SHidetoshi Shimokawa case MOD_UNLOAD: 707869093b1SHidetoshi Shimokawa printf("dcons: unload\n"); 708869093b1SHidetoshi Shimokawa callout_stop(&dcons_callout); 70920021e6aSHidetoshi Shimokawa #if __FreeBSD_version < 502122 71020021e6aSHidetoshi Shimokawa #if DDB && DCONS_FORCE_GDB 71120021e6aSHidetoshi Shimokawa #if CONS_NODEV 71220021e6aSHidetoshi Shimokawa gdb_arg = NULL; 71320021e6aSHidetoshi Shimokawa #else 71420021e6aSHidetoshi Shimokawa gdbdev = NULL; 71520021e6aSHidetoshi Shimokawa #endif 71620021e6aSHidetoshi Shimokawa #endif 71720021e6aSHidetoshi Shimokawa #endif 718869093b1SHidetoshi Shimokawa #if __FreeBSD_version >= 500000 719869093b1SHidetoshi Shimokawa cnremove(&dcons_consdev); 720869093b1SHidetoshi Shimokawa #endif 721869093b1SHidetoshi Shimokawa dcons_detach(DCONS_CON); 72220021e6aSHidetoshi Shimokawa dcons_detach(DCONS_GDB); 72319b3bba3SHidetoshi Shimokawa dg.buf->magic = 0; 724869093b1SHidetoshi Shimokawa 72519b3bba3SHidetoshi Shimokawa contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF); 726869093b1SHidetoshi Shimokawa 727869093b1SHidetoshi Shimokawa break; 728869093b1SHidetoshi Shimokawa case MOD_SHUTDOWN: 729869093b1SHidetoshi Shimokawa break; 7303e019deaSPoul-Henning Kamp default: 7313e019deaSPoul-Henning Kamp err = EOPNOTSUPP; 7323e019deaSPoul-Henning Kamp break; 733869093b1SHidetoshi Shimokawa } 734869093b1SHidetoshi Shimokawa return(err); 735869093b1SHidetoshi Shimokawa } 736869093b1SHidetoshi Shimokawa 73720021e6aSHidetoshi Shimokawa #if __FreeBSD_version >= 502122 73820021e6aSHidetoshi Shimokawa /* Debugger interface */ 73920021e6aSHidetoshi Shimokawa 74020021e6aSHidetoshi Shimokawa static int 74120021e6aSHidetoshi Shimokawa dcons_dbg_probe(void) 74220021e6aSHidetoshi Shimokawa { 74320021e6aSHidetoshi Shimokawa return(DCONS_FORCE_GDB); 74420021e6aSHidetoshi Shimokawa } 74520021e6aSHidetoshi Shimokawa 74620021e6aSHidetoshi Shimokawa static void 74720021e6aSHidetoshi Shimokawa dcons_dbg_init(void) 74820021e6aSHidetoshi Shimokawa { 74920021e6aSHidetoshi Shimokawa } 75020021e6aSHidetoshi Shimokawa 75120021e6aSHidetoshi Shimokawa static void 75220021e6aSHidetoshi Shimokawa dcons_dbg_term(void) 75320021e6aSHidetoshi Shimokawa { 75420021e6aSHidetoshi Shimokawa } 75520021e6aSHidetoshi Shimokawa 75620021e6aSHidetoshi Shimokawa static void 75720021e6aSHidetoshi Shimokawa dcons_dbg_putc(int c) 75820021e6aSHidetoshi Shimokawa { 75920021e6aSHidetoshi Shimokawa dcons_putc(&sc[DCONS_GDB], c); 76020021e6aSHidetoshi Shimokawa } 76120021e6aSHidetoshi Shimokawa 76220021e6aSHidetoshi Shimokawa static int 76320021e6aSHidetoshi Shimokawa dcons_dbg_checkc(void) 76420021e6aSHidetoshi Shimokawa { 76520021e6aSHidetoshi Shimokawa return (dcons_checkc(&sc[DCONS_GDB])); 76620021e6aSHidetoshi Shimokawa } 76720021e6aSHidetoshi Shimokawa 76820021e6aSHidetoshi Shimokawa static int 76920021e6aSHidetoshi Shimokawa dcons_dbg_getc(void) 77020021e6aSHidetoshi Shimokawa { 77120021e6aSHidetoshi Shimokawa return (dcons_getc(&sc[DCONS_GDB])); 77220021e6aSHidetoshi Shimokawa } 77320021e6aSHidetoshi Shimokawa #endif 77420021e6aSHidetoshi Shimokawa 775869093b1SHidetoshi Shimokawa DEV_MODULE(dcons, dcons_modevent, NULL); 776869093b1SHidetoshi Shimokawa MODULE_VERSION(dcons, DCONS_VERSION); 777