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