xref: /freebsd/sys/dev/vt/vt_core.c (revision b78ee15e9f04ae15c3e1200df974473167524d17)
1 /*-
2  * Copyright (c) 2009, 2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Ed Schouten under sponsorship from the
6  * FreeBSD Foundation.
7  *
8  * Portions of this software were developed by Oleksandr Rybalko
9  * under sponsorship from the FreeBSD Foundation.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include "opt_compat.h"
37 
38 #include <sys/param.h>
39 #include <sys/consio.h>
40 #include <sys/eventhandler.h>
41 #include <sys/fbio.h>
42 #include <sys/kbio.h>
43 #include <sys/kdb.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/mutex.h>
48 #include <sys/power.h>
49 #include <sys/priv.h>
50 #include <sys/proc.h>
51 #include <sys/random.h>
52 #include <sys/reboot.h>
53 #include <sys/systm.h>
54 #include <sys/terminal.h>
55 
56 #include <dev/kbd/kbdreg.h>
57 #include <dev/vt/vt.h>
58 
59 #if defined(__i386__) || defined(__amd64__)
60 #include <machine/psl.h>
61 #include <machine/frame.h>
62 #endif
63 
64 static tc_bell_t	vtterm_bell;
65 static tc_cursor_t	vtterm_cursor;
66 static tc_putchar_t	vtterm_putchar;
67 static tc_fill_t	vtterm_fill;
68 static tc_copy_t	vtterm_copy;
69 static tc_param_t	vtterm_param;
70 static tc_done_t	vtterm_done;
71 
72 static tc_cnprobe_t	vtterm_cnprobe;
73 static tc_cngetc_t	vtterm_cngetc;
74 
75 static tc_cngrab_t	vtterm_cngrab;
76 static tc_cnungrab_t	vtterm_cnungrab;
77 
78 static tc_opened_t	vtterm_opened;
79 static tc_ioctl_t	vtterm_ioctl;
80 static tc_mmap_t	vtterm_mmap;
81 
82 const struct terminal_class vt_termclass = {
83 	.tc_bell	= vtterm_bell,
84 	.tc_cursor	= vtterm_cursor,
85 	.tc_putchar	= vtterm_putchar,
86 	.tc_fill	= vtterm_fill,
87 	.tc_copy	= vtterm_copy,
88 	.tc_param	= vtterm_param,
89 	.tc_done	= vtterm_done,
90 
91 	.tc_cnprobe	= vtterm_cnprobe,
92 	.tc_cngetc	= vtterm_cngetc,
93 
94 	.tc_cngrab	= vtterm_cngrab,
95 	.tc_cnungrab	= vtterm_cnungrab,
96 
97 	.tc_opened	= vtterm_opened,
98 	.tc_ioctl	= vtterm_ioctl,
99 	.tc_mmap	= vtterm_mmap,
100 };
101 
102 /*
103  * Use a constant timer of 25 Hz to redraw the screen.
104  *
105  * XXX: In theory we should only fire up the timer when there is really
106  * activity. Unfortunately we cannot always start timers. We really
107  * don't want to process kernel messages synchronously, because it
108  * really slows down the system.
109  */
110 #define	VT_TIMERFREQ	25
111 
112 /* Bell pitch/duration. */
113 #define VT_BELLDURATION	((5 * hz + 99) / 100)
114 #define VT_BELLPITCH	800
115 
116 #define	VT_LOCK(vd)	mtx_lock(&(vd)->vd_lock)
117 #define	VT_UNLOCK(vd)	mtx_unlock(&(vd)->vd_lock)
118 #define	VT_LOCK_ASSERT(vd, what)	mtx_assert(&(vd)->vd_lock, what)
119 
120 #define	VT_UNIT(vw)	((vw)->vw_device->vd_unit * VT_MAXWINDOWS + \
121 			(vw)->vw_number)
122 
123 static SYSCTL_NODE(_kern, OID_AUTO, vt, CTLFLAG_RD, 0, "vt(9) parameters");
124 VT_SYSCTL_INT(enable_altgr, 1, "Enable AltGr key (Do not assume R.Alt as Alt)");
125 VT_SYSCTL_INT(enable_bell, 1, "Enable bell");
126 VT_SYSCTL_INT(debug, 0, "vt(9) debug level");
127 VT_SYSCTL_INT(deadtimer, 15, "Time to wait busy process in VT_PROCESS mode");
128 VT_SYSCTL_INT(suspendswitch, 1, "Switch to VT0 before suspend");
129 
130 /* Allow to disable some keyboard combinations. */
131 VT_SYSCTL_INT(kbd_halt, 1, "Enable halt keyboard combination.  "
132     "See kbdmap(5) to configure.");
133 VT_SYSCTL_INT(kbd_poweroff, 1, "Enable Power Off keyboard combination.  "
134     "See kbdmap(5) to configure.");
135 VT_SYSCTL_INT(kbd_reboot, 1, "Enable reboot keyboard combination.  "
136     "See kbdmap(5) to configure (typically Ctrl-Alt-Delete).");
137 VT_SYSCTL_INT(kbd_debug, 1, "Enable key combination to enter debugger.  "
138     "See kbdmap(5) to configure (typically Ctrl-Alt-Esc).");
139 VT_SYSCTL_INT(kbd_panic, 0, "Enable request to panic.  "
140     "See kbdmap(5) to configure.");
141 
142 static struct vt_device	vt_consdev;
143 static unsigned int vt_unit = 0;
144 static MALLOC_DEFINE(M_VT, "vt", "vt device");
145 struct vt_device *main_vd = &vt_consdev;
146 
147 /* Boot logo. */
148 extern unsigned int vt_logo_width;
149 extern unsigned int vt_logo_height;
150 extern unsigned int vt_logo_depth;
151 extern unsigned char vt_logo_image[];
152 
153 /* Font. */
154 extern struct vt_font vt_font_default;
155 #ifndef SC_NO_CUTPASTE
156 extern struct vt_mouse_cursor vt_default_mouse_pointer;
157 #endif
158 
159 static int signal_vt_rel(struct vt_window *);
160 static int signal_vt_acq(struct vt_window *);
161 static int finish_vt_rel(struct vt_window *, int, int *);
162 static int finish_vt_acq(struct vt_window *);
163 static int vt_window_switch(struct vt_window *);
164 static int vt_late_window_switch(struct vt_window *);
165 static int vt_proc_alive(struct vt_window *);
166 static void vt_resize(struct vt_device *);
167 static void vt_update_static(void *);
168 #ifndef SC_NO_CUTPASTE
169 static void vt_mouse_paste(void);
170 #endif
171 static void vt_suspend_handler(void *priv);
172 static void vt_resume_handler(void *priv);
173 
174 SET_DECLARE(vt_drv_set, struct vt_driver);
175 
176 #define _VTDEFH MAX(100, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT))
177 #define _VTDEFW MAX(200, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH))
178 
179 static struct terminal	vt_consterm;
180 static struct vt_window	vt_conswindow;
181 static struct vt_device	vt_consdev = {
182 	.vd_driver = NULL,
183 	.vd_softc = NULL,
184 	.vd_prev_driver = NULL,
185 	.vd_prev_softc = NULL,
186 	.vd_flags = VDF_INVALID,
187 	.vd_windows = { [VT_CONSWINDOW] =  &vt_conswindow, },
188 	.vd_curwindow = &vt_conswindow,
189 	.vd_kbstate = 0,
190 
191 #ifndef SC_NO_CUTPASTE
192 	.vd_pastebuf = {
193 		.vpb_buf = NULL,
194 		.vpb_bufsz = 0,
195 		.vpb_len = 0
196 	},
197 	.vd_mcursor = &vt_default_mouse_pointer,
198 	.vd_mcursor_fg = TC_WHITE,
199 	.vd_mcursor_bg = TC_BLACK,
200 #endif
201 };
202 static term_char_t vt_constextbuf[(_VTDEFW) * (VBF_DEFAULT_HISTORY_SIZE)];
203 static term_char_t *vt_constextbufrows[VBF_DEFAULT_HISTORY_SIZE];
204 static struct vt_window	vt_conswindow = {
205 	.vw_number = VT_CONSWINDOW,
206 	.vw_flags = VWF_CONSOLE,
207 	.vw_buf = {
208 		.vb_buffer = &vt_constextbuf[0],
209 		.vb_rows = &vt_constextbufrows[0],
210 		.vb_history_size = VBF_DEFAULT_HISTORY_SIZE,
211 		.vb_curroffset = 0,
212 		.vb_roffset = 0,
213 		.vb_flags = VBF_STATIC,
214 		.vb_mark_start = {.tp_row = 0, .tp_col = 0,},
215 		.vb_mark_end = {.tp_row = 0, .tp_col = 0,},
216 		.vb_scr_size = {
217 			.tp_row = _VTDEFH,
218 			.tp_col = _VTDEFW,
219 		},
220 	},
221 	.vw_device = &vt_consdev,
222 	.vw_terminal = &vt_consterm,
223 	.vw_kbdmode = K_XLATE,
224 	.vw_grabbed = 0,
225 };
226 static struct terminal vt_consterm = {
227 	.tm_class = &vt_termclass,
228 	.tm_softc = &vt_conswindow,
229 	.tm_flags = TF_CONS,
230 };
231 static struct consdev vt_consterm_consdev = {
232 	.cn_ops = &termcn_cnops,
233 	.cn_arg = &vt_consterm,
234 	.cn_name = "ttyv0",
235 };
236 
237 /* Add to set of consoles. */
238 DATA_SET(cons_set, vt_consterm_consdev);
239 
240 /*
241  * Right after kmem is done to allow early drivers to use locking and allocate
242  * memory.
243  */
244 SYSINIT(vt_update_static, SI_SUB_KMEM, SI_ORDER_ANY, vt_update_static,
245     &vt_consdev);
246 /* Delay until all devices attached, to not waste time. */
247 SYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, vt_upgrade,
248     &vt_consdev);
249 
250 /* Initialize locks/mem depended members. */
251 static void
252 vt_update_static(void *dummy)
253 {
254 
255 	if (!vty_enabled(VTY_VT))
256 		return;
257 	if (main_vd->vd_driver != NULL)
258 		printf("VT: running with driver \"%s\".\n",
259 		    main_vd->vd_driver->vd_name);
260 	else
261 		printf("VT: init without driver.\n");
262 
263 	mtx_init(&main_vd->vd_lock, "vtdev", NULL, MTX_DEF);
264 	cv_init(&main_vd->vd_winswitch, "vtwswt");
265 }
266 
267 static void
268 vt_schedule_flush(struct vt_device *vd, int ms)
269 {
270 
271 	if (ms <= 0)
272 		/* Default to initial value. */
273 		ms = 1000 / VT_TIMERFREQ;
274 
275 	callout_schedule(&vd->vd_timer, hz / (1000 / ms));
276 }
277 
278 static void
279 vt_resume_flush_timer(struct vt_device *vd, int ms)
280 {
281 
282 	if (!(vd->vd_flags & VDF_ASYNC) ||
283 	    !atomic_cmpset_int(&vd->vd_timer_armed, 0, 1))
284 		return;
285 
286 	vt_schedule_flush(vd, ms);
287 }
288 
289 static void
290 vt_suspend_flush_timer(struct vt_device *vd)
291 {
292 	/*
293 	 * As long as this function is called locked, callout_stop()
294 	 * has the same effect like callout_drain() with regard to
295 	 * preventing the callback function from executing.
296 	 */
297 	VT_LOCK_ASSERT(vd, MA_OWNED);
298 
299 	if (!(vd->vd_flags & VDF_ASYNC) ||
300 	    !atomic_cmpset_int(&vd->vd_timer_armed, 1, 0))
301 		return;
302 
303 	callout_stop(&vd->vd_timer);
304 }
305 
306 static void
307 vt_switch_timer(void *arg)
308 {
309 
310 	vt_late_window_switch((struct vt_window *)arg);
311 }
312 
313 static int
314 vt_save_kbd_mode(struct vt_window *vw, keyboard_t *kbd)
315 {
316 	int mode, ret;
317 
318 	mode = 0;
319 	ret = kbdd_ioctl(kbd, KDGKBMODE, (caddr_t)&mode);
320 	if (ret == ENOIOCTL)
321 		ret = ENODEV;
322 	if (ret != 0)
323 		return (ret);
324 
325 	vw->vw_kbdmode = mode;
326 
327 	return (0);
328 }
329 
330 static int
331 vt_update_kbd_mode(struct vt_window *vw, keyboard_t *kbd)
332 {
333 	int ret;
334 
335 	ret = kbdd_ioctl(kbd, KDSKBMODE, (caddr_t)&vw->vw_kbdmode);
336 	if (ret == ENOIOCTL)
337 		ret = ENODEV;
338 
339 	return (ret);
340 }
341 
342 static int
343 vt_save_kbd_state(struct vt_window *vw, keyboard_t *kbd)
344 {
345 	int state, ret;
346 
347 	state = 0;
348 	ret = kbdd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state);
349 	if (ret == ENOIOCTL)
350 		ret = ENODEV;
351 	if (ret != 0)
352 		return (ret);
353 
354 	vw->vw_kbdstate &= ~LOCK_MASK;
355 	vw->vw_kbdstate |= state & LOCK_MASK;
356 
357 	return (0);
358 }
359 
360 static int
361 vt_update_kbd_state(struct vt_window *vw, keyboard_t *kbd)
362 {
363 	int state, ret;
364 
365 	state = vw->vw_kbdstate & LOCK_MASK;
366 	ret = kbdd_ioctl(kbd, KDSKBSTATE, (caddr_t)&state);
367 	if (ret == ENOIOCTL)
368 		ret = ENODEV;
369 
370 	return (ret);
371 }
372 
373 static int
374 vt_save_kbd_leds(struct vt_window *vw, keyboard_t *kbd)
375 {
376 	int leds, ret;
377 
378 	leds = 0;
379 	ret = kbdd_ioctl(kbd, KDGETLED, (caddr_t)&leds);
380 	if (ret == ENOIOCTL)
381 		ret = ENODEV;
382 	if (ret != 0)
383 		return (ret);
384 
385 	vw->vw_kbdstate &= ~LED_MASK;
386 	vw->vw_kbdstate |= leds & LED_MASK;
387 
388 	return (0);
389 }
390 
391 static int
392 vt_update_kbd_leds(struct vt_window *vw, keyboard_t *kbd)
393 {
394 	int leds, ret;
395 
396 	leds = vw->vw_kbdstate & LED_MASK;
397 	ret = kbdd_ioctl(kbd, KDSETLED, (caddr_t)&leds);
398 	if (ret == ENOIOCTL)
399 		ret = ENODEV;
400 
401 	return (ret);
402 }
403 
404 static int
405 vt_window_preswitch(struct vt_window *vw, struct vt_window *curvw)
406 {
407 
408 	DPRINTF(40, "%s\n", __func__);
409 	curvw->vw_switch_to = vw;
410 	/* Set timer to allow switch in case when process hang. */
411 	callout_reset(&vw->vw_proc_dead_timer, hz * vt_deadtimer,
412 	    vt_switch_timer, (void *)vw);
413 	/* Notify process about vt switch attempt. */
414 	DPRINTF(30, "%s: Notify process.\n", __func__);
415 	signal_vt_rel(curvw);
416 
417 	return (0);
418 }
419 
420 static int
421 vt_window_postswitch(struct vt_window *vw)
422 {
423 
424 	signal_vt_acq(vw);
425 	return (0);
426 }
427 
428 /* vt_late_window_switch will done VT switching for regular case. */
429 static int
430 vt_late_window_switch(struct vt_window *vw)
431 {
432 	int ret;
433 
434 	callout_stop(&vw->vw_proc_dead_timer);
435 
436 	ret = vt_window_switch(vw);
437 	if (ret)
438 		return (ret);
439 
440 	/* Notify owner process about terminal availability. */
441 	if (vw->vw_smode.mode == VT_PROCESS) {
442 		ret = vt_window_postswitch(vw);
443 	}
444 	return (ret);
445 }
446 
447 /* Switch window. */
448 static int
449 vt_proc_window_switch(struct vt_window *vw)
450 {
451 	struct vt_window *curvw;
452 	struct vt_device *vd;
453 	int ret;
454 
455 	/* Prevent switching to NULL */
456 	if (vw == NULL) {
457 		DPRINTF(30, "%s: Cannot switch: vw is NULL.", __func__);
458 		return (EINVAL);
459 	}
460 	vd = vw->vw_device;
461 	curvw = vd->vd_curwindow;
462 
463 	/* Check if virtual terminal is locked */
464 	if (curvw->vw_flags & VWF_VTYLOCK)
465 		return (EBUSY);
466 
467 	/* Check if switch already in progress */
468 	if (curvw->vw_flags & VWF_SWWAIT_REL) {
469 		/* Check if switching to same window */
470 		if (curvw->vw_switch_to == vw) {
471 			DPRINTF(30, "%s: Switch in progress to same vw.", __func__);
472 			return (0);	/* success */
473 		}
474 		DPRINTF(30, "%s: Switch in progress to different vw.", __func__);
475 		return (EBUSY);
476 	}
477 
478 	/* Avoid switching to already selected window */
479 	if (vw == curvw) {
480 		DPRINTF(30, "%s: Cannot switch: vw == curvw.", __func__);
481 		return (0);	/* success */
482 	}
483 
484 	/* Ask current process permission to switch away. */
485 	if (curvw->vw_smode.mode == VT_PROCESS) {
486 		DPRINTF(30, "%s: VT_PROCESS ", __func__);
487 		if (vt_proc_alive(curvw) == FALSE) {
488 			DPRINTF(30, "Dead. Cleaning.");
489 			/* Dead */
490 		} else {
491 			DPRINTF(30, "%s: Signaling process.\n", __func__);
492 			/* Alive, try to ask him. */
493 			ret = vt_window_preswitch(vw, curvw);
494 			/* Wait for process answer or timeout. */
495 			return (ret);
496 		}
497 		DPRINTF(30, "\n");
498 	}
499 
500 	ret = vt_late_window_switch(vw);
501 	return (ret);
502 }
503 
504 /* Switch window ignoring process locking. */
505 static int
506 vt_window_switch(struct vt_window *vw)
507 {
508 	struct vt_device *vd = vw->vw_device;
509 	struct vt_window *curvw = vd->vd_curwindow;
510 	keyboard_t *kbd;
511 
512 	VT_LOCK(vd);
513 	if (curvw == vw) {
514 		/* Nothing to do. */
515 		VT_UNLOCK(vd);
516 		return (0);
517 	}
518 	if (!(vw->vw_flags & (VWF_OPENED|VWF_CONSOLE))) {
519 		VT_UNLOCK(vd);
520 		return (EINVAL);
521 	}
522 
523 	vt_suspend_flush_timer(vd);
524 
525 	vd->vd_curwindow = vw;
526 	vd->vd_flags |= VDF_INVALID;
527 	cv_broadcast(&vd->vd_winswitch);
528 	VT_UNLOCK(vd);
529 
530 	if (vd->vd_driver->vd_postswitch)
531 		vd->vd_driver->vd_postswitch(vd);
532 
533 	vt_resume_flush_timer(vd, 0);
534 
535 	/* Restore per-window keyboard mode. */
536 	mtx_lock(&Giant);
537 	kbd = kbd_get_keyboard(vd->vd_keyboard);
538 	if (kbd != NULL) {
539 		if (curvw->vw_kbdmode == K_XLATE)
540 			vt_save_kbd_state(curvw, kbd);
541 
542 		vt_update_kbd_mode(vw, kbd);
543 		vt_update_kbd_state(vw, kbd);
544 	}
545 	mtx_unlock(&Giant);
546 	DPRINTF(10, "%s(ttyv%d) done\n", __func__, vw->vw_number);
547 
548 	return (0);
549 }
550 
551 static inline void
552 vt_termsize(struct vt_device *vd, struct vt_font *vf, term_pos_t *size)
553 {
554 
555 	size->tp_row = vd->vd_height;
556 	size->tp_col = vd->vd_width;
557 	if (vf != NULL) {
558 		size->tp_row /= vf->vf_height;
559 		size->tp_col /= vf->vf_width;
560 	}
561 }
562 
563 static inline void
564 vt_winsize(struct vt_device *vd, struct vt_font *vf, struct winsize *size)
565 {
566 
567 	size->ws_row = size->ws_ypixel = vd->vd_height;
568 	size->ws_col = size->ws_xpixel = vd->vd_width;
569 	if (vf != NULL) {
570 		size->ws_row /= vf->vf_height;
571 		size->ws_col /= vf->vf_width;
572 	}
573 }
574 
575 static inline void
576 vt_compute_drawable_area(struct vt_window *vw)
577 {
578 	struct vt_device *vd;
579 	struct vt_font *vf;
580 
581 	vd = vw->vw_device;
582 
583 	if (vw->vw_font == NULL) {
584 		vw->vw_draw_area.tr_begin.tp_col = 0;
585 		vw->vw_draw_area.tr_begin.tp_row = 0;
586 		vw->vw_draw_area.tr_end.tp_col = vd->vd_width;
587 		vw->vw_draw_area.tr_end.tp_row = vd->vd_height;
588 		return;
589 	}
590 
591 	vf = vw->vw_font;
592 
593 	/*
594 	 * Compute the drawable area, so that the text is centered on
595 	 * the screen.
596 	 */
597 
598 	vw->vw_draw_area.tr_begin.tp_col = (vd->vd_width % vf->vf_width) / 2;
599 	vw->vw_draw_area.tr_begin.tp_row = (vd->vd_height % vf->vf_height) / 2;
600 	vw->vw_draw_area.tr_end.tp_col = vw->vw_draw_area.tr_begin.tp_col +
601 	    vd->vd_width / vf->vf_width * vf->vf_width;
602 	vw->vw_draw_area.tr_end.tp_row = vw->vw_draw_area.tr_begin.tp_row +
603 	    vd->vd_height / vf->vf_height * vf->vf_height;
604 }
605 
606 static void
607 vt_scroll(struct vt_window *vw, int offset, int whence)
608 {
609 	int diff;
610 	term_pos_t size;
611 
612 	if ((vw->vw_flags & VWF_SCROLL) == 0)
613 		return;
614 
615 	vt_termsize(vw->vw_device, vw->vw_font, &size);
616 
617 	diff = vthistory_seek(&vw->vw_buf, offset, whence);
618 	if (diff)
619 		vw->vw_device->vd_flags |= VDF_INVALID;
620 	vt_resume_flush_timer(vw->vw_device, 0);
621 }
622 
623 static int
624 vt_machine_kbdevent(int c)
625 {
626 
627 	switch (c) {
628 	case SPCLKEY | DBG: /* kbdmap(5) keyword `debug`. */
629 		if (vt_kbd_debug)
630 			kdb_enter(KDB_WHY_BREAK, "manual escape to debugger");
631 		return (1);
632 	case SPCLKEY | HALT: /* kbdmap(5) keyword `halt`. */
633 		if (vt_kbd_halt)
634 			shutdown_nice(RB_HALT);
635 		return (1);
636 	case SPCLKEY | PASTE: /* kbdmap(5) keyword `paste`. */
637 #ifndef SC_NO_CUTPASTE
638 		/* Insert text from cut-paste buffer. */
639 		vt_mouse_paste();
640 #endif
641 		break;
642 	case SPCLKEY | PDWN: /* kbdmap(5) keyword `pdwn`. */
643 		if (vt_kbd_poweroff)
644 			shutdown_nice(RB_HALT|RB_POWEROFF);
645 		return (1);
646 	case SPCLKEY | PNC: /* kbdmap(5) keyword `panic`. */
647 		/*
648 		 * Request to immediate panic if sysctl
649 		 * kern.vt.enable_panic_key allow it.
650 		 */
651 		if (vt_kbd_panic)
652 			panic("Forced by the panic key");
653 		return (1);
654 	case SPCLKEY | RBT: /* kbdmap(5) keyword `boot`. */
655 		if (vt_kbd_reboot)
656 			shutdown_nice(RB_AUTOBOOT);
657 		return (1);
658 	case SPCLKEY | SPSC: /* kbdmap(5) keyword `spsc`. */
659 		/* Force activatation/deactivation of the screen saver. */
660 		/* TODO */
661 		return (1);
662 	case SPCLKEY | STBY: /* XXX Not present in kbdcontrol parser. */
663 		/* Put machine into Stand-By mode. */
664 		power_pm_suspend(POWER_SLEEP_STATE_STANDBY);
665 		return (1);
666 	case SPCLKEY | SUSP: /* kbdmap(5) keyword `susp`. */
667 		/* Suspend machine. */
668 		power_pm_suspend(POWER_SLEEP_STATE_SUSPEND);
669 		return (1);
670 	};
671 
672 	return (0);
673 }
674 
675 static void
676 vt_scrollmode_kbdevent(struct vt_window *vw, int c, int console)
677 {
678 	struct vt_device *vd;
679 	term_pos_t size;
680 
681 	vd = vw->vw_device;
682 	/* Only special keys handled in ScrollLock mode */
683 	if ((c & SPCLKEY) == 0)
684 		return;
685 
686 	c &= ~SPCLKEY;
687 
688 	if (console == 0) {
689 		if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
690 			vw = vd->vd_windows[c - F_SCR];
691 			vt_proc_window_switch(vw);
692 			return;
693 		}
694 		VT_LOCK(vd);
695 	}
696 
697 	switch (c) {
698 	case SLK: {
699 		/* Turn scrolling off. */
700 		vt_scroll(vw, 0, VHS_END);
701 		VTBUF_SLCK_DISABLE(&vw->vw_buf);
702 		vw->vw_flags &= ~VWF_SCROLL;
703 		break;
704 	}
705 	case FKEY | F(49): /* Home key. */
706 		vt_scroll(vw, 0, VHS_SET);
707 		break;
708 	case FKEY | F(50): /* Arrow up. */
709 		vt_scroll(vw, -1, VHS_CUR);
710 		break;
711 	case FKEY | F(51): /* Page up. */
712 		vt_termsize(vd, vw->vw_font, &size);
713 		vt_scroll(vw, -size.tp_row, VHS_CUR);
714 		break;
715 	case FKEY | F(57): /* End key. */
716 		vt_scroll(vw, 0, VHS_END);
717 		break;
718 	case FKEY | F(58): /* Arrow down. */
719 		vt_scroll(vw, 1, VHS_CUR);
720 		break;
721 	case FKEY | F(59): /* Page down. */
722 		vt_termsize(vd, vw->vw_font, &size);
723 		vt_scroll(vw, size.tp_row, VHS_CUR);
724 		break;
725 	}
726 
727 	if (console == 0)
728 		VT_UNLOCK(vd);
729 }
730 
731 static int
732 vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
733 {
734 	struct vt_window *vw = vd->vd_curwindow;
735 
736 	random_harvest_queue(&c, sizeof(c), 1, RANDOM_KEYBOARD);
737 #if VT_ALT_TO_ESC_HACK
738 	if (c & RELKEY) {
739 		switch (c & ~RELKEY) {
740 		case (SPCLKEY | RALT):
741 			if (vt_enable_altgr != 0)
742 				break;
743 		case (SPCLKEY | LALT):
744 			vd->vd_kbstate &= ~ALKED;
745 		}
746 		/* Other keys ignored for RELKEY event. */
747 		return (0);
748 	} else {
749 		switch (c & ~RELKEY) {
750 		case (SPCLKEY | RALT):
751 			if (vt_enable_altgr != 0)
752 				break;
753 		case (SPCLKEY | LALT):
754 			vd->vd_kbstate |= ALKED;
755 		}
756 	}
757 #else
758 	if (c & RELKEY)
759 		/* Other keys ignored for RELKEY event. */
760 		return (0);
761 #endif
762 
763 	if (vt_machine_kbdevent(c))
764 		return (0);
765 
766 	if (vw->vw_flags & VWF_SCROLL) {
767 		vt_scrollmode_kbdevent(vw, c, 0/* Not a console */);
768 		/* Scroll mode keys handled, nothing to do more. */
769 		return (0);
770 	}
771 
772 	if (c & SPCLKEY) {
773 		c &= ~SPCLKEY;
774 
775 		if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
776 			vw = vd->vd_windows[c - F_SCR];
777 			vt_proc_window_switch(vw);
778 			return (0);
779 		}
780 
781 		switch (c) {
782 		case NEXT:
783 			/* Switch to next VT. */
784 			c = (vw->vw_number + 1) % VT_MAXWINDOWS;
785 			vw = vd->vd_windows[c];
786 			vt_proc_window_switch(vw);
787 			return (0);
788 		case PREV:
789 			/* Switch to previous VT. */
790 			c = (vw->vw_number + VT_MAXWINDOWS - 1) % VT_MAXWINDOWS;
791 			vw = vd->vd_windows[c];
792 			vt_proc_window_switch(vw);
793 			return (0);
794 		case SLK: {
795 			vt_save_kbd_state(vw, kbd);
796 			VT_LOCK(vd);
797 			if (vw->vw_kbdstate & SLKED) {
798 				/* Turn scrolling on. */
799 				vw->vw_flags |= VWF_SCROLL;
800 				VTBUF_SLCK_ENABLE(&vw->vw_buf);
801 			} else {
802 				/* Turn scrolling off. */
803 				vw->vw_flags &= ~VWF_SCROLL;
804 				VTBUF_SLCK_DISABLE(&vw->vw_buf);
805 				vt_scroll(vw, 0, VHS_END);
806 			}
807 			VT_UNLOCK(vd);
808 			break;
809 		}
810 		case FKEY | F(1):  case FKEY | F(2):  case FKEY | F(3):
811 		case FKEY | F(4):  case FKEY | F(5):  case FKEY | F(6):
812 		case FKEY | F(7):  case FKEY | F(8):  case FKEY | F(9):
813 		case FKEY | F(10): case FKEY | F(11): case FKEY | F(12):
814 			/* F1 through F12 keys. */
815 			terminal_input_special(vw->vw_terminal,
816 			    TKEY_F1 + c - (FKEY | F(1)));
817 			break;
818 		case FKEY | F(49): /* Home key. */
819 			terminal_input_special(vw->vw_terminal, TKEY_HOME);
820 			break;
821 		case FKEY | F(50): /* Arrow up. */
822 			terminal_input_special(vw->vw_terminal, TKEY_UP);
823 			break;
824 		case FKEY | F(51): /* Page up. */
825 			terminal_input_special(vw->vw_terminal, TKEY_PAGE_UP);
826 			break;
827 		case FKEY | F(53): /* Arrow left. */
828 			terminal_input_special(vw->vw_terminal, TKEY_LEFT);
829 			break;
830 		case FKEY | F(55): /* Arrow right. */
831 			terminal_input_special(vw->vw_terminal, TKEY_RIGHT);
832 			break;
833 		case FKEY | F(57): /* End key. */
834 			terminal_input_special(vw->vw_terminal, TKEY_END);
835 			break;
836 		case FKEY | F(58): /* Arrow down. */
837 			terminal_input_special(vw->vw_terminal, TKEY_DOWN);
838 			break;
839 		case FKEY | F(59): /* Page down. */
840 			terminal_input_special(vw->vw_terminal, TKEY_PAGE_DOWN);
841 			break;
842 		case FKEY | F(60): /* Insert key. */
843 			terminal_input_special(vw->vw_terminal, TKEY_INSERT);
844 			break;
845 		case FKEY | F(61): /* Delete key. */
846 			terminal_input_special(vw->vw_terminal, TKEY_DELETE);
847 			break;
848 		}
849 	} else if (KEYFLAGS(c) == 0) {
850 		/* Don't do UTF-8 conversion when doing raw mode. */
851 		if (vw->vw_kbdmode == K_XLATE) {
852 #if VT_ALT_TO_ESC_HACK
853 			if (vd->vd_kbstate & ALKED) {
854 				/*
855 				 * Prepend ESC sequence if one of ALT keys down.
856 				 */
857 				terminal_input_char(vw->vw_terminal, 0x1b);
858 			}
859 #endif
860 #if defined(KDB)
861 			kdb_alt_break(c, &vd->vd_altbrk);
862 #endif
863 			terminal_input_char(vw->vw_terminal, KEYCHAR(c));
864 		} else
865 			terminal_input_raw(vw->vw_terminal, c);
866 	}
867 	return (0);
868 }
869 
870 static int
871 vt_kbdevent(keyboard_t *kbd, int event, void *arg)
872 {
873 	struct vt_device *vd = arg;
874 	int c;
875 
876 	switch (event) {
877 	case KBDIO_KEYINPUT:
878 		break;
879 	case KBDIO_UNLOADING:
880 		mtx_lock(&Giant);
881 		vd->vd_keyboard = -1;
882 		kbd_release(kbd, (void *)vd);
883 		mtx_unlock(&Giant);
884 		return (0);
885 	default:
886 		return (EINVAL);
887 	}
888 
889 	while ((c = kbdd_read_char(kbd, 0)) != NOKEY)
890 		vt_processkey(kbd, vd, c);
891 
892 	return (0);
893 }
894 
895 static int
896 vt_allocate_keyboard(struct vt_device *vd)
897 {
898 	int		 idx0, idx;
899 	keyboard_t	*k0, *k;
900 	keyboard_info_t	 ki;
901 
902 	idx0 = kbd_allocate("kbdmux", -1, vd, vt_kbdevent, vd);
903 	if (idx0 >= 0) {
904 		DPRINTF(20, "%s: kbdmux allocated, idx = %d\n", __func__, idx0);
905 		k0 = kbd_get_keyboard(idx0);
906 
907 		for (idx = kbd_find_keyboard2("*", -1, 0);
908 		     idx != -1;
909 		     idx = kbd_find_keyboard2("*", -1, idx + 1)) {
910 			k = kbd_get_keyboard(idx);
911 
912 			if (idx == idx0 || KBD_IS_BUSY(k))
913 				continue;
914 
915 			bzero(&ki, sizeof(ki));
916 			strncpy(ki.kb_name, k->kb_name, sizeof(ki.kb_name));
917 			ki.kb_name[sizeof(ki.kb_name) - 1] = '\0';
918 			ki.kb_unit = k->kb_unit;
919 
920 			kbdd_ioctl(k0, KBADDKBD, (caddr_t) &ki);
921 		}
922 	} else {
923 		DPRINTF(20, "%s: no kbdmux allocated\n", __func__);
924 		idx0 = kbd_allocate("*", -1, vd, vt_kbdevent, vd);
925 		if (idx0 < 0) {
926 			DPRINTF(10, "%s: No keyboard found.\n", __func__);
927 			return (-1);
928 		}
929 	}
930 	vd->vd_keyboard = idx0;
931 	DPRINTF(20, "%s: vd_keyboard = %d\n", __func__, vd->vd_keyboard);
932 
933 	return (idx0);
934 }
935 
936 static void
937 vtterm_bell(struct terminal *tm)
938 {
939 	struct vt_window *vw = tm->tm_softc;
940 	struct vt_device *vd = vw->vw_device;
941 
942 	if (!vt_enable_bell)
943 		return;
944 
945 	if (vd->vd_flags & VDF_QUIET_BELL)
946 		return;
947 
948 	sysbeep(1193182 / VT_BELLPITCH, VT_BELLDURATION);
949 }
950 
951 static void
952 vtterm_beep(struct terminal *tm, u_int param)
953 {
954 	u_int freq, period;
955 
956 	if (!vt_enable_bell)
957 		return;
958 
959 	if ((param == 0) || ((param & 0xffff) == 0)) {
960 		vtterm_bell(tm);
961 		return;
962 	}
963 
964 	period = ((param >> 16) & 0xffff) * hz / 1000;
965 	freq = 1193182 / (param & 0xffff);
966 
967 	sysbeep(freq, period);
968 }
969 
970 static void
971 vtterm_cursor(struct terminal *tm, const term_pos_t *p)
972 {
973 	struct vt_window *vw = tm->tm_softc;
974 
975 	vtbuf_cursor_position(&vw->vw_buf, p);
976 	vt_resume_flush_timer(vw->vw_device, 0);
977 }
978 
979 static void
980 vtterm_putchar(struct terminal *tm, const term_pos_t *p, term_char_t c)
981 {
982 	struct vt_window *vw = tm->tm_softc;
983 
984 	vtbuf_putchar(&vw->vw_buf, p, c);
985 	vt_resume_flush_timer(vw->vw_device, 0);
986 }
987 
988 static void
989 vtterm_fill(struct terminal *tm, const term_rect_t *r, term_char_t c)
990 {
991 	struct vt_window *vw = tm->tm_softc;
992 
993 	vtbuf_fill_locked(&vw->vw_buf, r, c);
994 	vt_resume_flush_timer(vw->vw_device, 0);
995 }
996 
997 static void
998 vtterm_copy(struct terminal *tm, const term_rect_t *r,
999     const term_pos_t *p)
1000 {
1001 	struct vt_window *vw = tm->tm_softc;
1002 
1003 	vtbuf_copy(&vw->vw_buf, r, p);
1004 	vt_resume_flush_timer(vw->vw_device, 0);
1005 }
1006 
1007 static void
1008 vtterm_param(struct terminal *tm, int cmd, unsigned int arg)
1009 {
1010 	struct vt_window *vw = tm->tm_softc;
1011 
1012 	switch (cmd) {
1013 	case TP_SHOWCURSOR:
1014 		vtbuf_cursor_visibility(&vw->vw_buf, arg);
1015 		vt_resume_flush_timer(vw->vw_device, 0);
1016 		break;
1017 	case TP_MOUSE:
1018 		vw->vw_mouse_level = arg;
1019 		break;
1020 	}
1021 }
1022 
1023 void
1024 vt_determine_colors(term_char_t c, int cursor,
1025     term_color_t *fg, term_color_t *bg)
1026 {
1027 	term_color_t tmp;
1028 	int invert;
1029 
1030 	invert = 0;
1031 
1032 	*fg = TCHAR_FGCOLOR(c);
1033 	if (TCHAR_FORMAT(c) & TF_BOLD)
1034 		*fg = TCOLOR_LIGHT(*fg);
1035 	*bg = TCHAR_BGCOLOR(c);
1036 
1037 	if (TCHAR_FORMAT(c) & TF_REVERSE)
1038 		invert ^= 1;
1039 	if (cursor)
1040 		invert ^= 1;
1041 
1042 	if (invert) {
1043 		tmp = *fg;
1044 		*fg = *bg;
1045 		*bg = tmp;
1046 	}
1047 }
1048 
1049 #ifndef SC_NO_CUTPASTE
1050 int
1051 vt_is_cursor_in_area(const struct vt_device *vd, const term_rect_t *area)
1052 {
1053 	unsigned int mx, my;
1054 
1055 	/*
1056 	 * We use the cursor position saved during the current refresh,
1057 	 * in case the cursor moved since.
1058 	 */
1059 	mx = vd->vd_mx_drawn + vd->vd_curwindow->vw_draw_area.tr_begin.tp_col;
1060 	my = vd->vd_my_drawn + vd->vd_curwindow->vw_draw_area.tr_begin.tp_row;
1061 
1062 	if (mx >= area->tr_end.tp_col ||
1063 	    mx + vd->vd_mcursor->width <= area->tr_begin.tp_col ||
1064 	    my >= area->tr_end.tp_row ||
1065 	    my + vd->vd_mcursor->height <= area->tr_begin.tp_row)
1066 		return (0);
1067 	return (1);
1068 }
1069 
1070 static void
1071 vt_mark_mouse_position_as_dirty(struct vt_device *vd)
1072 {
1073 	term_rect_t area;
1074 	struct vt_window *vw;
1075 	struct vt_font *vf;
1076 	int x, y;
1077 
1078 	vw = vd->vd_curwindow;
1079 	vf = vw->vw_font;
1080 
1081 	x = vd->vd_mx_drawn;
1082 	y = vd->vd_my_drawn;
1083 
1084 	if (vf != NULL) {
1085 		area.tr_begin.tp_col = x / vf->vf_width;
1086 		area.tr_begin.tp_row = y / vf->vf_height;
1087 		area.tr_end.tp_col =
1088 		    ((x + vd->vd_mcursor->width) / vf->vf_width) + 1;
1089 		area.tr_end.tp_row =
1090 		    ((y + vd->vd_mcursor->height) / vf->vf_height) + 1;
1091 	} else {
1092 		/*
1093 		 * No font loaded (ie. vt_vga operating in textmode).
1094 		 *
1095 		 * FIXME: This fake area needs to be revisited once the
1096 		 * mouse cursor is supported in vt_vga's textmode.
1097 		 */
1098 		area.tr_begin.tp_col = x;
1099 		area.tr_begin.tp_row = y;
1100 		area.tr_end.tp_col = x + 2;
1101 		area.tr_end.tp_row = y + 2;
1102 	}
1103 
1104 	vtbuf_dirty(&vw->vw_buf, &area);
1105 }
1106 #endif
1107 
1108 static int
1109 vt_flush(struct vt_device *vd)
1110 {
1111 	struct vt_window *vw;
1112 	struct vt_font *vf;
1113 	term_rect_t tarea;
1114 	term_pos_t size;
1115 #ifndef SC_NO_CUTPASTE
1116 	int cursor_was_shown, cursor_moved;
1117 #endif
1118 
1119 	vw = vd->vd_curwindow;
1120 	if (vw == NULL)
1121 		return (0);
1122 
1123 	if (vd->vd_flags & VDF_SPLASH || vw->vw_flags & VWF_BUSY)
1124 		return (0);
1125 
1126 	vf = vw->vw_font;
1127 	if (((vd->vd_flags & VDF_TEXTMODE) == 0) && (vf == NULL))
1128 		return (0);
1129 
1130 #ifndef SC_NO_CUTPASTE
1131 	cursor_was_shown = vd->vd_mshown;
1132 	cursor_moved = (vd->vd_mx != vd->vd_mx_drawn ||
1133 	    vd->vd_my != vd->vd_my_drawn);
1134 
1135 	/* Check if the cursor should be displayed or not. */
1136 	if ((vd->vd_flags & VDF_MOUSECURSOR) && /* Mouse support enabled. */
1137 	    !(vw->vw_flags & VWF_MOUSE_HIDE) && /* Cursor displayed.      */
1138 	    !kdb_active && panicstr == NULL) {  /* DDB inactive.          */
1139 		vd->vd_mshown = 1;
1140 	} else {
1141 		vd->vd_mshown = 0;
1142 	}
1143 
1144 	/*
1145 	 * If the cursor changed display state or moved, we must mark
1146 	 * the old position as dirty, so that it's erased.
1147 	 */
1148 	if (cursor_was_shown != vd->vd_mshown ||
1149 	    (vd->vd_mshown && cursor_moved))
1150 		vt_mark_mouse_position_as_dirty(vd);
1151 
1152 	/*
1153          * Save position of the mouse cursor. It's used by backends to
1154          * know where to draw the cursor and during the next refresh to
1155          * erase the previous position.
1156 	 */
1157 	vd->vd_mx_drawn = vd->vd_mx;
1158 	vd->vd_my_drawn = vd->vd_my;
1159 
1160 	/*
1161 	 * If the cursor is displayed and has moved since last refresh,
1162 	 * mark the new position as dirty.
1163 	 */
1164 	if (vd->vd_mshown && cursor_moved)
1165 		vt_mark_mouse_position_as_dirty(vd);
1166 #endif
1167 
1168 	vtbuf_undirty(&vw->vw_buf, &tarea);
1169 	vt_termsize(vd, vf, &size);
1170 
1171 	/* Force a full redraw when the screen contents are invalid. */
1172 	if (vd->vd_flags & VDF_INVALID) {
1173 		tarea.tr_begin.tp_row = tarea.tr_begin.tp_col = 0;
1174 		tarea.tr_end = size;
1175 
1176 		vd->vd_flags &= ~VDF_INVALID;
1177 	}
1178 
1179 	if (tarea.tr_begin.tp_col < tarea.tr_end.tp_col) {
1180 		vd->vd_driver->vd_bitblt_text(vd, vw, &tarea);
1181 		return (1);
1182 	}
1183 
1184 	return (0);
1185 }
1186 
1187 static void
1188 vt_timer(void *arg)
1189 {
1190 	struct vt_device *vd;
1191 	int changed;
1192 
1193 	vd = arg;
1194 	/* Update screen if required. */
1195 	changed = vt_flush(vd);
1196 
1197 	/* Schedule for next update. */
1198 	if (changed)
1199 		vt_schedule_flush(vd, 0);
1200 	else
1201 		vd->vd_timer_armed = 0;
1202 }
1203 
1204 static void
1205 vtterm_done(struct terminal *tm)
1206 {
1207 	struct vt_window *vw = tm->tm_softc;
1208 	struct vt_device *vd = vw->vw_device;
1209 
1210 	if (kdb_active || panicstr != NULL) {
1211 		/* Switch to the debugger. */
1212 		if (vd->vd_curwindow != vw) {
1213 			vd->vd_curwindow = vw;
1214 			vd->vd_flags |= VDF_INVALID;
1215 			if (vd->vd_driver->vd_postswitch)
1216 				vd->vd_driver->vd_postswitch(vd);
1217 		}
1218 		vd->vd_flags &= ~VDF_SPLASH;
1219 		vt_flush(vd);
1220 	} else if (!(vd->vd_flags & VDF_ASYNC)) {
1221 		vt_flush(vd);
1222 	}
1223 }
1224 
1225 #ifdef DEV_SPLASH
1226 static void
1227 vtterm_splash(struct vt_device *vd)
1228 {
1229 	vt_axis_t top, left;
1230 
1231 	/* Display a nice boot splash. */
1232 	if (!(vd->vd_flags & VDF_TEXTMODE) && (boothowto & RB_MUTE)) {
1233 
1234 		top = (vd->vd_height - vt_logo_height) / 2;
1235 		left = (vd->vd_width - vt_logo_width) / 2;
1236 		switch (vt_logo_depth) {
1237 		case 1:
1238 			/* XXX: Unhardcode colors! */
1239 			vd->vd_driver->vd_bitblt_bmp(vd, vd->vd_curwindow,
1240 			    vt_logo_image, NULL, vt_logo_width, vt_logo_height,
1241 			    left, top, TC_WHITE, TC_BLACK);
1242 		}
1243 		vd->vd_flags |= VDF_SPLASH;
1244 	}
1245 }
1246 #endif
1247 
1248 
1249 static void
1250 vtterm_cnprobe(struct terminal *tm, struct consdev *cp)
1251 {
1252 	struct vt_driver *vtd, **vtdlist, *vtdbest = NULL;
1253 	struct vt_window *vw = tm->tm_softc;
1254 	struct vt_device *vd = vw->vw_device;
1255 	struct winsize wsz;
1256 	term_attr_t attr;
1257 	term_char_t c;
1258 
1259 	if (!vty_enabled(VTY_VT))
1260 		return;
1261 
1262 	if (vd->vd_flags & VDF_INITIALIZED)
1263 		/* Initialization already done. */
1264 		return;
1265 
1266 	SET_FOREACH(vtdlist, vt_drv_set) {
1267 		vtd = *vtdlist;
1268 		if (vtd->vd_probe == NULL)
1269 			continue;
1270 		if (vtd->vd_probe(vd) == CN_DEAD)
1271 			continue;
1272 		if ((vtdbest == NULL) ||
1273 		    (vtd->vd_priority > vtdbest->vd_priority))
1274 			vtdbest = vtd;
1275 	}
1276 	if (vtdbest == NULL) {
1277 		cp->cn_pri = CN_DEAD;
1278 		vd->vd_flags |= VDF_DEAD;
1279 	} else {
1280 		vd->vd_driver = vtdbest;
1281 		cp->cn_pri = vd->vd_driver->vd_init(vd);
1282 	}
1283 
1284 	/* Check if driver's vt_init return CN_DEAD. */
1285 	if (cp->cn_pri == CN_DEAD) {
1286 		vd->vd_flags |= VDF_DEAD;
1287 	}
1288 
1289 	/* Initialize any early-boot keyboard drivers */
1290 	kbd_configure(KB_CONF_PROBE_ONLY);
1291 
1292 	vd->vd_unit = atomic_fetchadd_int(&vt_unit, 1);
1293 	vd->vd_windows[VT_CONSWINDOW] = vw;
1294 	sprintf(cp->cn_name, "ttyv%r", VT_UNIT(vw));
1295 
1296 	/* Attach default font if not in TEXTMODE. */
1297 	if ((vd->vd_flags & VDF_TEXTMODE) == 0) {
1298 		vw->vw_font = vtfont_ref(&vt_font_default);
1299 		vt_compute_drawable_area(vw);
1300 	}
1301 
1302 	/*
1303 	 * The original screen size was faked (_VTDEFW x _VTDEFH). Now
1304 	 * that we have the real viewable size, fix it in the static
1305 	 * buffer.
1306 	 */
1307 	if (vd->vd_width != 0 && vd->vd_height != 0)
1308 		vt_termsize(vd, vw->vw_font, &vw->vw_buf.vb_scr_size);
1309 
1310 	vtbuf_init_early(&vw->vw_buf);
1311 	vt_winsize(vd, vw->vw_font, &wsz);
1312 	c = (boothowto & RB_MUTE) == 0 ? TERMINAL_KERN_ATTR :
1313 	    TERMINAL_NORM_ATTR;
1314 	attr.ta_format = TCHAR_FORMAT(c);
1315 	attr.ta_fgcolor = TCHAR_FGCOLOR(c);
1316 	attr.ta_bgcolor = TCHAR_BGCOLOR(c);
1317 	terminal_set_winsize_blank(tm, &wsz, 1, &attr);
1318 
1319 	if (vtdbest != NULL) {
1320 #ifdef DEV_SPLASH
1321 		vtterm_splash(vd);
1322 #endif
1323 		vd->vd_flags |= VDF_INITIALIZED;
1324 	}
1325 }
1326 
1327 static int
1328 vtterm_cngetc(struct terminal *tm)
1329 {
1330 	struct vt_window *vw = tm->tm_softc;
1331 	struct vt_device *vd = vw->vw_device;
1332 	keyboard_t *kbd;
1333 	u_int c;
1334 
1335 	if (vw->vw_kbdsq && *vw->vw_kbdsq)
1336 		return (*vw->vw_kbdsq++);
1337 
1338 	/* Make sure the splash screen is not there. */
1339 	if (vd->vd_flags & VDF_SPLASH) {
1340 		/* Remove splash */
1341 		vd->vd_flags &= ~VDF_SPLASH;
1342 		/* Mark screen as invalid to force update */
1343 		vd->vd_flags |= VDF_INVALID;
1344 		vt_flush(vd);
1345 	}
1346 
1347 	/* Stripped down keyboard handler. */
1348 	kbd = kbd_get_keyboard(vd->vd_keyboard);
1349 	if (kbd == NULL)
1350 		return (-1);
1351 
1352 	/* Force keyboard input mode to K_XLATE */
1353 	vw->vw_kbdmode = K_XLATE;
1354 	vt_update_kbd_mode(vw, kbd);
1355 
1356 	/* Switch the keyboard to polling to make it work here. */
1357 	kbdd_poll(kbd, TRUE);
1358 	c = kbdd_read_char(kbd, 0);
1359 	kbdd_poll(kbd, FALSE);
1360 	if (c & RELKEY)
1361 		return (-1);
1362 
1363 	if (vw->vw_flags & VWF_SCROLL) {
1364 		vt_scrollmode_kbdevent(vw, c, 1/* Console mode */);
1365 		vt_flush(vd);
1366 		return (-1);
1367 	}
1368 
1369 	/* Stripped down handling of vt_kbdevent(), without locking, etc. */
1370 	if (c & SPCLKEY) {
1371 		switch (c) {
1372 		case SPCLKEY | SLK:
1373 			vt_save_kbd_state(vw, kbd);
1374 			if (vw->vw_kbdstate & SLKED) {
1375 				/* Turn scrolling on. */
1376 				vw->vw_flags |= VWF_SCROLL;
1377 				VTBUF_SLCK_ENABLE(&vw->vw_buf);
1378 			} else {
1379 				/* Turn scrolling off. */
1380 				vt_scroll(vw, 0, VHS_END);
1381 				vw->vw_flags &= ~VWF_SCROLL;
1382 				VTBUF_SLCK_DISABLE(&vw->vw_buf);
1383 			}
1384 			break;
1385 		/* XXX: KDB can handle history. */
1386 		case SPCLKEY | FKEY | F(50): /* Arrow up. */
1387 			vw->vw_kbdsq = "\x1b[A";
1388 			break;
1389 		case SPCLKEY | FKEY | F(58): /* Arrow down. */
1390 			vw->vw_kbdsq = "\x1b[B";
1391 			break;
1392 		case SPCLKEY | FKEY | F(55): /* Arrow right. */
1393 			vw->vw_kbdsq = "\x1b[C";
1394 			break;
1395 		case SPCLKEY | FKEY | F(53): /* Arrow left. */
1396 			vw->vw_kbdsq = "\x1b[D";
1397 			break;
1398 		}
1399 
1400 		/* Force refresh to make scrollback work. */
1401 		vt_flush(vd);
1402 	} else if (KEYFLAGS(c) == 0) {
1403 		return (KEYCHAR(c));
1404 	}
1405 
1406 	if (vw->vw_kbdsq && *vw->vw_kbdsq)
1407 		return (*vw->vw_kbdsq++);
1408 
1409 	return (-1);
1410 }
1411 
1412 static void
1413 vtterm_cngrab(struct terminal *tm)
1414 {
1415 	struct vt_device *vd;
1416 	struct vt_window *vw;
1417 	keyboard_t *kbd;
1418 
1419 	vw = tm->tm_softc;
1420 	vd = vw->vw_device;
1421 
1422 	if (!cold)
1423 		vt_window_switch(vw);
1424 
1425 	kbd = kbd_get_keyboard(vd->vd_keyboard);
1426 	if (kbd == NULL)
1427 		return;
1428 
1429 	if (vw->vw_grabbed++ > 0)
1430 		return;
1431 
1432 	/*
1433 	 * Make sure the keyboard is accessible even when the kbd device
1434 	 * driver is disabled.
1435 	 */
1436 	kbdd_enable(kbd);
1437 
1438 	/* We shall always use the keyboard in the XLATE mode here. */
1439 	vw->vw_prev_kbdmode = vw->vw_kbdmode;
1440 	vw->vw_kbdmode = K_XLATE;
1441 	vt_update_kbd_mode(vw, kbd);
1442 
1443 	kbdd_poll(kbd, TRUE);
1444 }
1445 
1446 static void
1447 vtterm_cnungrab(struct terminal *tm)
1448 {
1449 	struct vt_device *vd;
1450 	struct vt_window *vw;
1451 	keyboard_t *kbd;
1452 
1453 	vw = tm->tm_softc;
1454 	vd = vw->vw_device;
1455 
1456 	kbd = kbd_get_keyboard(vd->vd_keyboard);
1457 	if (kbd == NULL)
1458 		return;
1459 
1460 	if (--vw->vw_grabbed > 0)
1461 		return;
1462 
1463 	kbdd_poll(kbd, FALSE);
1464 
1465 	vw->vw_kbdmode = vw->vw_prev_kbdmode;
1466 	vt_update_kbd_mode(vw, kbd);
1467 	kbdd_disable(kbd);
1468 }
1469 
1470 static void
1471 vtterm_opened(struct terminal *tm, int opened)
1472 {
1473 	struct vt_window *vw = tm->tm_softc;
1474 	struct vt_device *vd = vw->vw_device;
1475 
1476 	VT_LOCK(vd);
1477 	vd->vd_flags &= ~VDF_SPLASH;
1478 	if (opened)
1479 		vw->vw_flags |= VWF_OPENED;
1480 	else {
1481 		vw->vw_flags &= ~VWF_OPENED;
1482 		/* TODO: finish ACQ/REL */
1483 	}
1484 	VT_UNLOCK(vd);
1485 }
1486 
1487 static int
1488 vt_set_border(struct vt_window *vw, term_color_t c)
1489 {
1490 	struct vt_device *vd = vw->vw_device;
1491 
1492 	if (vd->vd_driver->vd_drawrect == NULL)
1493 		return (ENOTSUP);
1494 
1495 	/* Top bar. */
1496 	if (vw->vw_draw_area.tr_begin.tp_row > 0)
1497 		vd->vd_driver->vd_drawrect(vd,
1498 		    0, 0,
1499 		    vd->vd_width - 1, vw->vw_draw_area.tr_begin.tp_row - 1,
1500 		    1, c);
1501 
1502 	/* Left bar. */
1503 	if (vw->vw_draw_area.tr_begin.tp_col > 0)
1504 		vd->vd_driver->vd_drawrect(vd,
1505 		    0, 0,
1506 		    vw->vw_draw_area.tr_begin.tp_col - 1, vd->vd_height - 1,
1507 		    1, c);
1508 
1509 	/* Right bar. */
1510 	if (vw->vw_draw_area.tr_end.tp_col < vd->vd_width)
1511 		vd->vd_driver->vd_drawrect(vd,
1512 		    vw->vw_draw_area.tr_end.tp_col - 1, 0,
1513 		    vd->vd_width - 1, vd->vd_height - 1,
1514 		    1, c);
1515 
1516 	/* Bottom bar. */
1517 	if (vw->vw_draw_area.tr_end.tp_row < vd->vd_height)
1518 		vd->vd_driver->vd_drawrect(vd,
1519 		    0, vw->vw_draw_area.tr_end.tp_row - 1,
1520 		    vd->vd_width - 1, vd->vd_height - 1,
1521 		    1, c);
1522 
1523 	return (0);
1524 }
1525 
1526 static int
1527 vt_change_font(struct vt_window *vw, struct vt_font *vf)
1528 {
1529 	struct vt_device *vd = vw->vw_device;
1530 	struct terminal *tm = vw->vw_terminal;
1531 	term_pos_t size;
1532 	struct winsize wsz;
1533 
1534 	/*
1535 	 * Changing fonts.
1536 	 *
1537 	 * Changing fonts is a little tricky.  We must prevent
1538 	 * simultaneous access to the device, so we must stop
1539 	 * the display timer and the terminal from accessing.
1540 	 * We need to switch fonts and grow our screen buffer.
1541 	 *
1542 	 * XXX: Right now the code uses terminal_mute() to
1543 	 * prevent data from reaching the console driver while
1544 	 * resizing the screen buffer.  This isn't elegant...
1545 	 */
1546 
1547 	VT_LOCK(vd);
1548 	if (vw->vw_flags & VWF_BUSY) {
1549 		/* Another process is changing the font. */
1550 		VT_UNLOCK(vd);
1551 		return (EBUSY);
1552 	}
1553 	vw->vw_flags |= VWF_BUSY;
1554 	VT_UNLOCK(vd);
1555 
1556 	vt_termsize(vd, vf, &size);
1557 	vt_winsize(vd, vf, &wsz);
1558 
1559 	/* Grow the screen buffer and terminal. */
1560 	terminal_mute(tm, 1);
1561 	vtbuf_grow(&vw->vw_buf, &size, vw->vw_buf.vb_history_size);
1562 	terminal_set_winsize_blank(tm, &wsz, 0, NULL);
1563 	terminal_set_cursor(tm, &vw->vw_buf.vb_cursor);
1564 	terminal_mute(tm, 0);
1565 
1566 	/* Actually apply the font to the current window. */
1567 	VT_LOCK(vd);
1568 	if (vw->vw_font != vf && vw->vw_font != NULL && vf != NULL) {
1569 		/*
1570 		 * In case vt_change_font called to update size we don't need
1571 		 * to update font link.
1572 		 */
1573 		vtfont_unref(vw->vw_font);
1574 		vw->vw_font = vtfont_ref(vf);
1575 	}
1576 
1577 	/*
1578 	 * Compute the drawable area and move the mouse cursor inside
1579 	 * it, in case the new area is smaller than the previous one.
1580 	 */
1581 	vt_compute_drawable_area(vw);
1582 	vd->vd_mx = min(vd->vd_mx,
1583 	    vw->vw_draw_area.tr_end.tp_col -
1584 	    vw->vw_draw_area.tr_begin.tp_col - 1);
1585 	vd->vd_my = min(vd->vd_my,
1586 	    vw->vw_draw_area.tr_end.tp_row -
1587 	    vw->vw_draw_area.tr_begin.tp_row - 1);
1588 
1589 	/* Force a full redraw the next timer tick. */
1590 	if (vd->vd_curwindow == vw) {
1591 		vt_set_border(vw, TC_BLACK);
1592 		vd->vd_flags |= VDF_INVALID;
1593 		vt_resume_flush_timer(vw->vw_device, 0);
1594 	}
1595 	vw->vw_flags &= ~VWF_BUSY;
1596 	VT_UNLOCK(vd);
1597 	return (0);
1598 }
1599 
1600 static int
1601 vt_proc_alive(struct vt_window *vw)
1602 {
1603 	struct proc *p;
1604 
1605 	if (vw->vw_smode.mode != VT_PROCESS)
1606 		return (FALSE);
1607 
1608 	if (vw->vw_proc) {
1609 		if ((p = pfind(vw->vw_pid)) != NULL)
1610 			PROC_UNLOCK(p);
1611 		if (vw->vw_proc == p)
1612 			return (TRUE);
1613 		vw->vw_proc = NULL;
1614 		vw->vw_smode.mode = VT_AUTO;
1615 		DPRINTF(1, "vt controlling process %d died\n", vw->vw_pid);
1616 		vw->vw_pid = 0;
1617 	}
1618 	return (FALSE);
1619 }
1620 
1621 static int
1622 signal_vt_rel(struct vt_window *vw)
1623 {
1624 
1625 	if (vw->vw_smode.mode != VT_PROCESS)
1626 		return (FALSE);
1627 	if (vw->vw_proc == NULL || vt_proc_alive(vw) == FALSE) {
1628 		vw->vw_proc = NULL;
1629 		vw->vw_pid = 0;
1630 		return (TRUE);
1631 	}
1632 	vw->vw_flags |= VWF_SWWAIT_REL;
1633 	PROC_LOCK(vw->vw_proc);
1634 	kern_psignal(vw->vw_proc, vw->vw_smode.relsig);
1635 	PROC_UNLOCK(vw->vw_proc);
1636 	DPRINTF(1, "sending relsig to %d\n", vw->vw_pid);
1637 	return (TRUE);
1638 }
1639 
1640 static int
1641 signal_vt_acq(struct vt_window *vw)
1642 {
1643 
1644 	if (vw->vw_smode.mode != VT_PROCESS)
1645 		return (FALSE);
1646 	if (vw == vw->vw_device->vd_windows[VT_CONSWINDOW])
1647 		cnavailable(vw->vw_terminal->consdev, FALSE);
1648 	if (vw->vw_proc == NULL || vt_proc_alive(vw) == FALSE) {
1649 		vw->vw_proc = NULL;
1650 		vw->vw_pid = 0;
1651 		return (TRUE);
1652 	}
1653 	vw->vw_flags |= VWF_SWWAIT_ACQ;
1654 	PROC_LOCK(vw->vw_proc);
1655 	kern_psignal(vw->vw_proc, vw->vw_smode.acqsig);
1656 	PROC_UNLOCK(vw->vw_proc);
1657 	DPRINTF(1, "sending acqsig to %d\n", vw->vw_pid);
1658 	return (TRUE);
1659 }
1660 
1661 static int
1662 finish_vt_rel(struct vt_window *vw, int release, int *s)
1663 {
1664 
1665 	if (vw->vw_flags & VWF_SWWAIT_REL) {
1666 		vw->vw_flags &= ~VWF_SWWAIT_REL;
1667 		if (release) {
1668 			callout_drain(&vw->vw_proc_dead_timer);
1669 			vt_late_window_switch(vw->vw_switch_to);
1670 		}
1671 		return (0);
1672 	}
1673 	return (EINVAL);
1674 }
1675 
1676 static int
1677 finish_vt_acq(struct vt_window *vw)
1678 {
1679 
1680 	if (vw->vw_flags & VWF_SWWAIT_ACQ) {
1681 		vw->vw_flags &= ~VWF_SWWAIT_ACQ;
1682 		return (0);
1683 	}
1684 	return (EINVAL);
1685 }
1686 
1687 #ifndef SC_NO_CUTPASTE
1688 static void
1689 vt_mouse_terminput_button(struct vt_device *vd, int button)
1690 {
1691 	struct vt_window *vw;
1692 	struct vt_font *vf;
1693 	char mouseb[6] = "\x1B[M";
1694 	int i, x, y;
1695 
1696 	vw = vd->vd_curwindow;
1697 	vf = vw->vw_font;
1698 
1699 	/* Translate to char position. */
1700 	x = vd->vd_mx / vf->vf_width;
1701 	y = vd->vd_my / vf->vf_height;
1702 	/* Avoid overflow. */
1703 	x = MIN(x, 255 - '!');
1704 	y = MIN(y, 255 - '!');
1705 
1706 	mouseb[3] = ' ' + button;
1707 	mouseb[4] = '!' + x;
1708 	mouseb[5] = '!' + y;
1709 
1710 	for (i = 0; i < sizeof(mouseb); i++)
1711 		terminal_input_char(vw->vw_terminal, mouseb[i]);
1712 }
1713 
1714 static void
1715 vt_mouse_terminput(struct vt_device *vd, int type, int x, int y, int event,
1716     int cnt)
1717 {
1718 
1719 	switch (type) {
1720 	case MOUSE_BUTTON_EVENT:
1721 		if (cnt > 0) {
1722 			/* Mouse button pressed. */
1723 			if (event & MOUSE_BUTTON1DOWN)
1724 				vt_mouse_terminput_button(vd, 0);
1725 			if (event & MOUSE_BUTTON2DOWN)
1726 				vt_mouse_terminput_button(vd, 1);
1727 			if (event & MOUSE_BUTTON3DOWN)
1728 				vt_mouse_terminput_button(vd, 2);
1729 		} else {
1730 			/* Mouse button released. */
1731 			vt_mouse_terminput_button(vd, 3);
1732 		}
1733 		break;
1734 #ifdef notyet
1735 	case MOUSE_MOTION_EVENT:
1736 		if (mouse->u.data.z < 0) {
1737 			/* Scroll up. */
1738 			sc_mouse_input_button(vd, 64);
1739 		} else if (mouse->u.data.z > 0) {
1740 			/* Scroll down. */
1741 			sc_mouse_input_button(vd, 65);
1742 		}
1743 		break;
1744 #endif
1745 	}
1746 }
1747 
1748 static void
1749 vt_mouse_paste()
1750 {
1751 	term_char_t *buf;
1752 	int i, len;
1753 
1754 	len = VD_PASTEBUFLEN(main_vd);
1755 	buf = VD_PASTEBUF(main_vd);
1756 	len /= sizeof(term_char_t);
1757 	for (i = 0; i < len; i++) {
1758 		if (buf[i] == '\0')
1759 			continue;
1760 		terminal_input_char(main_vd->vd_curwindow->vw_terminal,
1761 		    buf[i]);
1762 	}
1763 }
1764 
1765 void
1766 vt_mouse_event(int type, int x, int y, int event, int cnt, int mlevel)
1767 {
1768 	struct vt_device *vd;
1769 	struct vt_window *vw;
1770 	struct vt_font *vf;
1771 	term_pos_t size;
1772 	int len, mark;
1773 
1774 	vd = main_vd;
1775 	vw = vd->vd_curwindow;
1776 	vf = vw->vw_font;
1777 	mark = 0;
1778 
1779 	if (vw->vw_flags & (VWF_MOUSE_HIDE | VWF_GRAPHICS))
1780 		/*
1781 		 * Either the mouse is disabled, or the window is in
1782 		 * "graphics mode". The graphics mode is usually set by
1783 		 * an X server, using the KDSETMODE ioctl.
1784 		 */
1785 		return;
1786 
1787 	if (vf == NULL)	/* Text mode. */
1788 		return;
1789 
1790 	/*
1791 	 * TODO: add flag about pointer position changed, to not redraw chars
1792 	 * under mouse pointer when nothing changed.
1793 	 */
1794 
1795 	if (vw->vw_mouse_level > 0)
1796 		vt_mouse_terminput(vd, type, x, y, event, cnt);
1797 
1798 	switch (type) {
1799 	case MOUSE_ACTION:
1800 	case MOUSE_MOTION_EVENT:
1801 		/* Movement */
1802 		x += vd->vd_mx;
1803 		y += vd->vd_my;
1804 
1805 		vt_termsize(vd, vf, &size);
1806 
1807 		/* Apply limits. */
1808 		x = MAX(x, 0);
1809 		y = MAX(y, 0);
1810 		x = MIN(x, (size.tp_col * vf->vf_width) - 1);
1811 		y = MIN(y, (size.tp_row * vf->vf_height) - 1);
1812 
1813 		vd->vd_mx = x;
1814 		vd->vd_my = y;
1815 		if (vd->vd_mstate & MOUSE_BUTTON1DOWN)
1816 			vtbuf_set_mark(&vw->vw_buf, VTB_MARK_MOVE,
1817 			    vd->vd_mx / vf->vf_width,
1818 			    vd->vd_my / vf->vf_height);
1819 
1820 		vt_resume_flush_timer(vw->vw_device, 0);
1821 		return; /* Done */
1822 	case MOUSE_BUTTON_EVENT:
1823 		/* Buttons */
1824 		break;
1825 	default:
1826 		return; /* Done */
1827 	}
1828 
1829 	switch (event) {
1830 	case MOUSE_BUTTON1DOWN:
1831 		switch (cnt % 4) {
1832 		case 0:	/* up */
1833 			mark = VTB_MARK_END;
1834 			break;
1835 		case 1: /* single click: start cut operation */
1836 			mark = VTB_MARK_START;
1837 			break;
1838 		case 2:	/* double click: cut a word */
1839 			mark = VTB_MARK_WORD;
1840 			break;
1841 		case 3:	/* triple click: cut a line */
1842 			mark = VTB_MARK_ROW;
1843 			break;
1844 		}
1845 		break;
1846 	case VT_MOUSE_PASTEBUTTON:
1847 		switch (cnt) {
1848 		case 0:	/* up */
1849 			break;
1850 		default:
1851 			vt_mouse_paste();
1852 			break;
1853 		}
1854 		return; /* Done */
1855 	case VT_MOUSE_EXTENDBUTTON:
1856 		switch (cnt) {
1857 		case 0:	/* up */
1858 			if (!(vd->vd_mstate & MOUSE_BUTTON1DOWN))
1859 				mark = VTB_MARK_EXTEND;
1860 			else
1861 				mark = 0;
1862 			break;
1863 		default:
1864 			mark = VTB_MARK_EXTEND;
1865 			break;
1866 		}
1867 		break;
1868 	default:
1869 		return; /* Done */
1870 	}
1871 
1872 	/* Save buttons state. */
1873 	if (cnt > 0)
1874 		vd->vd_mstate |= event;
1875 	else
1876 		vd->vd_mstate &= ~event;
1877 
1878 	if (vtbuf_set_mark(&vw->vw_buf, mark, vd->vd_mx / vf->vf_width,
1879 	    vd->vd_my / vf->vf_height) == 1) {
1880 		/*
1881 		 * We have something marked to copy, so update pointer to
1882 		 * window with selection.
1883 		 */
1884 		vt_resume_flush_timer(vw->vw_device, 0);
1885 
1886 		switch (mark) {
1887 		case VTB_MARK_END:
1888 		case VTB_MARK_WORD:
1889 		case VTB_MARK_ROW:
1890 		case VTB_MARK_EXTEND:
1891 			break;
1892 		default:
1893 			/* Other types of mark do not require to copy data. */
1894 			return;
1895 		}
1896 
1897 		/* Get current selection size in bytes. */
1898 		len = vtbuf_get_marked_len(&vw->vw_buf);
1899 		if (len <= 0)
1900 			return;
1901 
1902 		/* Reallocate buffer only if old one is too small. */
1903 		if (len > VD_PASTEBUFSZ(vd)) {
1904 			VD_PASTEBUF(vd) = realloc(VD_PASTEBUF(vd), len, M_VT,
1905 			    M_WAITOK | M_ZERO);
1906 			/* Update buffer size. */
1907 			VD_PASTEBUFSZ(vd) = len;
1908 		}
1909 		/* Request copy/paste buffer data, no more than `len' */
1910 		vtbuf_extract_marked(&vw->vw_buf, VD_PASTEBUF(vd),
1911 		    VD_PASTEBUFSZ(vd));
1912 
1913 		VD_PASTEBUFLEN(vd) = len;
1914 
1915 		/* XXX VD_PASTEBUF(vd) have to be freed on shutdown/unload. */
1916 	}
1917 }
1918 
1919 void
1920 vt_mouse_state(int show)
1921 {
1922 	struct vt_device *vd;
1923 	struct vt_window *vw;
1924 
1925 	vd = main_vd;
1926 	vw = vd->vd_curwindow;
1927 
1928 	switch (show) {
1929 	case VT_MOUSE_HIDE:
1930 		vw->vw_flags |= VWF_MOUSE_HIDE;
1931 		break;
1932 	case VT_MOUSE_SHOW:
1933 		vw->vw_flags &= ~VWF_MOUSE_HIDE;
1934 		break;
1935 	}
1936 
1937 	/* Mark mouse position as dirty. */
1938 	vt_mark_mouse_position_as_dirty(vd);
1939 	vt_resume_flush_timer(vw->vw_device, 0);
1940 }
1941 #endif
1942 
1943 static int
1944 vtterm_mmap(struct terminal *tm, vm_ooffset_t offset, vm_paddr_t * paddr,
1945     int nprot, vm_memattr_t *memattr)
1946 {
1947 	struct vt_window *vw = tm->tm_softc;
1948 	struct vt_device *vd = vw->vw_device;
1949 
1950 	if (vd->vd_driver->vd_fb_mmap)
1951 		return (vd->vd_driver->vd_fb_mmap(vd, offset, paddr, nprot,
1952 		    memattr));
1953 
1954 	return (ENXIO);
1955 }
1956 
1957 static int
1958 vtterm_ioctl(struct terminal *tm, u_long cmd, caddr_t data,
1959     struct thread *td)
1960 {
1961 	struct vt_window *vw = tm->tm_softc;
1962 	struct vt_device *vd = vw->vw_device;
1963 	keyboard_t *kbd;
1964 	int error, i, s;
1965 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
1966     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
1967 	int ival;
1968 
1969 	switch (cmd) {
1970 	case _IO('v', 4):
1971 		cmd = VT_RELDISP;
1972 		break;
1973 	case _IO('v', 5):
1974 		cmd = VT_ACTIVATE;
1975 		break;
1976 	case _IO('v', 6):
1977 		cmd = VT_WAITACTIVE;
1978 		break;
1979 	case _IO('K', 20):
1980 		cmd = KDSKBSTATE;
1981 		break;
1982 	case _IO('K', 67):
1983 		cmd = KDSETRAD;
1984 		break;
1985 	case _IO('K', 7):
1986 		cmd = KDSKBMODE;
1987 		break;
1988 	case _IO('K', 8):
1989 		cmd = KDMKTONE;
1990 		break;
1991 	case _IO('K', 63):
1992 		cmd = KIOCSOUND;
1993 		break;
1994 	case _IO('K', 66):
1995 		cmd = KDSETLED;
1996 		break;
1997 	case _IO('c', 110):
1998 		cmd = CONS_SETKBD;
1999 		break;
2000 	default:
2001 		goto skip_thunk;
2002 	}
2003 	ival = IOCPARM_IVAL(data);
2004 	data = (caddr_t)&ival;
2005 skip_thunk:
2006 #endif
2007 
2008 	switch (cmd) {
2009 	case KDSETRAD:		/* set keyboard repeat & delay rates (old) */
2010 		if (*(int *)data & ~0x7f)
2011 			return (EINVAL);
2012 		/* FALLTHROUGH */
2013 	case GIO_KEYMAP:
2014 	case PIO_KEYMAP:
2015 	case GIO_DEADKEYMAP:
2016 	case PIO_DEADKEYMAP:
2017 	case GETFKEY:
2018 	case SETFKEY:
2019 	case KDGKBINFO:
2020 	case KDGKBTYPE:
2021 	case KDGETREPEAT:	/* get keyboard repeat & delay rates */
2022 	case KDSETREPEAT:	/* set keyboard repeat & delay rates (new) */
2023 	case KBADDKBD:		/* add/remove keyboard to/from mux */
2024 	case KBRELKBD: {
2025 		error = 0;
2026 
2027 		mtx_lock(&Giant);
2028 		kbd = kbd_get_keyboard(vd->vd_keyboard);
2029 		if (kbd != NULL)
2030 			error = kbdd_ioctl(kbd, cmd, data);
2031 		mtx_unlock(&Giant);
2032 		if (error == ENOIOCTL) {
2033 			if (cmd == KDGKBTYPE) {
2034 				/* always return something? XXX */
2035 				*(int *)data = 0;
2036 			} else {
2037 				return (ENODEV);
2038 			}
2039 		}
2040 		return (error);
2041 	}
2042 	case KDGKBSTATE: {	/* get keyboard state (locks) */
2043 		error = 0;
2044 
2045 		if (vw == vd->vd_curwindow) {
2046 			mtx_lock(&Giant);
2047 			kbd = kbd_get_keyboard(vd->vd_keyboard);
2048 			if (kbd != NULL)
2049 				error = vt_save_kbd_state(vw, kbd);
2050 			mtx_unlock(&Giant);
2051 
2052 			if (error != 0)
2053 				return (error);
2054 		}
2055 
2056 		*(int *)data = vw->vw_kbdstate & LOCK_MASK;
2057 
2058 		return (error);
2059 	}
2060 	case KDSKBSTATE: {	/* set keyboard state (locks) */
2061 		int state;
2062 
2063 		state = *(int *)data;
2064 		if (state & ~LOCK_MASK)
2065 			return (EINVAL);
2066 
2067 		vw->vw_kbdstate &= ~LOCK_MASK;
2068 		vw->vw_kbdstate |= state;
2069 
2070 		error = 0;
2071 		if (vw == vd->vd_curwindow) {
2072 			mtx_lock(&Giant);
2073 			kbd = kbd_get_keyboard(vd->vd_keyboard);
2074 			if (kbd != NULL)
2075 				error = vt_update_kbd_state(vw, kbd);
2076 			mtx_unlock(&Giant);
2077 		}
2078 
2079 		return (error);
2080 	}
2081 	case KDGETLED: {	/* get keyboard LED status */
2082 		error = 0;
2083 
2084 		if (vw == vd->vd_curwindow) {
2085 			mtx_lock(&Giant);
2086 			kbd = kbd_get_keyboard(vd->vd_keyboard);
2087 			if (kbd != NULL)
2088 				error = vt_save_kbd_leds(vw, kbd);
2089 			mtx_unlock(&Giant);
2090 
2091 			if (error != 0)
2092 				return (error);
2093 		}
2094 
2095 		*(int *)data = vw->vw_kbdstate & LED_MASK;
2096 
2097 		return (error);
2098 	}
2099 	case KDSETLED: {	/* set keyboard LED status */
2100 		int leds;
2101 
2102 		leds = *(int *)data;
2103 		if (leds & ~LED_MASK)
2104 			return (EINVAL);
2105 
2106 		vw->vw_kbdstate &= ~LED_MASK;
2107 		vw->vw_kbdstate |= leds;
2108 
2109 		error = 0;
2110 		if (vw == vd->vd_curwindow) {
2111 			mtx_lock(&Giant);
2112 			kbd = kbd_get_keyboard(vd->vd_keyboard);
2113 			if (kbd != NULL)
2114 				error = vt_update_kbd_leds(vw, kbd);
2115 			mtx_unlock(&Giant);
2116 		}
2117 
2118 		return (error);
2119 	}
2120 	case KDGKBMODE: {
2121 		error = 0;
2122 
2123 		if (vw == vd->vd_curwindow) {
2124 			mtx_lock(&Giant);
2125 			kbd = kbd_get_keyboard(vd->vd_keyboard);
2126 			if (kbd != NULL)
2127 				error = vt_save_kbd_mode(vw, kbd);
2128 			mtx_unlock(&Giant);
2129 
2130 			if (error != 0)
2131 				return (error);
2132 		}
2133 
2134 		*(int *)data = vw->vw_kbdmode;
2135 
2136 		return (error);
2137 	}
2138 	case KDSKBMODE: {
2139 		int mode;
2140 
2141 		mode = *(int *)data;
2142 		switch (mode) {
2143 		case K_XLATE:
2144 		case K_RAW:
2145 		case K_CODE:
2146 			vw->vw_kbdmode = mode;
2147 
2148 			error = 0;
2149 			if (vw == vd->vd_curwindow) {
2150 				mtx_lock(&Giant);
2151 				kbd = kbd_get_keyboard(vd->vd_keyboard);
2152 				if (kbd != NULL)
2153 					error = vt_update_kbd_mode(vw, kbd);
2154 				mtx_unlock(&Giant);
2155 			}
2156 
2157 			return (error);
2158 		default:
2159 			return (EINVAL);
2160 		}
2161 	}
2162 	case FBIOGTYPE:
2163 	case FBIO_GETWINORG:	/* get frame buffer window origin */
2164 	case FBIO_GETDISPSTART:	/* get display start address */
2165 	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
2166 	case FBIO_BLANK:	/* blank display */
2167 		if (vd->vd_driver->vd_fb_ioctl)
2168 			return (vd->vd_driver->vd_fb_ioctl(vd, cmd, data, td));
2169 		break;
2170 	case CONS_BLANKTIME:
2171 		/* XXX */
2172 		return (0);
2173 	case CONS_GET:
2174 		/* XXX */
2175 		*(int *)data = M_CG640x480;
2176 		return (0);
2177 	case CONS_BELLTYPE: 	/* set bell type sound */
2178 		if ((*(int *)data) & CONS_QUIET_BELL)
2179 			vd->vd_flags |= VDF_QUIET_BELL;
2180 		else
2181 			vd->vd_flags &= ~VDF_QUIET_BELL;
2182 		return (0);
2183 	case CONS_GETINFO: {
2184 		vid_info_t *vi = (vid_info_t *)data;
2185 		if (vi->size != sizeof(struct vid_info))
2186 			return (EINVAL);
2187 
2188 		if (vw == vd->vd_curwindow) {
2189 			kbd = kbd_get_keyboard(vd->vd_keyboard);
2190 			if (kbd != NULL)
2191 				vt_save_kbd_state(vw, kbd);
2192 		}
2193 
2194 		vi->m_num = vd->vd_curwindow->vw_number + 1;
2195 		vi->mk_keylock = vw->vw_kbdstate & LOCK_MASK;
2196 		/* XXX: other fields! */
2197 		return (0);
2198 	}
2199 	case CONS_GETVERS:
2200 		*(int *)data = 0x200;
2201 		return (0);
2202 	case CONS_MODEINFO:
2203 		/* XXX */
2204 		return (0);
2205 	case CONS_MOUSECTL: {
2206 		mouse_info_t *mouse = (mouse_info_t*)data;
2207 
2208 		/*
2209 		 * All the commands except MOUSE_SHOW nd MOUSE_HIDE
2210 		 * should not be applied to individual TTYs, but only to
2211 		 * consolectl.
2212 		 */
2213 		switch (mouse->operation) {
2214 		case MOUSE_HIDE:
2215 			if (vd->vd_flags & VDF_MOUSECURSOR) {
2216 				vd->vd_flags &= ~VDF_MOUSECURSOR;
2217 #ifndef SC_NO_CUTPASTE
2218 				vt_mouse_state(VT_MOUSE_HIDE);
2219 #endif
2220 			}
2221 			return (0);
2222 		case MOUSE_SHOW:
2223 			if (!(vd->vd_flags & VDF_MOUSECURSOR)) {
2224 				vd->vd_flags |= VDF_MOUSECURSOR;
2225 				vd->vd_mx = vd->vd_width / 2;
2226 				vd->vd_my = vd->vd_height / 2;
2227 #ifndef SC_NO_CUTPASTE
2228 				vt_mouse_state(VT_MOUSE_SHOW);
2229 #endif
2230 			}
2231 			return (0);
2232 		default:
2233 			return (EINVAL);
2234 		}
2235 	}
2236 	case PIO_VFONT: {
2237 		struct vt_font *vf;
2238 
2239 		if (vd->vd_flags & VDF_TEXTMODE)
2240 			return (ENOTSUP);
2241 
2242 		error = vtfont_load((void *)data, &vf);
2243 		if (error != 0)
2244 			return (error);
2245 
2246 		error = vt_change_font(vw, vf);
2247 		vtfont_unref(vf);
2248 		return (error);
2249 	}
2250 	case PIO_VFONT_DEFAULT: {
2251 		/* Reset to default font. */
2252 		error = vt_change_font(vw, &vt_font_default);
2253 		return (error);
2254 	}
2255 	case GIO_SCRNMAP: {
2256 		scrmap_t *sm = (scrmap_t *)data;
2257 
2258 		/* We don't have screen maps, so return a handcrafted one. */
2259 		for (i = 0; i < 256; i++)
2260 			sm->scrmap[i] = i;
2261 		return (0);
2262 	}
2263 	case KDSETMODE:
2264 		/*
2265 		 * FIXME: This implementation is incomplete compared to
2266 		 * syscons.
2267 		 */
2268 		switch (*(int *)data) {
2269 		case KD_TEXT:
2270 		case KD_TEXT1:
2271 		case KD_PIXEL:
2272 			vw->vw_flags &= ~VWF_GRAPHICS;
2273 			break;
2274 		case KD_GRAPHICS:
2275 			vw->vw_flags |= VWF_GRAPHICS;
2276 			break;
2277 		}
2278 		return (0);
2279 	case KDENABIO:      	/* allow io operations */
2280 		error = priv_check(td, PRIV_IO);
2281 		if (error != 0)
2282 			return (error);
2283 		error = securelevel_gt(td->td_ucred, 0);
2284 		if (error != 0)
2285 			return (error);
2286 #if defined(__i386__)
2287 		td->td_frame->tf_eflags |= PSL_IOPL;
2288 #elif defined(__amd64__)
2289 		td->td_frame->tf_rflags |= PSL_IOPL;
2290 #endif
2291 		return (0);
2292 	case KDDISABIO:     	/* disallow io operations (default) */
2293 #if defined(__i386__)
2294 		td->td_frame->tf_eflags &= ~PSL_IOPL;
2295 #elif defined(__amd64__)
2296 		td->td_frame->tf_rflags &= ~PSL_IOPL;
2297 #endif
2298 		return (0);
2299 	case KDMKTONE:      	/* sound the bell */
2300 		vtterm_beep(tm, *(u_int *)data);
2301 		return (0);
2302 	case KIOCSOUND:     	/* make tone (*data) hz */
2303 		/* TODO */
2304 		return (0);
2305 	case CONS_SETKBD: 		/* set the new keyboard */
2306 		mtx_lock(&Giant);
2307 		error = 0;
2308 		if (vd->vd_keyboard != *(int *)data) {
2309 			kbd = kbd_get_keyboard(*(int *)data);
2310 			if (kbd == NULL) {
2311 				mtx_unlock(&Giant);
2312 				return (EINVAL);
2313 			}
2314 			i = kbd_allocate(kbd->kb_name, kbd->kb_unit,
2315 			    (void *)vd, vt_kbdevent, vd);
2316 			if (i >= 0) {
2317 				if (vd->vd_keyboard != -1) {
2318 					vt_save_kbd_state(vd->vd_curwindow, kbd);
2319 					kbd_release(kbd, (void *)vd);
2320 				}
2321 				kbd = kbd_get_keyboard(i);
2322 				vd->vd_keyboard = i;
2323 
2324 				vt_update_kbd_mode(vd->vd_curwindow, kbd);
2325 				vt_update_kbd_state(vd->vd_curwindow, kbd);
2326 			} else {
2327 				error = EPERM;	/* XXX */
2328 			}
2329 		}
2330 		mtx_unlock(&Giant);
2331 		return (error);
2332 	case CONS_RELKBD: 		/* release the current keyboard */
2333 		mtx_lock(&Giant);
2334 		error = 0;
2335 		if (vd->vd_keyboard != -1) {
2336 			kbd = kbd_get_keyboard(vd->vd_keyboard);
2337 			if (kbd == NULL) {
2338 				mtx_unlock(&Giant);
2339 				return (EINVAL);
2340 			}
2341 			vt_save_kbd_state(vd->vd_curwindow, kbd);
2342 			error = kbd_release(kbd, (void *)vd);
2343 			if (error == 0) {
2344 				vd->vd_keyboard = -1;
2345 			}
2346 		}
2347 		mtx_unlock(&Giant);
2348 		return (error);
2349 	case VT_ACTIVATE: {
2350 		int win;
2351 		win = *(int *)data - 1;
2352 		DPRINTF(5, "%s%d: VT_ACTIVATE ttyv%d ", SC_DRIVER_NAME,
2353 		    VT_UNIT(vw), win);
2354 		if ((win >= VT_MAXWINDOWS) || (win < 0))
2355 			return (EINVAL);
2356 		return (vt_proc_window_switch(vd->vd_windows[win]));
2357 	}
2358 	case VT_GETACTIVE:
2359 		*(int *)data = vd->vd_curwindow->vw_number + 1;
2360 		return (0);
2361 	case VT_GETINDEX:
2362 		*(int *)data = vw->vw_number + 1;
2363 		return (0);
2364 	case VT_LOCKSWITCH:
2365 		/* TODO: Check current state, switching can be in progress. */
2366 		if ((*(int *)data) == 0x01)
2367 			vw->vw_flags |= VWF_VTYLOCK;
2368 		else if ((*(int *)data) == 0x02)
2369 			vw->vw_flags &= ~VWF_VTYLOCK;
2370 		else
2371 			return (EINVAL);
2372 		return (0);
2373 	case VT_OPENQRY:
2374 		VT_LOCK(vd);
2375 		for (i = 0; i < VT_MAXWINDOWS; i++) {
2376 			vw = vd->vd_windows[i];
2377 			if (vw == NULL)
2378 				continue;
2379 			if (!(vw->vw_flags & VWF_OPENED)) {
2380 				*(int *)data = vw->vw_number + 1;
2381 				VT_UNLOCK(vd);
2382 				return (0);
2383 			}
2384 		}
2385 		VT_UNLOCK(vd);
2386 		return (EINVAL);
2387 	case VT_WAITACTIVE: {
2388 		unsigned int idx;
2389 
2390 		error = 0;
2391 
2392 		idx = *(unsigned int *)data;
2393 		if (idx > VT_MAXWINDOWS)
2394 			return (EINVAL);
2395 		if (idx > 0)
2396 			vw = vd->vd_windows[idx - 1];
2397 
2398 		VT_LOCK(vd);
2399 		while (vd->vd_curwindow != vw && error == 0)
2400 			error = cv_wait_sig(&vd->vd_winswitch, &vd->vd_lock);
2401 		VT_UNLOCK(vd);
2402 		return (error);
2403 	}
2404 	case VT_SETMODE: {    	/* set screen switcher mode */
2405 		struct vt_mode *mode;
2406 		struct proc *p1;
2407 
2408 		mode = (struct vt_mode *)data;
2409 		DPRINTF(5, "%s%d: VT_SETMODE ", SC_DRIVER_NAME, VT_UNIT(vw));
2410 		if (vw->vw_smode.mode == VT_PROCESS) {
2411 			p1 = pfind(vw->vw_pid);
2412 			if (vw->vw_proc == p1 && vw->vw_proc != td->td_proc) {
2413 				if (p1)
2414 					PROC_UNLOCK(p1);
2415 				DPRINTF(5, "error EPERM\n");
2416 				return (EPERM);
2417 			}
2418 			if (p1)
2419 				PROC_UNLOCK(p1);
2420 		}
2421 		if (mode->mode == VT_AUTO) {
2422 			vw->vw_smode.mode = VT_AUTO;
2423 			vw->vw_proc = NULL;
2424 			vw->vw_pid = 0;
2425 			DPRINTF(5, "VT_AUTO, ");
2426 			if (vw == vw->vw_device->vd_windows[VT_CONSWINDOW])
2427 				cnavailable(vw->vw_terminal->consdev, TRUE);
2428 			/* were we in the middle of the vty switching process? */
2429 			if (finish_vt_rel(vw, TRUE, &s) == 0)
2430 				DPRINTF(5, "reset WAIT_REL, ");
2431 			if (finish_vt_acq(vw) == 0)
2432 				DPRINTF(5, "reset WAIT_ACQ, ");
2433 			return (0);
2434 		} else if (mode->mode == VT_PROCESS) {
2435 			if (!ISSIGVALID(mode->relsig) ||
2436 			    !ISSIGVALID(mode->acqsig) ||
2437 			    !ISSIGVALID(mode->frsig)) {
2438 				DPRINTF(5, "error EINVAL\n");
2439 				return (EINVAL);
2440 			}
2441 			DPRINTF(5, "VT_PROCESS %d, ", td->td_proc->p_pid);
2442 			bcopy(data, &vw->vw_smode, sizeof(struct vt_mode));
2443 			vw->vw_proc = td->td_proc;
2444 			vw->vw_pid = vw->vw_proc->p_pid;
2445 			if (vw == vw->vw_device->vd_windows[VT_CONSWINDOW])
2446 				cnavailable(vw->vw_terminal->consdev, FALSE);
2447 		} else {
2448 			DPRINTF(5, "VT_SETMODE failed, unknown mode %d\n",
2449 			    mode->mode);
2450 			return (EINVAL);
2451 		}
2452 		DPRINTF(5, "\n");
2453 		return (0);
2454 	}
2455 	case VT_GETMODE:	/* get screen switcher mode */
2456 		bcopy(&vw->vw_smode, data, sizeof(struct vt_mode));
2457 		return (0);
2458 
2459 	case VT_RELDISP:	/* screen switcher ioctl */
2460 		/*
2461 		 * This must be the current vty which is in the VT_PROCESS
2462 		 * switching mode...
2463 		 */
2464 		if ((vw != vd->vd_curwindow) || (vw->vw_smode.mode !=
2465 		    VT_PROCESS)) {
2466 			return (EINVAL);
2467 		}
2468 		/* ...and this process is controlling it. */
2469 		if (vw->vw_proc != td->td_proc) {
2470 			return (EPERM);
2471 		}
2472 		error = EINVAL;
2473 		switch(*(int *)data) {
2474 		case VT_FALSE:	/* user refuses to release screen, abort */
2475 			if ((error = finish_vt_rel(vw, FALSE, &s)) == 0)
2476 				DPRINTF(5, "%s%d: VT_RELDISP: VT_FALSE\n",
2477 				    SC_DRIVER_NAME, VT_UNIT(vw));
2478 			break;
2479 		case VT_TRUE:	/* user has released screen, go on */
2480 			/* finish_vt_rel(..., TRUE, ...) should not be locked */
2481 			if (vw->vw_flags & VWF_SWWAIT_REL) {
2482 				if ((error = finish_vt_rel(vw, TRUE, &s)) == 0)
2483 					DPRINTF(5, "%s%d: VT_RELDISP: VT_TRUE\n",
2484 					    SC_DRIVER_NAME, VT_UNIT(vw));
2485 			} else {
2486 				error = EINVAL;
2487 			}
2488 			return (error);
2489 		case VT_ACKACQ:	/* acquire acknowledged, switch completed */
2490 			if ((error = finish_vt_acq(vw)) == 0)
2491 				DPRINTF(5, "%s%d: VT_RELDISP: VT_ACKACQ\n",
2492 				    SC_DRIVER_NAME, VT_UNIT(vw));
2493 			break;
2494 		default:
2495 			break;
2496 		}
2497 		return (error);
2498 	}
2499 
2500 	return (ENOIOCTL);
2501 }
2502 
2503 static struct vt_window *
2504 vt_allocate_window(struct vt_device *vd, unsigned int window)
2505 {
2506 	struct vt_window *vw;
2507 	struct terminal *tm;
2508 	term_pos_t size;
2509 	struct winsize wsz;
2510 
2511 	vw = malloc(sizeof *vw, M_VT, M_WAITOK|M_ZERO);
2512 	vw->vw_device = vd;
2513 	vw->vw_number = window;
2514 	vw->vw_kbdmode = K_XLATE;
2515 
2516 	if ((vd->vd_flags & VDF_TEXTMODE) == 0) {
2517 		vw->vw_font = vtfont_ref(&vt_font_default);
2518 		vt_compute_drawable_area(vw);
2519 	}
2520 
2521 	vt_termsize(vd, vw->vw_font, &size);
2522 	vt_winsize(vd, vw->vw_font, &wsz);
2523 	vtbuf_init(&vw->vw_buf, &size);
2524 
2525 	tm = vw->vw_terminal = terminal_alloc(&vt_termclass, vw);
2526 	terminal_set_winsize(tm, &wsz);
2527 	vd->vd_windows[window] = vw;
2528 	callout_init(&vw->vw_proc_dead_timer, 0);
2529 
2530 	return (vw);
2531 }
2532 
2533 void
2534 vt_upgrade(struct vt_device *vd)
2535 {
2536 	struct vt_window *vw;
2537 	unsigned int i;
2538 	int register_handlers;
2539 
2540 	if (!vty_enabled(VTY_VT))
2541 		return;
2542 	if (main_vd->vd_driver == NULL)
2543 		return;
2544 
2545 	for (i = 0; i < VT_MAXWINDOWS; i++) {
2546 		vw = vd->vd_windows[i];
2547 		if (vw == NULL) {
2548 			/* New window. */
2549 			vw = vt_allocate_window(vd, i);
2550 		}
2551 		if (!(vw->vw_flags & VWF_READY)) {
2552 			callout_init(&vw->vw_proc_dead_timer, 0);
2553 			terminal_maketty(vw->vw_terminal, "v%r", VT_UNIT(vw));
2554 			vw->vw_flags |= VWF_READY;
2555 			if (vw->vw_flags & VWF_CONSOLE) {
2556 				/* For existing console window. */
2557 				EVENTHANDLER_REGISTER(shutdown_pre_sync,
2558 				    vt_window_switch, vw, SHUTDOWN_PRI_DEFAULT);
2559 			}
2560 		}
2561 
2562 	}
2563 	VT_LOCK(vd);
2564 	if (vd->vd_curwindow == NULL)
2565 		vd->vd_curwindow = vd->vd_windows[VT_CONSWINDOW];
2566 
2567 	register_handlers = 0;
2568 	if (!(vd->vd_flags & VDF_ASYNC)) {
2569 		/* Attach keyboard. */
2570 		vt_allocate_keyboard(vd);
2571 
2572 		/* Init 25 Hz timer. */
2573 		callout_init_mtx(&vd->vd_timer, &vd->vd_lock, 0);
2574 
2575 		/* Start timer when everything ready. */
2576 		vd->vd_flags |= VDF_ASYNC;
2577 		callout_reset(&vd->vd_timer, hz / VT_TIMERFREQ, vt_timer, vd);
2578 		vd->vd_timer_armed = 1;
2579 		register_handlers = 1;
2580 	}
2581 
2582 	VT_UNLOCK(vd);
2583 
2584 	/* Refill settings with new sizes. */
2585 	vt_resize(vd);
2586 
2587 	if (register_handlers) {
2588 		/* Register suspend/resume handlers. */
2589 		EVENTHANDLER_REGISTER(power_suspend_early, vt_suspend_handler,
2590 		    vd, EVENTHANDLER_PRI_ANY);
2591 		EVENTHANDLER_REGISTER(power_resume, vt_resume_handler, vd,
2592 		    EVENTHANDLER_PRI_ANY);
2593 	}
2594 }
2595 
2596 static void
2597 vt_resize(struct vt_device *vd)
2598 {
2599 	struct vt_window *vw;
2600 	int i;
2601 
2602 	for (i = 0; i < VT_MAXWINDOWS; i++) {
2603 		vw = vd->vd_windows[i];
2604 		VT_LOCK(vd);
2605 		/* Assign default font to window, if not textmode. */
2606 		if (!(vd->vd_flags & VDF_TEXTMODE) && vw->vw_font == NULL)
2607 			vw->vw_font = vtfont_ref(&vt_font_default);
2608 		VT_UNLOCK(vd);
2609 
2610 		/* Resize terminal windows */
2611 		while (vt_change_font(vw, vw->vw_font) == EBUSY) {
2612 			DPRINTF(100, "%s: vt_change_font() is busy, "
2613 			    "window %d\n", __func__, i);
2614 		}
2615 	}
2616 }
2617 
2618 static void
2619 vt_replace_backend(const struct vt_driver *drv, void *softc)
2620 {
2621 	struct vt_device *vd;
2622 
2623 	vd = main_vd;
2624 
2625 	if (vd->vd_flags & VDF_ASYNC) {
2626 		/* Stop vt_flush periodic task. */
2627 		VT_LOCK(vd);
2628 		vt_suspend_flush_timer(vd);
2629 		VT_UNLOCK(vd);
2630 		/*
2631 		 * Mute current terminal until we done. vt_change_font (called
2632 		 * from vt_resize) will unmute it.
2633 		 */
2634 		terminal_mute(vd->vd_curwindow->vw_terminal, 1);
2635 	}
2636 
2637 	/*
2638 	 * Reset VDF_TEXTMODE flag, driver who require that flag (vt_vga) will
2639 	 * set it.
2640 	 */
2641 	VT_LOCK(vd);
2642 	vd->vd_flags &= ~VDF_TEXTMODE;
2643 
2644 	if (drv != NULL) {
2645 		/*
2646 		 * We want to upgrade from the current driver to the
2647 		 * given driver.
2648 		 */
2649 
2650 		vd->vd_prev_driver = vd->vd_driver;
2651 		vd->vd_prev_softc = vd->vd_softc;
2652 		vd->vd_driver = drv;
2653 		vd->vd_softc = softc;
2654 
2655 		vd->vd_driver->vd_init(vd);
2656 	} else if (vd->vd_prev_driver != NULL && vd->vd_prev_softc != NULL) {
2657 		/*
2658 		 * No driver given: we want to downgrade to the previous
2659 		 * driver.
2660 		 */
2661 		const struct vt_driver *old_drv;
2662 		void *old_softc;
2663 
2664 		old_drv = vd->vd_driver;
2665 		old_softc = vd->vd_softc;
2666 
2667 		vd->vd_driver = vd->vd_prev_driver;
2668 		vd->vd_softc = vd->vd_prev_softc;
2669 		vd->vd_prev_driver = NULL;
2670 		vd->vd_prev_softc = NULL;
2671 
2672 		vd->vd_flags |= VDF_DOWNGRADE;
2673 
2674 		vd->vd_driver->vd_init(vd);
2675 
2676 		if (old_drv->vd_fini)
2677 			old_drv->vd_fini(vd, old_softc);
2678 
2679 		vd->vd_flags &= ~VDF_DOWNGRADE;
2680 	}
2681 
2682 	VT_UNLOCK(vd);
2683 
2684 	/* Update windows sizes and initialize last items. */
2685 	vt_upgrade(vd);
2686 
2687 #ifdef DEV_SPLASH
2688 	if (vd->vd_flags & VDF_SPLASH)
2689 		vtterm_splash(vd);
2690 #endif
2691 
2692 	if (vd->vd_flags & VDF_ASYNC) {
2693 		/* Allow to put chars now. */
2694 		terminal_mute(vd->vd_curwindow->vw_terminal, 0);
2695 		/* Rerun timer for screen updates. */
2696 		vt_resume_flush_timer(vd, 0);
2697 	}
2698 
2699 	/*
2700 	 * Register as console. If it already registered, cnadd() will ignore
2701 	 * it.
2702 	 */
2703 	termcn_cnregister(vd->vd_windows[VT_CONSWINDOW]->vw_terminal);
2704 }
2705 
2706 static void
2707 vt_suspend_handler(void *priv)
2708 {
2709 	struct vt_device *vd;
2710 
2711 	vd = priv;
2712 	if (vd->vd_driver != NULL && vd->vd_driver->vd_suspend != NULL)
2713 		vd->vd_driver->vd_suspend(vd);
2714 }
2715 
2716 static void
2717 vt_resume_handler(void *priv)
2718 {
2719 	struct vt_device *vd;
2720 
2721 	vd = priv;
2722 	if (vd->vd_driver != NULL && vd->vd_driver->vd_resume != NULL)
2723 		vd->vd_driver->vd_resume(vd);
2724 }
2725 
2726 void
2727 vt_allocate(const struct vt_driver *drv, void *softc)
2728 {
2729 
2730 	if (!vty_enabled(VTY_VT))
2731 		return;
2732 
2733 	if (main_vd->vd_driver == NULL) {
2734 		main_vd->vd_driver = drv;
2735 		printf("VT: initialize with new VT driver \"%s\".\n",
2736 		    drv->vd_name);
2737 	} else {
2738 		/*
2739 		 * Check if have rights to replace current driver. For example:
2740 		 * it is bad idea to replace KMS driver with generic VGA one.
2741 		 */
2742 		if (drv->vd_priority <= main_vd->vd_driver->vd_priority) {
2743 			printf("VT: Driver priority %d too low. Current %d\n ",
2744 			    drv->vd_priority, main_vd->vd_driver->vd_priority);
2745 			return;
2746 		}
2747 		printf("VT: Replacing driver \"%s\" with new \"%s\".\n",
2748 		    main_vd->vd_driver->vd_name, drv->vd_name);
2749 	}
2750 
2751 	vt_replace_backend(drv, softc);
2752 }
2753 
2754 void
2755 vt_deallocate(const struct vt_driver *drv, void *softc)
2756 {
2757 
2758 	if (!vty_enabled(VTY_VT))
2759 		return;
2760 
2761 	if (main_vd->vd_prev_driver == NULL ||
2762 	    main_vd->vd_driver != drv ||
2763 	    main_vd->vd_softc != softc)
2764 		return;
2765 
2766 	printf("VT: Switching back from \"%s\" to \"%s\".\n",
2767 	    main_vd->vd_driver->vd_name, main_vd->vd_prev_driver->vd_name);
2768 
2769 	vt_replace_backend(NULL, NULL);
2770 }
2771 
2772 void
2773 vt_suspend(struct vt_device *vd)
2774 {
2775 	int error;
2776 
2777 	if (vt_suspendswitch == 0)
2778 		return;
2779 	/* Save current window. */
2780 	vd->vd_savedwindow = vd->vd_curwindow;
2781 	/* Ask holding process to free window and switch to console window */
2782 	vt_proc_window_switch(vd->vd_windows[VT_CONSWINDOW]);
2783 
2784 	/* Wait for the window switch to complete. */
2785 	error = 0;
2786 	VT_LOCK(vd);
2787 	while (vd->vd_curwindow != vd->vd_windows[VT_CONSWINDOW] && error == 0)
2788 		error = cv_wait_sig(&vd->vd_winswitch, &vd->vd_lock);
2789 	VT_UNLOCK(vd);
2790 }
2791 
2792 void
2793 vt_resume(struct vt_device *vd)
2794 {
2795 
2796 	if (vt_suspendswitch == 0)
2797 		return;
2798 	/* Switch back to saved window, if any */
2799 	vt_proc_window_switch(vd->vd_savedwindow);
2800 	vd->vd_savedwindow = NULL;
2801 }
2802