xref: /freebsd-src/sys/dev/dcons/dcons_os.c (revision d1bdc2821fcd416ab9b238580386eb605a6128d0)
1098ca2bdSWarner Losh /*-
2df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
3df57947fSPedro F. Giffuni  *
431a58777SHidetoshi Shimokawa  * Copyright (C) 2003,2004
531a58777SHidetoshi Shimokawa  * 	Hidetoshi Shimokawa. All rights reserved.
631a58777SHidetoshi Shimokawa  *
731a58777SHidetoshi Shimokawa  * Redistribution and use in source and binary forms, with or without
831a58777SHidetoshi Shimokawa  * modification, are permitted provided that the following conditions
931a58777SHidetoshi Shimokawa  * are met:
1031a58777SHidetoshi Shimokawa  * 1. Redistributions of source code must retain the above copyright
1131a58777SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer.
1231a58777SHidetoshi Shimokawa  * 2. Redistributions in binary form must reproduce the above copyright
1331a58777SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer in the
1431a58777SHidetoshi Shimokawa  *    documentation and/or other materials provided with the distribution.
1531a58777SHidetoshi Shimokawa  * 3. All advertising materials mentioning features or use of this software
1631a58777SHidetoshi Shimokawa  *    must display the following acknowledgement:
1731a58777SHidetoshi Shimokawa  *
1831a58777SHidetoshi Shimokawa  *	This product includes software developed by Hidetoshi Shimokawa.
1931a58777SHidetoshi Shimokawa  *
2031a58777SHidetoshi Shimokawa  * 4. Neither the name of the author nor the names of its contributors
2131a58777SHidetoshi Shimokawa  *    may be used to endorse or promote products derived from this software
2231a58777SHidetoshi Shimokawa  *    without specific prior written permission.
2331a58777SHidetoshi Shimokawa  *
2431a58777SHidetoshi Shimokawa  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2531a58777SHidetoshi Shimokawa  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2631a58777SHidetoshi Shimokawa  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2731a58777SHidetoshi Shimokawa  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2831a58777SHidetoshi Shimokawa  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2931a58777SHidetoshi Shimokawa  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3031a58777SHidetoshi Shimokawa  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3131a58777SHidetoshi Shimokawa  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3231a58777SHidetoshi Shimokawa  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3331a58777SHidetoshi Shimokawa  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3431a58777SHidetoshi Shimokawa  * SUCH DAMAGE.
3531a58777SHidetoshi Shimokawa  */
3631a58777SHidetoshi Shimokawa 
3731a58777SHidetoshi Shimokawa #include <sys/param.h>
38e2e050c8SConrad Meyer #include <sys/eventhandler.h>
3931a58777SHidetoshi Shimokawa #include <sys/kdb.h>
4031a58777SHidetoshi Shimokawa #include <gdb/gdb.h>
4131a58777SHidetoshi Shimokawa #include <sys/kernel.h>
4231a58777SHidetoshi Shimokawa #include <sys/module.h>
4331a58777SHidetoshi Shimokawa #include <sys/systm.h>
4431a58777SHidetoshi Shimokawa #include <sys/types.h>
4531a58777SHidetoshi Shimokawa #include <sys/conf.h>
4631a58777SHidetoshi Shimokawa #include <sys/cons.h>
4731a58777SHidetoshi Shimokawa #include <sys/consio.h>
4831a58777SHidetoshi Shimokawa #include <sys/tty.h>
4931a58777SHidetoshi Shimokawa #include <sys/malloc.h>
50acd3428bSRobert Watson #include <sys/priv.h>
5131a58777SHidetoshi Shimokawa #include <sys/proc.h>
5231a58777SHidetoshi Shimokawa #include <sys/ucred.h>
5331a58777SHidetoshi Shimokawa 
540eba88cfSIan Lepore #include <machine/atomic.h>
5531a58777SHidetoshi Shimokawa #include <machine/bus.h>
5631a58777SHidetoshi Shimokawa 
5731a58777SHidetoshi Shimokawa #include <dev/dcons/dcons.h>
5831a58777SHidetoshi Shimokawa #include <dev/dcons/dcons_os.h>
5931a58777SHidetoshi Shimokawa 
6031a58777SHidetoshi Shimokawa #include <ddb/ddb.h>
6131a58777SHidetoshi Shimokawa #include <sys/reboot.h>
6231a58777SHidetoshi Shimokawa 
6331a58777SHidetoshi Shimokawa #include <sys/sysctl.h>
6431a58777SHidetoshi Shimokawa 
6531a58777SHidetoshi Shimokawa #include <vm/vm.h>
6631a58777SHidetoshi Shimokawa #include <vm/vm_param.h>
6731a58777SHidetoshi Shimokawa #include <vm/pmap.h>
6831a58777SHidetoshi Shimokawa 
6931a58777SHidetoshi Shimokawa #include "opt_dcons.h"
70207bcebeSHidetoshi Shimokawa #include "opt_kdb.h"
71207bcebeSHidetoshi Shimokawa #include "opt_gdb.h"
72207bcebeSHidetoshi Shimokawa #include "opt_ddb.h"
73207bcebeSHidetoshi Shimokawa 
7431a58777SHidetoshi Shimokawa 
7531a58777SHidetoshi Shimokawa #ifndef DCONS_POLL_HZ
762dae467dSEd Schouten #define DCONS_POLL_HZ	25
7731a58777SHidetoshi Shimokawa #endif
7831a58777SHidetoshi Shimokawa 
79fd7e6827SAlexander Motin #ifndef DCONS_POLL_IDLE
80fd7e6827SAlexander Motin #define DCONS_POLL_IDLE	256
81fd7e6827SAlexander Motin #endif
82fd7e6827SAlexander Motin 
8331a58777SHidetoshi Shimokawa #ifndef DCONS_BUF_SIZE
8431a58777SHidetoshi Shimokawa #define DCONS_BUF_SIZE (16*1024)
8531a58777SHidetoshi Shimokawa #endif
8631a58777SHidetoshi Shimokawa 
8731a58777SHidetoshi Shimokawa #ifndef DCONS_FORCE_CONSOLE
8831a58777SHidetoshi Shimokawa #define DCONS_FORCE_CONSOLE	0	/* Mostly for FreeBSD-4/DragonFly */
8931a58777SHidetoshi Shimokawa #endif
9031a58777SHidetoshi Shimokawa 
9131a58777SHidetoshi Shimokawa #ifndef KLD_MODULE
9231a58777SHidetoshi Shimokawa static char bssbuf[DCONS_BUF_SIZE];	/* buf in bss */
9331a58777SHidetoshi Shimokawa #endif
9431a58777SHidetoshi Shimokawa 
9531a58777SHidetoshi Shimokawa /* global data */
9631a58777SHidetoshi Shimokawa static struct dcons_global dg;
9731a58777SHidetoshi Shimokawa struct dcons_global *dcons_conf;
9831a58777SHidetoshi Shimokawa static int poll_hz = DCONS_POLL_HZ;
99fd7e6827SAlexander Motin static u_int poll_idle = DCONS_POLL_HZ * DCONS_POLL_IDLE;
10031a58777SHidetoshi Shimokawa 
10131a58777SHidetoshi Shimokawa static struct dcons_softc sc[DCONS_NPORT];
10231a58777SHidetoshi Shimokawa 
1037029da5cSPawel Biernacki static SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
1047029da5cSPawel Biernacki     "Dumb Console");
10531a58777SHidetoshi Shimokawa SYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0,
10631a58777SHidetoshi Shimokawa 				"dcons polling rate");
10731a58777SHidetoshi Shimokawa 
10831a58777SHidetoshi Shimokawa static int drv_init = 0;
10931a58777SHidetoshi Shimokawa static struct callout dcons_callout;
11031a58777SHidetoshi Shimokawa struct dcons_buf *dcons_buf;		/* for local dconschat */
11131a58777SHidetoshi Shimokawa 
11231a58777SHidetoshi Shimokawa static void	dcons_timeout(void *);
11331a58777SHidetoshi Shimokawa static int	dcons_drv_init(int);
11431a58777SHidetoshi Shimokawa 
11531a58777SHidetoshi Shimokawa static cn_probe_t	dcons_cnprobe;
11631a58777SHidetoshi Shimokawa static cn_init_t	dcons_cninit;
117a58a1ea0SPoul-Henning Kamp static cn_term_t	dcons_cnterm;
11831a58777SHidetoshi Shimokawa static cn_getc_t	dcons_cngetc;
11931a58777SHidetoshi Shimokawa static cn_putc_t	dcons_cnputc;
1209976156fSAndriy Gapon static cn_grab_t	dcons_cngrab;
1219976156fSAndriy Gapon static cn_ungrab_t	dcons_cnungrab;
12231a58777SHidetoshi Shimokawa 
123a58a1ea0SPoul-Henning Kamp CONSOLE_DRIVER(dcons);
12431a58777SHidetoshi Shimokawa 
125bc093719SEd Schouten #if defined(GDB)
12631a58777SHidetoshi Shimokawa static gdb_probe_f	dcons_dbg_probe;
12731a58777SHidetoshi Shimokawa static gdb_init_f	dcons_dbg_init;
12831a58777SHidetoshi Shimokawa static gdb_term_f	dcons_dbg_term;
12931a58777SHidetoshi Shimokawa static gdb_getc_f	dcons_dbg_getc;
13031a58777SHidetoshi Shimokawa static gdb_putc_f	dcons_dbg_putc;
13131a58777SHidetoshi Shimokawa 
13231a58777SHidetoshi Shimokawa GDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term,
1339b188af1SPoul-Henning Kamp     dcons_dbg_getc, dcons_dbg_putc);
13431a58777SHidetoshi Shimokawa 
13531a58777SHidetoshi Shimokawa extern struct gdb_dbgport *gdb_cur;
13631a58777SHidetoshi Shimokawa #endif
13731a58777SHidetoshi Shimokawa 
138bc093719SEd Schouten static tsw_outwakeup_t dcons_outwakeup;
1390eba88cfSIan Lepore static tsw_free_t      dcons_free;
140bc093719SEd Schouten 
141bc093719SEd Schouten static struct ttydevsw dcons_ttydevsw = {
142bc093719SEd Schouten 	.tsw_flags      = TF_NOPREFIX,
143bc093719SEd Schouten 	.tsw_outwakeup  = dcons_outwakeup,
1440eba88cfSIan Lepore 	.tsw_free       = dcons_free,
145bc093719SEd Schouten };
146bc093719SEd Schouten 
1470eba88cfSIan Lepore static int dcons_close_refs;
1480eba88cfSIan Lepore 
1494cf75455SRobert Watson #if (defined(GDB) || defined(DDB))
15031a58777SHidetoshi Shimokawa static int
15131a58777SHidetoshi Shimokawa dcons_check_break(struct dcons_softc *dc, int c)
15231a58777SHidetoshi Shimokawa {
153bc093719SEd Schouten 
15431a58777SHidetoshi Shimokawa 	if (c < 0)
15531a58777SHidetoshi Shimokawa 		return (c);
15631a58777SHidetoshi Shimokawa 
1573080596eSHidetoshi Shimokawa #ifdef GDB
1584cf75455SRobert Watson 	if ((dc->flags & DC_GDB) != 0 && gdb_cur == &dcons_gdb_dbgport)
1594cf75455SRobert Watson 		kdb_alt_break_gdb(c, &dc->brk_state);
1604cf75455SRobert Watson 	else
161207bcebeSHidetoshi Shimokawa #endif
1624cf75455SRobert Watson 		kdb_alt_break(c, &dc->brk_state);
1634cf75455SRobert Watson 
16431a58777SHidetoshi Shimokawa 	return (c);
16531a58777SHidetoshi Shimokawa }
16631a58777SHidetoshi Shimokawa #else
16731a58777SHidetoshi Shimokawa #define	dcons_check_break(dc, c)	(c)
16831a58777SHidetoshi Shimokawa #endif
16931a58777SHidetoshi Shimokawa 
17031a58777SHidetoshi Shimokawa static int
171ff038e3aSHidetoshi Shimokawa dcons_os_checkc_nopoll(struct dcons_softc *dc)
17231a58777SHidetoshi Shimokawa {
17331a58777SHidetoshi Shimokawa 	int c;
17431a58777SHidetoshi Shimokawa 
17531a58777SHidetoshi Shimokawa 	if (dg.dma_tag != NULL)
17631a58777SHidetoshi Shimokawa 		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD);
17731a58777SHidetoshi Shimokawa 
17831a58777SHidetoshi Shimokawa 	c = dcons_check_break(dc, dcons_checkc(dc));
17931a58777SHidetoshi Shimokawa 
18031a58777SHidetoshi Shimokawa 	if (dg.dma_tag != NULL)
18131a58777SHidetoshi Shimokawa 		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREREAD);
18231a58777SHidetoshi Shimokawa 
18331a58777SHidetoshi Shimokawa 	return (c);
18431a58777SHidetoshi Shimokawa }
18531a58777SHidetoshi Shimokawa 
186ff038e3aSHidetoshi Shimokawa static int
187ff038e3aSHidetoshi Shimokawa dcons_os_checkc(struct dcons_softc *dc)
188ff038e3aSHidetoshi Shimokawa {
189ff038e3aSHidetoshi Shimokawa 	EVENTHANDLER_INVOKE(dcons_poll, 0);
190ff038e3aSHidetoshi Shimokawa 	return (dcons_os_checkc_nopoll(dc));
191ff038e3aSHidetoshi Shimokawa }
192ff038e3aSHidetoshi Shimokawa 
19331a58777SHidetoshi Shimokawa static void
19431a58777SHidetoshi Shimokawa dcons_os_putc(struct dcons_softc *dc, int c)
19531a58777SHidetoshi Shimokawa {
19631a58777SHidetoshi Shimokawa 	if (dg.dma_tag != NULL)
19731a58777SHidetoshi Shimokawa 		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTWRITE);
19831a58777SHidetoshi Shimokawa 
19931a58777SHidetoshi Shimokawa 	dcons_putc(dc, c);
20031a58777SHidetoshi Shimokawa 
20131a58777SHidetoshi Shimokawa 	if (dg.dma_tag != NULL)
20231a58777SHidetoshi Shimokawa 		bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE);
20331a58777SHidetoshi Shimokawa }
20431a58777SHidetoshi Shimokawa 
20531a58777SHidetoshi Shimokawa static void
2060eba88cfSIan Lepore dcons_free(void *xsc __unused)
2070eba88cfSIan Lepore {
2080eba88cfSIan Lepore 
2090eba88cfSIan Lepore 	/* Our deferred free has arrived, now we're waiting for one fewer. */
2100eba88cfSIan Lepore 	atomic_subtract_rel_int(&dcons_close_refs, 1);
2110eba88cfSIan Lepore }
2120eba88cfSIan Lepore 
2130eba88cfSIan Lepore static void
214bc093719SEd Schouten dcons_outwakeup(struct tty *tp)
21531a58777SHidetoshi Shimokawa {
21631a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
217bc093719SEd Schouten 	char ch;
21831a58777SHidetoshi Shimokawa 
219bc093719SEd Schouten 	dc = tty_softc(tp);
22031a58777SHidetoshi Shimokawa 
221bc093719SEd Schouten 	while (ttydisc_getc(tp, &ch, sizeof ch) != 0)
222bc093719SEd Schouten 		dcons_os_putc(dc, ch);
22331a58777SHidetoshi Shimokawa }
22431a58777SHidetoshi Shimokawa 
22531a58777SHidetoshi Shimokawa static void
22631a58777SHidetoshi Shimokawa dcons_timeout(void *v)
22731a58777SHidetoshi Shimokawa {
22831a58777SHidetoshi Shimokawa 	struct	tty *tp;
22931a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
23031a58777SHidetoshi Shimokawa 	int i, c, polltime;
23131a58777SHidetoshi Shimokawa 
23231a58777SHidetoshi Shimokawa 	for (i = 0; i < DCONS_NPORT; i ++) {
23331a58777SHidetoshi Shimokawa 		dc = &sc[i];
234bc093719SEd Schouten 		tp = dc->tty;
235bc093719SEd Schouten 
236bc093719SEd Schouten 		tty_lock(tp);
237fd7e6827SAlexander Motin 		while ((c = dcons_os_checkc_nopoll(dc)) != -1) {
238bc093719SEd Schouten 			ttydisc_rint(tp, c, 0);
239fd7e6827SAlexander Motin 			poll_idle = 0;
240fd7e6827SAlexander Motin 		}
241bc093719SEd Schouten 		ttydisc_rint_done(tp);
242bc093719SEd Schouten 		tty_unlock(tp);
24331a58777SHidetoshi Shimokawa 	}
244fd7e6827SAlexander Motin 	poll_idle++;
245fd7e6827SAlexander Motin 	polltime = hz;
246fd7e6827SAlexander Motin 	if (poll_idle <= (poll_hz * DCONS_POLL_IDLE))
247fd7e6827SAlexander Motin 		polltime /= poll_hz;
24831a58777SHidetoshi Shimokawa 	callout_reset(&dcons_callout, polltime, dcons_timeout, tp);
24931a58777SHidetoshi Shimokawa }
25031a58777SHidetoshi Shimokawa 
25131a58777SHidetoshi Shimokawa static void
25231a58777SHidetoshi Shimokawa dcons_cnprobe(struct consdev *cp)
25331a58777SHidetoshi Shimokawa {
25431a58777SHidetoshi Shimokawa 	sprintf(cp->cn_name, "dcons");
25531a58777SHidetoshi Shimokawa #if DCONS_FORCE_CONSOLE
25631a58777SHidetoshi Shimokawa 	cp->cn_pri = CN_REMOTE;
25731a58777SHidetoshi Shimokawa #else
25831a58777SHidetoshi Shimokawa 	cp->cn_pri = CN_NORMAL;
25931a58777SHidetoshi Shimokawa #endif
26031a58777SHidetoshi Shimokawa }
26131a58777SHidetoshi Shimokawa 
26231a58777SHidetoshi Shimokawa static void
26331a58777SHidetoshi Shimokawa dcons_cninit(struct consdev *cp)
26431a58777SHidetoshi Shimokawa {
26531a58777SHidetoshi Shimokawa 	dcons_drv_init(0);
266bc093719SEd Schouten 	cp->cn_arg = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */
26731a58777SHidetoshi Shimokawa }
26831a58777SHidetoshi Shimokawa 
269a58a1ea0SPoul-Henning Kamp static void
270a58a1ea0SPoul-Henning Kamp dcons_cnterm(struct consdev *cp)
271a58a1ea0SPoul-Henning Kamp {
272a58a1ea0SPoul-Henning Kamp }
273a58a1ea0SPoul-Henning Kamp 
2749976156fSAndriy Gapon static void
2759976156fSAndriy Gapon dcons_cngrab(struct consdev *cp)
2769976156fSAndriy Gapon {
2779976156fSAndriy Gapon }
2789976156fSAndriy Gapon 
2799976156fSAndriy Gapon static void
2809976156fSAndriy Gapon dcons_cnungrab(struct consdev *cp)
2819976156fSAndriy Gapon {
2829976156fSAndriy Gapon }
2839976156fSAndriy Gapon 
28431a58777SHidetoshi Shimokawa static int
28531a58777SHidetoshi Shimokawa dcons_cngetc(struct consdev *cp)
28631a58777SHidetoshi Shimokawa {
28731a58777SHidetoshi Shimokawa 	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
28831a58777SHidetoshi Shimokawa 	return (dcons_os_checkc(dc));
28931a58777SHidetoshi Shimokawa }
290bc093719SEd Schouten 
29131a58777SHidetoshi Shimokawa static void
29231a58777SHidetoshi Shimokawa dcons_cnputc(struct consdev *cp, int c)
29331a58777SHidetoshi Shimokawa {
29431a58777SHidetoshi Shimokawa 	struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
29531a58777SHidetoshi Shimokawa 	dcons_os_putc(dc, c);
29631a58777SHidetoshi Shimokawa }
29731a58777SHidetoshi Shimokawa 
29831a58777SHidetoshi Shimokawa static int
29931a58777SHidetoshi Shimokawa dcons_drv_init(int stage)
30031a58777SHidetoshi Shimokawa {
301520d7d18SHidetoshi Shimokawa #if defined(__i386__) || defined(__amd64__)
302c751e6f0SHidetoshi Shimokawa 	quad_t addr, size;
303370f9086SHidetoshi Shimokawa #endif
30431a58777SHidetoshi Shimokawa 
30531a58777SHidetoshi Shimokawa 	if (drv_init)
30631a58777SHidetoshi Shimokawa 		return(drv_init);
30731a58777SHidetoshi Shimokawa 
30831a58777SHidetoshi Shimokawa 	drv_init = -1;
30931a58777SHidetoshi Shimokawa 
31031a58777SHidetoshi Shimokawa 	bzero(&dg, sizeof(dg));
31131a58777SHidetoshi Shimokawa 	dcons_conf = &dg;
31231a58777SHidetoshi Shimokawa 	dg.cdev = &dcons_consdev;
31331a58777SHidetoshi Shimokawa 	dg.buf = NULL;
31431a58777SHidetoshi Shimokawa 	dg.size = DCONS_BUF_SIZE;
31531a58777SHidetoshi Shimokawa 
316520d7d18SHidetoshi Shimokawa #if defined(__i386__) || defined(__amd64__)
317c751e6f0SHidetoshi Shimokawa 	if (getenv_quad("dcons.addr", &addr) > 0 &&
318c751e6f0SHidetoshi Shimokawa 	    getenv_quad("dcons.size", &size) > 0) {
319520d7d18SHidetoshi Shimokawa #ifdef __i386__
320c751e6f0SHidetoshi Shimokawa 		vm_paddr_t pa;
321c751e6f0SHidetoshi Shimokawa 		/*
322c751e6f0SHidetoshi Shimokawa 		 * Allow read/write access to dcons buffer.
323c751e6f0SHidetoshi Shimokawa 		 */
324c751e6f0SHidetoshi Shimokawa 		for (pa = trunc_page(addr); pa < addr + size; pa += PAGE_SIZE)
3259a527560SKonstantin Belousov 			pmap_ksetrw(PMAP_MAP_LOW + pa);
326c751e6f0SHidetoshi Shimokawa 		invltlb();
327520d7d18SHidetoshi Shimokawa #endif
32831a58777SHidetoshi Shimokawa 		/* XXX P to V */
329d86c1f0dSKonstantin Belousov #ifdef __amd64__
330c751e6f0SHidetoshi Shimokawa 		dg.buf = (struct dcons_buf *)(vm_offset_t)(KERNBASE + addr);
331d86c1f0dSKonstantin Belousov #else /* __i386__ */
332a9fca3b9SJohn Baldwin 		dg.buf = (struct dcons_buf *)(vm_offset_t)(PMAP_MAP_LOW +
333d86c1f0dSKonstantin Belousov 		    addr);
334d86c1f0dSKonstantin Belousov #endif
33531a58777SHidetoshi Shimokawa 		dg.size = size;
33631a58777SHidetoshi Shimokawa 		if (dcons_load_buffer(dg.buf, dg.size, sc) < 0)
33731a58777SHidetoshi Shimokawa 			dg.buf = NULL;
33831a58777SHidetoshi Shimokawa 	}
33931a58777SHidetoshi Shimokawa #endif
34031a58777SHidetoshi Shimokawa 	if (dg.buf != NULL)
34131a58777SHidetoshi Shimokawa 		goto ok;
34231a58777SHidetoshi Shimokawa 
34331a58777SHidetoshi Shimokawa #ifndef KLD_MODULE
34431a58777SHidetoshi Shimokawa 	if (stage == 0) { /* XXX or cold */
34531a58777SHidetoshi Shimokawa 		/*
34631a58777SHidetoshi Shimokawa 		 * DCONS_FORCE_CONSOLE == 1 and statically linked.
34731a58777SHidetoshi Shimokawa 		 * called from cninit(). can't use contigmalloc yet .
34831a58777SHidetoshi Shimokawa 		 */
34931a58777SHidetoshi Shimokawa 		dg.buf = (struct dcons_buf *) bssbuf;
35031a58777SHidetoshi Shimokawa 		dcons_init(dg.buf, dg.size, sc);
35131a58777SHidetoshi Shimokawa 	} else
35231a58777SHidetoshi Shimokawa #endif
35331a58777SHidetoshi Shimokawa 	{
35431a58777SHidetoshi Shimokawa 		/*
35531a58777SHidetoshi Shimokawa 		 * DCONS_FORCE_CONSOLE == 0 or kernel module case.
35631a58777SHidetoshi Shimokawa 		 * if the module is loaded after boot,
35731a58777SHidetoshi Shimokawa 		 * bssbuf could be non-continuous.
35831a58777SHidetoshi Shimokawa 		 */
35931a58777SHidetoshi Shimokawa 		dg.buf = (struct dcons_buf *) contigmalloc(dg.size,
36031a58777SHidetoshi Shimokawa 			M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
3613da80d3aSMarius Strobl 		if (dg.buf == NULL)
3623da80d3aSMarius Strobl 			return (-1);
36331a58777SHidetoshi Shimokawa 		dcons_init(dg.buf, dg.size, sc);
36431a58777SHidetoshi Shimokawa 	}
36531a58777SHidetoshi Shimokawa 
36631a58777SHidetoshi Shimokawa ok:
36731a58777SHidetoshi Shimokawa 	dcons_buf = dg.buf;
36831a58777SHidetoshi Shimokawa 
36931a58777SHidetoshi Shimokawa 	drv_init = 1;
37031a58777SHidetoshi Shimokawa 
37131a58777SHidetoshi Shimokawa 	return 0;
37231a58777SHidetoshi Shimokawa }
37331a58777SHidetoshi Shimokawa 
37431a58777SHidetoshi Shimokawa 
37531a58777SHidetoshi Shimokawa static int
37631a58777SHidetoshi Shimokawa dcons_attach_port(int port, char *name, int flags)
37731a58777SHidetoshi Shimokawa {
37831a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
37931a58777SHidetoshi Shimokawa 	struct tty *tp;
38031a58777SHidetoshi Shimokawa 
38131a58777SHidetoshi Shimokawa 	dc = &sc[port];
382c5e30cc0SEd Schouten 	tp = tty_alloc(&dcons_ttydevsw, dc);
38331a58777SHidetoshi Shimokawa 	dc->flags = flags;
384bc093719SEd Schouten 	dc->tty   = tp;
3853fdd7f16SWarner Losh 	tty_init_console(tp, 0);
386bc093719SEd Schouten 	tty_makedev(tp, NULL, "%s", name);
38731a58777SHidetoshi Shimokawa 	return(0);
38831a58777SHidetoshi Shimokawa }
38931a58777SHidetoshi Shimokawa 
39031a58777SHidetoshi Shimokawa static int
39131a58777SHidetoshi Shimokawa dcons_attach(void)
39231a58777SHidetoshi Shimokawa {
39331a58777SHidetoshi Shimokawa 	int polltime;
39431a58777SHidetoshi Shimokawa 
39531a58777SHidetoshi Shimokawa 	dcons_attach_port(DCONS_CON, "dcons", 0);
39631a58777SHidetoshi Shimokawa 	dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB);
397fd90e2edSJung-uk Kim 	callout_init(&dcons_callout, 1);
39831a58777SHidetoshi Shimokawa 	polltime = hz / poll_hz;
39931a58777SHidetoshi Shimokawa 	callout_reset(&dcons_callout, polltime, dcons_timeout, NULL);
40031a58777SHidetoshi Shimokawa 	return(0);
40131a58777SHidetoshi Shimokawa }
40231a58777SHidetoshi Shimokawa 
40331a58777SHidetoshi Shimokawa static int
40431a58777SHidetoshi Shimokawa dcons_detach(int port)
40531a58777SHidetoshi Shimokawa {
40631a58777SHidetoshi Shimokawa 	struct	tty *tp;
40731a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
40831a58777SHidetoshi Shimokawa 
40931a58777SHidetoshi Shimokawa 	dc = &sc[port];
410bc093719SEd Schouten 	tp = dc->tty;
41131a58777SHidetoshi Shimokawa 
4120eba88cfSIan Lepore 	/* tty_rel_gone() schedules a deferred free callback, count it. */
4130eba88cfSIan Lepore 	atomic_add_int(&dcons_close_refs, 1);
414bc093719SEd Schouten 	tty_lock(tp);
415bc093719SEd Schouten 	tty_rel_gone(tp);
41631a58777SHidetoshi Shimokawa 
41731a58777SHidetoshi Shimokawa 	return(0);
41831a58777SHidetoshi Shimokawa }
41931a58777SHidetoshi Shimokawa 
42031a58777SHidetoshi Shimokawa static int
42131a58777SHidetoshi Shimokawa dcons_modevent(module_t mode, int type, void *data)
42231a58777SHidetoshi Shimokawa {
42331a58777SHidetoshi Shimokawa 	int err = 0, ret;
42431a58777SHidetoshi Shimokawa 
42531a58777SHidetoshi Shimokawa 	switch (type) {
42631a58777SHidetoshi Shimokawa 	case MOD_LOAD:
42731a58777SHidetoshi Shimokawa 		ret = dcons_drv_init(1);
4289ec7a1f5SAlexander Kabaev 		if (ret != -1)
4293da80d3aSMarius Strobl 			dcons_attach();
4309ec7a1f5SAlexander Kabaev 		if (ret == 0) {
43131a58777SHidetoshi Shimokawa 			dcons_cnprobe(&dcons_consdev);
43231a58777SHidetoshi Shimokawa 			dcons_cninit(&dcons_consdev);
43331a58777SHidetoshi Shimokawa 			cnadd(&dcons_consdev);
43431a58777SHidetoshi Shimokawa 		}
43531a58777SHidetoshi Shimokawa 		break;
43631a58777SHidetoshi Shimokawa 	case MOD_UNLOAD:
43731a58777SHidetoshi Shimokawa 		printf("dcons: unload\n");
4383da80d3aSMarius Strobl 		if (drv_init == 1) {
43931a58777SHidetoshi Shimokawa 			callout_stop(&dcons_callout);
44031a58777SHidetoshi Shimokawa 			cnremove(&dcons_consdev);
44131a58777SHidetoshi Shimokawa 			dcons_detach(DCONS_CON);
44231a58777SHidetoshi Shimokawa 			dcons_detach(DCONS_GDB);
44331a58777SHidetoshi Shimokawa 			dg.buf->magic = 0;
44431a58777SHidetoshi Shimokawa 
445*d1bdc282SBjoern A. Zeeb 			free(dg.buf, M_DEVBUF);
4463da80d3aSMarius Strobl 		}
44731a58777SHidetoshi Shimokawa 
4480eba88cfSIan Lepore 		/* Wait for tty deferred free callbacks to complete. */
4490eba88cfSIan Lepore 		while (atomic_load_acq_int(&dcons_close_refs) > 0)
4500eba88cfSIan Lepore                         pause_sbt("dcunld", mstosbt(50), mstosbt(10), 0);
45131a58777SHidetoshi Shimokawa 		break;
45231a58777SHidetoshi Shimokawa 	case MOD_SHUTDOWN:
45355f84274SHidetoshi Shimokawa #if 0		/* Keep connection after halt */
45431a58777SHidetoshi Shimokawa 		dg.buf->magic = 0;
45555f84274SHidetoshi Shimokawa #endif
45631a58777SHidetoshi Shimokawa 		break;
45731a58777SHidetoshi Shimokawa 	default:
45831a58777SHidetoshi Shimokawa 		err = EOPNOTSUPP;
45931a58777SHidetoshi Shimokawa 		break;
46031a58777SHidetoshi Shimokawa 	}
46131a58777SHidetoshi Shimokawa 	return(err);
46231a58777SHidetoshi Shimokawa }
46331a58777SHidetoshi Shimokawa 
464bc093719SEd Schouten #if defined(GDB)
46531a58777SHidetoshi Shimokawa /* Debugger interface */
46631a58777SHidetoshi Shimokawa 
46731a58777SHidetoshi Shimokawa static int
468bc093719SEd Schouten dcons_os_getc(struct dcons_softc *dc)
469bc093719SEd Schouten {
470bc093719SEd Schouten 	int c;
471bc093719SEd Schouten 
472bc093719SEd Schouten 	while ((c = dcons_os_checkc(dc)) == -1);
473bc093719SEd Schouten 
474bc093719SEd Schouten 	return (c & 0xff);
475bc093719SEd Schouten }
476bc093719SEd Schouten 
477bc093719SEd Schouten static int
47831a58777SHidetoshi Shimokawa dcons_dbg_probe(void)
47931a58777SHidetoshi Shimokawa {
48040ca0d57SHidetoshi Shimokawa 	int dcons_gdb;
48140ca0d57SHidetoshi Shimokawa 
48240ca0d57SHidetoshi Shimokawa 	if (getenv_int("dcons_gdb", &dcons_gdb) == 0)
48340ca0d57SHidetoshi Shimokawa 		return (-1);
48440ca0d57SHidetoshi Shimokawa 	return (dcons_gdb);
48531a58777SHidetoshi Shimokawa }
48631a58777SHidetoshi Shimokawa 
48731a58777SHidetoshi Shimokawa static void
48831a58777SHidetoshi Shimokawa dcons_dbg_init(void)
48931a58777SHidetoshi Shimokawa {
49031a58777SHidetoshi Shimokawa }
49131a58777SHidetoshi Shimokawa 
49231a58777SHidetoshi Shimokawa static void
49331a58777SHidetoshi Shimokawa dcons_dbg_term(void)
49431a58777SHidetoshi Shimokawa {
49531a58777SHidetoshi Shimokawa }
49631a58777SHidetoshi Shimokawa 
49731a58777SHidetoshi Shimokawa static void
49831a58777SHidetoshi Shimokawa dcons_dbg_putc(int c)
49931a58777SHidetoshi Shimokawa {
50031a58777SHidetoshi Shimokawa 	struct dcons_softc *dc = &sc[DCONS_GDB];
50131a58777SHidetoshi Shimokawa 	dcons_os_putc(dc, c);
50231a58777SHidetoshi Shimokawa }
50331a58777SHidetoshi Shimokawa 
50431a58777SHidetoshi Shimokawa static int
50531a58777SHidetoshi Shimokawa dcons_dbg_getc(void)
50631a58777SHidetoshi Shimokawa {
50731a58777SHidetoshi Shimokawa 	struct dcons_softc *dc = &sc[DCONS_GDB];
50831a58777SHidetoshi Shimokawa 	return (dcons_os_getc(dc));
50931a58777SHidetoshi Shimokawa }
51031a58777SHidetoshi Shimokawa #endif
51131a58777SHidetoshi Shimokawa 
51231a58777SHidetoshi Shimokawa DEV_MODULE(dcons, dcons_modevent, NULL);
51331a58777SHidetoshi Shimokawa MODULE_VERSION(dcons, DCONS_VERSION);
514