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