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