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

Cache object: d258a38719b338199fa92ba27101a83f


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