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