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/syscons/syscons.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  * Copyright (c) 1992-1998 Søren Schmidt
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to The DragonFly Project
    6  * by Sascha Wildner <saw@online.de>
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer,
   13  *    without modification, immediately at the beginning of the file.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  * $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/dev/syscons/syscons.c,v 1.336.2.17 2004/03/25 08:41:09 ru Exp $
   32  */
   33 
   34 #include "use_splash.h"
   35 #include "opt_syscons.h"
   36 #include "opt_ddb.h"
   37 #ifdef __i386__
   38 #include "use_apm.h"
   39 #endif
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/eventhandler.h>
   44 #include <sys/reboot.h>
   45 #include <sys/conf.h>
   46 #include <sys/proc.h>
   47 #include <sys/priv.h>
   48 #include <sys/signalvar.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/tty.h>
   51 #include <sys/kernel.h>
   52 #include <sys/cons.h>
   53 #include <sys/random.h>
   54 
   55 #include <sys/thread2.h>
   56 #include <sys/mutex2.h>
   57 
   58 #include <machine/clock.h>
   59 #include <machine/console.h>
   60 #include <machine/psl.h>
   61 #include <machine/pc/display.h>
   62 #ifdef __i386__
   63 #include <machine/apm_bios.h>
   64 #endif
   65 #include <machine/frame.h>
   66 
   67 #include <dev/misc/kbd/kbdreg.h>
   68 #include <dev/video/fb/fbreg.h>
   69 #include <dev/video/fb/splashreg.h>
   70 #include "syscons.h"
   71 
   72 #define COLD 0
   73 #define WARM 1
   74 
   75 #define DEFAULT_BLANKTIME       (5*60)          /* 5 minutes */
   76 #define MAX_BLANKTIME           (7*24*60*60)    /* 7 days!? */
   77 
   78 #define KEYCODE_BS              0x0e            /* "<-- Backspace" key, XXX */
   79 #define WANT_UNLOCK(m) do {       \
   80         if (m)                    \
   81                 syscons_unlock(); \
   82 } while (0)
   83 
   84 #define WANT_LOCK(m) do {         \
   85         if (m)                    \
   86                 syscons_lock();   \
   87 } while(0)
   88 
   89 
   90 MALLOC_DEFINE(M_SYSCONS, "syscons", "Syscons");
   91 
   92 typedef struct default_attr {
   93         int             std_color;              /* normal hardware color */
   94         int             rev_color;              /* reverse hardware color */
   95 } default_attr;
   96 
   97 static default_attr user_default = {
   98     SC_NORM_ATTR,
   99     SC_NORM_REV_ATTR,
  100 };
  101 
  102 static default_attr kernel_default = {
  103     SC_KERNEL_CONS_ATTR,
  104     SC_KERNEL_CONS_REV_ATTR,
  105 };
  106 
  107 static  int             sc_console_unit = -1;
  108 static  scr_stat        *sc_console;
  109 static  struct tty      *sc_console_tty;
  110 static  void            *kernel_console_ts;
  111 
  112 static  char            init_done = COLD;
  113 static  char            shutdown_in_progress = FALSE;
  114 static  char            sc_malloc = FALSE;
  115 
  116 static  int             saver_mode = CONS_NO_SAVER; /* LKM/user saver */
  117 static  int             run_scrn_saver = FALSE; /* should run the saver? */
  118 static  long            scrn_blank_time = 0;    /* screen saver timeout value */
  119 #if NSPLASH > 0
  120 static  int             scrn_blanked;           /* # of blanked screen */
  121 static  int             sticky_splash = FALSE;
  122 
  123 static  void            none_saver(sc_softc_t *sc, int blank) { }
  124 static  void            (*current_saver)(sc_softc_t *, int) = none_saver;
  125 #endif
  126 
  127 #if !defined(SC_NO_FONT_LOADING) && defined(SC_DFLT_FONT)
  128 #include "font.h"
  129 #endif
  130 
  131 static  bios_values_t   bios_value;
  132 
  133 static  int             enable_panic_key;
  134 SYSCTL_INT(_machdep, OID_AUTO, enable_panic_key, CTLFLAG_RW, &enable_panic_key,
  135            0, "Enable the panic key (CTRL-ALT-SHIFT-ESC)");
  136 
  137 #define SC_CONSOLECTL   255
  138 
  139 #define VIRTUAL_TTY(sc, x) ((SC_DEV((sc),(x)) != NULL) ?        \
  140         (SC_DEV((sc),(x))->si_tty) : NULL)
  141 #define ISTTYOPEN(tp)   ((tp) && ((tp)->t_state & TS_ISOPEN))
  142 
  143 static  int     debugger;
  144 static  cdev_t  cctl_dev;
  145 #if 0
  146 static  timeout_t blink_screen_callout;
  147 #endif
  148 static  void    sc_blink_screen(scr_stat *scp);
  149 static  struct mtx      syscons_mtx = MTX_INITIALIZER;
  150 
  151 /* prototypes */
  152 static int scvidprobe(int unit, int flags, int cons);
  153 static int sckbdprobe(int unit, int flags, int cons);
  154 static void scmeminit(void *arg);
  155 static int scdevtounit(cdev_t dev);
  156 static kbd_callback_func_t sckbdevent;
  157 static int scparam(struct tty *tp, struct termios *t);
  158 static void scstart(struct tty *tp);
  159 static void scinit(int unit, int flags);
  160 static void scterm(int unit, int flags);
  161 static void scshutdown(void *arg, int howto);
  162 static void sc_puts(scr_stat *scp, u_char *buf, int len);
  163 static u_int scgetc(sc_softc_t *sc, u_int flags);
  164 #define SCGETC_CN       1
  165 #define SCGETC_NONBLOCK 2
  166 static int sccngetch(int flags);
  167 static void sccnupdate(scr_stat *scp);
  168 static scr_stat *alloc_scp(sc_softc_t *sc, int vty);
  169 static void init_scp(sc_softc_t *sc, int vty, scr_stat *scp);
  170 static timeout_t scrn_timer;
  171 static int and_region(int *s1, int *e1, int s2, int e2);
  172 static void scrn_update(scr_stat *scp, int show_cursor);
  173 
  174 #if NSPLASH > 0
  175 static int scsplash_callback(int event, void *arg);
  176 static void scsplash_saver(sc_softc_t *sc, int show);
  177 static int add_scrn_saver(void (*this_saver)(sc_softc_t *, int));
  178 static int remove_scrn_saver(void (*this_saver)(sc_softc_t *, int));
  179 static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border);
  180 static int restore_scrn_saver_mode(scr_stat *scp, int changemode);
  181 static void stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int));
  182 static int wait_scrn_saver_stop(sc_softc_t *sc);
  183 #define scsplash_stick(stick)           (sticky_splash = (stick))
  184 #else /* !NSPLASH */
  185 #define scsplash_stick(stick)
  186 #endif /* NSPLASH */
  187 
  188 static void do_switch_scr(sc_softc_t *sc);
  189 static int vt_proc_alive(scr_stat *scp);
  190 static int signal_vt_rel(scr_stat *scp);
  191 static int signal_vt_acq(scr_stat *scp);
  192 static int finish_vt_rel(scr_stat *scp, int release);
  193 static int finish_vt_acq(scr_stat *scp);
  194 static void exchange_scr(sc_softc_t *sc);
  195 static void update_cursor_image(scr_stat *scp);
  196 static int save_kbd_state(scr_stat *scp, int unlock);
  197 static int update_kbd_state(scr_stat *scp, int state, int mask, int unlock);
  198 static int update_kbd_leds(scr_stat *scp, int which);
  199 static int sc_allocate_keyboard(sc_softc_t *sc, int unit);
  200 
  201 /*
  202  * Console locking support functions.
  203  *
  204  * We use mutex spinlocks here in order to allow reentrancy which should
  205  * avoid issues during panics.
  206  */
  207 static void
  208 syscons_lock(void)
  209 {
  210         mtx_spinlock(&syscons_mtx);
  211 }
  212 
  213 /*
  214  * Returns 0 on success, EAGAIN on failure.
  215  */
  216 static int
  217 syscons_lock_nonblock(void)
  218 {
  219         return(mtx_spinlock_try(&syscons_mtx));
  220 }
  221 
  222 static void
  223 syscons_unlock(void)
  224 {
  225         mtx_spinunlock(&syscons_mtx);
  226 }
  227 
  228 /*
  229  * Console driver
  230  */
  231 static cn_probe_t       sccnprobe;
  232 static cn_init_t        sccninit;
  233 static cn_init_t        sccninit_fini;
  234 static cn_getc_t        sccngetc;
  235 static cn_checkc_t      sccncheckc;
  236 static cn_putc_t        sccnputc;
  237 static cn_dbctl_t       sccndbctl;
  238 static cn_term_t        sccnterm;
  239 
  240 CONS_DRIVER(sc, sccnprobe, sccninit, sccninit_fini, sccnterm,
  241             sccngetc, sccncheckc, sccnputc, sccndbctl);
  242 
  243 static  d_open_t        scopen;
  244 static  d_close_t       scclose;
  245 static  d_read_t        scread;
  246 static  d_ioctl_t       scioctl;
  247 static  d_mmap_t        scmmap;
  248 
  249 static struct dev_ops sc_ops = {
  250         { "sc", 0, D_TTY },
  251         .d_open =       scopen,
  252         .d_close =      scclose,
  253         .d_read =       scread,
  254         .d_write =      ttywrite,
  255         .d_ioctl =      scioctl,
  256         .d_mmap =       scmmap,
  257         .d_kqfilter =   ttykqfilter,
  258         .d_revoke =     ttyrevoke
  259 };
  260 
  261 int
  262 sc_probe_unit(int unit, int flags)
  263 {
  264     if (!scvidprobe(unit, flags, FALSE)) {
  265         if (bootverbose)
  266             kprintf("sc%d: no video adapter found.\n", unit);
  267         return ENXIO;
  268     }
  269 
  270     /* syscons will be attached even when there is no keyboard */
  271     sckbdprobe(unit, flags, FALSE);
  272 
  273     return 0;
  274 }
  275 
  276 /* probe video adapters, return TRUE if found */ 
  277 static int
  278 scvidprobe(int unit, int flags, int cons)
  279 {
  280     /*
  281      * Access the video adapter driver through the back door!
  282      * Video adapter drivers need to be configured before syscons.
  283      * However, when syscons is being probed as the low-level console,
  284      * they have not been initialized yet.  We force them to initialize
  285      * themselves here. XXX
  286      */
  287     vid_configure(cons ? VIO_PROBE_ONLY : 0);
  288 
  289     return (vid_find_adapter("*", unit) >= 0);
  290 }
  291 
  292 /* probe the keyboard, return TRUE if found */
  293 static int
  294 sckbdprobe(int unit, int flags, int cons)
  295 {
  296     /* access the keyboard driver through the backdoor! */
  297     kbd_configure(cons ? KB_CONF_PROBE_ONLY : 0);
  298 
  299     return (kbd_find_keyboard("*", unit) >= 0);
  300 }
  301 
  302 static char *
  303 adapter_name(video_adapter_t *adp)
  304 {
  305     static struct {
  306         int type;
  307         char *name[2];
  308     } names[] = {
  309         { KD_MONO,      { "MDA",        "MDA" } },
  310         { KD_HERCULES,  { "Hercules",   "Hercules" } },
  311         { KD_CGA,       { "CGA",        "CGA" } },
  312         { KD_EGA,       { "EGA",        "EGA (mono)" } },
  313         { KD_VGA,       { "VGA",        "VGA (mono)" } },
  314         { KD_TGA,       { "TGA",        "TGA" } },
  315         { -1,           { "Unknown",    "Unknown" } },
  316     };
  317     int i;
  318 
  319     for (i = 0; names[i].type != -1; ++i)
  320         if (names[i].type == adp->va_type)
  321             break;
  322     return names[i].name[(adp->va_flags & V_ADP_COLOR) ? 0 : 1];
  323 }
  324 
  325 int
  326 sc_attach_unit(int unit, int flags)
  327 {
  328     sc_softc_t *sc;
  329     scr_stat *scp;
  330 #ifdef SC_PIXEL_MODE
  331     video_info_t info;
  332 #endif
  333     int vc;
  334     cdev_t dev;
  335     flags &= ~SC_KERNEL_CONSOLE;
  336 
  337     if (sc_console_unit == unit) {
  338         /*
  339          * If this unit is being used as the system console, we need to
  340          * adjust some variables and buffers before and after scinit().
  341          */
  342         /* assert(sc_console != NULL) */
  343         flags |= SC_KERNEL_CONSOLE;
  344         scmeminit(NULL);
  345 
  346         scinit(unit, flags);
  347 
  348         if (sc_console->tsw->te_size > 0) {
  349             /* assert(sc_console->ts != NULL); */
  350             kernel_console_ts = sc_console->ts;
  351             sc_console->ts = kmalloc(sc_console->tsw->te_size,
  352                                     M_SYSCONS, M_WAITOK);
  353             bcopy(kernel_console_ts, sc_console->ts, sc_console->tsw->te_size);
  354             (*sc_console->tsw->te_default_attr)(sc_console,
  355                                                 user_default.std_color,
  356                                                 user_default.rev_color);
  357         }
  358     } else {
  359         scinit(unit, flags);
  360     }
  361 
  362     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
  363 
  364     /*
  365      * If this is the console we couldn't setup sc->dev before because
  366      * malloc wasn't working.  Set it up now.
  367      */
  368     if (flags & SC_KERNEL_CONSOLE) {
  369         KKASSERT(sc->dev == NULL);
  370         sc->dev = kmalloc(sizeof(cdev_t)*sc->vtys, M_SYSCONS, M_WAITOK|M_ZERO);
  371         sc->dev[0] = make_dev(&sc_ops, sc_console_unit*MAXCONS, UID_ROOT, 
  372                               GID_WHEEL, 0600, 
  373                               "ttyv%r", sc_console_unit*MAXCONS);
  374         sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
  375         sc->dev[0]->si_drv1 = sc_console;
  376     }
  377 
  378     /*
  379      * Finish up the standard attach
  380      */
  381     sc->config = flags;
  382     callout_init_mp(&sc->scrn_timer_ch);
  383     scp = SC_STAT(sc->dev[0]);
  384     if (sc_console == NULL)     /* sc_console_unit < 0 */
  385         sc_console = scp;
  386 
  387 #ifdef SC_PIXEL_MODE
  388     if ((sc->config & SC_VESA800X600)
  389         && ((*vidsw[sc->adapter]->get_info)(sc->adp, M_VESA_800x600, &info) == 0)) {
  390 #if NSPLASH > 0
  391         if (sc->flags & SC_SPLASH_SCRN)
  392             splash_term(sc->adp);
  393 #endif
  394         sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
  395         sc_set_pixel_mode(scp, NULL, 0, 0, 16);
  396         sc->initial_mode = M_VESA_800x600;
  397 #if NSPLASH > 0
  398         /* put up the splash again! */
  399         if (sc->flags & SC_SPLASH_SCRN)
  400             splash_init(sc->adp, scsplash_callback, sc);
  401 #endif
  402     }
  403 #endif /* SC_PIXEL_MODE */
  404 
  405     /* initialize cursor */
  406     if (!ISGRAPHSC(scp))
  407         update_cursor_image(scp);
  408 
  409     /* get screen update going */
  410     scrn_timer(sc);
  411 
  412     /* set up the keyboard */
  413     kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
  414     update_kbd_state(scp, scp->status, LOCK_MASK, FALSE);
  415 
  416     kprintf("sc%d: %s <%d virtual consoles, flags=0x%x>\n",
  417            unit, adapter_name(sc->adp), sc->vtys, sc->config);
  418     if (bootverbose) {
  419         kprintf("sc%d:", unit);
  420         if (sc->adapter >= 0)
  421             kprintf(" fb%d", sc->adapter);
  422         if (sc->keyboard >= 0)
  423             kprintf(", kbd%d", sc->keyboard);
  424         if (scp->tsw)
  425             kprintf(", terminal emulator: %s (%s)",
  426                    scp->tsw->te_name, scp->tsw->te_desc);
  427         kprintf("\n");
  428     }
  429 
  430     /* register a shutdown callback for the kernel console */
  431     if (sc_console_unit == unit)
  432         EVENTHANDLER_REGISTER(shutdown_pre_sync, scshutdown, 
  433                               (void *)(uintptr_t)unit, SHUTDOWN_PRI_DEFAULT);
  434 
  435     /* 
  436      * create devices.
  437      *
  438      * The first vty already has struct tty and scr_stat initialized
  439      * in scinit().  The other vtys will have these structs when
  440      * first opened.
  441      */
  442     for (vc = 1; vc < sc->vtys; vc++) {
  443         dev = make_dev(&sc_ops, vc + unit * MAXCONS,
  444                         UID_ROOT, GID_WHEEL,
  445                         0600, "ttyv%r", vc + unit * MAXCONS);
  446         sc->dev[vc] = dev;
  447     }
  448     cctl_dev = make_dev(&sc_ops, SC_CONSOLECTL,
  449                         UID_ROOT, GID_WHEEL, 0600, "consolectl");
  450     cctl_dev->si_tty = sc_console_tty = ttymalloc(sc_console_tty);
  451     cctl_dev->si_drv1 = sc_console;
  452     return 0;
  453 }
  454 
  455 static void
  456 scmeminit(void *arg)
  457 {
  458     if (sc_malloc)
  459         return;
  460     sc_malloc = TRUE;
  461 
  462     /*
  463      * As soon as malloc() becomes functional, we had better allocate
  464      * various buffers for the kernel console.
  465      */
  466 
  467     if (sc_console_unit < 0)    /* sc_console == NULL */
  468         return;
  469 
  470     /* copy the temporary buffer to the final buffer */
  471     sc_alloc_scr_buffer(sc_console, TRUE, FALSE);
  472 
  473 #ifndef SC_NO_CUTPASTE
  474     sc_alloc_cut_buffer(sc_console, TRUE);
  475 #endif
  476 
  477 #ifndef SC_NO_HISTORY
  478     /* initialize history buffer & pointers */
  479     sc_alloc_history_buffer(sc_console, 0, 0, TRUE);
  480 #endif
  481 }
  482 
  483 SYSINIT(sc_mem, SI_BOOT1_POST, SI_ORDER_ANY, scmeminit, NULL);
  484 
  485 static int
  486 scdevtounit(cdev_t dev)
  487 {
  488     int vty = SC_VTY(dev);
  489 
  490     if (vty == SC_CONSOLECTL)
  491         return ((sc_console != NULL) ? sc_console->sc->unit : -1);
  492     else if ((vty < 0) || (vty >= MAXCONS*sc_max_unit()))
  493         return -1;
  494     else
  495         return vty/MAXCONS;
  496 }
  497 
  498 int
  499 scopen(struct dev_open_args *ap)
  500 {
  501     cdev_t dev = ap->a_head.a_dev;
  502     int unit;
  503     sc_softc_t *sc;
  504     struct tty *tp;
  505     scr_stat *scp;
  506     keyarg_t key;
  507     int error;
  508 
  509     lwkt_gettoken(&tty_token);
  510     unit = scdevtounit(dev);
  511     DPRINTF(5, ("scopen: dev:%d,%d, unit:%d, vty:%d\n",
  512                 major(dev), minor(dev), unit, SC_VTY(dev)));
  513 
  514     sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0);
  515     if (sc == NULL) {
  516         lwkt_reltoken(&tty_token);
  517         return ENXIO;
  518     }
  519 
  520     tp = dev->si_tty = ttymalloc(dev->si_tty);
  521     tp->t_oproc = scstart;
  522     tp->t_param = scparam;
  523     tp->t_stop = nottystop;
  524 
  525     tp->t_dev = dev;
  526 
  527     if (!ISTTYOPEN(tp)) {
  528         ttychars(tp);
  529         /* Use the current setting of the <-- key as default VERASE. */  
  530         /* If the Delete key is preferable, an stty is necessary     */
  531         if (sc->kbd != NULL) {
  532             key.keynum = KEYCODE_BS;
  533             kbd_ioctl(sc->kbd, GIO_KEYMAPENT, (caddr_t)&key);
  534             tp->t_cc[VERASE] = key.key.map[0];
  535         }
  536         tp->t_iflag = TTYDEF_IFLAG;
  537         tp->t_oflag = TTYDEF_OFLAG;
  538         tp->t_cflag = TTYDEF_CFLAG;
  539         tp->t_lflag = TTYDEF_LFLAG;
  540         tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  541         scparam(tp, &tp->t_termios);
  542         (*linesw[tp->t_line].l_modem)(tp, 1);
  543     }
  544     else
  545         if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
  546             lwkt_reltoken(&tty_token);
  547             return(EBUSY);
  548         }
  549 
  550     error = (*linesw[tp->t_line].l_open)(dev, tp);
  551 
  552     scp = SC_STAT(dev);
  553     if (scp == NULL) {
  554         scp = dev->si_drv1 = alloc_scp(sc, SC_VTY(dev));
  555         syscons_lock();
  556         if (ISGRAPHSC(scp))
  557             sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
  558         syscons_unlock();
  559     }
  560     if (!tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
  561         tp->t_winsize.ws_col = scp->xsize;
  562         tp->t_winsize.ws_row = scp->ysize;
  563     }
  564 
  565     lwkt_reltoken(&tty_token);
  566     return error;
  567 }
  568 
  569 int
  570 scclose(struct dev_close_args *ap)
  571 {
  572     cdev_t dev = ap->a_head.a_dev;
  573     struct tty *tp = dev->si_tty;
  574     scr_stat *scp;
  575 
  576     lwkt_gettoken(&tty_token);
  577     if (SC_VTY(dev) != SC_CONSOLECTL) {
  578         scp = SC_STAT(tp->t_dev);
  579         /* were we in the middle of the VT switching process? */
  580         DPRINTF(5, ("sc%d: scclose(), ", scp->sc->unit));
  581         if ((scp == scp->sc->cur_scp) && (scp->sc->unit == sc_console_unit))
  582             cons_unavail = FALSE;
  583         if (finish_vt_rel(scp, TRUE) == 0)      /* force release */
  584             DPRINTF(5, ("reset WAIT_REL, "));
  585         if (finish_vt_acq(scp) == 0)            /* force acknowledge */
  586             DPRINTF(5, ("reset WAIT_ACQ, "));
  587         syscons_lock();
  588 #if 0 /* notyet */
  589         if (scp == &main_console) {
  590             scp->pid = 0;
  591             scp->proc = NULL;
  592             scp->smode.mode = VT_AUTO;
  593         }
  594         else {
  595             sc_vtb_destroy(&scp->vtb);
  596             sc_vtb_destroy(&scp->scr);
  597             sc_free_history_buffer(scp, scp->ysize);
  598             SC_STAT(dev) = NULL;
  599             kfree(scp, M_SYSCONS);
  600         }
  601 #else
  602         scp->pid = 0;
  603         scp->proc = NULL;
  604         scp->smode.mode = VT_AUTO;
  605 #endif
  606         scp->kbd_mode = K_XLATE;
  607         syscons_unlock();
  608         if (scp == scp->sc->cur_scp)
  609             kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
  610         DPRINTF(5, ("done.\n"));
  611     }
  612     (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
  613     ttyclose(tp);
  614     lwkt_reltoken(&tty_token);
  615 
  616     return(0);
  617 }
  618 
  619 int
  620 scread(struct dev_read_args *ap)
  621 {
  622     int ret;
  623 
  624     lwkt_gettoken(&tty_token);
  625     sc_touch_scrn_saver();
  626     ret = ttyread(ap);
  627     lwkt_reltoken(&tty_token);
  628     return ret;
  629 }
  630 
  631 static int
  632 sckbdevent(keyboard_t *thiskbd, int event, void *arg)
  633 {
  634     sc_softc_t *sc;
  635     struct tty *cur_tty;
  636     int c; 
  637     size_t len;
  638     u_char *cp;
  639 
  640     lwkt_gettoken(&tty_token);
  641     /*
  642      * WARNING: In early boot sc->dev may not be setup yet.
  643      */
  644     sc = (sc_softc_t *)arg;
  645     /* assert(thiskbd == sc->kbd) */
  646 
  647     switch (event) {
  648     case KBDIO_KEYINPUT:
  649         break;
  650     case KBDIO_UNLOADING:
  651         syscons_lock();
  652         sc->kbd = NULL;
  653         sc->keyboard = -1;
  654         syscons_unlock();
  655         kbd_release(thiskbd, (void *)&sc->keyboard);
  656         lwkt_reltoken(&tty_token);
  657         return 0;
  658     default:
  659         lwkt_reltoken(&tty_token);
  660         return EINVAL;
  661     }
  662 
  663     /* 
  664      * Loop while there is still input to get from the keyboard.
  665      * I don't think this is nessesary, and it doesn't fix
  666      * the Xaccel-2.1 keyboard hang, but it can't hurt.         XXX
  667      */
  668     while ((c = scgetc(sc, SCGETC_NONBLOCK)) != NOKEY) {
  669         cur_tty = VIRTUAL_TTY(sc, sc->cur_scp->index);
  670         if (!ISTTYOPEN(cur_tty)) {
  671             cur_tty = sc_console_tty;
  672             if (!ISTTYOPEN(cur_tty))
  673                 continue;
  674         }
  675 
  676         syscons_lock();
  677         if ((*sc->cur_scp->tsw->te_input)(sc->cur_scp, c, cur_tty)) {
  678             syscons_unlock();
  679             continue;
  680         }
  681         syscons_unlock();
  682 
  683         switch (KEYFLAGS(c)) {
  684         case 0x0000: /* normal key */
  685             (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty);
  686             break;
  687         case FKEY:  /* function key, return string */
  688             cp = kbd_get_fkeystr(thiskbd, KEYCHAR(c), &len);
  689             if (cp != NULL) {
  690                 while (len-- >  0)
  691                     (*linesw[cur_tty->t_line].l_rint)(*cp++, cur_tty);
  692             }
  693             break;
  694         case MKEY:  /* meta is active, prepend ESC */
  695             (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
  696             (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty);
  697             break;
  698         case BKEY:  /* backtab fixed sequence (esc [ Z) */
  699             (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
  700             (*linesw[cur_tty->t_line].l_rint)('[', cur_tty);
  701             (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty);
  702             break;
  703         }
  704     }
  705 
  706     syscons_lock();
  707     sc->cur_scp->status |= MOUSE_HIDDEN;
  708     syscons_unlock();
  709 
  710     lwkt_reltoken(&tty_token);
  711     return 0;
  712 }
  713 
  714 static int
  715 scparam(struct tty *tp, struct termios *t)
  716 {
  717     lwkt_gettoken(&tty_token);
  718     tp->t_ispeed = t->c_ispeed;
  719     tp->t_ospeed = t->c_ospeed;
  720     tp->t_cflag = t->c_cflag;
  721     lwkt_reltoken(&tty_token);
  722     return 0;
  723 }
  724 
  725 int
  726 scioctl(struct dev_ioctl_args *ap)
  727 {
  728     cdev_t dev = ap->a_head.a_dev;
  729     u_long cmd = ap->a_cmd;
  730     caddr_t data = ap->a_data;
  731     int flag = ap->a_fflag;
  732     int error;
  733     int i;
  734     struct tty *tp;
  735     sc_softc_t *sc;
  736     scr_stat *scp;
  737 
  738     lwkt_gettoken(&tty_token);
  739     tp = dev->si_tty;
  740 
  741     error = sc_vid_ioctl(tp, cmd, data, flag);
  742     if (error != ENOIOCTL) {
  743         lwkt_reltoken(&tty_token);
  744         return error;
  745     }
  746 
  747 #ifndef SC_NO_HISTORY
  748     error = sc_hist_ioctl(tp, cmd, data, flag);
  749     if (error != ENOIOCTL) {
  750         lwkt_reltoken(&tty_token);
  751         return error;
  752     }
  753 #endif
  754 
  755 #ifndef SC_NO_SYSMOUSE
  756     error = sc_mouse_ioctl(tp, cmd, data, flag);
  757     if (error != ENOIOCTL) {
  758         lwkt_reltoken(&tty_token);
  759         return error;
  760     }
  761 #endif
  762 
  763     scp = SC_STAT(tp->t_dev);
  764     /* assert(scp != NULL) */
  765     /* scp is sc_console, if SC_VTY(dev) == SC_CONSOLECTL. */
  766     sc = scp->sc;
  767 
  768     if (scp->tsw) {
  769         syscons_lock();
  770         error = (*scp->tsw->te_ioctl)(scp, tp, cmd, data, flag);
  771         syscons_unlock();
  772         if (error != ENOIOCTL) {
  773             lwkt_reltoken(&tty_token);
  774             return error;
  775         }
  776     }
  777 
  778     switch (cmd) {              /* process console hardware related ioctl's */
  779 
  780     case GIO_ATTR:              /* get current attributes */
  781         /* this ioctl is not processed here, but in the terminal emulator */
  782         lwkt_reltoken(&tty_token);
  783         return ENOTTY;
  784 
  785     case GIO_COLOR:             /* is this a color console ? */
  786         *(int *)data = (sc->adp->va_flags & V_ADP_COLOR) ? 1 : 0;
  787         lwkt_reltoken(&tty_token);
  788         return 0;
  789 
  790     case CONS_BLANKTIME:        /* set screen saver timeout (0 = no saver) */
  791         if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) {
  792             lwkt_reltoken(&tty_token);
  793             return EINVAL;
  794         }
  795         syscons_lock();
  796         scrn_blank_time = *(int *)data;
  797         run_scrn_saver = (scrn_blank_time != 0);
  798         syscons_unlock();
  799         lwkt_reltoken(&tty_token);
  800         return 0;
  801 
  802     case CONS_CURSORTYPE:       /* set cursor type blink/noblink */
  803         syscons_lock();
  804         if (!ISGRAPHSC(sc->cur_scp))
  805             sc_remove_cursor_image(sc->cur_scp);
  806         if ((*(int*)data) & 0x01)
  807             sc->flags |= SC_BLINK_CURSOR;
  808         else
  809             sc->flags &= ~SC_BLINK_CURSOR;
  810         if ((*(int*)data) & 0x02) {
  811             sc->flags |= SC_CHAR_CURSOR;
  812         } else
  813             sc->flags &= ~SC_CHAR_CURSOR;
  814         /* 
  815          * The cursor shape is global property; all virtual consoles
  816          * are affected. Update the cursor in the current console...
  817          */
  818         if (!ISGRAPHSC(sc->cur_scp)) {
  819             sc_set_cursor_image(sc->cur_scp);
  820             sc_draw_cursor_image(sc->cur_scp);
  821         }
  822         syscons_unlock();
  823         lwkt_reltoken(&tty_token);
  824         return 0;
  825 
  826     case CONS_BELLTYPE:         /* set bell type sound/visual */
  827         syscons_lock();
  828 
  829         if ((*(int *)data) & 0x01)
  830             sc->flags |= SC_VISUAL_BELL;
  831         else
  832             sc->flags &= ~SC_VISUAL_BELL;
  833 
  834         if ((*(int *)data) & 0x02)
  835             sc->flags |= SC_QUIET_BELL;
  836         else
  837             sc->flags &= ~SC_QUIET_BELL;
  838 
  839         syscons_unlock();
  840         lwkt_reltoken(&tty_token);
  841         return 0;
  842 
  843     case CONS_GETINFO:          /* get current (virtual) console info */
  844     {
  845         vid_info_t *ptr = (vid_info_t*)data;
  846         if (ptr->size == sizeof(struct vid_info)) {
  847             ptr->m_num = sc->cur_scp->index;
  848             ptr->font_size = scp->font_size;
  849             ptr->mv_col = scp->xpos;
  850             ptr->mv_row = scp->ypos;
  851             ptr->mv_csz = scp->xsize;
  852             ptr->mv_rsz = scp->ysize;
  853             /*
  854              * The following fields are filled by the terminal emulator. XXX
  855              *
  856              * ptr->mv_norm.fore
  857              * ptr->mv_norm.back
  858              * ptr->mv_rev.fore
  859              * ptr->mv_rev.back
  860              */
  861             ptr->mv_grfc.fore = 0;      /* not supported */
  862             ptr->mv_grfc.back = 0;      /* not supported */
  863             ptr->mv_ovscan = scp->border;
  864             if (scp == sc->cur_scp)
  865                 save_kbd_state(scp, FALSE);
  866             ptr->mk_keylock = scp->status & LOCK_MASK;
  867             lwkt_reltoken(&tty_token);
  868             return 0;
  869         }
  870         lwkt_reltoken(&tty_token);
  871         return EINVAL;
  872     }
  873 
  874     case CONS_GETVERS:          /* get version number */
  875         *(int*)data = 0x200;    /* version 2.0 */
  876         lwkt_reltoken(&tty_token);
  877         return 0;
  878 
  879     case CONS_IDLE:             /* see if the screen has been idle */
  880         /*
  881          * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE,
  882          * the user process may have been writing something on the
  883          * screen and syscons is not aware of it. Declare the screen
  884          * is NOT idle if it is in one of these modes. But there is
  885          * an exception to it; if a screen saver is running in the 
  886          * graphics mode in the current screen, we should say that the
  887          * screen has been idle.
  888          */
  889         *(int *)data = (sc->flags & SC_SCRN_IDLE)
  890                        && (!ISGRAPHSC(sc->cur_scp)
  891                            || (sc->cur_scp->status & SAVER_RUNNING));
  892         lwkt_reltoken(&tty_token);
  893         return 0;
  894 
  895     case CONS_SAVERMODE:        /* set saver mode */
  896         switch(*(int *)data) {
  897         case CONS_NO_SAVER:
  898         case CONS_USR_SAVER:
  899             syscons_lock();
  900             /* if a LKM screen saver is running, stop it first. */
  901             scsplash_stick(FALSE);
  902             saver_mode = *(int *)data;
  903 #if NSPLASH > 0
  904             if ((error = wait_scrn_saver_stop(NULL))) {
  905                 syscons_unlock();
  906                 lwkt_reltoken(&tty_token);
  907                 return error;
  908             }
  909 #endif /* NSPLASH */
  910             run_scrn_saver = TRUE;
  911             if (saver_mode == CONS_USR_SAVER)
  912                 scp->status |= SAVER_RUNNING;
  913             else
  914                 scp->status &= ~SAVER_RUNNING;
  915             scsplash_stick(TRUE);
  916             syscons_unlock();
  917             break;
  918         case CONS_LKM_SAVER:
  919             syscons_lock();
  920             if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING))
  921                 scp->status &= ~SAVER_RUNNING;
  922             saver_mode = *(int *)data;
  923             syscons_unlock();
  924             break;
  925         default:
  926             lwkt_reltoken(&tty_token);
  927             return EINVAL;
  928         }
  929         lwkt_reltoken(&tty_token);
  930         return 0;
  931 
  932     case CONS_SAVERSTART:       /* immediately start/stop the screen saver */
  933         /*
  934          * Note that this ioctl does not guarantee the screen saver 
  935          * actually starts or stops. It merely attempts to do so...
  936          */
  937         syscons_lock();
  938         run_scrn_saver = (*(int *)data != 0);
  939         if (run_scrn_saver)
  940             sc->scrn_time_stamp -= scrn_blank_time;
  941         syscons_unlock();
  942         lwkt_reltoken(&tty_token);
  943         return 0;
  944 
  945     case CONS_SCRSHOT:          /* get a screen shot */
  946     {
  947         scrshot_t *ptr = (scrshot_t*)data;
  948         syscons_lock();
  949         if (ISGRAPHSC(scp)) {
  950             syscons_unlock();
  951             lwkt_reltoken(&tty_token);
  952             return EOPNOTSUPP;
  953         }
  954         if (scp->xsize != ptr->xsize || scp->ysize != ptr->ysize) {
  955             syscons_unlock();
  956             lwkt_reltoken(&tty_token);
  957             return EINVAL;
  958         }
  959         syscons_unlock();
  960         copyout ((void*)scp->vtb.vtb_buffer, ptr->buf,
  961                  ptr->xsize * ptr->ysize * sizeof(uint16_t));
  962         lwkt_reltoken(&tty_token);
  963         return 0;
  964     }
  965 
  966     case VT_SETMODE:            /* set screen switcher mode */
  967     {
  968         struct vt_mode *mode;
  969 
  970         mode = (struct vt_mode *)data;
  971         DPRINTF(5, ("sc%d: VT_SETMODE ", sc->unit));
  972         if (scp->smode.mode == VT_PROCESS) {
  973             if (scp->proc == pfindn(scp->pid) && scp->proc != curproc) {
  974                 DPRINTF(5, ("error EPERM\n"));
  975                 lwkt_reltoken(&tty_token);
  976                 return EPERM;
  977             }
  978         }
  979         syscons_lock();
  980         if (mode->mode == VT_AUTO) {
  981             scp->smode.mode = VT_AUTO;
  982             scp->proc = NULL;
  983             scp->pid = 0;
  984             DPRINTF(5, ("VT_AUTO, "));
  985             if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
  986                 cons_unavail = FALSE;
  987             if (finish_vt_rel(scp, TRUE) == 0)
  988                 DPRINTF(5, ("reset WAIT_REL, "));
  989             if (finish_vt_acq(scp) == 0)
  990                 DPRINTF(5, ("reset WAIT_ACQ, "));
  991         } else {
  992             if (!ISSIGVALID(mode->relsig) || !ISSIGVALID(mode->acqsig)
  993                 || !ISSIGVALID(mode->frsig)) {
  994                 syscons_unlock();
  995                 DPRINTF(5, ("error EINVAL\n"));
  996                 lwkt_reltoken(&tty_token);
  997                 return EINVAL;
  998             }
  999             DPRINTF(5, ("VT_PROCESS %d, ", curproc->p_pid));
 1000             bcopy(data, &scp->smode, sizeof(struct vt_mode));
 1001             scp->proc = curproc;
 1002             scp->pid = scp->proc->p_pid;
 1003             if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
 1004                 cons_unavail = TRUE;
 1005         }
 1006         syscons_unlock();
 1007         DPRINTF(5, ("\n"));
 1008         lwkt_reltoken(&tty_token);
 1009         return 0;
 1010     }
 1011 
 1012     case VT_GETMODE:            /* get screen switcher mode */
 1013         bcopy(&scp->smode, data, sizeof(struct vt_mode));
 1014         lwkt_reltoken(&tty_token);
 1015         return 0;
 1016 
 1017     case VT_RELDISP:            /* screen switcher ioctl */
 1018         /*
 1019          * This must be the current vty which is in the VT_PROCESS
 1020          * switching mode...
 1021          */
 1022         syscons_lock();
 1023         if ((scp != sc->cur_scp) || (scp->smode.mode != VT_PROCESS)) {
 1024             syscons_unlock();
 1025             lwkt_reltoken(&tty_token);
 1026             return EINVAL;
 1027         }
 1028         /* ...and this process is controlling it. */
 1029         if (scp->proc != curproc) {
 1030             syscons_unlock();
 1031             lwkt_reltoken(&tty_token);
 1032             return EPERM;
 1033         }
 1034         error = EINVAL;
 1035         switch(*(int *)data) {
 1036         case VT_FALSE:          /* user refuses to release screen, abort */
 1037             if ((error = finish_vt_rel(scp, FALSE)) == 0)
 1038                 DPRINTF(5, ("sc%d: VT_FALSE\n", sc->unit));
 1039             break;
 1040         case VT_TRUE:           /* user has released screen, go on */
 1041             if ((error = finish_vt_rel(scp, TRUE)) == 0)
 1042                 DPRINTF(5, ("sc%d: VT_TRUE\n", sc->unit));
 1043             break;
 1044         case VT_ACKACQ:         /* acquire acknowledged, switch completed */
 1045             if ((error = finish_vt_acq(scp)) == 0)
 1046                 DPRINTF(5, ("sc%d: VT_ACKACQ\n", sc->unit));
 1047             break;
 1048         default:
 1049             break;
 1050         }
 1051         syscons_unlock();
 1052         lwkt_reltoken(&tty_token);
 1053         return error;
 1054 
 1055     case VT_OPENQRY:            /* return free virtual console */
 1056         for (i = sc->first_vty; i < sc->first_vty + sc->vtys; i++) {
 1057             tp = VIRTUAL_TTY(sc, i);
 1058             if (!ISTTYOPEN(tp)) {
 1059                 *(int *)data = i + 1;
 1060                 lwkt_reltoken(&tty_token);
 1061                 return 0;
 1062             }
 1063         }
 1064         lwkt_reltoken(&tty_token);
 1065         return EINVAL;
 1066 
 1067     case VT_ACTIVATE:           /* switch to screen *data */
 1068         i = (*(int *)data == 0) ? scp->index : (*(int *)data - 1);
 1069         syscons_lock();
 1070         sc_clean_up(sc->cur_scp);
 1071         error = sc_switch_scr(sc, i);
 1072         syscons_unlock();
 1073         lwkt_reltoken(&tty_token);
 1074         return error;
 1075 
 1076     case VT_WAITACTIVE:         /* wait for switch to occur */
 1077         i = (*(int *)data == 0) ? scp->index : (*(int *)data - 1);
 1078         if ((i < sc->first_vty) || (i >= sc->first_vty + sc->vtys)) {
 1079             lwkt_reltoken(&tty_token);
 1080             return EINVAL;
 1081         }
 1082         syscons_lock();
 1083         error = sc_clean_up(sc->cur_scp);
 1084         syscons_unlock();
 1085         if (error) {
 1086             lwkt_reltoken(&tty_token);
 1087             return error;
 1088         }
 1089 
 1090         /*
 1091          * scp might be NULL, we aren't sure why.  Check for NULL.
 1092          *
 1093          * http://bugs.dragonflybsd.org/issues/2481
 1094          */
 1095         scp = SC_STAT(SC_DEV(sc, i));
 1096         if (scp == NULL || scp == scp->sc->cur_scp) {
 1097             lwkt_reltoken(&tty_token);
 1098             return 0;
 1099         }
 1100         error = tsleep((caddr_t)&scp->smode, PCATCH, "waitvt", 0);
 1101         /* May return ERESTART */
 1102         lwkt_reltoken(&tty_token);
 1103         return error;
 1104 
 1105     case VT_GETACTIVE:          /* get active vty # */
 1106         *(int *)data = sc->cur_scp->index + 1;
 1107         lwkt_reltoken(&tty_token);
 1108         return 0;
 1109 
 1110     case VT_GETINDEX:           /* get this vty # */
 1111         *(int *)data = scp->index + 1;
 1112         lwkt_reltoken(&tty_token);
 1113         return 0;
 1114 
 1115     case VT_LOCKSWITCH:         /* prevent vty switching */
 1116         syscons_lock();
 1117         if ((*(int *)data) & 0x01)
 1118             sc->flags |= SC_SCRN_VTYLOCK;
 1119         else
 1120             sc->flags &= ~SC_SCRN_VTYLOCK;
 1121         syscons_unlock();
 1122         lwkt_reltoken(&tty_token);
 1123         return 0;
 1124 
 1125     case KDENABIO:              /* allow io operations */
 1126         error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
 1127         if (error != 0) {
 1128             lwkt_reltoken(&tty_token);
 1129             return error;
 1130         }
 1131         if (securelevel > 0) {
 1132             lwkt_reltoken(&tty_token);
 1133             return EPERM;
 1134         }
 1135 #if defined(__i386__)
 1136         curthread->td_lwp->lwp_md.md_regs->tf_eflags |= PSL_IOPL;
 1137 #elif defined(__x86_64__)
 1138         curthread->td_lwp->lwp_md.md_regs->tf_rflags |= PSL_IOPL;
 1139 #endif
 1140         lwkt_reltoken(&tty_token);
 1141         return 0;
 1142 
 1143     case KDDISABIO:             /* disallow io operations (default) */
 1144 #if defined(__i386__)
 1145         curthread->td_lwp->lwp_md.md_regs->tf_eflags &= ~PSL_IOPL;
 1146 #elif defined(__x86_64__)
 1147         curthread->td_lwp->lwp_md.md_regs->tf_rflags &= ~PSL_IOPL;
 1148 #endif
 1149         lwkt_reltoken(&tty_token);
 1150         return 0;
 1151 
 1152     case KDSKBSTATE:            /* set keyboard state (locks) */
 1153         if (*(int *)data & ~LOCK_MASK) {
 1154             lwkt_reltoken(&tty_token);
 1155             return EINVAL;
 1156         }
 1157         syscons_lock();
 1158         scp->status &= ~LOCK_MASK;
 1159         scp->status |= *(int *)data;
 1160         syscons_unlock();
 1161         if (scp == sc->cur_scp)
 1162             update_kbd_state(scp, scp->status, LOCK_MASK, FALSE);
 1163         lwkt_reltoken(&tty_token);
 1164         return 0;
 1165 
 1166     case KDGKBSTATE:            /* get keyboard state (locks) */
 1167         if (scp == sc->cur_scp)
 1168             save_kbd_state(scp, FALSE);
 1169         *(int *)data = scp->status & LOCK_MASK;
 1170         lwkt_reltoken(&tty_token);
 1171         return 0;
 1172 
 1173     case KDGETREPEAT:           /* get keyboard repeat & delay rates */
 1174     case KDSETREPEAT:           /* set keyboard repeat & delay rates (new) */
 1175         error = kbd_ioctl(sc->kbd, cmd, data);
 1176         if (error == ENOIOCTL)
 1177             error = ENODEV;
 1178         lwkt_reltoken(&tty_token);
 1179         return error;
 1180 
 1181     case KDSETRAD:              /* set keyboard repeat & delay rates (old) */
 1182         if (*(int *)data & ~0x7f) {
 1183             lwkt_reltoken(&tty_token);
 1184             return EINVAL;
 1185         }
 1186         error = kbd_ioctl(sc->kbd, cmd, data);
 1187         if (error == ENOIOCTL)
 1188             error = ENODEV;
 1189         lwkt_reltoken(&tty_token);
 1190         return error;
 1191 
 1192     case KDSKBMODE:             /* set keyboard mode */
 1193         switch (*(int *)data) {
 1194         case K_XLATE:           /* switch to XLT ascii mode */
 1195         case K_RAW:             /* switch to RAW scancode mode */
 1196         case K_CODE:            /* switch to CODE mode */
 1197             scp->kbd_mode = *(int *)data;
 1198             if (scp == sc->cur_scp)
 1199                 kbd_ioctl(sc->kbd, cmd, data);
 1200             lwkt_reltoken(&tty_token);
 1201             return 0;
 1202         default:
 1203             lwkt_reltoken(&tty_token);
 1204             return EINVAL;
 1205         }
 1206         /* NOT REACHED */
 1207 
 1208     case KDGKBMODE:             /* get keyboard mode */
 1209         *(int *)data = scp->kbd_mode;
 1210         lwkt_reltoken(&tty_token);
 1211         return 0;
 1212 
 1213     case KDGKBINFO:
 1214         error = kbd_ioctl(sc->kbd, cmd, data);
 1215         if (error == ENOIOCTL)
 1216             error = ENODEV;
 1217         lwkt_reltoken(&tty_token);
 1218         return error;
 1219 
 1220     case KDMKTONE:              /* sound the bell */
 1221         syscons_lock();
 1222         if (*(int*)data)
 1223             sc_bell(scp, (*(int*)data)&0xffff,
 1224                     (((*(int*)data)>>16)&0xffff)*hz/1000);
 1225         else
 1226             sc_bell(scp, scp->bell_pitch, scp->bell_duration);
 1227         syscons_unlock();
 1228         lwkt_reltoken(&tty_token);
 1229         return 0;
 1230 
 1231     case KIOCSOUND:             /* make tone (*data) hz */
 1232         syscons_lock();
 1233         if (scp == sc->cur_scp) {
 1234             if (*(int *)data) {
 1235                 error = sc_tone(*(int *)data);
 1236             } else {
 1237                 error = sc_tone(0);
 1238             }
 1239         } else {
 1240             error = 0;
 1241         }
 1242         syscons_unlock();
 1243         lwkt_reltoken(&tty_token);
 1244         return error;
 1245 
 1246     case KDGKBTYPE:             /* get keyboard type */
 1247         error = kbd_ioctl(sc->kbd, cmd, data);
 1248         if (error == ENOIOCTL) {
 1249             /* always return something? XXX */
 1250             *(int *)data = 0;
 1251         }
 1252         lwkt_reltoken(&tty_token);
 1253         return 0;
 1254 
 1255     case KDSETLED:              /* set keyboard LED status */
 1256         if (*(int *)data & ~LED_MASK) { /* FIXME: LOCK_MASK? */
 1257             lwkt_reltoken(&tty_token);
 1258             return EINVAL;
 1259         }
 1260         syscons_lock();
 1261         scp->status &= ~LED_MASK;
 1262         scp->status |= *(int *)data;
 1263         syscons_unlock();
 1264         if (scp == sc->cur_scp)
 1265             update_kbd_leds(scp, scp->status);
 1266         lwkt_reltoken(&tty_token);
 1267         return 0;
 1268 
 1269     case KDGETLED:              /* get keyboard LED status */
 1270         if (scp == sc->cur_scp)
 1271             save_kbd_state(scp, FALSE);
 1272         *(int *)data = scp->status & LED_MASK;
 1273         lwkt_reltoken(&tty_token);
 1274         return 0;
 1275 
 1276         case KBADDKBD:              /* add/remove keyboard to/from mux */
 1277         case KBRELKBD:
 1278                 error = kbd_ioctl(sc->kbd, cmd, data);
 1279                 if (error == ENOIOCTL)
 1280                         error = ENODEV;
 1281                 lwkt_reltoken(&tty_token);
 1282                 return error;
 1283 
 1284     case CONS_SETKBD:           /* set the new keyboard */
 1285         {
 1286             keyboard_t *newkbd;
 1287 
 1288             newkbd = kbd_get_keyboard(*(int *)data);
 1289             if (newkbd == NULL) {
 1290                 lwkt_reltoken(&tty_token);
 1291                 return EINVAL;
 1292             }
 1293             error = 0;
 1294             if (sc->kbd != newkbd) {
 1295                 i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit,
 1296                                  (void *)&sc->keyboard, sckbdevent, sc);
 1297                 /* i == newkbd->kb_index */
 1298                 if (i >= 0) {
 1299                     if (sc->kbd != NULL) {
 1300                         save_kbd_state(sc->cur_scp, FALSE);
 1301                         kbd_release(sc->kbd, (void *)&sc->keyboard);
 1302                     }
 1303                     syscons_lock();
 1304                     sc->kbd = kbd_get_keyboard(i); /* sc->kbd == newkbd */
 1305                     sc->keyboard = i;
 1306                     syscons_unlock();
 1307                     kbd_ioctl(sc->kbd, KDSKBMODE,
 1308                               (caddr_t)&sc->cur_scp->kbd_mode);
 1309                     update_kbd_state(sc->cur_scp, sc->cur_scp->status,
 1310                         LOCK_MASK, FALSE);
 1311                 } else {
 1312                     error = EPERM;      /* XXX */
 1313                 }
 1314             }
 1315             lwkt_reltoken(&tty_token);
 1316             return error;
 1317         }
 1318 
 1319     case CONS_RELKBD:           /* release the current keyboard */
 1320         error = 0;
 1321         if (sc->kbd != NULL) {
 1322             save_kbd_state(sc->cur_scp, FALSE);
 1323             error = kbd_release(sc->kbd, (void *)&sc->keyboard);
 1324             if (error == 0) {
 1325                 syscons_lock();
 1326                 sc->kbd = NULL;
 1327                 sc->keyboard = -1;
 1328                 syscons_unlock();
 1329             }
 1330         }
 1331         lwkt_reltoken(&tty_token);
 1332         return error;
 1333 
 1334     case CONS_GETTERM:          /* get the current terminal emulator info */
 1335         {
 1336             sc_term_sw_t *sw;
 1337 
 1338             if (((term_info_t *)data)->ti_index == 0) {
 1339                 sw = scp->tsw;
 1340             } else {
 1341                 sw = sc_term_match_by_number(((term_info_t *)data)->ti_index);
 1342             }
 1343             if (sw != NULL) {
 1344                 strncpy(((term_info_t *)data)->ti_name, sw->te_name, 
 1345                         sizeof(((term_info_t *)data)->ti_name));
 1346                 strncpy(((term_info_t *)data)->ti_desc, sw->te_desc, 
 1347                         sizeof(((term_info_t *)data)->ti_desc));
 1348                 ((term_info_t *)data)->ti_flags = 0;
 1349                 lwkt_reltoken(&tty_token);
 1350                 return 0;
 1351             } else {
 1352                 ((term_info_t *)data)->ti_name[0] = '\0';
 1353                 ((term_info_t *)data)->ti_desc[0] = '\0';
 1354                 ((term_info_t *)data)->ti_flags = 0;
 1355                 lwkt_reltoken(&tty_token);
 1356                 return EINVAL;
 1357             }
 1358         }
 1359 
 1360     case CONS_SETTERM:          /* set the current terminal emulator */
 1361         syscons_lock();
 1362         error = sc_init_emulator(scp, ((term_info_t *)data)->ti_name);
 1363         /* FIXME: what if scp == sc_console! XXX */
 1364         syscons_unlock();
 1365         lwkt_reltoken(&tty_token);
 1366         return error;
 1367 
 1368     case GIO_SCRNMAP:           /* get output translation table */
 1369         bcopy(&sc->scr_map, data, sizeof(sc->scr_map));
 1370         lwkt_reltoken(&tty_token);
 1371         return 0;
 1372 
 1373     case PIO_SCRNMAP:           /* set output translation table */
 1374         bcopy(data, &sc->scr_map, sizeof(sc->scr_map));
 1375         for (i=0; i<sizeof(sc->scr_map); i++) {
 1376             sc->scr_rmap[sc->scr_map[i]] = i;
 1377         }
 1378         lwkt_reltoken(&tty_token);
 1379         return 0;
 1380 
 1381     case GIO_KEYMAP:            /* get keyboard translation table */
 1382     case PIO_KEYMAP:            /* set keyboard translation table */
 1383     case GIO_DEADKEYMAP:        /* get accent key translation table */
 1384     case PIO_DEADKEYMAP:        /* set accent key translation table */
 1385     case GETFKEY:               /* get function key string */
 1386     case SETFKEY:               /* set function key string */
 1387         error = kbd_ioctl(sc->kbd, cmd, data);
 1388         if (error == ENOIOCTL)
 1389             error = ENODEV;
 1390         lwkt_reltoken(&tty_token);
 1391         return error;
 1392 
 1393 #ifndef SC_NO_FONT_LOADING
 1394 
 1395     case PIO_FONT8x8:           /* set 8x8 dot font */
 1396         if (!ISFONTAVAIL(sc->adp->va_flags)) {
 1397             lwkt_reltoken(&tty_token);
 1398             return ENXIO;
 1399         }
 1400         syscons_lock();
 1401         bcopy(data, sc->font_8, 8*256);
 1402         sc->fonts_loaded |= FONT_8;
 1403         /*
 1404          * FONT KLUDGE
 1405          * Always use the font page #0. XXX
 1406          * Don't load if the current font size is not 8x8.
 1407          */
 1408         if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size < 14))
 1409             sc_load_font(sc->cur_scp, 0, 8, sc->font_8, 0, 256);
 1410         syscons_unlock();
 1411         lwkt_reltoken(&tty_token);
 1412         return 0;
 1413 
 1414     case GIO_FONT8x8:           /* get 8x8 dot font */
 1415         if (!ISFONTAVAIL(sc->adp->va_flags)) {
 1416             lwkt_reltoken(&tty_token);
 1417             return ENXIO;
 1418         }
 1419         if (sc->fonts_loaded & FONT_8) {
 1420             bcopy(sc->font_8, data, 8*256);
 1421             lwkt_reltoken(&tty_token);
 1422             return 0;
 1423         }
 1424         else {
 1425             lwkt_reltoken(&tty_token);
 1426             return ENXIO;
 1427         }
 1428 
 1429     case PIO_FONT8x14:          /* set 8x14 dot font */
 1430         if (!ISFONTAVAIL(sc->adp->va_flags)) {
 1431             lwkt_reltoken(&tty_token);
 1432             return ENXIO;
 1433         }
 1434         syscons_lock();
 1435         bcopy(data, sc->font_14, 14*256);
 1436         sc->fonts_loaded |= FONT_14;
 1437         /*
 1438          * FONT KLUDGE
 1439          * Always use the font page #0. XXX
 1440          * Don't load if the current font size is not 8x14.
 1441          */
 1442         if (ISTEXTSC(sc->cur_scp)
 1443             && (sc->cur_scp->font_size >= 14)
 1444             && (sc->cur_scp->font_size < 16)) {
 1445             sc_load_font(sc->cur_scp, 0, 14, sc->font_14, 0, 256);
 1446         }
 1447         syscons_unlock();
 1448         lwkt_reltoken(&tty_token);
 1449         return 0;
 1450 
 1451     case GIO_FONT8x14:          /* get 8x14 dot font */
 1452         if (!ISFONTAVAIL(sc->adp->va_flags)) {
 1453             lwkt_reltoken(&tty_token);
 1454             return ENXIO;
 1455         }
 1456         if (sc->fonts_loaded & FONT_14) {
 1457             bcopy(sc->font_14, data, 14*256);
 1458             lwkt_reltoken(&tty_token);
 1459             return 0;
 1460         }
 1461         else {
 1462             lwkt_reltoken(&tty_token);
 1463             return ENXIO;
 1464         }
 1465 
 1466     case PIO_FONT8x16:          /* set 8x16 dot font */
 1467         if (!ISFONTAVAIL(sc->adp->va_flags)) {
 1468             lwkt_reltoken(&tty_token);
 1469             return ENXIO;
 1470         }
 1471         syscons_lock();
 1472         bcopy(data, sc->font_16, 16*256);
 1473         sc->fonts_loaded |= FONT_16;
 1474         /*
 1475          * FONT KLUDGE
 1476          * Always use the font page #0. XXX
 1477          * Don't load if the current font size is not 8x16.
 1478          */
 1479         if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size >= 16))
 1480             sc_load_font(sc->cur_scp, 0, 16, sc->font_16, 0, 256);
 1481         syscons_unlock();
 1482         lwkt_reltoken(&tty_token);
 1483         return 0;
 1484 
 1485     case GIO_FONT8x16:          /* get 8x16 dot font */
 1486         if (!ISFONTAVAIL(sc->adp->va_flags)) {
 1487             lwkt_reltoken(&tty_token);
 1488             return ENXIO;
 1489         }
 1490         if (sc->fonts_loaded & FONT_16) {
 1491             bcopy(sc->font_16, data, 16*256);
 1492             lwkt_reltoken(&tty_token);
 1493             return 0;
 1494         }
 1495         else {
 1496             lwkt_reltoken(&tty_token);
 1497             return ENXIO;
 1498         }
 1499 
 1500 #endif /* SC_NO_FONT_LOADING */
 1501 
 1502     default:
 1503         break;
 1504     }
 1505 
 1506     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, ap->a_cred);
 1507     if (error != ENOIOCTL) {
 1508         lwkt_reltoken(&tty_token);
 1509         return(error);
 1510     }
 1511     error = ttioctl(tp, cmd, data, flag);
 1512     if (error != ENOIOCTL) {
 1513         lwkt_reltoken(&tty_token);
 1514         return(error);
 1515     }
 1516     lwkt_reltoken(&tty_token);
 1517     return(ENOTTY);
 1518 }
 1519 
 1520 static void
 1521 scstart(struct tty *tp)
 1522 {
 1523     struct clist *rbp;
 1524     int len;
 1525     u_char buf[PCBURST];
 1526     scr_stat *scp = SC_STAT(tp->t_dev);
 1527 
 1528     syscons_lock();
 1529     if (scp->status & SLKED ||
 1530         (scp == scp->sc->cur_scp && scp->sc->blink_in_progress))
 1531     {
 1532         syscons_unlock();
 1533         return;
 1534     }
 1535     if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
 1536         tp->t_state |= TS_BUSY;
 1537         rbp = &tp->t_outq;
 1538         while (rbp->c_cc) {
 1539             len = q_to_b(rbp, buf, PCBURST);
 1540             sc_puts(scp, buf, len);
 1541         }
 1542         tp->t_state &= ~TS_BUSY;
 1543         syscons_unlock();
 1544         ttwwakeup(tp);
 1545     } else {
 1546         syscons_unlock();
 1547     }
 1548 }
 1549 
 1550 static void
 1551 sccnprobe(struct consdev *cp)
 1552 {
 1553     int unit;
 1554     int flags;
 1555 
 1556     cp->cn_pri = sc_get_cons_priority(&unit, &flags);
 1557 
 1558     /* a video card is always required */
 1559     if (!scvidprobe(unit, flags, TRUE))
 1560         cp->cn_pri = CN_DEAD;
 1561 
 1562     /* syscons will become console even when there is no keyboard */
 1563     sckbdprobe(unit, flags, TRUE);
 1564 
 1565     if (cp->cn_pri == CN_DEAD) {
 1566         return;
 1567     }
 1568 
 1569     /* initialize required fields */
 1570     cp->cn_probegood = 1;
 1571 }
 1572 
 1573 static void
 1574 sccninit(struct consdev *cp)
 1575 {
 1576     int unit;
 1577     int flags;
 1578 
 1579     sc_get_cons_priority(&unit, &flags);
 1580     scinit(unit, flags | SC_KERNEL_CONSOLE);
 1581     sc_console_unit = unit;
 1582     sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console_scp;
 1583 }
 1584 
 1585 static void
 1586 sccninit_fini(struct consdev *cp)
 1587 {
 1588         if (cctl_dev == NULL)
 1589                 kprintf("sccninit_fini: WARNING: cctl_dev is NULL!\n");
 1590         cp->cn_dev = cctl_dev;
 1591 }
 1592 
 1593 static void
 1594 sccnterm(struct consdev *cp)
 1595 {
 1596     /* we are not the kernel console any more, release everything */
 1597 
 1598     if (sc_console_unit < 0)
 1599         return;                 /* shouldn't happen */
 1600 
 1601 #if 0 /* XXX */
 1602     syscons_lock();
 1603     sc_clear_screen(sc_console);
 1604     sccnupdate(sc_console);
 1605     syscons_unlock();
 1606 #endif
 1607     scterm(sc_console_unit, SC_KERNEL_CONSOLE);
 1608     sc_console_unit = -1;
 1609     sc_console = NULL;
 1610 }
 1611 
 1612 /*
 1613  * Console path - cannot block!
 1614  */
 1615 static void
 1616 sccnputc(void *private, int c)
 1617 {
 1618     u_char buf[1];
 1619     scr_stat *scp = sc_console;
 1620     void *save;
 1621 #ifndef SC_NO_HISTORY
 1622 #if 0
 1623     struct tty *tp;
 1624 #endif
 1625 #endif /* !SC_NO_HISTORY */
 1626 
 1627     /* assert(sc_console != NULL) */
 1628 
 1629     syscons_lock();
 1630 #ifndef SC_NO_HISTORY
 1631     if (scp == scp->sc->cur_scp && scp->status & SLKED) {
 1632         scp->status &= ~SLKED;
 1633 #if 0
 1634         /* This can block, illegal in the console path */
 1635         update_kbd_state(scp, scp->status, SLKED, TRUE);
 1636 #endif
 1637         if (scp->status & BUFFER_SAVED) {
 1638             if (!sc_hist_restore(scp))
 1639                 sc_remove_cutmarking(scp);
 1640             scp->status &= ~BUFFER_SAVED;
 1641             scp->status |= CURSOR_ENABLED;
 1642             sc_draw_cursor_image(scp);
 1643         }
 1644 #if 0
 1645         tp = VIRTUAL_TTY(scp->sc, scp->index);
 1646         /* This can block, illegal in the console path */
 1647         if (ISTTYOPEN(tp)) {
 1648             scstart(tp);
 1649         }
 1650 #endif
 1651     }
 1652 #endif /* !SC_NO_HISTORY */
 1653 
 1654     save = scp->ts;
 1655     if (kernel_console_ts != NULL)
 1656         scp->ts = kernel_console_ts;
 1657     buf[0] = c;
 1658     sc_puts(scp, buf, 1);
 1659     scp->ts = save;
 1660 
 1661     sccnupdate(scp);
 1662     syscons_unlock();
 1663 }
 1664 
 1665 /*
 1666  * Console path - cannot block!
 1667  */
 1668 static int
 1669 sccngetc(void *private)
 1670 {
 1671     return sccngetch(0);
 1672 }
 1673 
 1674 /*
 1675  * Console path - cannot block!
 1676  */
 1677 static int
 1678 sccncheckc(void *private)
 1679 {
 1680     return sccngetch(SCGETC_NONBLOCK);
 1681 }
 1682 
 1683 static void
 1684 sccndbctl(void *private, int on)
 1685 {
 1686     /* assert(sc_console_unit >= 0) */
 1687     /* try to switch to the kernel console screen */
 1688     if (on && debugger == 0) {
 1689         /*
 1690          * TRY to make sure the screen saver is stopped, 
 1691          * and the screen is updated before switching to 
 1692          * the vty0.
 1693          */
 1694         scrn_timer(NULL);
 1695         if (!cold
 1696             && sc_console->sc->cur_scp->smode.mode == VT_AUTO
 1697             && sc_console->smode.mode == VT_AUTO) {
 1698             sc_console->sc->cur_scp->status |= MOUSE_HIDDEN;
 1699             syscons_lock();
 1700             sc_switch_scr(sc_console->sc, sc_console->index);
 1701             syscons_unlock();
 1702         }
 1703     }
 1704     if (on)
 1705         ++debugger;
 1706     else
 1707         --debugger;
 1708 }
 1709 
 1710 /*
 1711  * Console path - cannot block!
 1712  */
 1713 static int
 1714 sccngetch(int flags)
 1715 {
 1716     static struct fkeytab fkey;
 1717     static int fkeycp;
 1718     scr_stat *scp;
 1719     u_char *p;
 1720     int cur_mode;
 1721     int c;
 1722 
 1723     syscons_lock();
 1724     /* assert(sc_console != NULL) */
 1725 
 1726     /* 
 1727      * Stop the screen saver and update the screen if necessary.
 1728      * What if we have been running in the screen saver code... XXX
 1729      */
 1730     sc_touch_scrn_saver();
 1731     scp = sc_console->sc->cur_scp;      /* XXX */
 1732     sccnupdate(scp);
 1733     syscons_unlock();
 1734 
 1735     if (fkeycp < fkey.len) {
 1736         return fkey.str[fkeycp++];
 1737     }
 1738 
 1739     if (scp->sc->kbd == NULL) {
 1740         return -1;
 1741     }
 1742 
 1743     /* 
 1744      * Make sure the keyboard is accessible even when the kbd device
 1745      * driver is disabled.
 1746      */
 1747     crit_enter();
 1748     kbd_enable(scp->sc->kbd);
 1749 
 1750     /* we shall always use the keyboard in the XLATE mode here */
 1751     cur_mode = scp->kbd_mode;
 1752     scp->kbd_mode = K_XLATE;
 1753     kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
 1754 
 1755     kbd_poll(scp->sc->kbd, TRUE);
 1756     c = scgetc(scp->sc, SCGETC_CN | flags);
 1757     kbd_poll(scp->sc->kbd, FALSE);
 1758 
 1759     scp->kbd_mode = cur_mode;
 1760     kbd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
 1761     kbd_disable(scp->sc->kbd);
 1762     crit_exit();
 1763 
 1764     switch (KEYFLAGS(c)) {
 1765     case 0:     /* normal char */
 1766         return KEYCHAR(c);
 1767     case FKEY:  /* function key */
 1768         p = kbd_get_fkeystr(scp->sc->kbd, KEYCHAR(c), (size_t *)&fkeycp);
 1769         fkey.len = fkeycp;
 1770         if ((p != NULL) && (fkey.len > 0)) {
 1771             bcopy(p, fkey.str, fkey.len);
 1772             fkeycp = 1;
 1773             return fkey.str[0];
 1774         }
 1775         return c;       /* XXX */
 1776     case NOKEY:
 1777     case ERRKEY:
 1778     default:
 1779         return -1;
 1780     }
 1781     /* NOT REACHED */
 1782 }
 1783 
 1784 static void
 1785 sccnupdate(scr_stat *scp)
 1786 {
 1787     /* this is a cut-down version of scrn_timer()... */
 1788 
 1789     if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress) {
 1790         return;
 1791     }
 1792 
 1793     if (debugger > 0 || panicstr || shutdown_in_progress) {
 1794         sc_touch_scrn_saver();
 1795     } else if (scp != scp->sc->cur_scp) {
 1796         return;
 1797     }
 1798 
 1799     if (!run_scrn_saver)
 1800         scp->sc->flags &= ~SC_SCRN_IDLE;
 1801 #if NSPLASH > 0
 1802     /*
 1803      * This is a hard path, we cannot call stop_scrn_saver() here.
 1804      */
 1805     if ((saver_mode != CONS_LKM_SAVER) || !(scp->sc->flags & SC_SCRN_IDLE))
 1806         if (scp->sc->flags & SC_SCRN_BLANKED) {
 1807             sc_touch_scrn_saver();
 1808             /*stop_scrn_saver(scp->sc, current_saver);*/
 1809         }
 1810 #endif /* NSPLASH */
 1811 
 1812     if (scp != scp->sc->cur_scp || scp->sc->blink_in_progress
 1813         || scp->sc->switch_in_progress) {
 1814         return;
 1815     }
 1816     /*
 1817      * FIXME: unlike scrn_timer(), we call scrn_update() from here even
 1818      * when write_in_progress is non-zero.  XXX
 1819      */
 1820 
 1821     if (!ISGRAPHSC(scp) && !(scp->sc->flags & SC_SCRN_BLANKED))
 1822         scrn_update(scp, TRUE);
 1823 }
 1824 
 1825 static void
 1826 scrn_timer(void *arg)
 1827 {
 1828     static int kbd_interval = 0;
 1829     struct timeval tv;
 1830     sc_softc_t *sc;
 1831     scr_stat *scp;
 1832     int again;
 1833 
 1834     /*
 1835      * Setup depending on who called us
 1836      */
 1837     again = (arg != NULL);
 1838     if (arg != NULL) {
 1839         sc = (sc_softc_t *)arg;
 1840     } else if (sc_console != NULL) {
 1841         sc = sc_console->sc;
 1842     } else {
 1843         return;
 1844     }
 1845 
 1846     /*
 1847      * Don't do anything when we are performing some I/O operations.
 1848      * (These are initiated by the frontend?)
 1849      */
 1850     if (sc->font_loading_in_progress || sc->videoio_in_progress) {
 1851         if (again)
 1852             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
 1853         return;
 1854     }
 1855 
 1856     /*
 1857      * Try to allocate a keyboard automatically
 1858      */
 1859     if ((sc->kbd == NULL) && (sc->config & SC_AUTODETECT_KBD)) {
 1860         if (++kbd_interval >= 25) {
 1861             sc->keyboard = sc_allocate_keyboard(sc, -1);
 1862             if (sc->keyboard >= 0) {
 1863                 sc->kbd = kbd_get_keyboard(sc->keyboard);
 1864                 kbd_ioctl(sc->kbd, KDSKBMODE,
 1865                           (caddr_t)&sc->cur_scp->kbd_mode);
 1866                 update_kbd_state(sc->cur_scp, sc->cur_scp->status,
 1867                     LOCK_MASK, FALSE);
 1868             }
 1869             kbd_interval = 0;
 1870         }
 1871     }
 1872 
 1873     /*
 1874      * Should we stop the screen saver?  We need the syscons_lock
 1875      * for most of this stuff.
 1876      */
 1877     getmicrouptime(&tv);
 1878 
 1879     if (syscons_lock_nonblock() != 0) {
 1880         /* failed to get the lock */
 1881         if (again)
 1882             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
 1883         return;
 1884     }
 1885     /* successful lock */
 1886 
 1887     if (debugger > 0 || panicstr || shutdown_in_progress)
 1888         sc_touch_scrn_saver();
 1889     if (run_scrn_saver) {
 1890         if (tv.tv_sec > sc->scrn_time_stamp + scrn_blank_time)
 1891             sc->flags |= SC_SCRN_IDLE;
 1892         else
 1893             sc->flags &= ~SC_SCRN_IDLE;
 1894     } else {
 1895         sc->scrn_time_stamp = tv.tv_sec;
 1896         sc->flags &= ~SC_SCRN_IDLE;
 1897         if (scrn_blank_time > 0)
 1898             run_scrn_saver = TRUE;
 1899     }
 1900 #if NSPLASH > 0
 1901     if ((saver_mode != CONS_LKM_SAVER) || !(sc->flags & SC_SCRN_IDLE))
 1902         if (sc->flags & SC_SCRN_BLANKED)
 1903             stop_scrn_saver(sc, current_saver);
 1904 #endif /* NSPLASH */
 1905 
 1906     /* should we just return ? */
 1907     if (sc->blink_in_progress || sc->switch_in_progress ||
 1908         sc->write_in_progress)
 1909     {
 1910         syscons_unlock();
 1911         if (again)
 1912             callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
 1913         return;
 1914     }
 1915 
 1916     /* Update the screen */
 1917     scp = sc->cur_scp;          /* cur_scp may have changed... */
 1918     if (!ISGRAPHSC(scp) && !(sc->flags & SC_SCRN_BLANKED))
 1919         scrn_update(scp, TRUE);
 1920 
 1921 #if NSPLASH > 0
 1922     /* should we activate the screen saver? */
 1923     if ((saver_mode == CONS_LKM_SAVER) && (sc->flags & SC_SCRN_IDLE))
 1924         if (!ISGRAPHSC(scp) || (sc->flags & SC_SCRN_BLANKED))
 1925             (*current_saver)(sc, TRUE);
 1926 #endif /* NSPLASH */
 1927 
 1928     syscons_unlock();
 1929     if (again)
 1930         callout_reset(&sc->scrn_timer_ch, hz / 25, scrn_timer, sc);
 1931 }
 1932 
 1933 static int
 1934 and_region(int *s1, int *e1, int s2, int e2)
 1935 {
 1936     if (*e1 < s2 || e2 < *s1)
 1937         return FALSE;
 1938     *s1 = imax(*s1, s2);
 1939     *e1 = imin(*e1, e2);
 1940     return TRUE;
 1941 }
 1942 
 1943 static void 
 1944 scrn_update(scr_stat *scp, int show_cursor)
 1945 {
 1946     int start;
 1947     int end;
 1948     int s;
 1949     int e;
 1950 
 1951     /* assert(scp == scp->sc->cur_scp) */
 1952 
 1953     ++scp->sc->videoio_in_progress;
 1954 
 1955 #ifndef SC_NO_CUTPASTE
 1956     /* remove the previous mouse pointer image if necessary */
 1957     if (scp->status & MOUSE_VISIBLE) {
 1958         s = scp->mouse_pos;
 1959         e = scp->mouse_pos + scp->xsize + 1;
 1960         if ((scp->status & (MOUSE_MOVED | MOUSE_HIDDEN))
 1961             || and_region(&s, &e, scp->start, scp->end)
 1962             || ((scp->status & CURSOR_ENABLED) && 
 1963                 (scp->cursor_pos != scp->cursor_oldpos) &&
 1964                 (and_region(&s, &e, scp->cursor_pos, scp->cursor_pos)
 1965                  || and_region(&s, &e, scp->cursor_oldpos, scp->cursor_oldpos)))) {
 1966             sc_remove_mouse_image(scp);
 1967             if (scp->end >= scp->xsize*scp->ysize)
 1968                 scp->end = scp->xsize*scp->ysize - 1;
 1969         }
 1970     }
 1971 #endif /* !SC_NO_CUTPASTE */
 1972 
 1973 #if 1
 1974     /* debug: XXX */
 1975     if (scp->end >= scp->xsize*scp->ysize) {
 1976         kprintf("scrn_update(): scp->end %d > size_of_screen!!\n", scp->end);
 1977         scp->end = scp->xsize*scp->ysize - 1;
 1978     }
 1979     if (scp->start < 0) {
 1980         kprintf("scrn_update(): scp->start %d < 0\n", scp->start);
 1981         scp->start = 0;
 1982     }
 1983 #endif
 1984 
 1985     /* update screen image */
 1986     if (scp->start <= scp->end)  {
 1987         if (scp->mouse_cut_end >= 0) {
 1988             /* there is a marked region for cut & paste */
 1989             if (scp->mouse_cut_start <= scp->mouse_cut_end) {
 1990                 start = scp->mouse_cut_start;
 1991                 end = scp->mouse_cut_end;
 1992             } else {
 1993                 start = scp->mouse_cut_end;
 1994                 end = scp->mouse_cut_start - 1;
 1995             }
 1996             s = start;
 1997             e = end;
 1998             /* does the cut-mark region overlap with the update region? */
 1999             if (and_region(&s, &e, scp->start, scp->end)) {
 2000                 (*scp->rndr->draw)(scp, s, e - s + 1, TRUE);
 2001                 s = 0;
 2002                 e = start - 1;
 2003                 if (and_region(&s, &e, scp->start, scp->end))
 2004                     (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
 2005                 s = end + 1;
 2006                 e = scp->xsize*scp->ysize - 1;
 2007                 if (and_region(&s, &e, scp->start, scp->end))
 2008                     (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
 2009             } else {
 2010                 (*scp->rndr->draw)(scp, scp->start,
 2011                                    scp->end - scp->start + 1, FALSE);
 2012             }
 2013         } else {
 2014             (*scp->rndr->draw)(scp, scp->start,
 2015                                scp->end - scp->start + 1, FALSE);
 2016         }
 2017     }
 2018 
 2019     /* we are not to show the cursor and the mouse pointer... */
 2020     if (!show_cursor) {
 2021         scp->end = 0;
 2022         scp->start = scp->xsize*scp->ysize - 1;
 2023         --scp->sc->videoio_in_progress;
 2024         return;
 2025     }
 2026 
 2027     /* update cursor image */
 2028     if (scp->status & CURSOR_ENABLED) {
 2029         s = scp->start;
 2030         e = scp->end;
 2031         /* did cursor move since last time ? */
 2032         if (scp->cursor_pos != scp->cursor_oldpos) {
 2033             /* do we need to remove old cursor image ? */
 2034             if (!and_region(&s, &e, scp->cursor_oldpos, scp->cursor_oldpos))
 2035                 sc_remove_cursor_image(scp);
 2036             sc_draw_cursor_image(scp);
 2037         } else {
 2038             if (and_region(&s, &e, scp->cursor_pos, scp->cursor_pos))
 2039                 /* cursor didn't move, but has been overwritten */
 2040                 sc_draw_cursor_image(scp);
 2041             else if (scp->sc->flags & SC_BLINK_CURSOR)
 2042                 /* if it's a blinking cursor, update it */
 2043                 (*scp->rndr->blink_cursor)(scp, scp->cursor_pos,
 2044                                            sc_inside_cutmark(scp,
 2045                                                scp->cursor_pos));
 2046         }
 2047     }
 2048 
 2049 #ifndef SC_NO_CUTPASTE
 2050     /* update "pseudo" mouse pointer image */
 2051     if (scp->sc->flags & SC_MOUSE_ENABLED) {
 2052         if (!(scp->status & (MOUSE_VISIBLE | MOUSE_HIDDEN))) {
 2053             scp->status &= ~MOUSE_MOVED;
 2054             sc_draw_mouse_image(scp);
 2055         }
 2056     }
 2057 #endif /* SC_NO_CUTPASTE */
 2058 
 2059     scp->end = 0;
 2060     scp->start = scp->xsize*scp->ysize - 1;
 2061 
 2062     --scp->sc->videoio_in_progress;
 2063 }
 2064 
 2065 #if NSPLASH > 0
 2066 static int
 2067 scsplash_callback(int event, void *arg)
 2068 {
 2069     sc_softc_t *sc;
 2070     int error;
 2071 
 2072     sc = (sc_softc_t *)arg;
 2073 
 2074     switch (event) {
 2075     case SPLASH_INIT:
 2076         if (add_scrn_saver(scsplash_saver) == 0) {
 2077             sc->flags &= ~SC_SAVER_FAILED;
 2078             run_scrn_saver = TRUE;
 2079             if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) {
 2080                 scsplash_stick(TRUE);
 2081                 (*current_saver)(sc, TRUE);
 2082             }
 2083         }
 2084         return 0;
 2085 
 2086     case SPLASH_TERM:
 2087         if (current_saver == scsplash_saver) {
 2088             scsplash_stick(FALSE);
 2089             error = remove_scrn_saver(scsplash_saver);
 2090             if (error) {
 2091                 return error;
 2092             }
 2093         }
 2094         return 0;
 2095 
 2096     default:
 2097         return EINVAL;
 2098     }
 2099 }
 2100 
 2101 static void
 2102 scsplash_saver(sc_softc_t *sc, int show)
 2103 {
 2104     static int busy = FALSE;
 2105     scr_stat *scp;
 2106 
 2107     if (busy)
 2108         return;
 2109     busy = TRUE;
 2110 
 2111     scp = sc->cur_scp;
 2112     if (show) {
 2113         if (!(sc->flags & SC_SAVER_FAILED)) {
 2114             if (!(sc->flags & SC_SCRN_BLANKED))
 2115                 set_scrn_saver_mode(scp, -1, NULL, 0);
 2116             switch (splash(sc->adp, TRUE)) {
 2117             case 0:             /* succeeded */
 2118                 break;
 2119             case EAGAIN:        /* try later */
 2120                 restore_scrn_saver_mode(scp, FALSE);
 2121                 sc_touch_scrn_saver();          /* XXX */
 2122                 break;
 2123             default:
 2124                 sc->flags |= SC_SAVER_FAILED;
 2125                 scsplash_stick(FALSE);
 2126                 restore_scrn_saver_mode(scp, TRUE);
 2127                 kprintf("scsplash_saver(): failed to put up the image\n");
 2128                 break;
 2129             }
 2130         }
 2131     } else if (!sticky_splash) {
 2132         if ((sc->flags & SC_SCRN_BLANKED) && (splash(sc->adp, FALSE) == 0))
 2133             restore_scrn_saver_mode(scp, TRUE);
 2134     }
 2135     busy = FALSE;
 2136 }
 2137 
 2138 static int
 2139 add_scrn_saver(void (*this_saver)(sc_softc_t *, int))
 2140 {
 2141 #if 0
 2142     int error;
 2143 
 2144     if (current_saver != none_saver) {
 2145         error = remove_scrn_saver(current_saver);
 2146         if (error)
 2147             return error;
 2148     }
 2149 #endif
 2150     if (current_saver != none_saver) {
 2151         return EBUSY;
 2152     }
 2153 
 2154     run_scrn_saver = FALSE;
 2155     saver_mode = CONS_LKM_SAVER;
 2156     current_saver = this_saver;
 2157     return 0;
 2158 }
 2159 
 2160 static int
 2161 remove_scrn_saver(void (*this_saver)(sc_softc_t *, int))
 2162 {
 2163     if (current_saver != this_saver)
 2164         return EINVAL;
 2165 
 2166 #if 0
 2167     /*
 2168      * In order to prevent `current_saver' from being called by
 2169      * the timeout routine `scrn_timer()' while we manipulate 
 2170      * the saver list, we shall set `current_saver' to `none_saver' 
 2171      * before stopping the current saver, rather than blocking by `splXX()'.
 2172      */
 2173     current_saver = none_saver;
 2174     if (scrn_blanked)
 2175         stop_scrn_saver(this_saver);
 2176 #endif
 2177     /* unblank all blanked screens */
 2178     wait_scrn_saver_stop(NULL);
 2179     if (scrn_blanked) {
 2180         return EBUSY;
 2181     }
 2182 
 2183     current_saver = none_saver;
 2184     return 0;
 2185 }
 2186 
 2187 static int
 2188 set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
 2189 {
 2190 
 2191     /* assert(scp == scp->sc->cur_scp) */
 2192     crit_enter();
 2193     if (!ISGRAPHSC(scp))
 2194         sc_remove_cursor_image(scp);
 2195     scp->splash_save_mode = scp->mode;
 2196     scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE);
 2197     scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE);
 2198     scp->status |= (UNKNOWN_MODE | SAVER_RUNNING);
 2199     scp->sc->flags |= SC_SCRN_BLANKED;
 2200     ++scrn_blanked;
 2201     crit_exit();
 2202     if (mode < 0) {
 2203         return 0;
 2204     }
 2205     scp->mode = mode;
 2206     if (set_mode(scp) == 0) {
 2207         if (scp->sc->adp->va_info.vi_flags & V_INFO_GRAPHICS)
 2208             scp->status |= GRAPHICS_MODE;
 2209 #ifndef SC_NO_PALETTE_LOADING
 2210         if (pal != NULL)
 2211             load_palette(scp->sc->adp, pal);
 2212 #endif
 2213         sc_set_border(scp, border);
 2214         return 0;
 2215     } else {
 2216         crit_enter();
 2217         scp->mode = scp->splash_save_mode;
 2218         scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
 2219         scp->status |= scp->splash_save_status;
 2220         crit_exit();
 2221         return 1;
 2222     }
 2223     /* NOTREACHED */
 2224 }
 2225 
 2226 static int
 2227 restore_scrn_saver_mode(scr_stat *scp, int changemode)
 2228 {
 2229     int mode;
 2230     int status;
 2231 
 2232     /* assert(scp == scp->sc->cur_scp) */
 2233     crit_enter();
 2234     mode = scp->mode;
 2235     status = scp->status;
 2236     scp->mode = scp->splash_save_mode;
 2237     scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
 2238     scp->status |= scp->splash_save_status;
 2239     scp->sc->flags &= ~SC_SCRN_BLANKED;
 2240     if (!changemode) {
 2241         if (!ISGRAPHSC(scp))
 2242             sc_draw_cursor_image(scp);
 2243         --scrn_blanked;
 2244         crit_exit();
 2245         return 0;
 2246     }
 2247     if (set_mode(scp) == 0) {
 2248 #ifndef SC_NO_PALETTE_LOADING
 2249         load_palette(scp->sc->adp, scp->sc->palette);
 2250 #endif
 2251         --scrn_blanked;
 2252         crit_exit();
 2253         return 0;
 2254     } else {
 2255         scp->mode = mode;
 2256         scp->status = status;
 2257         crit_exit();
 2258         return 1;
 2259     }
 2260     /* NOTREACHED */
 2261 }
 2262 
 2263 static void
 2264 stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int))
 2265 {
 2266     (*saver)(sc, FALSE);
 2267     run_scrn_saver = FALSE;
 2268     /* the screen saver may have chosen not to stop after all... */
 2269     if (sc->flags & SC_SCRN_BLANKED) {
 2270         return;
 2271     }
 2272 
 2273     mark_all(sc->cur_scp);
 2274     if (sc->delayed_next_scr)
 2275         sc_switch_scr(sc, sc->delayed_next_scr - 1);
 2276     wakeup((caddr_t)&scrn_blanked);
 2277 }
 2278 
 2279 static int
 2280 wait_scrn_saver_stop(sc_softc_t *sc)
 2281 {
 2282     int error = 0;
 2283 
 2284     while (scrn_blanked > 0) {
 2285         run_scrn_saver = FALSE;
 2286         if (sc && !(sc->flags & SC_SCRN_BLANKED)) {
 2287             error = 0;
 2288             break;
 2289         }
 2290         error = tsleep((caddr_t)&scrn_blanked, PCATCH, "scrsav", 0);
 2291         /* May return ERESTART */
 2292         if (error)
 2293                 break;
 2294     }
 2295     run_scrn_saver = FALSE;
 2296     return error;
 2297 }
 2298 #endif /* NSPLASH */
 2299 
 2300 void
 2301 sc_touch_scrn_saver(void)
 2302 {
 2303     scsplash_stick(FALSE);
 2304     run_scrn_saver = FALSE;
 2305 }
 2306 
 2307 int
 2308 sc_switch_scr(sc_softc_t *sc, u_int next_scr)
 2309 {
 2310     scr_stat *cur_scp;
 2311     struct tty *tp;
 2312 
 2313     DPRINTF(5, ("sc0: sc_switch_scr() %d ", next_scr + 1));
 2314 
 2315     /* prevent switch if previously requested */
 2316     if (sc->flags & SC_SCRN_VTYLOCK) {
 2317             sc_bell(sc->cur_scp, sc->cur_scp->bell_pitch,
 2318                 sc->cur_scp->bell_duration);
 2319             return EPERM;
 2320     }
 2321 
 2322     /* delay switch if the screen is blanked or being updated */
 2323     if ((sc->flags & SC_SCRN_BLANKED) || sc->write_in_progress
 2324         || sc->blink_in_progress || sc->videoio_in_progress) {
 2325         sc->delayed_next_scr = next_scr + 1;
 2326         sc_touch_scrn_saver();
 2327         DPRINTF(5, ("switch delayed\n"));
 2328         return 0;
 2329     }
 2330 
 2331     cur_scp = sc->cur_scp;
 2332 
 2333     /*
 2334      * we are in the middle of the vty switching process...
 2335      *
 2336      * This may be in the console path, be very careful.  pfindn() is
 2337      * still going to use a spinlock but it no longer uses tokens so
 2338      * we should be ok.
 2339      */
 2340     if (sc->switch_in_progress &&
 2341         (cur_scp->smode.mode == VT_PROCESS) &&
 2342         cur_scp->proc) {
 2343         if (cur_scp->proc != pfindn(cur_scp->pid)) {
 2344             /* 
 2345              * The controlling process has died!!.  Do some clean up.
 2346              * NOTE:`cur_scp->proc' and `cur_scp->smode.mode' 
 2347              * are not reset here yet; they will be cleared later.
 2348              */
 2349             DPRINTF(5, ("cur_scp controlling process %d died, ", cur_scp->pid));
 2350             if (cur_scp->status & SWITCH_WAIT_REL) {
 2351                 /*
 2352                  * Force the previous switch to finish, but return now 
 2353                  * with error.
 2354                  *
 2355                  */
 2356                 DPRINTF(5, ("reset WAIT_REL, "));
 2357                 finish_vt_rel(cur_scp, TRUE);
 2358                 DPRINTF(5, ("finishing previous switch\n"));
 2359                 return EINVAL;
 2360             } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
 2361                 /* let's assume screen switch has been completed. */
 2362                 DPRINTF(5, ("reset WAIT_ACQ, "));
 2363                 finish_vt_acq(cur_scp);
 2364             } else {
 2365                 /* 
 2366                  * We are in between screen release and acquisition, and
 2367                  * reached here via scgetc() or scrn_timer() which has 
 2368                  * interrupted exchange_scr(). Don't do anything stupid.
 2369                  */
 2370                 DPRINTF(5, ("waiting nothing, "));
 2371             }
 2372         } else {
 2373             /*
 2374              * The controlling process is alive, but not responding... 
 2375              * It is either buggy or it may be just taking time.
 2376              * The following code is a gross kludge to cope with this
 2377              * problem for which there is no clean solution. XXX
 2378              */
 2379             if (cur_scp->status & SWITCH_WAIT_REL) {
 2380                 switch (sc->switch_in_progress++) {
 2381                 case 1:
 2382                     break;
 2383                 case 2:
 2384                     DPRINTF(5, ("sending relsig again, "));
 2385                     signal_vt_rel(cur_scp);
 2386                     break;
 2387                 case 3:
 2388                     break;
 2389                 case 4:
 2390                 default:
 2391                     /*
 2392                      * Act as if the controlling program returned
 2393                      * VT_FALSE.
 2394                      *
 2395                      */
 2396                     DPRINTF(5, ("force reset WAIT_REL, "));
 2397                     finish_vt_rel(cur_scp, FALSE);
 2398                     DPRINTF(5, ("act as if VT_FALSE was seen\n"));
 2399                     return EINVAL;
 2400                 }
 2401             } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
 2402                 switch (sc->switch_in_progress++) {
 2403                 case 1:
 2404                     break;
 2405                 case 2:
 2406                     DPRINTF(5, ("sending acqsig again, "));
 2407                     signal_vt_acq(cur_scp);
 2408                     break;
 2409                 case 3:
 2410                     break;
 2411                 case 4:
 2412                 default:
 2413                      /* clear the flag and finish the previous switch */
 2414                     DPRINTF(5, ("force reset WAIT_ACQ, "));
 2415                     finish_vt_acq(cur_scp);
 2416                     break;
 2417                 }
 2418             }
 2419         }
 2420     }
 2421 
 2422     /*
 2423      * Return error if an invalid argument is given, or vty switch
 2424      * is still in progress.
 2425      */
 2426     if ((next_scr < sc->first_vty) || (next_scr >= sc->first_vty + sc->vtys)
 2427         || sc->switch_in_progress) {
 2428         sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
 2429         DPRINTF(5, ("error 1\n"));
 2430         return EINVAL;
 2431     }
 2432 
 2433     /*
 2434      * Don't allow switching away from the graphics mode vty
 2435      * if the switch mode is VT_AUTO, unless the next vty is the same 
 2436      * as the current or the current vty has been closed (but showing).
 2437      */
 2438     tp = VIRTUAL_TTY(sc, cur_scp->index);
 2439     if ((cur_scp->index != next_scr)
 2440         && ISTTYOPEN(tp)
 2441         && (cur_scp->smode.mode == VT_AUTO)
 2442         && ISGRAPHSC(cur_scp)) {
 2443         sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
 2444         DPRINTF(5, ("error, graphics mode\n"));
 2445         return EINVAL;
 2446     }
 2447 
 2448     /*
 2449      * Is the wanted vty open? Don't allow switching to a closed vty.
 2450      * If we are in DDB, don't switch to a vty in the VT_PROCESS mode.
 2451      * Note that we always allow the user to switch to the kernel 
 2452      * console even if it is closed.
 2453      */
 2454     if ((sc_console == NULL) || (next_scr != sc_console->index)) {
 2455         tp = VIRTUAL_TTY(sc, next_scr);
 2456         if (!ISTTYOPEN(tp)) {
 2457             sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
 2458             DPRINTF(5, ("error 2, requested vty isn't open!\n"));
 2459             return EINVAL;
 2460         }
 2461         if ((debugger > 0) && (SC_STAT(tp->t_dev)->smode.mode == VT_PROCESS)) {
 2462             DPRINTF(5, ("error 3, requested vty is in the VT_PROCESS mode\n"));
 2463             return EINVAL;
 2464         }
 2465     }
 2466 
 2467     /* this is the start of vty switching process... */
 2468     ++sc->switch_in_progress;
 2469     sc->delayed_next_scr = 0;
 2470     sc->old_scp = cur_scp;
 2471     sc->new_scp = SC_STAT(SC_DEV(sc, next_scr));
 2472     if (sc->new_scp == sc->old_scp) {
 2473         sc->switch_in_progress = 0;
 2474         wakeup((caddr_t)&sc->new_scp->smode);
 2475         DPRINTF(5, ("switch done (new == old)\n"));
 2476         return 0;
 2477     }
 2478 
 2479     /* has controlling process died? */
 2480     vt_proc_alive(sc->old_scp);
 2481     vt_proc_alive(sc->new_scp);
 2482 
 2483     /* wait for the controlling process to release the screen, if necessary */
 2484     if (signal_vt_rel(sc->old_scp)) {
 2485         return 0;
 2486     }
 2487 
 2488     /* go set up the new vty screen */
 2489     exchange_scr(sc);
 2490 
 2491     /* wake up processes waiting for this vty */
 2492     wakeup((caddr_t)&sc->cur_scp->smode);
 2493 
 2494     /* wait for the controlling process to acknowledge, if necessary */
 2495     if (signal_vt_acq(sc->cur_scp)) {
 2496         return 0;
 2497     }
 2498 
 2499     sc->switch_in_progress = 0;
 2500     if (sc->unit == sc_console_unit)
 2501         cons_unavail = FALSE;
 2502     DPRINTF(5, ("switch done\n"));
 2503 
 2504     return 0;
 2505 }
 2506 
 2507 static void
 2508 do_switch_scr(sc_softc_t *sc)
 2509 {
 2510     lwkt_gettoken(&tty_token);
 2511     vt_proc_alive(sc->new_scp);
 2512 
 2513     exchange_scr(sc);
 2514     /* sc->cur_scp == sc->new_scp */
 2515     wakeup((caddr_t)&sc->cur_scp->smode);
 2516 
 2517     /* wait for the controlling process to acknowledge, if necessary */
 2518     if (!signal_vt_acq(sc->cur_scp)) {
 2519         sc->switch_in_progress = 0;
 2520         if (sc->unit == sc_console_unit)
 2521             cons_unavail = FALSE;
 2522     }
 2523     lwkt_reltoken(&tty_token);
 2524 }
 2525 
 2526 static int
 2527 vt_proc_alive(scr_stat *scp)
 2528 {
 2529     lwkt_gettoken(&tty_token);
 2530     if (scp->proc) {
 2531         if (scp->proc == pfindn(scp->pid)) {
 2532             lwkt_reltoken(&tty_token);
 2533             return TRUE;
 2534         }
 2535         scp->proc = NULL;
 2536         scp->smode.mode = VT_AUTO;
 2537         DPRINTF(5, ("vt controlling process %d died\n", scp->pid));
 2538     }
 2539     lwkt_reltoken(&tty_token);
 2540     return FALSE;
 2541 }
 2542 
 2543 static int
 2544 signal_vt_rel(scr_stat *scp)
 2545 {
 2546     struct proc *p;
 2547 
 2548     lwkt_gettoken(&tty_token);
 2549     if (scp->smode.mode != VT_PROCESS) {
 2550         lwkt_reltoken(&tty_token);
 2551         return FALSE;
 2552     }
 2553     scp->status |= SWITCH_WAIT_REL;
 2554     p = scp->proc;
 2555     PHOLD(p);
 2556     ksignal(p, scp->smode.relsig);
 2557     PRELE(p);
 2558     DPRINTF(5, ("sending relsig to %d\n", scp->pid));
 2559     lwkt_reltoken(&tty_token);
 2560 
 2561     return TRUE;
 2562 }
 2563 
 2564 static int
 2565 signal_vt_acq(scr_stat *scp)
 2566 {
 2567     struct proc *p;
 2568 
 2569     lwkt_gettoken(&tty_token);
 2570     if (scp->smode.mode != VT_PROCESS) {
 2571         lwkt_reltoken(&tty_token);
 2572         return FALSE;
 2573     }
 2574     if (scp->sc->unit == sc_console_unit)
 2575         cons_unavail = TRUE;
 2576     scp->status |= SWITCH_WAIT_ACQ;
 2577     p = scp->proc;
 2578     PHOLD(p);
 2579     ksignal(p, scp->smode.acqsig);
 2580     PRELE(p);
 2581     DPRINTF(5, ("sending acqsig to %d\n", scp->pid));
 2582     lwkt_reltoken(&tty_token);
 2583 
 2584     return TRUE;
 2585 }
 2586 
 2587 static int
 2588 finish_vt_rel(scr_stat *scp, int release)
 2589 {
 2590     lwkt_gettoken(&tty_token);
 2591     if (scp == scp->sc->old_scp && scp->status & SWITCH_WAIT_REL) {
 2592         scp->status &= ~SWITCH_WAIT_REL;
 2593         if (release)
 2594             do_switch_scr(scp->sc);
 2595         else
 2596             scp->sc->switch_in_progress = 0;
 2597         lwkt_reltoken(&tty_token);
 2598         return 0;
 2599     }
 2600     lwkt_reltoken(&tty_token);
 2601     return EINVAL;
 2602 }
 2603 
 2604 static int
 2605 finish_vt_acq(scr_stat *scp)
 2606 {
 2607     lwkt_gettoken(&tty_token);
 2608     if (scp == scp->sc->new_scp && scp->status & SWITCH_WAIT_ACQ) {
 2609         scp->status &= ~SWITCH_WAIT_ACQ;
 2610         scp->sc->switch_in_progress = 0;
 2611         lwkt_reltoken(&tty_token);
 2612         return 0;
 2613     }
 2614     lwkt_reltoken(&tty_token);
 2615     return EINVAL;
 2616 }
 2617 
 2618 static void
 2619 exchange_scr(sc_softc_t *sc)
 2620 {
 2621     scr_stat *scp;
 2622 
 2623     lwkt_gettoken(&tty_token);
 2624     /* save the current state of video and keyboard */
 2625     sc_move_cursor(sc->old_scp, sc->old_scp->xpos, sc->old_scp->ypos);
 2626     if (!ISGRAPHSC(sc->old_scp))
 2627         sc_remove_cursor_image(sc->old_scp);
 2628     if (sc->old_scp->kbd_mode == K_XLATE)
 2629         save_kbd_state(sc->old_scp, TRUE);
 2630 
 2631     /* set up the video for the new screen */
 2632     scp = sc->cur_scp = sc->new_scp;
 2633     if (sc->old_scp->mode != scp->mode || ISUNKNOWNSC(sc->old_scp))
 2634         set_mode(scp);
 2635     else
 2636         sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
 2637                     (void *)sc->adp->va_window, FALSE);
 2638     scp->status |= MOUSE_HIDDEN;
 2639     sc_move_cursor(scp, scp->xpos, scp->ypos);
 2640     if (!ISGRAPHSC(scp))
 2641         sc_set_cursor_image(scp);
 2642 #ifndef SC_NO_PALETTE_LOADING
 2643     if (ISGRAPHSC(sc->old_scp))
 2644         load_palette(sc->adp, sc->palette);
 2645 #endif
 2646     sc_set_border(scp, scp->border);
 2647 
 2648     /* set up the keyboard for the new screen */
 2649     if (sc->old_scp->kbd_mode != scp->kbd_mode)
 2650         kbd_ioctl(sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
 2651     update_kbd_state(scp, scp->status, LOCK_MASK, TRUE);
 2652 
 2653     mark_all(scp);
 2654     lwkt_reltoken(&tty_token);
 2655 }
 2656 
 2657 static void
 2658 sc_puts(scr_stat *scp, u_char *buf, int len)
 2659 {
 2660 #if NSPLASH > 0
 2661     /* make screensaver happy */
 2662     if (!sticky_splash && scp == scp->sc->cur_scp)
 2663         run_scrn_saver = FALSE;
 2664 #endif
 2665 
 2666     if (scp->tsw)
 2667         (*scp->tsw->te_puts)(scp, buf, len);
 2668 
 2669     if (scp->sc->delayed_next_scr)
 2670         sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
 2671 
 2672 }
 2673 
 2674 void
 2675 sc_draw_cursor_image(scr_stat *scp)
 2676 {
 2677     /* assert(scp == scp->sc->cur_scp); */
 2678     ++scp->sc->videoio_in_progress;
 2679     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos,
 2680                               scp->sc->flags & SC_BLINK_CURSOR, TRUE,
 2681                               sc_inside_cutmark(scp, scp->cursor_pos));
 2682     scp->cursor_oldpos = scp->cursor_pos;
 2683     --scp->sc->videoio_in_progress;
 2684 }
 2685 
 2686 void
 2687 sc_remove_cursor_image(scr_stat *scp)
 2688 {
 2689     /* assert(scp == scp->sc->cur_scp); */
 2690     ++scp->sc->videoio_in_progress;
 2691     (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos,
 2692                               scp->sc->flags & SC_BLINK_CURSOR, FALSE,
 2693                               sc_inside_cutmark(scp, scp->cursor_oldpos));
 2694     --scp->sc->videoio_in_progress;
 2695 }
 2696 
 2697 static void
 2698 update_cursor_image(scr_stat *scp)
 2699 {
 2700     int blink;
 2701 
 2702     if (scp->sc->flags & SC_CHAR_CURSOR) {
 2703         scp->cursor_base = imax(0, scp->sc->cursor_base);
 2704         scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
 2705     } else {
 2706         scp->cursor_base = 0;
 2707         scp->cursor_height = scp->font_size;
 2708     }
 2709     blink = scp->sc->flags & SC_BLINK_CURSOR;
 2710 
 2711     /* assert(scp == scp->sc->cur_scp); */
 2712     ++scp->sc->videoio_in_progress;
 2713     (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos, blink, FALSE, 
 2714                               sc_inside_cutmark(scp, scp->cursor_pos));
 2715     (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height, blink);
 2716     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos, blink, TRUE, 
 2717                               sc_inside_cutmark(scp, scp->cursor_pos));
 2718     --scp->sc->videoio_in_progress;
 2719 }
 2720 
 2721 void
 2722 sc_set_cursor_image(scr_stat *scp)
 2723 {
 2724     if (scp->sc->flags & SC_CHAR_CURSOR) {
 2725         scp->cursor_base = imax(0, scp->sc->cursor_base);
 2726         scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
 2727     } else {
 2728         scp->cursor_base = 0;
 2729         scp->cursor_height = scp->font_size;
 2730     }
 2731 
 2732     /* assert(scp == scp->sc->cur_scp); */
 2733     ++scp->sc->videoio_in_progress;
 2734     (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height,
 2735                              scp->sc->flags & SC_BLINK_CURSOR);
 2736     --scp->sc->videoio_in_progress;
 2737 }
 2738 
 2739 static void
 2740 scinit(int unit, int flags)
 2741 {
 2742     /*
 2743      * When syscons is being initialized as the kernel console, malloc()
 2744      * is not yet functional, because various kernel structures has not been
 2745      * fully initialized yet.  Therefore, we need to declare the following
 2746      * static buffers for the console.  This is less than ideal, 
 2747      * but is necessry evil for the time being.  XXX
 2748      */
 2749     static scr_stat main_console;
 2750     static u_short sc_buffer[ROW*COL];  /* XXX */
 2751 #ifndef SC_NO_FONT_LOADING
 2752     static u_char font_8[256*8];
 2753     static u_char font_14[256*14];
 2754     static u_char font_16[256*16];
 2755 #endif
 2756 
 2757     sc_softc_t *sc;
 2758     scr_stat *scp;
 2759     video_adapter_t *adp;
 2760     int col;
 2761     int row;
 2762     int i;
 2763 
 2764     /* one time initialization */
 2765     if (init_done == COLD)
 2766         sc_get_bios_values(&bios_value);
 2767     init_done = WARM;
 2768 
 2769     /*
 2770      * Allocate resources.  Even if we are being called for the second
 2771      * time, we must allocate them again, because they might have 
 2772      * disappeared...
 2773      */
 2774     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
 2775     adp = NULL;
 2776     if (sc->adapter >= 0) {
 2777         vid_release(sc->adp, (void *)&sc->adapter);
 2778         adp = sc->adp;
 2779         sc->adp = NULL;
 2780     }
 2781     if (sc->keyboard >= 0) {
 2782         DPRINTF(5, ("sc%d: releasing kbd%d\n", unit, sc->keyboard));
 2783         i = kbd_release(sc->kbd, (void *)&sc->keyboard);
 2784         DPRINTF(5, ("sc%d: kbd_release returned %d\n", unit, i));
 2785         if (sc->kbd != NULL) {
 2786             DPRINTF(5, ("sc%d: kbd != NULL!, index:%d, unit:%d, flags:0x%x\n",
 2787                 unit, sc->kbd->kb_index, sc->kbd->kb_unit, sc->kbd->kb_flags));
 2788         }
 2789         sc->kbd = NULL;
 2790     }
 2791     sc->adapter = vid_allocate("*", unit, (void *)&sc->adapter);
 2792     sc->adp = vid_get_adapter(sc->adapter);
 2793     /* assert((sc->adapter >= 0) && (sc->adp != NULL)) */
 2794     sc->keyboard = sc_allocate_keyboard(sc, unit);
 2795     DPRINTF(1, ("sc%d: keyboard %d\n", unit, sc->keyboard));
 2796     sc->kbd = kbd_get_keyboard(sc->keyboard);
 2797     if (sc->kbd != NULL) {
 2798         DPRINTF(1, ("sc%d: kbd index:%d, unit:%d, flags:0x%x\n",
 2799                 unit, sc->kbd->kb_index, sc->kbd->kb_unit, sc->kbd->kb_flags));
 2800     }
 2801 
 2802     if (!(sc->flags & SC_INIT_DONE) || (adp != sc->adp)) {
 2803 
 2804         sc->initial_mode = sc->adp->va_initial_mode;
 2805 
 2806 #ifndef SC_NO_FONT_LOADING
 2807         if (flags & SC_KERNEL_CONSOLE) {
 2808             sc->font_8 = font_8;
 2809             sc->font_14 = font_14;
 2810             sc->font_16 = font_16;
 2811         } else if (sc->font_8 == NULL) {
 2812             /* assert(sc_malloc) */
 2813             sc->font_8 = kmalloc(sizeof(font_8), M_SYSCONS, M_WAITOK);
 2814             sc->font_14 = kmalloc(sizeof(font_14), M_SYSCONS, M_WAITOK);
 2815             sc->font_16 = kmalloc(sizeof(font_16), M_SYSCONS, M_WAITOK);
 2816         }
 2817 #endif
 2818 
 2819         lwkt_gettoken(&tty_token);
 2820         /* extract the hardware cursor location and hide the cursor for now */
 2821         (*vidsw[sc->adapter]->read_hw_cursor)(sc->adp, &col, &row);
 2822         (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, -1, -1);
 2823         lwkt_reltoken(&tty_token);
 2824 
 2825         /* set up the first console */
 2826         sc->first_vty = unit*MAXCONS;
 2827         sc->vtys = MAXCONS;             /* XXX: should be configurable */
 2828         if (flags & SC_KERNEL_CONSOLE) {
 2829             scp = &main_console;
 2830             sc->console_scp = scp;
 2831             init_scp(sc, sc->first_vty, scp);
 2832             sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize,
 2833                         (void *)sc_buffer, FALSE);
 2834             if (sc_init_emulator(scp, SC_DFLT_TERM))
 2835                 sc_init_emulator(scp, "*");
 2836             (*scp->tsw->te_default_attr)(scp,
 2837                                          kernel_default.std_color,
 2838                                          kernel_default.rev_color);
 2839         } else {
 2840             /* assert(sc_malloc) */
 2841             sc->dev = kmalloc(sizeof(cdev_t)*sc->vtys, M_SYSCONS, M_WAITOK | M_ZERO);
 2842 
 2843             sc->dev[0] = make_dev(&sc_ops, unit*MAXCONS, UID_ROOT, 
 2844                                 GID_WHEEL, 0600, "ttyv%r", unit*MAXCONS);
 2845 
 2846             sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
 2847             scp = alloc_scp(sc, sc->first_vty);
 2848             sc->dev[0]->si_drv1 = scp;
 2849         }
 2850         sc->cur_scp = scp;
 2851 
 2852         /* copy screen to temporary buffer */
 2853         sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
 2854                     (void *)scp->sc->adp->va_window, FALSE);
 2855         if (ISTEXTSC(scp))
 2856             sc_vtb_copy(&scp->scr, 0, &scp->vtb, 0, scp->xsize*scp->ysize);
 2857 
 2858         /* move cursors to the initial positions */
 2859         if (col >= scp->xsize)
 2860             col = 0;
 2861         if (row >= scp->ysize)
 2862             row = scp->ysize - 1;
 2863         scp->xpos = col;
 2864         scp->ypos = row;
 2865         scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col;
 2866         if (bios_value.cursor_end < scp->font_size)
 2867             sc->cursor_base = scp->font_size - bios_value.cursor_end - 1;
 2868         else
 2869             sc->cursor_base = 0;
 2870         i = bios_value.cursor_end - bios_value.cursor_start + 1;
 2871         sc->cursor_height = imin(i, scp->font_size);
 2872 #ifndef SC_NO_SYSMOUSE
 2873         sc_mouse_move(scp, scp->xpixel/2, scp->ypixel/2);
 2874 #endif
 2875         if (!ISGRAPHSC(scp)) {
 2876             sc_set_cursor_image(scp);
 2877             sc_draw_cursor_image(scp);
 2878         }
 2879 
 2880         /* save font and palette */
 2881 #ifndef SC_NO_FONT_LOADING
 2882         sc->fonts_loaded = 0;
 2883         if (ISFONTAVAIL(sc->adp->va_flags)) {
 2884 #ifdef SC_DFLT_FONT
 2885             bcopy(dflt_font_8, sc->font_8, sizeof(dflt_font_8));
 2886             bcopy(dflt_font_14, sc->font_14, sizeof(dflt_font_14));
 2887             bcopy(dflt_font_16, sc->font_16, sizeof(dflt_font_16));
 2888             sc->fonts_loaded = FONT_16 | FONT_14 | FONT_8;
 2889             if (scp->font_size < 14) {
 2890                 sc_load_font(scp, 0, 8, sc->font_8, 0, 256);
 2891             } else if (scp->font_size >= 16) {
 2892                 sc_load_font(scp, 0, 16, sc->font_16, 0, 256);
 2893             } else {
 2894                 sc_load_font(scp, 0, 14, sc->font_14, 0, 256);
 2895             }
 2896 #else /* !SC_DFLT_FONT */
 2897             if (scp->font_size < 14) {
 2898                 sc_save_font(scp, 0, 8, sc->font_8, 0, 256);
 2899                 sc->fonts_loaded = FONT_8;
 2900             } else if (scp->font_size >= 16) {
 2901                 sc_save_font(scp, 0, 16, sc->font_16, 0, 256);
 2902                 sc->fonts_loaded = FONT_16;
 2903             } else {
 2904                 sc_save_font(scp, 0, 14, sc->font_14, 0, 256);
 2905                 sc->fonts_loaded = FONT_14;
 2906             }
 2907 #endif /* SC_DFLT_FONT */
 2908             /* FONT KLUDGE: always use the font page #0. XXX */
 2909             sc_show_font(scp, 0);
 2910         }
 2911 #endif /* !SC_NO_FONT_LOADING */
 2912 
 2913 #ifndef SC_NO_PALETTE_LOADING
 2914         save_palette(sc->adp, sc->palette);
 2915 #endif
 2916 
 2917 #if NSPLASH > 0
 2918         if (!(sc->flags & SC_SPLASH_SCRN) && (flags & SC_KERNEL_CONSOLE)) {
 2919             /* we are ready to put up the splash image! */
 2920             splash_init(sc->adp, scsplash_callback, sc);
 2921             sc->flags |= SC_SPLASH_SCRN;
 2922         }
 2923 #endif /* NSPLASH */
 2924     }
 2925 
 2926     /* the rest is not necessary, if we have done it once */
 2927     if (sc->flags & SC_INIT_DONE) {
 2928         return;
 2929     }
 2930 
 2931     /* initialize mapscrn arrays to a one to one map */
 2932     for (i = 0; i < sizeof(sc->scr_map); i++)
 2933         sc->scr_map[i] = sc->scr_rmap[i] = i;
 2934 
 2935     sc->flags |= SC_INIT_DONE;
 2936 }
 2937 
 2938 static void
 2939 scterm(int unit, int flags)
 2940 {
 2941     sc_softc_t *sc;
 2942     scr_stat *scp;
 2943 
 2944     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
 2945     if (sc == NULL)
 2946         return;                 /* shouldn't happen */
 2947 
 2948     lwkt_gettoken(&tty_token);
 2949 #if NSPLASH > 0
 2950     /* this console is no longer available for the splash screen */
 2951     if (sc->flags & SC_SPLASH_SCRN) {
 2952         splash_term(sc->adp);
 2953         sc->flags &= ~SC_SPLASH_SCRN;
 2954     }
 2955 #endif /* NSPLASH */
 2956 
 2957 #if 0 /* XXX */
 2958     /* move the hardware cursor to the upper-left corner */
 2959     (*vidsw[sc->adapter]->set_hw_cursor)(sc->adp, 0, 0);
 2960 #endif
 2961 
 2962     /* release the keyboard and the video card */
 2963     if (sc->keyboard >= 0)
 2964         kbd_release(sc->kbd, &sc->keyboard);
 2965     if (sc->adapter >= 0)
 2966         vid_release(sc->adp, &sc->adapter);
 2967 
 2968     /* 
 2969      * Stop the terminal emulator, if any.  If operating on the
 2970      * kernel console sc->dev may not be setup yet.
 2971      */
 2972     if (flags & SC_KERNEL_CONSOLE)
 2973         scp = sc->console_scp;
 2974     else
 2975         scp = SC_STAT(sc->dev[0]);
 2976     if (scp->tsw)
 2977         (*scp->tsw->te_term)(scp, &scp->ts);
 2978     if (scp->ts != NULL)
 2979         kfree(scp->ts, M_SYSCONS);
 2980 
 2981     /* clear the structure */
 2982     if (!(flags & SC_KERNEL_CONSOLE)) {
 2983         /* XXX: We need delete_dev() for this */
 2984         kfree(sc->dev, M_SYSCONS);
 2985 #if 0
 2986         /* XXX: We need a ttyunregister for this */
 2987         kfree(sc->tty, M_SYSCONS);
 2988 #endif
 2989 #ifndef SC_NO_FONT_LOADING
 2990         kfree(sc->font_8, M_SYSCONS);
 2991         kfree(sc->font_14, M_SYSCONS);
 2992         kfree(sc->font_16, M_SYSCONS);
 2993 #endif
 2994         /* XXX vtb, history */
 2995     }
 2996     bzero(sc, sizeof(*sc));
 2997     sc->keyboard = -1;
 2998     sc->adapter = -1;
 2999     lwkt_reltoken(&tty_token);
 3000 }
 3001 
 3002 static void
 3003 scshutdown(void *arg, int howto)
 3004 {
 3005     /* assert(sc_console != NULL) */
 3006 
 3007     lwkt_gettoken(&tty_token);
 3008     syscons_lock();
 3009     sc_touch_scrn_saver();
 3010     if (!cold && sc_console
 3011         && sc_console->sc->cur_scp->smode.mode == VT_AUTO 
 3012         && sc_console->smode.mode == VT_AUTO) {
 3013         sc_switch_scr(sc_console->sc, sc_console->index);
 3014     }
 3015     shutdown_in_progress = TRUE;
 3016     syscons_unlock();
 3017     lwkt_reltoken(&tty_token);
 3018 }
 3019 
 3020 int
 3021 sc_clean_up(scr_stat *scp)
 3022 {
 3023 #if NSPLASH > 0
 3024     int error;
 3025 #endif /* NSPLASH */
 3026 
 3027     lwkt_gettoken(&tty_token);
 3028     if (scp->sc->flags & SC_SCRN_BLANKED) {
 3029         sc_touch_scrn_saver();
 3030 #if NSPLASH > 0
 3031         if ((error = wait_scrn_saver_stop(scp->sc))) {
 3032             lwkt_reltoken(&tty_token);
 3033             return error;
 3034         }
 3035 #endif /* NSPLASH */
 3036     }
 3037     scp->status |= MOUSE_HIDDEN;
 3038     sc_remove_mouse_image(scp);
 3039     sc_remove_cutmarking(scp);
 3040     lwkt_reltoken(&tty_token);
 3041     return 0;
 3042 }
 3043 
 3044 void
 3045 sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard)
 3046 {
 3047     sc_vtb_t new;
 3048     sc_vtb_t old;
 3049 
 3050     lwkt_gettoken(&tty_token);
 3051     old = scp->vtb;
 3052     sc_vtb_init(&new, VTB_MEMORY, scp->xsize, scp->ysize, NULL, wait);
 3053     if (!discard && (old.vtb_flags & VTB_VALID)) {
 3054         /* retain the current cursor position and buffer contants */
 3055         scp->cursor_oldpos = scp->cursor_pos;
 3056         /* 
 3057          * This works only if the old buffer has the same size as or larger 
 3058          * than the new one. XXX
 3059          */
 3060         sc_vtb_copy(&old, 0, &new, 0, scp->xsize*scp->ysize);
 3061         scp->vtb = new;
 3062     } else {
 3063         scp->vtb = new;
 3064         sc_vtb_destroy(&old);
 3065     }
 3066 
 3067 #ifndef SC_NO_SYSMOUSE
 3068     /* move the mouse cursor at the center of the screen */
 3069     sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
 3070 #endif
 3071     lwkt_reltoken(&tty_token);
 3072 }
 3073 
 3074 static scr_stat *
 3075 alloc_scp(sc_softc_t *sc, int vty)
 3076 {
 3077     scr_stat *scp;
 3078 
 3079     /* assert(sc_malloc) */
 3080 
 3081     scp = kmalloc(sizeof(scr_stat), M_SYSCONS, M_WAITOK);
 3082     init_scp(sc, vty, scp);
 3083 
 3084     sc_alloc_scr_buffer(scp, TRUE, TRUE);
 3085     if (sc_init_emulator(scp, SC_DFLT_TERM))
 3086         sc_init_emulator(scp, "*");
 3087 
 3088 #ifndef SC_NO_CUTPASTE
 3089     sc_alloc_cut_buffer(scp, TRUE);
 3090 #endif
 3091 
 3092 #ifndef SC_NO_HISTORY
 3093     sc_alloc_history_buffer(scp, 0, 0, TRUE);
 3094 #endif
 3095     return scp;
 3096 }
 3097 
 3098 /*
 3099  * NOTE: Must be called with tty_token held.
 3100  */
 3101 static void
 3102 init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
 3103 {
 3104     video_info_t info;
 3105 
 3106     bzero(scp, sizeof(*scp));
 3107 
 3108     scp->index = vty;
 3109     scp->sc = sc;
 3110     scp->status = 0;
 3111     scp->mode = sc->initial_mode;
 3112     callout_init_mp(&scp->blink_screen_ch);
 3113     lwkt_gettoken(&tty_token);
 3114     (*vidsw[sc->adapter]->get_info)(sc->adp, scp->mode, &info);
 3115     lwkt_reltoken(&tty_token);
 3116     if (info.vi_flags & V_INFO_GRAPHICS) {
 3117         scp->status |= GRAPHICS_MODE;
 3118         scp->xpixel = info.vi_width;
 3119         scp->ypixel = info.vi_height;
 3120         scp->xsize = info.vi_width/8;
 3121         scp->ysize = info.vi_height/info.vi_cheight;
 3122         scp->font_size = 0;
 3123         scp->font = NULL;
 3124     } else {
 3125         scp->xsize = info.vi_width;
 3126         scp->ysize = info.vi_height;
 3127         scp->xpixel = scp->xsize*8;
 3128         scp->ypixel = scp->ysize*info.vi_cheight;
 3129         if (info.vi_cheight < 14) {
 3130             scp->font_size = 8;
 3131 #ifndef SC_NO_FONT_LOADING
 3132             scp->font = sc->font_8;
 3133 #else
 3134             scp->font = NULL;
 3135 #endif
 3136         } else if (info.vi_cheight >= 16) {
 3137             scp->font_size = 16;
 3138 #ifndef SC_NO_FONT_LOADING
 3139             scp->font = sc->font_16;
 3140 #else
 3141             scp->font = NULL;
 3142 #endif
 3143         } else {
 3144             scp->font_size = 14;
 3145 #ifndef SC_NO_FONT_LOADING
 3146             scp->font = sc->font_14;
 3147 #else
 3148             scp->font = NULL;
 3149 #endif
 3150         }
 3151     }
 3152     sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
 3153     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
 3154     scp->xoff = scp->yoff = 0;
 3155     scp->xpos = scp->ypos = 0;
 3156     scp->start = scp->xsize * scp->ysize - 1;
 3157     scp->end = 0;
 3158     scp->tsw = NULL;
 3159     scp->ts = NULL;
 3160     scp->rndr = NULL;
 3161     scp->border = BG_BLACK;
 3162     scp->cursor_base = sc->cursor_base;
 3163     scp->cursor_height = imin(sc->cursor_height, scp->font_size);
 3164     scp->mouse_cut_start = scp->xsize*scp->ysize;
 3165     scp->mouse_cut_end = -1;
 3166     scp->mouse_signal = 0;
 3167     scp->mouse_pid = 0;
 3168     scp->mouse_proc = NULL;
 3169     scp->kbd_mode = K_XLATE;
 3170     scp->bell_pitch = bios_value.bell_pitch;
 3171     scp->bell_duration = BELL_DURATION;
 3172     scp->status |= (bios_value.shift_state & NLKED);
 3173     scp->status |= CURSOR_ENABLED | MOUSE_HIDDEN;
 3174     scp->pid = 0;
 3175     scp->proc = NULL;
 3176     scp->smode.mode = VT_AUTO;
 3177     scp->history = NULL;
 3178     scp->history_pos = 0;
 3179     scp->history_size = 0;
 3180 }
 3181 
 3182 int
 3183 sc_init_emulator(scr_stat *scp, char *name)
 3184 {
 3185     sc_term_sw_t *sw;
 3186     sc_rndr_sw_t *rndr;
 3187     void *p;
 3188     int error;
 3189 
 3190     if (name == NULL)   /* if no name is given, use the current emulator */
 3191         sw = scp->tsw;
 3192     else                /* ...otherwise find the named emulator */
 3193         sw = sc_term_match(name);
 3194     if (sw == NULL) {
 3195         return EINVAL;
 3196     }
 3197 
 3198     rndr = NULL;
 3199     if (strcmp(sw->te_renderer, "*") != 0) {
 3200         rndr = sc_render_match(scp, sw->te_renderer, scp->model);
 3201     }
 3202     if (rndr == NULL) {
 3203         rndr = sc_render_match(scp, scp->sc->adp->va_name, scp->model);
 3204         if (rndr == NULL) {
 3205             return ENODEV;
 3206         }
 3207     }
 3208 
 3209     if (sw == scp->tsw) {
 3210         error = (*sw->te_init)(scp, &scp->ts, SC_TE_WARM_INIT);
 3211         scp->rndr = rndr;
 3212         sc_clear_screen(scp);
 3213         /* assert(error == 0); */
 3214         return error;
 3215     }
 3216 
 3217     if (sc_malloc && (sw->te_size > 0))
 3218         p = kmalloc(sw->te_size, M_SYSCONS, M_NOWAIT);
 3219     else
 3220         p = NULL;
 3221     error = (*sw->te_init)(scp, &p, SC_TE_COLD_INIT);
 3222     if (error) {
 3223         return error;
 3224     }
 3225 
 3226     if (scp->tsw)
 3227         (*scp->tsw->te_term)(scp, &scp->ts);
 3228     if (scp->ts != NULL)
 3229         kfree(scp->ts, M_SYSCONS);
 3230     scp->tsw = sw;
 3231     scp->ts = p;
 3232     scp->rndr = rndr;
 3233 
 3234     /* XXX */
 3235     (*sw->te_default_attr)(scp, user_default.std_color, user_default.rev_color);
 3236     sc_clear_screen(scp);
 3237 
 3238     return 0;
 3239 }
 3240 
 3241 /*
 3242  * scgetc(flags) - get character from keyboard.
 3243  * If flags & SCGETC_CN, then avoid harmful side effects.
 3244  * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else
 3245  * return NOKEY if there is nothing there.
 3246  */
 3247 static u_int
 3248 scgetc(sc_softc_t *sc, u_int flags)
 3249 {
 3250     scr_stat *scp;
 3251 #ifndef SC_NO_HISTORY
 3252     struct tty *tp;
 3253 #endif
 3254     u_int c;
 3255     int this_scr;
 3256     int f;
 3257     int i;
 3258 
 3259     lwkt_gettoken(&tty_token);
 3260     if (sc->kbd == NULL) {
 3261         lwkt_reltoken(&tty_token);
 3262         return NOKEY;
 3263     }
 3264 
 3265 next_code:
 3266 #if 1
 3267     /* I don't like this, but... XXX */
 3268     if (flags & SCGETC_CN) {
 3269         syscons_lock();
 3270         sccnupdate(sc->cur_scp);
 3271         syscons_unlock();
 3272     }
 3273 #endif
 3274     scp = sc->cur_scp;
 3275     /* first see if there is something in the keyboard port */
 3276     for (;;) {
 3277         c = kbd_read_char(sc->kbd, !(flags & SCGETC_NONBLOCK));
 3278         if (c == ERRKEY) {
 3279             if (!(flags & SCGETC_CN))
 3280                 sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
 3281         } else if (c == NOKEY) {
 3282             lwkt_reltoken(&tty_token);
 3283             return c;
 3284         } else {
 3285             break;
 3286         }
 3287     }
 3288 
 3289     /* make screensaver happy */
 3290     if (!(c & RELKEY))
 3291         sc_touch_scrn_saver();
 3292 
 3293     if (!(flags & SCGETC_CN))
 3294         /* do the /dev/random device a favour */
 3295         add_keyboard_randomness(c);
 3296 
 3297     if (scp->kbd_mode != K_XLATE) {
 3298         lwkt_reltoken(&tty_token);
 3299         return KEYCHAR(c);
 3300     }
 3301 
 3302     /* if scroll-lock pressed allow history browsing */
 3303     if (!ISGRAPHSC(scp) && scp->history && scp->status & SLKED) {
 3304 
 3305         scp->status &= ~CURSOR_ENABLED;
 3306         sc_remove_cursor_image(scp);
 3307 
 3308 #ifndef SC_NO_HISTORY
 3309         if (!(scp->status & BUFFER_SAVED)) {
 3310             scp->status |= BUFFER_SAVED;
 3311             sc_hist_save(scp);
 3312         }
 3313         switch (c) {
 3314         /* FIXME: key codes */
 3315         case SPCLKEY | FKEY | F(49):  /* home key */
 3316             sc_remove_cutmarking(scp);
 3317             sc_hist_home(scp);
 3318             goto next_code;
 3319 
 3320         case SPCLKEY | FKEY | F(57):  /* end key */
 3321             sc_remove_cutmarking(scp);
 3322             sc_hist_end(scp);
 3323             goto next_code;
 3324 
 3325         case SPCLKEY | FKEY | F(50):  /* up arrow key */
 3326             sc_remove_cutmarking(scp);
 3327             if (sc_hist_up_line(scp))
 3328                 if (!(flags & SCGETC_CN))
 3329                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
 3330             goto next_code;
 3331 
 3332         case SPCLKEY | FKEY | F(58):  /* down arrow key */
 3333             sc_remove_cutmarking(scp);
 3334             if (sc_hist_down_line(scp))
 3335                 if (!(flags & SCGETC_CN))
 3336                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
 3337             goto next_code;
 3338 
 3339         case SPCLKEY | FKEY | F(51):  /* page up key */
 3340             sc_remove_cutmarking(scp);
 3341             for (i=0; i<scp->ysize; i++)
 3342             if (sc_hist_up_line(scp)) {
 3343                 if (!(flags & SCGETC_CN))
 3344                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
 3345                 break;
 3346             }
 3347             goto next_code;
 3348 
 3349         case SPCLKEY | FKEY | F(59):  /* page down key */
 3350             sc_remove_cutmarking(scp);
 3351             for (i=0; i<scp->ysize; i++)
 3352             if (sc_hist_down_line(scp)) {
 3353                 if (!(flags & SCGETC_CN))
 3354                     sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
 3355                 break;
 3356             }
 3357             goto next_code;
 3358         }
 3359 #endif /* SC_NO_HISTORY */
 3360     }
 3361 
 3362     /* 
 3363      * Process and consume special keys here.  Return a plain char code
 3364      * or a char code with the META flag or a function key code.
 3365      */
 3366     if (c & RELKEY) {
 3367         /* key released */
 3368         /* goto next_code */
 3369     } else {
 3370         /* key pressed */
 3371         if (c & SPCLKEY) {
 3372             c &= ~SPCLKEY;
 3373             switch (KEYCHAR(c)) {
 3374             /* LOCKING KEYS */
 3375             case NLK: case CLK: case ALK:
 3376                 break;
 3377             case SLK:
 3378                 kbd_ioctl(sc->kbd, KDGKBSTATE, (caddr_t)&f);
 3379                 if (f & SLKED) {
 3380                     scp->status |= SLKED;
 3381                 } else {
 3382                     if (scp->status & SLKED) {
 3383                         scp->status &= ~SLKED;
 3384 #ifndef SC_NO_HISTORY
 3385                         if (scp->status & BUFFER_SAVED) {
 3386                             if (!sc_hist_restore(scp))
 3387                                 sc_remove_cutmarking(scp);
 3388                             scp->status &= ~BUFFER_SAVED;
 3389                             scp->status |= CURSOR_ENABLED;
 3390                             sc_draw_cursor_image(scp);
 3391                         }
 3392                         tp = VIRTUAL_TTY(sc, scp->index);
 3393                         if (ISTTYOPEN(tp))
 3394                             scstart(tp);
 3395 #endif
 3396                     }
 3397                 }
 3398                 break;
 3399 
 3400             /* NON-LOCKING KEYS */
 3401             case NOP:
 3402             case LSH:  case RSH:  case LCTR: case RCTR:
 3403             case LALT: case RALT: case ASH:  case META:
 3404                 break;
 3405 
 3406             case BTAB:
 3407                 if (!(sc->flags & SC_SCRN_BLANKED)) {
 3408                     lwkt_reltoken(&tty_token);
 3409                     return c;
 3410                 }
 3411                 break;
 3412 
 3413             case SPSC:
 3414 #if NSPLASH > 0
 3415                 /* force activatation/deactivation of the screen saver */
 3416                 if (!(sc->flags & SC_SCRN_BLANKED)) {
 3417                     run_scrn_saver = TRUE;
 3418                     sc->scrn_time_stamp -= scrn_blank_time;
 3419                 }
 3420                 if (cold) {
 3421                     /*
 3422                      * While devices are being probed, the screen saver need
 3423                      * to be invoked explictly. XXX
 3424                      */
 3425                     if (sc->flags & SC_SCRN_BLANKED) {
 3426                         scsplash_stick(FALSE);
 3427                         stop_scrn_saver(sc, current_saver);
 3428                     } else {
 3429                         if (!ISGRAPHSC(scp)) {
 3430                             scsplash_stick(TRUE);
 3431                             (*current_saver)(sc, TRUE);
 3432                         }
 3433                     }
 3434                 }
 3435 #endif /* NSPLASH */
 3436                 break;
 3437 
 3438             case RBT:
 3439 #ifndef SC_DISABLE_REBOOT
 3440                 shutdown_nice(0);
 3441 #endif
 3442                 break;
 3443 
 3444             case HALT:
 3445 #ifndef SC_DISABLE_REBOOT
 3446                 shutdown_nice(RB_HALT);
 3447 #endif
 3448                 break;
 3449 
 3450             case PDWN:
 3451 #ifndef SC_DISABLE_REBOOT
 3452                 shutdown_nice(RB_HALT|RB_POWEROFF);
 3453 #endif
 3454                 break;
 3455 
 3456 #if NAPM > 0
 3457             case SUSP:
 3458                 apm_suspend(PMST_SUSPEND);
 3459                 break;
 3460             case STBY:
 3461                 apm_suspend(PMST_STANDBY);
 3462                 break;
 3463 #else
 3464             case SUSP:
 3465             case STBY:
 3466                 break;
 3467 #endif
 3468 
 3469             case DBG:
 3470 #ifndef SC_DISABLE_DDBKEY
 3471 #ifdef DDB
 3472                 lwkt_reltoken(&tty_token);
 3473                 Debugger("manual escape to debugger");
 3474                 lwkt_gettoken(&tty_token);
 3475 #else
 3476                 kprintf("No debugger in kernel\n");
 3477 #endif
 3478 #else /* SC_DISABLE_DDBKEY */
 3479                 /* do nothing */
 3480 #endif /* SC_DISABLE_DDBKEY */
 3481                 break;
 3482 
 3483             case PNC:
 3484                 if (enable_panic_key)
 3485                         panic("Forced by the panic key");
 3486                 break;
 3487 
 3488             case NEXT:
 3489                 this_scr = scp->index;
 3490                 for (i = (this_scr - sc->first_vty + 1)%sc->vtys;
 3491                         sc->first_vty + i != this_scr; 
 3492                         i = (i + 1)%sc->vtys) {
 3493                     struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
 3494                     if (ISTTYOPEN(tp)) {
 3495                         syscons_lock();
 3496                         sc_switch_scr(scp->sc, sc->first_vty + i);
 3497                         syscons_unlock();
 3498                         break;
 3499                     }
 3500                 }
 3501                 break;
 3502 
 3503             case PREV:
 3504                 this_scr = scp->index;
 3505                 for (i = (this_scr - sc->first_vty + sc->vtys - 1)%sc->vtys;
 3506                         sc->first_vty + i != this_scr;
 3507                         i = (i + sc->vtys - 1)%sc->vtys) {
 3508                     struct tty *tp = VIRTUAL_TTY(sc, sc->first_vty + i);
 3509                     if (ISTTYOPEN(tp)) {
 3510                         syscons_lock();
 3511                         sc_switch_scr(scp->sc, sc->first_vty + i);
 3512                         syscons_unlock();
 3513                         break;
 3514                     }
 3515                 }
 3516                 break;
 3517 
 3518             default:
 3519                 if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) {
 3520                     syscons_lock();
 3521                     sc_switch_scr(scp->sc, sc->first_vty + KEYCHAR(c) - F_SCR);
 3522                     syscons_unlock();
 3523                     break;
 3524                 }
 3525                 /* assert(c & FKEY) */
 3526                 if (!(sc->flags & SC_SCRN_BLANKED)) {
 3527                     lwkt_reltoken(&tty_token);
 3528                     return c;
 3529                 }
 3530                 break;
 3531             }
 3532             /* goto next_code */
 3533         } else {
 3534             /* regular keys (maybe MKEY is set) */
 3535             if (!(sc->flags & SC_SCRN_BLANKED)) {
 3536                 lwkt_reltoken(&tty_token);
 3537                 return c;
 3538             }
 3539         }
 3540     }
 3541 
 3542     goto next_code;
 3543 }
 3544 
 3545 int
 3546 scmmap(struct dev_mmap_args *ap)
 3547 {
 3548     scr_stat *scp;
 3549 
 3550     lwkt_gettoken(&tty_token);
 3551     scp = SC_STAT(ap->a_head.a_dev);
 3552     if (scp != scp->sc->cur_scp) {
 3553         lwkt_reltoken(&tty_token);
 3554         return EINVAL;
 3555     }
 3556     ap->a_result = (*vidsw[scp->sc->adapter]->mmap)(scp->sc->adp, ap->a_offset,
 3557                                                     ap->a_nprot);
 3558     lwkt_reltoken(&tty_token);
 3559     return(0);
 3560 }
 3561 
 3562 static int
 3563 save_kbd_state(scr_stat *scp, int unlock)
 3564 {
 3565     int state;
 3566     int error;
 3567 
 3568     WANT_UNLOCK(unlock);
 3569     error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
 3570     WANT_LOCK(unlock);
 3571 
 3572     if (error == ENOIOCTL)
 3573         error = ENODEV;
 3574     if (error == 0) {
 3575         scp->status &= ~LOCK_MASK;
 3576         scp->status |= state;
 3577     }
 3578     return error;
 3579 }
 3580 
 3581 static int
 3582 update_kbd_state(scr_stat *scp, int new_bits, int mask, int unlock)
 3583 {
 3584     int state;
 3585     int error;
 3586 
 3587     if (mask != LOCK_MASK) {
 3588         WANT_UNLOCK(unlock);
 3589         error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
 3590         WANT_LOCK(unlock);
 3591 
 3592         if (error == ENOIOCTL)
 3593             error = ENODEV;
 3594         if (error) {
 3595             return error;
 3596         }
 3597         state &= ~mask;
 3598         state |= new_bits & mask;
 3599     } else {
 3600         state = new_bits & LOCK_MASK;
 3601     }
 3602     WANT_UNLOCK(unlock);
 3603     error = kbd_ioctl(scp->sc->kbd, KDSKBSTATE, (caddr_t)&state);
 3604     WANT_LOCK(unlock);
 3605     if (error == ENOIOCTL)
 3606         error = ENODEV;
 3607     return error;
 3608 }
 3609 
 3610 static int
 3611 update_kbd_leds(scr_stat *scp, int which)
 3612 {
 3613     int error;
 3614 
 3615     which &= LOCK_MASK;
 3616     error = kbd_ioctl(scp->sc->kbd, KDSETLED, (caddr_t)&which);
 3617     if (error == ENOIOCTL)
 3618         error = ENODEV;
 3619     return error;
 3620 }
 3621 
 3622 int
 3623 set_mode(scr_stat *scp)
 3624 {
 3625     video_info_t info;
 3626 
 3627     lwkt_gettoken(&tty_token);
 3628     /* reject unsupported mode */
 3629     if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) {
 3630         lwkt_reltoken(&tty_token);
 3631         return 1;
 3632     }
 3633 
 3634     /* if this vty is not currently showing, do nothing */
 3635     if (scp != scp->sc->cur_scp) {
 3636         lwkt_reltoken(&tty_token);
 3637         return 0;
 3638     }
 3639 
 3640     /* setup video hardware for the given mode */
 3641     (*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
 3642     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
 3643                 (void *)scp->sc->adp->va_window, FALSE);
 3644 
 3645 #ifndef SC_NO_FONT_LOADING
 3646     /* load appropriate font */
 3647     if (!(scp->status & GRAPHICS_MODE)) {
 3648         if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->sc->adp->va_flags)) {
 3649             if (scp->font_size < 14) {
 3650                 if (scp->sc->fonts_loaded & FONT_8)
 3651                     sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256);
 3652             } else if (scp->font_size >= 16) {
 3653                 if (scp->sc->fonts_loaded & FONT_16)
 3654                     sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256);
 3655             } else {
 3656                 if (scp->sc->fonts_loaded & FONT_14)
 3657                     sc_load_font(scp, 0, 14, scp->sc->font_14, 0, 256);
 3658             }
 3659             /*
 3660              * FONT KLUDGE:
 3661              * This is an interim kludge to display correct font.
 3662              * Always use the font page #0 on the video plane 2.
 3663              * Somehow we cannot show the font in other font pages on
 3664              * some video cards... XXX
 3665              */ 
 3666             sc_show_font(scp, 0);
 3667         }
 3668         mark_all(scp);
 3669     }
 3670 #endif /* !SC_NO_FONT_LOADING */
 3671 
 3672     sc_set_border(scp, scp->border);
 3673     sc_set_cursor_image(scp);
 3674 
 3675     lwkt_reltoken(&tty_token);
 3676     return 0;
 3677 }
 3678 
 3679 void
 3680 refresh_ega_palette(scr_stat *scp)
 3681 {
 3682     uint32_t r, g, b;
 3683     int reg;
 3684     int rsize, gsize, bsize;
 3685     int rfld, gfld, bfld;
 3686     int i;
 3687 
 3688     rsize = scp->sc->adp->va_info.vi_pixel_fsizes[0];
 3689     gsize = scp->sc->adp->va_info.vi_pixel_fsizes[1];
 3690     bsize = scp->sc->adp->va_info.vi_pixel_fsizes[2];
 3691     rfld = scp->sc->adp->va_info.vi_pixel_fields[0];
 3692     gfld = scp->sc->adp->va_info.vi_pixel_fields[1];
 3693     bfld = scp->sc->adp->va_info.vi_pixel_fields[2];
 3694 
 3695     for (i = 0; i < 16; i++) {
 3696         reg = scp->sc->adp->va_palette_regs[i];
 3697 
 3698         r = scp->sc->palette[reg * 3] >> (8 - rsize);
 3699         g = scp->sc->palette[reg * 3 + 1] >> (8 - gsize);
 3700         b = scp->sc->palette[reg * 3 + 2] >> (8 - bsize);
 3701 
 3702         scp->ega_palette[i] = (r << rfld) + (g << gfld) + (b << bfld);
 3703     }
 3704 }
 3705 
 3706 void
 3707 sc_set_border(scr_stat *scp, int color)
 3708 {
 3709     ++scp->sc->videoio_in_progress;
 3710     (*scp->rndr->draw_border)(scp, color);
 3711     --scp->sc->videoio_in_progress;
 3712 }
 3713 
 3714 #ifndef SC_NO_FONT_LOADING
 3715 void
 3716 sc_load_font(scr_stat *scp, int page, int size, u_char *buf,
 3717              int base, int count)
 3718 {
 3719     sc_softc_t *sc;
 3720 
 3721     sc = scp->sc;
 3722     sc->font_loading_in_progress = TRUE;
 3723     (*vidsw[sc->adapter]->load_font)(sc->adp, page, size, buf, base, count);
 3724     sc->font_loading_in_progress = FALSE;
 3725 }
 3726 
 3727 void
 3728 sc_save_font(scr_stat *scp, int page, int size, u_char *buf,
 3729              int base, int count)
 3730 {
 3731     sc_softc_t *sc;
 3732 
 3733     sc = scp->sc;
 3734     sc->font_loading_in_progress = TRUE;
 3735     (*vidsw[sc->adapter]->save_font)(sc->adp, page, size, buf, base, count);
 3736     sc->font_loading_in_progress = FALSE;
 3737 }
 3738 
 3739 void
 3740 sc_show_font(scr_stat *scp, int page)
 3741 {
 3742     (*vidsw[scp->sc->adapter]->show_font)(scp->sc->adp, page);
 3743 }
 3744 #endif /* !SC_NO_FONT_LOADING */
 3745 
 3746 void
 3747 sc_paste(scr_stat *scp, u_char *p, int count) 
 3748 {
 3749     struct tty *tp;
 3750     u_char *rmap;
 3751 
 3752     lwkt_gettoken(&tty_token);
 3753     if (scp->status & MOUSE_VISIBLE) {
 3754         tp = VIRTUAL_TTY(scp->sc, scp->sc->cur_scp->index);
 3755         if (!ISTTYOPEN(tp)) {
 3756             lwkt_reltoken(&tty_token);
 3757             return;
 3758         }
 3759         rmap = scp->sc->scr_rmap;
 3760         for (; count > 0; --count)
 3761             (*linesw[tp->t_line].l_rint)(rmap[*p++], tp);
 3762     }
 3763     lwkt_reltoken(&tty_token);
 3764 }
 3765 
 3766 void
 3767 sc_bell(scr_stat *scp, int pitch, int duration)
 3768 {
 3769     if (cold || shutdown_in_progress)
 3770         return;
 3771 
 3772     if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL)) {
 3773         return;
 3774     }
 3775 
 3776     if (scp->sc->flags & SC_VISUAL_BELL) {
 3777         if (scp->sc->blink_in_progress) {
 3778             return;
 3779         }
 3780         scp->sc->blink_in_progress = 3;
 3781         if (scp != scp->sc->cur_scp)
 3782             scp->sc->blink_in_progress += 2;
 3783         sc_blink_screen(scp->sc->cur_scp);
 3784     } else if (duration != 0 && pitch != 0) {
 3785         if (scp != scp->sc->cur_scp)
 3786             pitch *= 2;
 3787         sysbeep(pitch, duration);
 3788     }
 3789 }
 3790 
 3791 /*
 3792  * Two versions of blink_screen(), one called from the console path
 3793  * with the syscons locked, and one called from a timer callout.
 3794  */
 3795 static void
 3796 sc_blink_screen(scr_stat *scp)
 3797 {
 3798     if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
 3799         scp->sc->blink_in_progress = 0;
 3800         mark_all(scp);
 3801         if (scp->sc->delayed_next_scr)
 3802             sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
 3803     } else {
 3804         (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize,
 3805                            scp->sc->blink_in_progress & 1);
 3806         scp->sc->blink_in_progress--;
 3807     }
 3808 }
 3809 
 3810 #if 0
 3811 static void
 3812 blink_screen_callout(void *arg)
 3813 {
 3814     scr_stat *scp = arg;
 3815     struct tty *tp;
 3816 
 3817     if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
 3818         syscons_lock();
 3819         scp->sc->blink_in_progress = 0;
 3820         mark_all(scp);
 3821         syscons_unlock();
 3822         tp = VIRTUAL_TTY(scp->sc, scp->index);
 3823         if (ISTTYOPEN(tp))
 3824             scstart(tp);
 3825         if (scp->sc->delayed_next_scr) {
 3826             syscons_lock();
 3827             sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
 3828             syscons_unlock();
 3829         }
 3830     } else {
 3831         syscons_lock();
 3832         (*scp->rndr->draw)(scp, 0, scp->xsize*scp->ysize, 
 3833                            scp->sc->blink_in_progress & 1);
 3834         scp->sc->blink_in_progress--;
 3835         syscons_unlock();
 3836         callout_reset(&scp->blink_screen_ch, hz / 10,
 3837                       blink_screen_callout, scp);
 3838     }
 3839 }
 3840 #endif
 3841 
 3842 /*
 3843  * Allocate active keyboard. Try to allocate "kbdmux" keyboard first, and,
 3844  * if found, add all non-busy keyboards to "kbdmux". Otherwise look for
 3845  * any keyboard.
 3846  */
 3847 
 3848 static int
 3849 sc_allocate_keyboard(sc_softc_t *sc, int unit)
 3850 {
 3851         int              idx0, idx;
 3852         keyboard_t      *k0, *k;
 3853         keyboard_info_t  ki;
 3854 
 3855         idx0 = kbd_allocate("kbdmux", -1, (void *)&sc->keyboard, sckbdevent, sc);
 3856         if (idx0 != -1) {
 3857                 k0 = kbd_get_keyboard(idx0);
 3858 
 3859                 for (idx = kbd_find_keyboard2("*", -1, 0, 0);
 3860                      idx != -1;
 3861                      idx = kbd_find_keyboard2("*", -1, idx + 1, 0)) {
 3862                         k = kbd_get_keyboard(idx);
 3863 
 3864                         if (idx == idx0 || KBD_IS_BUSY(k))
 3865                                 continue;
 3866 
 3867                         bzero(&ki, sizeof(ki));
 3868                         strcpy(ki.kb_name, k->kb_name);
 3869                         ki.kb_unit = k->kb_unit;
 3870 
 3871                         kbd_ioctl(k0, KBADDKBD, (caddr_t) &ki);
 3872                 }
 3873         } else
 3874                 idx0 = kbd_allocate("*", unit, (void *)&sc->keyboard, sckbdevent, sc);
 3875 
 3876         return (idx0);
 3877 }

Cache object: 08107d73fa24da60cd6b4b70c6a99f9d


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