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/misc/dcons/dcons_os.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: b38c4e62bdb99a868f3577d63c100840


[ 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.