xref: /dragonfly/sys/dev/misc/syscons/syscons.c (revision b0d289c2)
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 }
3941