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