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