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