xref: /freebsd/sys/dev/dcons/dcons.c (revision 5a11c2d9ea85e0111b6cb29f790fd1c09b8fd0cc)
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