The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/dcons/dcons_os.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (C) 2003,2004
    3  *      Hidetoshi Shimokawa. All rights reserved.
    4  * 
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *
   16  *      This product includes software developed by Hidetoshi Shimokawa.
   17  *
   18  * 4. Neither the name of the author nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  * 
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  * 
   34  * $FreeBSD$
   35  */
   36 
   37 #include <sys/param.h>
   38 #if __FreeBSD_version >= 502122
   39 #include <sys/kdb.h>
   40 #include <gdb/gdb.h>
   41 #endif
   42 #include <sys/kernel.h>
   43 #include <sys/module.h>
   44 #include <sys/systm.h>
   45 #include <sys/types.h>
   46 #include <sys/conf.h>
   47 #include <sys/cons.h>
   48 #include <sys/consio.h>
   49 #include <sys/tty.h>
   50 #include <sys/malloc.h>
   51 #include <sys/priv.h>
   52 #include <sys/proc.h>
   53 #include <sys/ucred.h>
   54 
   55 #include <machine/bus.h>
   56 
   57 #ifdef __DragonFly__
   58 #include "dcons.h"
   59 #include "dcons_os.h"
   60 #else
   61 #include <dev/dcons/dcons.h>
   62 #include <dev/dcons/dcons_os.h>
   63 #endif
   64 
   65 #include <ddb/ddb.h>
   66 #include <sys/reboot.h>
   67 
   68 #include <sys/sysctl.h>
   69 
   70 #include <vm/vm.h>
   71 #include <vm/vm_param.h>
   72 #include <vm/pmap.h>
   73 
   74 #include "opt_comconsole.h"
   75 #include "opt_dcons.h"
   76 #include "opt_kdb.h"
   77 #include "opt_gdb.h"
   78 #include "opt_ddb.h"
   79 
   80 
   81 #ifndef DCONS_POLL_HZ
   82 #define DCONS_POLL_HZ   100
   83 #endif
   84 
   85 #ifndef DCONS_BUF_SIZE
   86 #define DCONS_BUF_SIZE (16*1024)
   87 #endif
   88 
   89 #ifndef DCONS_FORCE_CONSOLE
   90 #define DCONS_FORCE_CONSOLE     0       /* Mostly for FreeBSD-4/DragonFly */
   91 #endif
   92 
   93 #ifndef DCONS_FORCE_GDB
   94 #define DCONS_FORCE_GDB 1
   95 #endif
   96 
   97 #if __FreeBSD_version >= 500101
   98 #define CONS_NODEV      1
   99 #if __FreeBSD_version < 502122
  100 static struct consdev gdbconsdev;
  101 #endif
  102 #endif
  103 
  104 static d_open_t         dcons_open;
  105 static d_close_t        dcons_close;
  106 #if defined(__DragonFly__) || __FreeBSD_version < 500104
  107 static d_ioctl_t        dcons_ioctl;
  108 #endif
  109 
  110 static struct cdevsw dcons_cdevsw = {
  111 #ifdef __DragonFly__
  112 #define CDEV_MAJOR      184
  113         "dcons", CDEV_MAJOR, D_TTY, NULL, 0,
  114         dcons_open, dcons_close, ttyread, ttywrite, dcons_ioctl,
  115         ttypoll, nommap, nostrategy, nodump, nopsize,
  116 #elif __FreeBSD_version >= 500104
  117         .d_version =    D_VERSION,
  118         .d_open =       dcons_open,
  119         .d_close =      dcons_close,
  120         .d_name =       "dcons",
  121         .d_flags =      D_TTY | D_NEEDGIANT,
  122 #else
  123 #define CDEV_MAJOR      184
  124         /* open */      dcons_open,
  125         /* close */     dcons_close,
  126         /* read */      ttyread,
  127         /* write */     ttywrite,
  128         /* ioctl */     dcons_ioctl,
  129         /* poll */      ttypoll,
  130         /* mmap */      nommap,
  131         /* strategy */  nostrategy,
  132         /* name */      "dcons",
  133         /* major */     CDEV_MAJOR,
  134         /* dump */      nodump,
  135         /* psize */     nopsize,
  136         /* flags */     D_TTY,
  137 #endif
  138 };
  139 
  140 #ifndef KLD_MODULE
  141 static char bssbuf[DCONS_BUF_SIZE];     /* buf in bss */
  142 #endif
  143 
  144 /* global data */
  145 static struct dcons_global dg;
  146 struct dcons_global *dcons_conf;
  147 static int poll_hz = DCONS_POLL_HZ;
  148 
  149 static struct dcons_softc sc[DCONS_NPORT];
  150 
  151 SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console");
  152 SYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0,
  153                                 "dcons polling rate");
  154 
  155 static int drv_init = 0;
  156 static struct callout dcons_callout;
  157 struct dcons_buf *dcons_buf;            /* for local dconschat */
  158 
  159 #ifdef __DragonFly__
  160 #define DEV     dev_t
  161 #define THREAD  d_thread_t
  162 #elif __FreeBSD_version < 500000
  163 #define DEV     dev_t
  164 #define THREAD  struct proc
  165 #else
  166 #define DEV     struct cdev *
  167 #define THREAD  struct thread
  168 #endif
  169 
  170 
  171 static void     dcons_tty_start(struct tty *);
  172 static int      dcons_tty_param(struct tty *, struct termios *);
  173 static void     dcons_timeout(void *);
  174 static int      dcons_drv_init(int);
  175 
  176 static cn_probe_t       dcons_cnprobe;
  177 static cn_init_t        dcons_cninit;
  178 static cn_term_t        dcons_cnterm;
  179 static cn_getc_t        dcons_cngetc;
  180 static cn_putc_t        dcons_cnputc;
  181 
  182 CONSOLE_DRIVER(dcons);
  183 
  184 #if defined(GDB) && (__FreeBSD_version >= 502122)
  185 static gdb_probe_f dcons_dbg_probe;
  186 static gdb_init_f dcons_dbg_init;
  187 static gdb_term_f dcons_dbg_term;
  188 static gdb_getc_f dcons_dbg_getc;
  189 static gdb_putc_f dcons_dbg_putc;
  190 
  191 GDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term,
  192     dcons_dbg_getc, dcons_dbg_putc);
  193 
  194 extern struct gdb_dbgport *gdb_cur;
  195 #endif
  196 
  197 #if (defined(GDB) || defined(DDB)) && defined(ALT_BREAK_TO_DEBUGGER)
  198 static int
  199 dcons_check_break(struct dcons_softc *dc, int c)
  200 {
  201         if (c < 0)
  202                 return (c);
  203 
  204 #if __FreeBSD_version >= 502122
  205         if (kdb_alt_break(c, &dc->brk_state)) {
  206                 if ((dc->flags & DC_GDB) != 0) {
  207 #ifdef GDB
  208                         if (gdb_cur == &dcons_gdb_dbgport) {
  209                                 kdb_dbbe_select("gdb");
  210                                 kdb_enter_why(KDB_WHY_BREAK,
  211                                     "Break sequence on dcons gdb port");
  212                         }
  213 #endif
  214                 } else
  215                         kdb_enter_why(KDB_WHY_BREAK,
  216                             "Break sequence on dcons console port");
  217         }
  218 #else
  219         switch (dc->brk_state) {
  220         case STATE1:
  221                 if (c == KEY_TILDE)
  222                         dc->brk_state = STATE2;
  223                 else
  224                         dc->brk_state = STATE0;
  225                 break;
  226         case STATE2:
  227                 dc->brk_state = STATE0;
  228                 if (c == KEY_CTRLB) {
  229 #if DCONS_FORCE_GDB
  230                         if (dc->flags & DC_GDB)
  231                                 boothowto |= RB_GDB;
  232 #endif
  233                         breakpoint();
  234                 }
  235         }
  236         if (c == KEY_CR)
  237                 dc->brk_state = STATE1;
  238 #endif
  239         return (c);
  240 }
  241 #else
  242 #define dcons_check_break(dc, c)        (c)
  243 #endif
  244 
  245 static int
  246 dcons_os_checkc_nopoll(struct dcons_softc *dc)
  247 {
  248         int c;
  249 
  250         if (dg.dma_tag != NULL)
  251                 bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD);
  252   
  253         c = dcons_check_break(dc, dcons_checkc(dc));
  254 
  255         if (dg.dma_tag != NULL)
  256                 bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREREAD);
  257 
  258         return (c);
  259 }
  260 
  261 static int
  262 dcons_os_checkc(struct dcons_softc *dc)
  263 {
  264         EVENTHANDLER_INVOKE(dcons_poll, 0);
  265         return (dcons_os_checkc_nopoll(dc));
  266 }
  267 
  268 #if defined(GDB) || !defined(CONS_NODEV)
  269 static int
  270 dcons_os_getc(struct dcons_softc *dc)
  271 {
  272         int c;
  273 
  274         while ((c = dcons_os_checkc(dc)) == -1);
  275 
  276         return (c & 0xff);
  277 } 
  278 #endif
  279 
  280 static void
  281 dcons_os_putc(struct dcons_softc *dc, int c)
  282 {
  283         if (dg.dma_tag != NULL)
  284                 bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTWRITE);
  285 
  286         dcons_putc(dc, c);
  287 
  288         if (dg.dma_tag != NULL)
  289                 bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE);
  290 }
  291 static int
  292 dcons_open(DEV dev, int flag, int mode, THREAD *td)
  293 {
  294         struct tty *tp;
  295         int unit, error, s;
  296 
  297         unit = minor(dev);
  298         if (unit != 0)
  299                 return (ENXIO);
  300 
  301         tp = dev->si_tty;
  302         tp->t_oproc = dcons_tty_start;
  303         tp->t_param = dcons_tty_param;
  304         tp->t_stop = nottystop;
  305         tp->t_dev = dev;
  306 
  307         error = 0;
  308 
  309         s = spltty();
  310         if ((tp->t_state & TS_ISOPEN) == 0) {
  311                 tp->t_state |= TS_CARR_ON;
  312                 ttyconsolemode(tp, 0);
  313         } else if ((tp->t_state & TS_XCLUDE) &&
  314             priv_check(td, PRIV_TTY_EXCLUSIVE)) {
  315                 splx(s);
  316                 return (EBUSY);
  317         }
  318         splx(s);
  319 
  320 #if __FreeBSD_version < 502113
  321         error = (*linesw[tp->t_line].l_open)(dev, tp);
  322 #else
  323         error = ttyld_open(tp, dev);
  324 #endif
  325 
  326         return (error);
  327 }
  328 
  329 static int
  330 dcons_close(DEV dev, int flag, int mode, THREAD *td)
  331 {
  332         int     unit;
  333         struct  tty *tp;
  334 
  335         unit = minor(dev);
  336         if (unit != 0)
  337                 return (ENXIO);
  338 
  339         tp = dev->si_tty;
  340         if (tp->t_state & TS_ISOPEN) {
  341 #if __FreeBSD_version < 502113
  342                 (*linesw[tp->t_line].l_close)(tp, flag);
  343                 ttyclose(tp);
  344 #else
  345                 ttyld_close(tp, flag);
  346                 tty_close(tp);
  347 #endif
  348         }
  349 
  350         return (0);
  351 }
  352 
  353 #if defined(__DragonFly__) || __FreeBSD_version < 500104
  354 static int
  355 dcons_ioctl(DEV dev, u_long cmd, caddr_t data, int flag, THREAD *td)
  356 {
  357         int     unit;
  358         struct  tty *tp;
  359         int     error;
  360 
  361         unit = minor(dev);
  362         if (unit != 0)
  363                 return (ENXIO);
  364 
  365         tp = dev->si_tty;
  366         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
  367         if (error != ENOIOCTL)
  368                 return (error);
  369 
  370         error = ttioctl(tp, cmd, data, flag);
  371         if (error != ENOIOCTL)
  372                 return (error);
  373 
  374         return (ENOTTY);
  375 }
  376 #endif
  377 
  378 static int
  379 dcons_tty_param(struct tty *tp, struct termios *t)
  380 {
  381         tp->t_ispeed = t->c_ispeed;
  382         tp->t_ospeed = t->c_ospeed;
  383         tp->t_cflag = t->c_cflag;
  384         return 0;
  385 }
  386 
  387 static void
  388 dcons_tty_start(struct tty *tp)
  389 {
  390         struct dcons_softc *dc;
  391         int s;
  392 
  393         dc = (struct dcons_softc *)tp->t_dev->si_drv1;
  394         s = spltty();
  395         if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
  396                 ttwwakeup(tp);
  397                 return;
  398         }
  399 
  400         tp->t_state |= TS_BUSY;
  401         while (tp->t_outq.c_cc != 0)
  402                 dcons_os_putc(dc, getc(&tp->t_outq));
  403         tp->t_state &= ~TS_BUSY;
  404 
  405         ttwwakeup(tp);
  406         splx(s);
  407 }
  408 
  409 static void
  410 dcons_timeout(void *v)
  411 {
  412         struct  tty *tp;
  413         struct dcons_softc *dc;
  414         int i, c, polltime;
  415 
  416         for (i = 0; i < DCONS_NPORT; i ++) {
  417                 dc = &sc[i];
  418                 tp = ((DEV)dc->dev)->si_tty;
  419                 while ((c = dcons_os_checkc_nopoll(dc)) != -1)
  420                         if (tp->t_state & TS_ISOPEN)
  421 #if __FreeBSD_version < 502113
  422                                 (*linesw[tp->t_line].l_rint)(c, tp);
  423 #else
  424                                 ttyld_rint(tp, c);
  425 #endif
  426         }
  427         polltime = hz / poll_hz;
  428         if (polltime < 1)
  429                 polltime = 1;
  430         callout_reset(&dcons_callout, polltime, dcons_timeout, tp);
  431 }
  432 
  433 static void
  434 dcons_cnprobe(struct consdev *cp)
  435 {
  436 #ifdef __DragonFly__
  437         cp->cn_dev = make_dev(&dcons_cdevsw, DCONS_CON,
  438             UID_ROOT, GID_WHEEL, 0600, "dcons");
  439 #elif __FreeBSD_version >= 501109
  440         sprintf(cp->cn_name, "dcons");
  441 #else
  442         cp->cn_dev = makedev(CDEV_MAJOR, DCONS_CON);
  443 #endif
  444 #if DCONS_FORCE_CONSOLE
  445         cp->cn_pri = CN_REMOTE;
  446 #else
  447         cp->cn_pri = CN_NORMAL;
  448 #endif
  449 }
  450 
  451 static void
  452 dcons_cninit(struct consdev *cp)
  453 {
  454         dcons_drv_init(0);
  455 #if CONS_NODEV
  456         cp->cn_arg
  457 #else
  458         cp->cn_dev->si_drv1
  459 #endif
  460                 = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */
  461 }
  462 
  463 static void
  464 dcons_cnterm(struct consdev *cp)
  465 {
  466 }
  467 
  468 #if CONS_NODEV
  469 static int
  470 dcons_cngetc(struct consdev *cp)
  471 {
  472         struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
  473         return (dcons_os_checkc(dc));
  474 }
  475 static void
  476 dcons_cnputc(struct consdev *cp, int c)
  477 {
  478         struct dcons_softc *dc = (struct dcons_softc *)cp->cn_arg;
  479         dcons_os_putc(dc, c);
  480 }
  481 #else
  482 static int
  483 dcons_cngetc(DEV dev)
  484 {
  485         struct dcons_softc *dc = (struct dcons_softc *)dev->si_drv1;
  486         return (dcons_os_getc(dc));
  487 }
  488 static int
  489 dcons_cncheckc(DEV dev)
  490 {
  491         struct dcons_softc *dc = (struct dcons_softc *)dev->si_drv1;
  492         return (dcons_os_checkc(dc));
  493 }
  494 static void
  495 dcons_cnputc(DEV dev, int c)
  496 {
  497         struct dcons_softc *dc = (struct dcons_softc *)dev->si_drv1;
  498         dcons_os_putc(dc, c);
  499 }
  500 #endif
  501 
  502 static int
  503 dcons_drv_init(int stage)
  504 {
  505 #if defined(__i386__) || defined(__amd64__)
  506         quad_t addr, size;
  507 #endif
  508 
  509         if (drv_init)
  510                 return(drv_init);
  511 
  512         drv_init = -1;
  513 
  514         bzero(&dg, sizeof(dg));
  515         dcons_conf = &dg;
  516         dg.cdev = &dcons_consdev;
  517         dg.buf = NULL;
  518         dg.size = DCONS_BUF_SIZE;
  519 
  520 #if defined(__i386__) || defined(__amd64__)
  521         if (getenv_quad("dcons.addr", &addr) > 0 &&
  522             getenv_quad("dcons.size", &size) > 0) {
  523 #ifdef __i386__
  524                 vm_paddr_t pa;
  525                 /*
  526                  * Allow read/write access to dcons buffer.
  527                  */
  528                 for (pa = trunc_page(addr); pa < addr + size; pa += PAGE_SIZE)
  529                         *vtopte(KERNBASE + pa) |= PG_RW;
  530                 invltlb();
  531 #endif
  532                 /* XXX P to V */
  533                 dg.buf = (struct dcons_buf *)(vm_offset_t)(KERNBASE + addr);
  534                 dg.size = size;
  535                 if (dcons_load_buffer(dg.buf, dg.size, sc) < 0)
  536                         dg.buf = NULL;
  537         }
  538 #endif
  539         if (dg.buf != NULL)
  540                 goto ok;
  541 
  542 #ifndef KLD_MODULE
  543         if (stage == 0) { /* XXX or cold */
  544                 /*
  545                  * DCONS_FORCE_CONSOLE == 1 and statically linked.
  546                  * called from cninit(). can't use contigmalloc yet .
  547                  */
  548                 dg.buf = (struct dcons_buf *) bssbuf;
  549                 dcons_init(dg.buf, dg.size, sc);
  550         } else
  551 #endif
  552         {
  553                 /*
  554                  * DCONS_FORCE_CONSOLE == 0 or kernel module case.
  555                  * if the module is loaded after boot,
  556                  * bssbuf could be non-continuous.
  557                  */ 
  558                 dg.buf = (struct dcons_buf *) contigmalloc(dg.size,
  559                         M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
  560                 if (dg.buf == NULL)
  561                         return (-1);
  562                 dcons_init(dg.buf, dg.size, sc);
  563         }
  564 
  565 ok:
  566         dcons_buf = dg.buf;
  567 
  568 #if __FreeBSD_version < 502122
  569 #if defined(DDB) && DCONS_FORCE_GDB
  570 #if CONS_NODEV
  571         gdbconsdev.cn_arg = (void *)&sc[DCONS_GDB];
  572 #if __FreeBSD_version >= 501109
  573         sprintf(gdbconsdev.cn_name, "dgdb");
  574 #endif
  575         gdb_arg = &gdbconsdev;
  576 #elif defined(__DragonFly__)
  577         gdbdev = make_dev(&dcons_cdevsw, DCONS_GDB,
  578             UID_ROOT, GID_WHEEL, 0600, "dgdb");
  579 #else
  580         gdbdev = makedev(CDEV_MAJOR, DCONS_GDB);
  581 #endif
  582         gdb_getc = dcons_cngetc;
  583         gdb_putc = dcons_cnputc;
  584 #endif
  585 #endif
  586         drv_init = 1;
  587 
  588         return 0;
  589 }
  590 
  591 
  592 static int
  593 dcons_attach_port(int port, char *name, int flags)
  594 {
  595         struct dcons_softc *dc;
  596         struct tty *tp;
  597         DEV dev;
  598 
  599         dc = &sc[port];
  600         dc->flags = flags;
  601         dev = make_dev(&dcons_cdevsw, port,
  602                         UID_ROOT, GID_WHEEL, 0600, name);
  603         dc->dev = (void *)dev;
  604         tp = ttyalloc();
  605 
  606         dev->si_drv1 = (void *)dc;
  607         dev->si_tty = tp;
  608 
  609         tp->t_oproc = dcons_tty_start;
  610         tp->t_param = dcons_tty_param;
  611         tp->t_stop = nottystop;
  612         tp->t_dev = dc->dev;
  613 
  614         return(0);
  615 }
  616 
  617 static int
  618 dcons_attach(void)
  619 {
  620         int polltime;
  621 
  622 #ifdef __DragonFly__
  623         cdevsw_add(&dcons_cdevsw, -1, 0);
  624 #endif
  625         dcons_attach_port(DCONS_CON, "dcons", 0);
  626         dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB);
  627 #if __FreeBSD_version < 500000
  628         callout_init(&dcons_callout);
  629 #else
  630         callout_init(&dcons_callout, 0);
  631 #endif
  632         polltime = hz / poll_hz;
  633         if (polltime < 1)
  634                 polltime = 1;
  635         callout_reset(&dcons_callout, polltime, dcons_timeout, NULL);
  636         return(0);
  637 }
  638 
  639 static int
  640 dcons_detach(int port)
  641 {
  642         struct  tty *tp;
  643         struct dcons_softc *dc;
  644 
  645         dc = &sc[port];
  646 
  647         tp = ((DEV)dc->dev)->si_tty;
  648 
  649         if (tp->t_state & TS_ISOPEN) {
  650                 printf("dcons: still opened\n");
  651 #if __FreeBSD_version < 502113
  652                 (*linesw[tp->t_line].l_close)(tp, 0);
  653                 tp->t_gen++;
  654                 ttyclose(tp);
  655                 ttwakeup(tp);
  656                 ttwwakeup(tp);
  657 #else
  658                 ttyld_close(tp, 0);
  659                 tty_close(tp);
  660 #endif
  661         }
  662         /* XXX
  663          * must wait until all device are closed.
  664          */
  665 #ifdef __DragonFly__
  666         tsleep((void *)dc, 0, "dcodtc", hz/4);
  667 #else
  668         tsleep((void *)dc, PWAIT, "dcodtc", hz/4);
  669 #endif
  670         destroy_dev(dc->dev);
  671 
  672         return(0);
  673 }
  674 
  675 
  676 /* cnXXX works only for FreeBSD-5 */
  677 static int
  678 dcons_modevent(module_t mode, int type, void *data)
  679 {
  680         int err = 0, ret;
  681 
  682         switch (type) {
  683         case MOD_LOAD:
  684                 ret = dcons_drv_init(1);
  685 #if __FreeBSD_version >= 500000
  686                 if (ret != -1)
  687                         dcons_attach();
  688                 if (ret == 0) {
  689                         dcons_cnprobe(&dcons_consdev);
  690                         dcons_cninit(&dcons_consdev);
  691                         cnadd(&dcons_consdev);
  692                 }
  693 #endif
  694                 break;
  695         case MOD_UNLOAD:
  696                 printf("dcons: unload\n");
  697                 if (drv_init == 1) {
  698                         callout_stop(&dcons_callout);
  699 #if __FreeBSD_version < 502122
  700 #if defined(DDB) && DCONS_FORCE_GDB
  701 #if CONS_NODEV
  702                         gdb_arg = NULL;
  703 #else
  704                         gdbdev = NULL;
  705 #endif
  706 #endif
  707 #endif
  708 #if __FreeBSD_version >= 500000
  709                         cnremove(&dcons_consdev);
  710 #endif
  711                         dcons_detach(DCONS_CON);
  712                         dcons_detach(DCONS_GDB);
  713                         dg.buf->magic = 0;
  714 
  715                         contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF);
  716                 }
  717 
  718                 break;
  719         case MOD_SHUTDOWN:
  720 #if 0           /* Keep connection after halt */
  721                 dg.buf->magic = 0;
  722 #endif
  723                 break;
  724         default:
  725                 err = EOPNOTSUPP;
  726                 break;
  727         }
  728         return(err);
  729 }
  730 
  731 #if defined(GDB) && (__FreeBSD_version >= 502122)
  732 /* Debugger interface */
  733 
  734 static int
  735 dcons_dbg_probe(void)
  736 {
  737         int dcons_gdb;
  738 
  739         if (getenv_int("dcons_gdb", &dcons_gdb) == 0)
  740                 return (-1);
  741         return (dcons_gdb);
  742 }
  743 
  744 static void
  745 dcons_dbg_init(void)
  746 {
  747 }
  748 
  749 static void
  750 dcons_dbg_term(void)
  751 {
  752 }
  753 
  754 static void
  755 dcons_dbg_putc(int c)
  756 {
  757         struct dcons_softc *dc = &sc[DCONS_GDB];
  758         dcons_os_putc(dc, c);
  759 }
  760 
  761 static int
  762 dcons_dbg_getc(void)
  763 {
  764         struct dcons_softc *dc = &sc[DCONS_GDB];
  765         return (dcons_os_getc(dc));
  766 }
  767 #endif
  768 
  769 DEV_MODULE(dcons, dcons_modevent, NULL);
  770 MODULE_VERSION(dcons, DCONS_VERSION);

Cache object: 57d064b1158c22bd03fd0ffa27c4926a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.