xref: /freebsd/sys/dev/vt/vt_core.c (revision 9f31240773ae369c8285b700840a35e6bfa9f762)
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/priv.h>
49 #include <sys/proc.h>
50 #include <sys/reboot.h>
51 #include <sys/systm.h>
52 #include <sys/terminal.h>
53 
54 #include <dev/kbd/kbdreg.h>
55 #include <dev/vt/vt.h>
56 
57 #if defined(__i386__) || defined(__amd64__)
58 #include <machine/psl.h>
59 #include <machine/frame.h>
60 #endif
61 
62 static tc_bell_t	vtterm_bell;
63 static tc_cursor_t	vtterm_cursor;
64 static tc_putchar_t	vtterm_putchar;
65 static tc_fill_t	vtterm_fill;
66 static tc_copy_t	vtterm_copy;
67 static tc_param_t	vtterm_param;
68 static tc_done_t	vtterm_done;
69 
70 static tc_cnprobe_t	vtterm_cnprobe;
71 static tc_cngetc_t	vtterm_cngetc;
72 
73 static tc_opened_t	vtterm_opened;
74 static tc_ioctl_t	vtterm_ioctl;
75 static tc_mmap_t	vtterm_mmap;
76 
77 const struct terminal_class vt_termclass = {
78 	.tc_bell	= vtterm_bell,
79 	.tc_cursor	= vtterm_cursor,
80 	.tc_putchar	= vtterm_putchar,
81 	.tc_fill	= vtterm_fill,
82 	.tc_copy	= vtterm_copy,
83 	.tc_param	= vtterm_param,
84 	.tc_done	= vtterm_done,
85 
86 	.tc_cnprobe	= vtterm_cnprobe,
87 	.tc_cngetc	= vtterm_cngetc,
88 
89 	.tc_opened	= vtterm_opened,
90 	.tc_ioctl	= vtterm_ioctl,
91 	.tc_mmap	= vtterm_mmap,
92 };
93 
94 /*
95  * Use a constant timer of 25 Hz to redraw the screen.
96  *
97  * XXX: In theory we should only fire up the timer when there is really
98  * activity. Unfortunately we cannot always start timers. We really
99  * don't want to process kernel messages synchronously, because it
100  * really slows down the system.
101  */
102 #define	VT_TIMERFREQ	25
103 
104 /* Bell pitch/duration. */
105 #define VT_BELLDURATION	((5 * hz + 99) / 100)
106 #define VT_BELLPITCH	800
107 
108 #define	VT_LOCK(vd)	mtx_lock(&(vd)->vd_lock)
109 #define	VT_UNLOCK(vd)	mtx_unlock(&(vd)->vd_lock)
110 
111 #define	VT_UNIT(vw)	((vw)->vw_device->vd_unit * VT_MAXWINDOWS + \
112 			(vw)->vw_number)
113 
114 static SYSCTL_NODE(_kern, OID_AUTO, vt, CTLFLAG_RD, 0, "vt(9) parameters");
115 VT_SYSCTL_INT(enable_altgr, 1, "Enable AltGr key (Do not assume R.Alt as Alt)");
116 VT_SYSCTL_INT(debug, 0, "vt(9) debug level");
117 VT_SYSCTL_INT(deadtimer, 15, "Time to wait busy process in VT_PROCESS mode");
118 VT_SYSCTL_INT(suspendswitch, 1, "Switch to VT0 before suspend");
119 VT_SYSCTL_INT(spclkeys, (VT_DEBUG_KEY_ENABLED|VT_REBOOT_KEY_ENABLED|
120     VT_HALT_KEY_ENABLED|VT_POWEROFF_KEY_ENABLED), "Enabled special keys "
121     "handled by vt(4)");
122 
123 static struct vt_device	vt_consdev;
124 static unsigned int vt_unit = 0;
125 static MALLOC_DEFINE(M_VT, "vt", "vt device");
126 struct vt_device *main_vd = &vt_consdev;
127 
128 /* Boot logo. */
129 extern unsigned int vt_logo_width;
130 extern unsigned int vt_logo_height;
131 extern unsigned int vt_logo_depth;
132 extern unsigned char vt_logo_image[];
133 
134 /* Font. */
135 extern struct vt_font vt_font_default;
136 #ifndef SC_NO_CUTPASTE
137 extern struct mouse_cursor vt_default_mouse_pointer;
138 #endif
139 
140 static int signal_vt_rel(struct vt_window *);
141 static int signal_vt_acq(struct vt_window *);
142 static int finish_vt_rel(struct vt_window *, int, int *);
143 static int finish_vt_acq(struct vt_window *);
144 static int vt_window_switch(struct vt_window *);
145 static int vt_late_window_switch(struct vt_window *);
146 static int vt_proc_alive(struct vt_window *);
147 static void vt_resize(struct vt_device *);
148 static void vt_update_static(void *);
149 
150 SET_DECLARE(vt_drv_set, struct vt_driver);
151 
152 #define _VTDEFH MAX(100, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT))
153 #define _VTDEFW MAX(200, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH))
154 
155 static struct terminal	vt_consterm;
156 static struct vt_window	vt_conswindow;
157 static struct vt_device	vt_consdev = {
158 	.vd_driver = NULL,
159 	.vd_softc = NULL,
160 	.vd_flags = VDF_INVALID,
161 	.vd_windows = { [VT_CONSWINDOW] =  &vt_conswindow, },
162 	.vd_curwindow = &vt_conswindow,
163 	.vd_markedwin = NULL,
164 	.vd_kbstate = 0,
165 };
166 static term_char_t vt_constextbuf[(_VTDEFW) * (VBF_DEFAULT_HISTORY_SIZE)];
167 static term_char_t *vt_constextbufrows[VBF_DEFAULT_HISTORY_SIZE];
168 static struct vt_window	vt_conswindow = {
169 	.vw_number = VT_CONSWINDOW,
170 	.vw_flags = VWF_CONSOLE,
171 	.vw_buf = {
172 		.vb_buffer = &vt_constextbuf[0],
173 		.vb_rows = &vt_constextbufrows[0],
174 		.vb_history_size = VBF_DEFAULT_HISTORY_SIZE,
175 		.vb_curroffset = 0,
176 		.vb_roffset = 0,
177 		.vb_flags = VBF_STATIC,
178 		.vb_mark_start = {.tp_row = 0, .tp_col = 0,},
179 		.vb_mark_end = {.tp_row = 0, .tp_col = 0,},
180 		.vb_scr_size = {
181 			.tp_row = _VTDEFH,
182 			.tp_col = _VTDEFW,
183 		},
184 	},
185 	.vw_device = &vt_consdev,
186 	.vw_terminal = &vt_consterm,
187 	.vw_kbdmode = K_XLATE,
188 };
189 static struct terminal vt_consterm = {
190 	.tm_class = &vt_termclass,
191 	.tm_softc = &vt_conswindow,
192 	.tm_flags = TF_CONS,
193 };
194 static struct consdev vt_consterm_consdev = {
195 	.cn_ops = &termcn_cnops,
196 	.cn_arg = &vt_consterm,
197 	.cn_name = "ttyv0",
198 };
199 
200 /* Add to set of consoles. */
201 DATA_SET(cons_set, vt_consterm_consdev);
202 
203 /*
204  * Right after kmem is done to allow early drivers to use locking and allocate
205  * memory.
206  */
207 SYSINIT(vt_update_static, SI_SUB_KMEM, SI_ORDER_ANY, vt_update_static,
208     &vt_consdev);
209 /* Delay until all devices attached, to not waste time. */
210 SYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, vt_upgrade,
211     &vt_consdev);
212 
213 /* Initialize locks/mem depended members. */
214 static void
215 vt_update_static(void *dummy)
216 {
217 
218 	if (!vty_enabled(VTY_VT))
219 		return;
220 	if (main_vd->vd_driver != NULL)
221 		printf("VT: running with driver \"%s\".\n",
222 		    main_vd->vd_driver->vd_name);
223 	else
224 		printf("VT: init without driver.\n");
225 
226 	mtx_init(&main_vd->vd_lock, "vtdev", NULL, MTX_DEF);
227 	cv_init(&main_vd->vd_winswitch, "vtwswt");
228 }
229 
230 static void
231 vt_switch_timer(void *arg)
232 {
233 
234 	vt_late_window_switch((struct vt_window *)arg);
235 }
236 
237 static int
238 vt_window_preswitch(struct vt_window *vw, struct vt_window *curvw)
239 {
240 
241 	DPRINTF(40, "%s\n", __func__);
242 	curvw->vw_switch_to = vw;
243 	/* Set timer to allow switch in case when process hang. */
244 	callout_reset(&vw->vw_proc_dead_timer, hz * vt_deadtimer,
245 	    vt_switch_timer, (void *)vw);
246 	/* Notify process about vt switch attempt. */
247 	DPRINTF(30, "%s: Notify process.\n", __func__);
248 	signal_vt_rel(curvw);
249 
250 	return (0);
251 }
252 
253 static int
254 vt_window_postswitch(struct vt_window *vw)
255 {
256 
257 	signal_vt_acq(vw);
258 	return (0);
259 }
260 
261 /* vt_late_window_switch will done VT switching for regular case. */
262 static int
263 vt_late_window_switch(struct vt_window *vw)
264 {
265 	int ret;
266 
267 	callout_stop(&vw->vw_proc_dead_timer);
268 
269 	ret = vt_window_switch(vw);
270 	if (ret)
271 		return (ret);
272 
273 	/* Notify owner process about terminal availability. */
274 	if (vw->vw_smode.mode == VT_PROCESS) {
275 		ret = vt_window_postswitch(vw);
276 	}
277 	return (ret);
278 }
279 
280 /* Switch window. */
281 static int
282 vt_proc_window_switch(struct vt_window *vw)
283 {
284 	struct vt_window *curvw;
285 	struct vt_device *vd;
286 	int ret;
287 
288 	vd = vw->vw_device;
289 	curvw = vd->vd_curwindow;
290 
291 	if (curvw->vw_flags & VWF_VTYLOCK)
292 		return (EBUSY);
293 
294 	/* Ask current process permitions to switch away. */
295 	if (curvw->vw_smode.mode == VT_PROCESS) {
296 		DPRINTF(30, "%s: VT_PROCESS ", __func__);
297 		if (vt_proc_alive(curvw) == FALSE) {
298 			DPRINTF(30, "Dead. Cleaning.");
299 			/* Dead */
300 		} else {
301 			DPRINTF(30, "%s: Signaling process.\n", __func__);
302 			/* Alive, try to ask him. */
303 			ret = vt_window_preswitch(vw, curvw);
304 			/* Wait for process answer or timeout. */
305 			return (ret);
306 		}
307 		DPRINTF(30, "\n");
308 	}
309 
310 	ret = vt_late_window_switch(vw);
311 	return (ret);
312 }
313 
314 /* Switch window ignoring process locking. */
315 static int
316 vt_window_switch(struct vt_window *vw)
317 {
318 	struct vt_device *vd = vw->vw_device;
319 	struct vt_window *curvw = vd->vd_curwindow;
320 	keyboard_t *kbd;
321 
322 	VT_LOCK(vd);
323 	if (curvw == vw) {
324 		/* Nothing to do. */
325 		VT_UNLOCK(vd);
326 		return (0);
327 	}
328 	if (!(vw->vw_flags & (VWF_OPENED|VWF_CONSOLE))) {
329 		VT_UNLOCK(vd);
330 		return (EINVAL);
331 	}
332 
333 	vd->vd_curwindow = vw;
334 	vd->vd_flags |= VDF_INVALID;
335 	cv_broadcast(&vd->vd_winswitch);
336 	VT_UNLOCK(vd);
337 
338 	if (vd->vd_driver->vd_postswitch)
339 		vd->vd_driver->vd_postswitch(vd);
340 
341 	/* Restore per-window keyboard mode. */
342 	mtx_lock(&Giant);
343 	kbd = kbd_get_keyboard(vd->vd_keyboard);
344 	if (kbd != NULL) {
345 		kbdd_ioctl(kbd, KDSKBMODE, (void *)&vw->vw_kbdmode);
346 	}
347 	mtx_unlock(&Giant);
348 	DPRINTF(10, "%s(ttyv%d) done\n", __func__, vw->vw_number);
349 
350 	return (0);
351 }
352 
353 static inline void
354 vt_termsize(struct vt_device *vd, struct vt_font *vf, term_pos_t *size)
355 {
356 
357 	size->tp_row = vd->vd_height;
358 	size->tp_col = vd->vd_width;
359 	if (vf != NULL) {
360 		size->tp_row /= vf->vf_height;
361 		size->tp_col /= vf->vf_width;
362 	}
363 }
364 
365 static inline void
366 vt_winsize(struct vt_device *vd, struct vt_font *vf, struct winsize *size)
367 {
368 
369 	size->ws_row = size->ws_ypixel = vd->vd_height;
370 	size->ws_col = size->ws_xpixel = vd->vd_width;
371 	if (vf != NULL) {
372 		size->ws_row /= vf->vf_height;
373 		size->ws_col /= vf->vf_width;
374 	}
375 }
376 
377 static void
378 vt_scroll(struct vt_window *vw, int offset, int whence)
379 {
380 	int diff;
381 	term_pos_t size;
382 
383 	if ((vw->vw_flags & VWF_SCROLL) == 0)
384 		return;
385 
386 	vt_termsize(vw->vw_device, vw->vw_font, &size);
387 
388 	diff = vthistory_seek(&vw->vw_buf, offset, whence);
389 	/*
390 	 * Offset changed, please update Nth lines on sceen.
391 	 * +N - Nth lines at top;
392 	 * -N - Nth lines at bottom.
393 	 */
394 
395 	if (diff < -size.tp_row || diff > size.tp_row) {
396 		vw->vw_device->vd_flags |= VDF_INVALID;
397 		return;
398 	}
399 	vw->vw_device->vd_flags |= VDF_INVALID; /*XXX*/
400 }
401 
402 static int
403 vt_machine_kbdevent(int c)
404 {
405 
406 	switch (c) {
407 	case SPCLKEY | DBG:
408 		if (vt_spclkeys & VT_DEBUG_KEY_ENABLED)
409 			kdb_enter(KDB_WHY_BREAK, "manual escape to debugger");
410 		return (1);
411 	case SPCLKEY | RBT:
412 		if (vt_spclkeys & VT_REBOOT_KEY_ENABLED)
413 			/* XXX: Make this configurable! */
414 			shutdown_nice(0);
415 		return (1);
416 	case SPCLKEY | HALT:
417 		if (vt_spclkeys & VT_HALT_KEY_ENABLED)
418 			shutdown_nice(RB_HALT);
419 		return (1);
420 	case SPCLKEY | PDWN:
421 		if (vt_spclkeys & VT_POWEROFF_KEY_ENABLED)
422 			shutdown_nice(RB_HALT|RB_POWEROFF);
423 		return (1);
424 	};
425 
426 	return (0);
427 }
428 
429 static void
430 vt_scrollmode_kbdevent(struct vt_window *vw, int c, int console)
431 {
432 	struct vt_device *vd;
433 	term_pos_t size;
434 
435 	vd = vw->vw_device;
436 	/* Only special keys handled in ScrollLock mode */
437 	if ((c & SPCLKEY) == 0)
438 		return;
439 
440 	c &= ~SPCLKEY;
441 
442 	if (console == 0) {
443 		if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
444 			vw = vd->vd_windows[c - F_SCR];
445 			if (vw != NULL)
446 				vt_proc_window_switch(vw);
447 			return;
448 		}
449 		VT_LOCK(vd);
450 	}
451 
452 	switch (c) {
453 	case SLK: {
454 		/* Turn scrolling off. */
455 		vt_scroll(vw, 0, VHS_END);
456 		VTBUF_SLCK_DISABLE(&vw->vw_buf);
457 		vw->vw_flags &= ~VWF_SCROLL;
458 		break;
459 	}
460 	case FKEY | F(49): /* Home key. */
461 		vt_scroll(vw, 0, VHS_SET);
462 		break;
463 	case FKEY | F(50): /* Arrow up. */
464 		vt_scroll(vw, -1, VHS_CUR);
465 		break;
466 	case FKEY | F(51): /* Page up. */
467 		vt_termsize(vd, vw->vw_font, &size);
468 		vt_scroll(vw, -size.tp_row, VHS_CUR);
469 		break;
470 	case FKEY | F(57): /* End key. */
471 		vt_scroll(vw, 0, VHS_END);
472 		break;
473 	case FKEY | F(58): /* Arrow down. */
474 		vt_scroll(vw, 1, VHS_CUR);
475 		break;
476 	case FKEY | F(59): /* Page down. */
477 		vt_termsize(vd, vw->vw_font, &size);
478 		vt_scroll(vw, size.tp_row, VHS_CUR);
479 		break;
480 	}
481 
482 	if (console == 0)
483 		VT_UNLOCK(vd);
484 }
485 
486 static int
487 vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
488 {
489 	struct vt_window *vw = vd->vd_curwindow;
490 	int state = 0;
491 
492 #if VT_ALT_TO_ESC_HACK
493 	if (c & RELKEY) {
494 		switch (c & ~RELKEY) {
495 		case (SPCLKEY | RALT):
496 			if (vt_enable_altgr != 0)
497 				break;
498 		case (SPCLKEY | LALT):
499 			vd->vd_kbstate &= ~ALKED;
500 		}
501 		/* Other keys ignored for RELKEY event. */
502 		return (0);
503 	} else {
504 		switch (c & ~RELKEY) {
505 		case (SPCLKEY | RALT):
506 			if (vt_enable_altgr != 0)
507 				break;
508 		case (SPCLKEY | LALT):
509 			vd->vd_kbstate |= ALKED;
510 		}
511 	}
512 #else
513 	if (c & RELKEY)
514 		/* Other keys ignored for RELKEY event. */
515 		return (0);
516 #endif
517 
518 	if (vt_machine_kbdevent(c))
519 		return (0);
520 
521 	if (vw->vw_flags & VWF_SCROLL) {
522 		vt_scrollmode_kbdevent(vw, c, 0/* Not a console */);
523 		/* Scroll mode keys handled, nothing to do more. */
524 		return (0);
525 	}
526 
527 	if (c & SPCLKEY) {
528 		c &= ~SPCLKEY;
529 
530 		if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
531 			vw = vd->vd_windows[c - F_SCR];
532 			if (vw != NULL)
533 				vt_proc_window_switch(vw);
534 			return (0);
535 		}
536 
537 		switch (c) {
538 		case SLK: {
539 
540 			kbdd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state);
541 			VT_LOCK(vd);
542 			if (state & SLKED) {
543 				/* Turn scrolling on. */
544 				vw->vw_flags |= VWF_SCROLL;
545 				VTBUF_SLCK_ENABLE(&vw->vw_buf);
546 			} else {
547 				/* Turn scrolling off. */
548 				vw->vw_flags &= ~VWF_SCROLL;
549 				VTBUF_SLCK_DISABLE(&vw->vw_buf);
550 				vt_scroll(vw, 0, VHS_END);
551 			}
552 			VT_UNLOCK(vd);
553 			break;
554 		}
555 		case FKEY | F(1):  case FKEY | F(2):  case FKEY | F(3):
556 		case FKEY | F(4):  case FKEY | F(5):  case FKEY | F(6):
557 		case FKEY | F(7):  case FKEY | F(8):  case FKEY | F(9):
558 		case FKEY | F(10): case FKEY | F(11): case FKEY | F(12):
559 			/* F1 through F12 keys. */
560 			terminal_input_special(vw->vw_terminal,
561 			    TKEY_F1 + c - (FKEY | F(1)));
562 			break;
563 		case FKEY | F(49): /* Home key. */
564 			terminal_input_special(vw->vw_terminal, TKEY_HOME);
565 			break;
566 		case FKEY | F(50): /* Arrow up. */
567 			terminal_input_special(vw->vw_terminal, TKEY_UP);
568 			break;
569 		case FKEY | F(51): /* Page up. */
570 			terminal_input_special(vw->vw_terminal, TKEY_PAGE_UP);
571 			break;
572 		case FKEY | F(53): /* Arrow left. */
573 			terminal_input_special(vw->vw_terminal, TKEY_LEFT);
574 			break;
575 		case FKEY | F(55): /* Arrow right. */
576 			terminal_input_special(vw->vw_terminal, TKEY_RIGHT);
577 			break;
578 		case FKEY | F(57): /* End key. */
579 			terminal_input_special(vw->vw_terminal, TKEY_END);
580 			break;
581 		case FKEY | F(58): /* Arrow down. */
582 			terminal_input_special(vw->vw_terminal, TKEY_DOWN);
583 			break;
584 		case FKEY | F(59): /* Page down. */
585 			terminal_input_special(vw->vw_terminal, TKEY_PAGE_DOWN);
586 			break;
587 		case FKEY | F(60): /* Insert key. */
588 			terminal_input_special(vw->vw_terminal, TKEY_INSERT);
589 			break;
590 		case FKEY | F(61): /* Delete key. */
591 			terminal_input_special(vw->vw_terminal, TKEY_DELETE);
592 			break;
593 		}
594 	} else if (KEYFLAGS(c) == 0) {
595 		/* Don't do UTF-8 conversion when doing raw mode. */
596 		if (vw->vw_kbdmode == K_XLATE) {
597 #if VT_ALT_TO_ESC_HACK
598 			if (vd->vd_kbstate & ALKED) {
599 				/*
600 				 * Prepend ESC sequence if one of ALT keys down.
601 				 */
602 				terminal_input_char(vw->vw_terminal, 0x1b);
603 			}
604 #endif
605 
606 			terminal_input_char(vw->vw_terminal, KEYCHAR(c));
607 		} else
608 			terminal_input_raw(vw->vw_terminal, c);
609 	}
610 	return (0);
611 }
612 
613 static int
614 vt_kbdevent(keyboard_t *kbd, int event, void *arg)
615 {
616 	struct vt_device *vd = arg;
617 	int c;
618 
619 	switch (event) {
620 	case KBDIO_KEYINPUT:
621 		break;
622 	case KBDIO_UNLOADING:
623 		mtx_lock(&Giant);
624 		vd->vd_keyboard = -1;
625 		kbd_release(kbd, (void *)vd);
626 		mtx_unlock(&Giant);
627 		return (0);
628 	default:
629 		return (EINVAL);
630 	}
631 
632 	while ((c = kbdd_read_char(kbd, 0)) != NOKEY)
633 		vt_processkey(kbd, vd, c);
634 
635 	return (0);
636 }
637 
638 static int
639 vt_allocate_keyboard(struct vt_device *vd)
640 {
641 	int		 idx0, idx;
642 	keyboard_t	*k0, *k;
643 	keyboard_info_t	 ki;
644 
645 	idx0 = kbd_allocate("kbdmux", -1, vd, vt_kbdevent, vd);
646 	vd->vd_keyboard = idx0;
647 	if (idx0 >= 0) {
648 		DPRINTF(20, "%s: kbdmux allocated, idx = %d\n", __func__, idx0);
649 		k0 = kbd_get_keyboard(idx0);
650 
651 		for (idx = kbd_find_keyboard2("*", -1, 0);
652 		     idx != -1;
653 		     idx = kbd_find_keyboard2("*", -1, idx + 1)) {
654 			k = kbd_get_keyboard(idx);
655 
656 			if (idx == idx0 || KBD_IS_BUSY(k))
657 				continue;
658 
659 			bzero(&ki, sizeof(ki));
660 			strcpy(ki.kb_name, k->kb_name);
661 			ki.kb_unit = k->kb_unit;
662 
663 			kbdd_ioctl(k0, KBADDKBD, (caddr_t) &ki);
664 		}
665 	} else {
666 		DPRINTF(20, "%s: no kbdmux allocated\n", __func__);
667 		idx0 = kbd_allocate("*", -1, vd, vt_kbdevent, vd);
668 		if (idx0 < 0) {
669 			DPRINTF(10, "%s: No keyboard found.\n", __func__);
670 			return (-1);
671 		}
672 	}
673 	DPRINTF(20, "%s: vd_keyboard = %d\n", __func__, vd->vd_keyboard);
674 
675 	return (idx0);
676 }
677 
678 static void
679 vtterm_bell(struct terminal *tm)
680 {
681 	struct vt_window *vw = tm->tm_softc;
682 	struct vt_device *vd = vw->vw_device;
683 
684 	if (vd->vd_flags & VDF_QUIET_BELL)
685 		return;
686 
687 	sysbeep(1193182 / VT_BELLPITCH, VT_BELLDURATION);
688 }
689 
690 static void
691 vtterm_beep(struct terminal *tm, u_int param)
692 {
693 	u_int freq, period;
694 
695 	if ((param == 0) || ((param & 0xffff) == 0)) {
696 		vtterm_bell(tm);
697 		return;
698 	}
699 
700 	period = ((param >> 16) & 0xffff) * hz / 1000;
701 	freq = 1193182 / (param & 0xffff);
702 
703 	sysbeep(freq, period);
704 }
705 
706 static void
707 vtterm_cursor(struct terminal *tm, const term_pos_t *p)
708 {
709 	struct vt_window *vw = tm->tm_softc;
710 
711 	vtbuf_cursor_position(&vw->vw_buf, p);
712 }
713 
714 static void
715 vtterm_putchar(struct terminal *tm, const term_pos_t *p, term_char_t c)
716 {
717 	struct vt_window *vw = tm->tm_softc;
718 
719 	vtbuf_putchar(&vw->vw_buf, p, c);
720 }
721 
722 static void
723 vtterm_fill(struct terminal *tm, const term_rect_t *r, term_char_t c)
724 {
725 	struct vt_window *vw = tm->tm_softc;
726 
727 	vtbuf_fill_locked(&vw->vw_buf, r, c);
728 }
729 
730 static void
731 vtterm_copy(struct terminal *tm, const term_rect_t *r,
732     const term_pos_t *p)
733 {
734 	struct vt_window *vw = tm->tm_softc;
735 
736 	vtbuf_copy(&vw->vw_buf, r, p);
737 }
738 
739 static void
740 vtterm_param(struct terminal *tm, int cmd, unsigned int arg)
741 {
742 	struct vt_window *vw = tm->tm_softc;
743 
744 	switch (cmd) {
745 	case TP_SHOWCURSOR:
746 		vtbuf_cursor_visibility(&vw->vw_buf, arg);
747 		break;
748 	case TP_MOUSE:
749 		vw->vw_mouse_level = arg;
750 		break;
751 	}
752 }
753 
754 static inline void
755 vt_determine_colors(term_char_t c, int cursor,
756     term_color_t *fg, term_color_t *bg)
757 {
758 	term_color_t tmp;
759 	int invert;
760 
761 	invert = 0;
762 
763 	*fg = TCHAR_FGCOLOR(c);
764 	if (TCHAR_FORMAT(c) & TF_BOLD)
765 		*fg = TCOLOR_LIGHT(*fg);
766 	*bg = TCHAR_BGCOLOR(c);
767 
768 	if (TCHAR_FORMAT(c) & TF_REVERSE)
769 		invert ^= 1;
770 	if (cursor)
771 		invert ^= 1;
772 
773 	if (invert) {
774 		tmp = *fg;
775 		*fg = *bg;
776 		*bg = tmp;
777 	}
778 }
779 
780 static void
781 vt_bitblt_char(struct vt_device *vd, struct vt_font *vf, term_char_t c,
782     int iscursor, unsigned int row, unsigned int col)
783 {
784 	term_color_t fg, bg;
785 
786 	vt_determine_colors(c, iscursor, &fg, &bg);
787 
788 	if (vf != NULL) {
789 		const uint8_t *src;
790 		vt_axis_t top, left;
791 
792 		src = vtfont_lookup(vf, c);
793 
794 		/*
795 		 * Align the terminal to the centre of the screen.
796 		 * Fonts may not always be able to fill the entire
797 		 * screen.
798 		 */
799 		top = row * vf->vf_height + vd->vd_offset.tp_row;
800 		left = col * vf->vf_width + vd->vd_offset.tp_col;
801 
802 		vd->vd_driver->vd_bitbltchr(vd, src, NULL, 0, top, left,
803 		    vf->vf_width, vf->vf_height, fg, bg);
804 	} else {
805 		vd->vd_driver->vd_putchar(vd, TCHAR_CHARACTER(c),
806 		    row, col, fg, bg);
807 	}
808 }
809 
810 static void
811 vt_flush(struct vt_device *vd)
812 {
813 	struct vt_window *vw;
814 	struct vt_font *vf;
815 	struct vt_bufmask tmask;
816 	unsigned int row, col;
817 	term_rect_t tarea;
818 	term_pos_t size;
819 	term_char_t *r;
820 #ifndef SC_NO_CUTPASTE
821 	struct mouse_cursor *m;
822 	int bpl, h, w;
823 #endif
824 
825 	vw = vd->vd_curwindow;
826 	if (vw == NULL)
827 		return;
828 	vf = vw->vw_font;
829 	if (((vd->vd_flags & VDF_TEXTMODE) == 0) && (vf == NULL))
830 		return;
831 
832 	if (vd->vd_flags & VDF_SPLASH || vw->vw_flags & VWF_BUSY)
833 		return;
834 
835 	vtbuf_undirty(&vw->vw_buf, &tarea, &tmask);
836 	vt_termsize(vd, vf, &size);
837 
838 	/* Force a full redraw when the screen contents are invalid. */
839 	if (vd->vd_flags & VDF_INVALID) {
840 		tarea.tr_begin.tp_row = tarea.tr_begin.tp_col = 0;
841 		tarea.tr_end = size;
842 		tmask.vbm_row = tmask.vbm_col = VBM_DIRTY;
843 
844 		vd->vd_flags &= ~VDF_INVALID;
845 	}
846 
847 #ifndef SC_NO_CUTPASTE
848 	if ((vw->vw_flags & VWF_MOUSE_HIDE) == 0) {
849 		/* Mark last mouse position as dirty to erase. */
850 		vtbuf_mouse_cursor_position(&vw->vw_buf, vd->vd_mdirtyx,
851 		    vd->vd_mdirtyy);
852 	}
853 #endif
854 
855 	for (row = tarea.tr_begin.tp_row; row < tarea.tr_end.tp_row; row++) {
856 		if (!VTBUF_DIRTYROW(&tmask, row))
857 			continue;
858 		r = VTBUF_GET_ROW(&vw->vw_buf, row);
859 		for (col = tarea.tr_begin.tp_col;
860 		    col < tarea.tr_end.tp_col; col++) {
861 			if (!VTBUF_DIRTYCOL(&tmask, col))
862 				continue;
863 
864 			vt_bitblt_char(vd, vf, r[col],
865 			    VTBUF_ISCURSOR(&vw->vw_buf, row, col), row, col);
866 		}
867 	}
868 
869 #ifndef SC_NO_CUTPASTE
870 	/* Mouse disabled. */
871 	if (vw->vw_flags & VWF_MOUSE_HIDE)
872 		return;
873 
874 	/* No mouse for DDB. */
875 	if (kdb_active || panicstr != NULL)
876 		return;
877 
878 	if ((vd->vd_flags & (VDF_MOUSECURSOR|VDF_TEXTMODE)) ==
879 	    VDF_MOUSECURSOR) {
880 		m = &vt_default_mouse_pointer;
881 		bpl = (m->w + 7) >> 3; /* Bytes per source line. */
882 		w = m->w;
883 		h = m->h;
884 
885 		if ((vd->vd_mx + m->w) > (size.tp_col * vf->vf_width))
886 			w = (size.tp_col * vf->vf_width) - vd->vd_mx - 1;
887 		if ((vd->vd_my + m->h) > (size.tp_row * vf->vf_height))
888 			h = (size.tp_row * vf->vf_height) - vd->vd_my - 1;
889 
890 		vd->vd_driver->vd_bitbltchr(vd, m->map, m->mask, bpl,
891 		    vd->vd_offset.tp_row + vd->vd_my,
892 		    vd->vd_offset.tp_col + vd->vd_mx,
893 		    w, h, TC_WHITE, TC_BLACK);
894 		/* Save point of last mouse cursor to erase it later. */
895 		vd->vd_mdirtyx = vd->vd_mx / vf->vf_width;
896 		vd->vd_mdirtyy = vd->vd_my / vf->vf_height;
897 	}
898 #endif
899 }
900 
901 static void
902 vt_timer(void *arg)
903 {
904 	struct vt_device *vd;
905 
906 	vd = arg;
907 	/* Update screen if required. */
908 	vt_flush(vd);
909 
910 	/* Schedule for next update. */
911 	callout_schedule(&vd->vd_timer, hz / VT_TIMERFREQ);
912 }
913 
914 static void
915 vtterm_done(struct terminal *tm)
916 {
917 	struct vt_window *vw = tm->tm_softc;
918 	struct vt_device *vd = vw->vw_device;
919 
920 	if (kdb_active || panicstr != NULL) {
921 		/* Switch to the debugger. */
922 		if (vd->vd_curwindow != vw) {
923 			vd->vd_curwindow = vw;
924 			vd->vd_flags |= VDF_INVALID;
925 			if (vd->vd_driver->vd_postswitch)
926 				vd->vd_driver->vd_postswitch(vd);
927 		}
928 		vd->vd_flags &= ~VDF_SPLASH;
929 		vt_flush(vd);
930 	} else if (!(vd->vd_flags & VDF_ASYNC)) {
931 		vt_flush(vd);
932 	}
933 }
934 
935 #ifdef DEV_SPLASH
936 static void
937 vtterm_splash(struct vt_device *vd)
938 {
939 	vt_axis_t top, left;
940 
941 	/* Display a nice boot splash. */
942 	if (!(vd->vd_flags & VDF_TEXTMODE) && (boothowto & RB_MUTE)) {
943 
944 		top = (vd->vd_height - vt_logo_height) / 2;
945 		left = (vd->vd_width - vt_logo_width) / 2;
946 		switch (vt_logo_depth) {
947 		case 1:
948 			/* XXX: Unhardcode colors! */
949 			vd->vd_driver->vd_bitbltchr(vd, vt_logo_image, NULL, 0,
950 			    top, left, vt_logo_width, vt_logo_height, 0xf, 0x0);
951 		}
952 		vd->vd_flags |= VDF_SPLASH;
953 	}
954 }
955 #endif
956 
957 
958 static void
959 vtterm_cnprobe(struct terminal *tm, struct consdev *cp)
960 {
961 	struct vt_driver *vtd, **vtdlist, *vtdbest = NULL;
962 	struct vt_window *vw = tm->tm_softc;
963 	struct vt_device *vd = vw->vw_device;
964 	struct winsize wsz;
965 	term_attr_t attr;
966 	term_char_t c;
967 
968 	if (!vty_enabled(VTY_VT))
969 		return;
970 
971 	if (vd->vd_flags & VDF_INITIALIZED)
972 		/* Initialization already done. */
973 		return;
974 
975 	SET_FOREACH(vtdlist, vt_drv_set) {
976 		vtd = *vtdlist;
977 		if (vtd->vd_probe == NULL)
978 			continue;
979 		if (vtd->vd_probe(vd) == CN_DEAD)
980 			continue;
981 		if ((vtdbest == NULL) ||
982 		    (vtd->vd_priority > vtdbest->vd_priority))
983 			vtdbest = vtd;
984 	}
985 	if (vtdbest == NULL) {
986 		cp->cn_pri = CN_DEAD;
987 		vd->vd_flags |= VDF_DEAD;
988 	} else {
989 		vd->vd_driver = vtdbest;
990 		cp->cn_pri = vd->vd_driver->vd_init(vd);
991 	}
992 
993 	/* Check if driver's vt_init return CN_DEAD. */
994 	if (cp->cn_pri == CN_DEAD) {
995 		vd->vd_flags |= VDF_DEAD;
996 	}
997 
998 	/* Initialize any early-boot keyboard drivers */
999 	kbd_configure(KB_CONF_PROBE_ONLY);
1000 
1001 	vd->vd_unit = atomic_fetchadd_int(&vt_unit, 1);
1002 	vd->vd_windows[VT_CONSWINDOW] = vw;
1003 	sprintf(cp->cn_name, "ttyv%r", VT_UNIT(vw));
1004 
1005 	/* Attach default font if not in TEXTMODE. */
1006 	if ((vd->vd_flags & VDF_TEXTMODE) == 0)
1007 		vw->vw_font = vtfont_ref(&vt_font_default);
1008 
1009 	vtbuf_init_early(&vw->vw_buf);
1010 	vt_winsize(vd, vw->vw_font, &wsz);
1011 	c = (boothowto & RB_MUTE) == 0 ? TERMINAL_KERN_ATTR :
1012 	    TERMINAL_NORM_ATTR;
1013 	attr.ta_format = TCHAR_FORMAT(c);
1014 	attr.ta_fgcolor = TCHAR_FGCOLOR(c);
1015 	attr.ta_bgcolor = TCHAR_BGCOLOR(c);
1016 	terminal_set_winsize_blank(tm, &wsz, 1, &attr);
1017 
1018 	if (vtdbest != NULL) {
1019 #ifdef DEV_SPLASH
1020 		vtterm_splash(vd);
1021 #endif
1022 		vd->vd_flags |= VDF_INITIALIZED;
1023 	}
1024 }
1025 
1026 static int
1027 vtterm_cngetc(struct terminal *tm)
1028 {
1029 	struct vt_window *vw = tm->tm_softc;
1030 	struct vt_device *vd = vw->vw_device;
1031 	keyboard_t *kbd;
1032 	int state;
1033 	u_int c;
1034 
1035 	if (vw->vw_kbdsq && *vw->vw_kbdsq)
1036 		return (*vw->vw_kbdsq++);
1037 
1038 	state = 0;
1039 	/* Make sure the splash screen is not there. */
1040 	if (vd->vd_flags & VDF_SPLASH) {
1041 		/* Remove splash */
1042 		vd->vd_flags &= ~VDF_SPLASH;
1043 		/* Mark screen as invalid to force update */
1044 		vd->vd_flags |= VDF_INVALID;
1045 		vt_flush(vd);
1046 	}
1047 
1048 	/* Stripped down keyboard handler. */
1049 	kbd = kbd_get_keyboard(vd->vd_keyboard);
1050 	if (kbd == NULL)
1051 		return (-1);
1052 
1053 	/* Force keyboard input mode to K_XLATE */
1054 	c = K_XLATE;
1055 	kbdd_ioctl(kbd, KDSKBMODE, (void *)&c);
1056 
1057 	/* Switch the keyboard to polling to make it work here. */
1058 	kbdd_poll(kbd, TRUE);
1059 	c = kbdd_read_char(kbd, 0);
1060 	kbdd_poll(kbd, FALSE);
1061 	if (c & RELKEY)
1062 		return (-1);
1063 
1064 	if (vw->vw_flags & VWF_SCROLL) {
1065 		vt_scrollmode_kbdevent(vw, c, 1/* Console mode */);
1066 		vt_flush(vd);
1067 		return (-1);
1068 	}
1069 
1070 	/* Stripped down handling of vt_kbdevent(), without locking, etc. */
1071 	if (c & SPCLKEY) {
1072 		switch (c) {
1073 		case SPCLKEY | SLK:
1074 			kbdd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state);
1075 			if (state & SLKED) {
1076 				/* Turn scrolling on. */
1077 				vw->vw_flags |= VWF_SCROLL;
1078 				VTBUF_SLCK_ENABLE(&vw->vw_buf);
1079 			} else {
1080 				/* Turn scrolling off. */
1081 				vt_scroll(vw, 0, VHS_END);
1082 				vw->vw_flags &= ~VWF_SCROLL;
1083 				VTBUF_SLCK_DISABLE(&vw->vw_buf);
1084 			}
1085 			break;
1086 		/* XXX: KDB can handle history. */
1087 		case SPCLKEY | FKEY | F(50): /* Arrow up. */
1088 			vw->vw_kbdsq = "\x1b[A";
1089 			break;
1090 		case SPCLKEY | FKEY | F(58): /* Arrow down. */
1091 			vw->vw_kbdsq = "\x1b[B";
1092 			break;
1093 		case SPCLKEY | FKEY | F(55): /* Arrow right. */
1094 			vw->vw_kbdsq = "\x1b[C";
1095 			break;
1096 		case SPCLKEY | FKEY | F(53): /* Arrow left. */
1097 			vw->vw_kbdsq = "\x1b[D";
1098 			break;
1099 		}
1100 
1101 		/* Force refresh to make scrollback work. */
1102 		vt_flush(vd);
1103 	} else if (KEYFLAGS(c) == 0) {
1104 		return (KEYCHAR(c));
1105 	}
1106 
1107 	if (vw->vw_kbdsq && *vw->vw_kbdsq)
1108 		return (*vw->vw_kbdsq++);
1109 
1110 	return (-1);
1111 }
1112 
1113 static void
1114 vtterm_opened(struct terminal *tm, int opened)
1115 {
1116 	struct vt_window *vw = tm->tm_softc;
1117 	struct vt_device *vd = vw->vw_device;
1118 
1119 	VT_LOCK(vd);
1120 	vd->vd_flags &= ~VDF_SPLASH;
1121 	if (opened)
1122 		vw->vw_flags |= VWF_OPENED;
1123 	else {
1124 		vw->vw_flags &= ~VWF_OPENED;
1125 		/* TODO: finish ACQ/REL */
1126 	}
1127 	VT_UNLOCK(vd);
1128 }
1129 
1130 static int
1131 vt_change_font(struct vt_window *vw, struct vt_font *vf)
1132 {
1133 	struct vt_device *vd = vw->vw_device;
1134 	struct terminal *tm = vw->vw_terminal;
1135 	term_pos_t size;
1136 	struct winsize wsz;
1137 
1138 	/*
1139 	 * Changing fonts.
1140 	 *
1141 	 * Changing fonts is a little tricky.  We must prevent
1142 	 * simultaneous access to the device, so we must stop
1143 	 * the display timer and the terminal from accessing.
1144 	 * We need to switch fonts and grow our screen buffer.
1145 	 *
1146 	 * XXX: Right now the code uses terminal_mute() to
1147 	 * prevent data from reaching the console driver while
1148 	 * resizing the screen buffer.  This isn't elegant...
1149 	 */
1150 
1151 	VT_LOCK(vd);
1152 	if (vw->vw_flags & VWF_BUSY) {
1153 		/* Another process is changing the font. */
1154 		VT_UNLOCK(vd);
1155 		return (EBUSY);
1156 	}
1157 	if (vd->vd_flags & VDF_TEXTMODE) {
1158 		/* Our device doesn't need fonts. */
1159 		VT_UNLOCK(vd);
1160 		return (ENOTTY);
1161 	}
1162 	vw->vw_flags |= VWF_BUSY;
1163 	VT_UNLOCK(vd);
1164 
1165 	vt_termsize(vd, vf, &size);
1166 	vt_winsize(vd, vf, &wsz);
1167 	/* Save offset to font aligned area. */
1168 	vd->vd_offset.tp_col = (vd->vd_width % vf->vf_width) / 2;
1169 	vd->vd_offset.tp_row = (vd->vd_height % vf->vf_height) / 2;
1170 
1171 	/* Grow the screen buffer and terminal. */
1172 	terminal_mute(tm, 1);
1173 	vtbuf_grow(&vw->vw_buf, &size, vw->vw_buf.vb_history_size);
1174 	terminal_set_winsize_blank(tm, &wsz, 0, NULL);
1175 	terminal_mute(tm, 0);
1176 
1177 	/* Actually apply the font to the current window. */
1178 	VT_LOCK(vd);
1179 	if (vw->vw_font != vf) {
1180 		/*
1181 		 * In case vt_change_font called to update size we don't need
1182 		 * to update font link.
1183 		 */
1184 		vtfont_unref(vw->vw_font);
1185 		vw->vw_font = vtfont_ref(vf);
1186 	}
1187 
1188 	/* Force a full redraw the next timer tick. */
1189 	if (vd->vd_curwindow == vw)
1190 		vd->vd_flags |= VDF_INVALID;
1191 	vw->vw_flags &= ~VWF_BUSY;
1192 	VT_UNLOCK(vd);
1193 	return (0);
1194 }
1195 
1196 static int
1197 vt_set_border(struct vt_window *vw, struct vt_font *vf, term_color_t c)
1198 {
1199 	struct vt_device *vd = vw->vw_device;
1200 	int x, y, off_x, off_y;
1201 
1202 	if (vd->vd_driver->vd_drawrect == NULL)
1203 		return (ENOTSUP);
1204 
1205 	x = vd->vd_width - 1;
1206 	y = vd->vd_height - 1;
1207 	off_x = vd->vd_offset.tp_col;
1208 	off_y = vd->vd_offset.tp_row;
1209 
1210 	/* Top bar. */
1211 	if (off_y > 0)
1212 		vd->vd_driver->vd_drawrect(vd, 0, 0, x, off_y - 1, 1, c);
1213 	/* Left bar. */
1214 	if (off_x > 0)
1215 		vd->vd_driver->vd_drawrect(vd, 0, off_y, off_x - 1, y - off_y,
1216 		    1, c);
1217 	/* Right bar.  May be 1 pixel wider than necessary due to rounding. */
1218 	vd->vd_driver->vd_drawrect(vd, x - off_x, off_y, x, y - off_y, 1, c);
1219 	/* Bottom bar.  May be 1 mixel taller than necessary due to rounding. */
1220 	vd->vd_driver->vd_drawrect(vd, 0, y - off_y, x, y, 1, c);
1221 
1222 	return (0);
1223 }
1224 
1225 static int
1226 vt_proc_alive(struct vt_window *vw)
1227 {
1228 	struct proc *p;
1229 
1230 	if (vw->vw_smode.mode != VT_PROCESS)
1231 		return (FALSE);
1232 
1233 	if (vw->vw_proc) {
1234 		if ((p = pfind(vw->vw_pid)) != NULL)
1235 			PROC_UNLOCK(p);
1236 		if (vw->vw_proc == p)
1237 			return (TRUE);
1238 		vw->vw_proc = NULL;
1239 		vw->vw_smode.mode = VT_AUTO;
1240 		DPRINTF(1, "vt controlling process %d died\n", vw->vw_pid);
1241 		vw->vw_pid = 0;
1242 	}
1243 	return (FALSE);
1244 }
1245 
1246 static int
1247 signal_vt_rel(struct vt_window *vw)
1248 {
1249 
1250 	if (vw->vw_smode.mode != VT_PROCESS)
1251 		return (FALSE);
1252 	if (vw->vw_proc == NULL || vt_proc_alive(vw) == FALSE) {
1253 		vw->vw_proc = NULL;
1254 		vw->vw_pid = 0;
1255 		return (TRUE);
1256 	}
1257 	vw->vw_flags |= VWF_SWWAIT_REL;
1258 	PROC_LOCK(vw->vw_proc);
1259 	kern_psignal(vw->vw_proc, vw->vw_smode.relsig);
1260 	PROC_UNLOCK(vw->vw_proc);
1261 	DPRINTF(1, "sending relsig to %d\n", vw->vw_pid);
1262 	return (TRUE);
1263 }
1264 
1265 static int
1266 signal_vt_acq(struct vt_window *vw)
1267 {
1268 
1269 	if (vw->vw_smode.mode != VT_PROCESS)
1270 		return (FALSE);
1271 	if (vw == vw->vw_device->vd_windows[VT_CONSWINDOW])
1272 		cnavailable(vw->vw_terminal->consdev, FALSE);
1273 	if (vw->vw_proc == NULL || vt_proc_alive(vw) == FALSE) {
1274 		vw->vw_proc = NULL;
1275 		vw->vw_pid = 0;
1276 		return (TRUE);
1277 	}
1278 	vw->vw_flags |= VWF_SWWAIT_ACQ;
1279 	PROC_LOCK(vw->vw_proc);
1280 	kern_psignal(vw->vw_proc, vw->vw_smode.acqsig);
1281 	PROC_UNLOCK(vw->vw_proc);
1282 	DPRINTF(1, "sending acqsig to %d\n", vw->vw_pid);
1283 	return (TRUE);
1284 }
1285 
1286 static int
1287 finish_vt_rel(struct vt_window *vw, int release, int *s)
1288 {
1289 
1290 	if (vw->vw_flags & VWF_SWWAIT_REL) {
1291 		vw->vw_flags &= ~VWF_SWWAIT_REL;
1292 		if (release) {
1293 			callout_drain(&vw->vw_proc_dead_timer);
1294 			vt_late_window_switch(vw->vw_switch_to);
1295 		}
1296 		return (0);
1297 	}
1298 	return (EINVAL);
1299 }
1300 
1301 static int
1302 finish_vt_acq(struct vt_window *vw)
1303 {
1304 
1305 	if (vw->vw_flags & VWF_SWWAIT_ACQ) {
1306 		vw->vw_flags &= ~VWF_SWWAIT_ACQ;
1307 		return (0);
1308 	}
1309 	return (EINVAL);
1310 }
1311 
1312 #ifndef SC_NO_CUTPASTE
1313 static void
1314 vt_mouse_terminput_button(struct vt_device *vd, int button)
1315 {
1316 	struct vt_window *vw;
1317 	struct vt_font *vf;
1318 	char mouseb[6] = "\x1B[M";
1319 	int i, x, y;
1320 
1321 	vw = vd->vd_curwindow;
1322 	vf = vw->vw_font;
1323 
1324 	/* Translate to char position. */
1325 	x = vd->vd_mx / vf->vf_width;
1326 	y = vd->vd_my / vf->vf_height;
1327 	/* Avoid overflow. */
1328 	x = MIN(x, 255 - '!');
1329 	y = MIN(y, 255 - '!');
1330 
1331 	mouseb[3] = ' ' + button;
1332 	mouseb[4] = '!' + x;
1333 	mouseb[5] = '!' + y;
1334 
1335 	for (i = 0; i < sizeof(mouseb); i++ )
1336 		terminal_input_char(vw->vw_terminal, mouseb[i]);
1337 }
1338 
1339 static void
1340 vt_mouse_terminput(struct vt_device *vd, int type, int x, int y, int event,
1341     int cnt)
1342 {
1343 
1344 	switch (type) {
1345 	case MOUSE_BUTTON_EVENT:
1346 		if (cnt > 0) {
1347 			/* Mouse button pressed. */
1348 			if (event & MOUSE_BUTTON1DOWN)
1349 				vt_mouse_terminput_button(vd, 0);
1350 			if (event & MOUSE_BUTTON2DOWN)
1351 				vt_mouse_terminput_button(vd, 1);
1352 			if (event & MOUSE_BUTTON3DOWN)
1353 				vt_mouse_terminput_button(vd, 2);
1354 		} else {
1355 			/* Mouse button released. */
1356 			vt_mouse_terminput_button(vd, 3);
1357 		}
1358 		break;
1359 #ifdef notyet
1360 	case MOUSE_MOTION_EVENT:
1361 		if (mouse->u.data.z < 0) {
1362 			/* Scroll up. */
1363 			sc_mouse_input_button(vd, 64);
1364 		} else if (mouse->u.data.z > 0) {
1365 			/* Scroll down. */
1366 			sc_mouse_input_button(vd, 65);
1367 		}
1368 		break;
1369 #endif
1370 	}
1371 }
1372 
1373 void
1374 vt_mouse_event(int type, int x, int y, int event, int cnt, int mlevel)
1375 {
1376 	struct vt_device *vd;
1377 	struct vt_window *vw;
1378 	struct vt_font *vf;
1379 	term_pos_t size;
1380 	term_char_t *buf;
1381 	int i, len, mark;
1382 
1383 	vd = main_vd;
1384 	vw = vd->vd_curwindow;
1385 	vf = vw->vw_font;
1386 	mark = 0;
1387 
1388 	if (vw->vw_flags & VWF_MOUSE_HIDE)
1389 		return; /* Mouse disabled. */
1390 
1391 	if (vf == NULL)	/* Text mode. */
1392 		return;
1393 
1394 	/*
1395 	 * TODO: add flag about pointer position changed, to not redraw chars
1396 	 * under mouse pointer when nothing changed.
1397 	 */
1398 
1399 	if (vw->vw_mouse_level > 0)
1400 		vt_mouse_terminput(vd, type, x, y, event, cnt);
1401 
1402 	switch (type) {
1403 	case MOUSE_ACTION:
1404 	case MOUSE_MOTION_EVENT:
1405 		/* Movement */
1406 		x += vd->vd_mx;
1407 		y += vd->vd_my;
1408 
1409 		vt_termsize(vd, vf, &size);
1410 
1411 		/* Apply limits. */
1412 		x = MAX(x, 0);
1413 		y = MAX(y, 0);
1414 		x = MIN(x, (size.tp_col * vf->vf_width) - 1);
1415 		y = MIN(y, (size.tp_row * vf->vf_height) - 1);
1416 
1417 		vd->vd_mx = x;
1418 		vd->vd_my = y;
1419 		if ((vd->vd_mstate & MOUSE_BUTTON1DOWN) &&
1420 		    (vtbuf_set_mark(&vw->vw_buf, VTB_MARK_MOVE,
1421 			vd->vd_mx / vf->vf_width,
1422 			vd->vd_my / vf->vf_height) == 1)) {
1423 
1424 			/*
1425 			 * We have something marked to copy, so update pointer
1426 			 * to window with selection.
1427 			 */
1428 			vd->vd_markedwin = vw;
1429 		}
1430 		return; /* Done */
1431 	case MOUSE_BUTTON_EVENT:
1432 		/* Buttons */
1433 		break;
1434 	default:
1435 		return; /* Done */
1436 	}
1437 
1438 	switch (event) {
1439 	case MOUSE_BUTTON1DOWN:
1440 		switch (cnt % 4) {
1441 		case 0:	/* up */
1442 			mark = VTB_MARK_END;
1443 			break;
1444 		case 1: /* single click: start cut operation */
1445 			mark = VTB_MARK_START;
1446 			break;
1447 		case 2:	/* double click: cut a word */
1448 			mark = VTB_MARK_WORD;
1449 			break;
1450 		case 3:	/* triple click: cut a line */
1451 			mark = VTB_MARK_ROW;
1452 			break;
1453 		}
1454 		break;
1455 	case VT_MOUSE_PASTEBUTTON:
1456 		switch (cnt) {
1457 		case 0:	/* up */
1458 			break;
1459 		default:
1460 			if (vd->vd_markedwin == NULL)
1461 				return;
1462 			/* Get current selecton size in bytes. */
1463 			len = vtbuf_get_marked_len(&vd->vd_markedwin->vw_buf);
1464 			if (len <= 0)
1465 				return;
1466 
1467 			buf = malloc(len, M_VT, M_WAITOK | M_ZERO);
1468 			/* Request cupy/paste buffer data, no more than `len' */
1469 			vtbuf_extract_marked(&vd->vd_markedwin->vw_buf, buf,
1470 			    len);
1471 
1472 			len /= sizeof(term_char_t);
1473 			for (i = 0; i < len; i++ ) {
1474 				if (buf[i] == '\0')
1475 					continue;
1476 				terminal_input_char(vw->vw_terminal, buf[i]);
1477 			}
1478 
1479 			/* Done, so cleanup. */
1480 			free(buf, M_VT);
1481 			break;
1482 		}
1483 		return; /* Done */
1484 	case VT_MOUSE_EXTENDBUTTON:
1485 		switch (cnt) {
1486 		case 0:	/* up */
1487 			if (!(vd->vd_mstate & MOUSE_BUTTON1DOWN))
1488 				mark = VTB_MARK_EXTEND;
1489 			else
1490 				mark = 0;
1491 			break;
1492 		default:
1493 			mark = VTB_MARK_EXTEND;
1494 			break;
1495 		}
1496 		break;
1497 	default:
1498 		return; /* Done */
1499 	}
1500 
1501 	/* Save buttons state. */
1502 	if (cnt > 0)
1503 		vd->vd_mstate |= event;
1504 	else
1505 		vd->vd_mstate &= ~event;
1506 
1507 	if (vtbuf_set_mark(&vw->vw_buf, mark, vd->vd_mx / vf->vf_width,
1508 	    vd->vd_my / vf->vf_height) == 1) {
1509 		/*
1510 		 * We have something marked to copy, so update pointer to
1511 		 * window with selection.
1512 		 */
1513 		vd->vd_markedwin = vw;
1514 	}
1515 }
1516 
1517 void
1518 vt_mouse_state(int show)
1519 {
1520 	struct vt_device *vd;
1521 	struct vt_window *vw;
1522 
1523 	vd = main_vd;
1524 	vw = vd->vd_curwindow;
1525 
1526 	switch (show) {
1527 	case VT_MOUSE_HIDE:
1528 		vw->vw_flags |= VWF_MOUSE_HIDE;
1529 		break;
1530 	case VT_MOUSE_SHOW:
1531 		vw->vw_flags &= ~VWF_MOUSE_HIDE;
1532 		break;
1533 	}
1534 }
1535 #endif
1536 
1537 static int
1538 vtterm_mmap(struct terminal *tm, vm_ooffset_t offset, vm_paddr_t * paddr,
1539     int nprot, vm_memattr_t *memattr)
1540 {
1541 	struct vt_window *vw = tm->tm_softc;
1542 	struct vt_device *vd = vw->vw_device;
1543 
1544 	if (vd->vd_driver->vd_fb_mmap)
1545 		return (vd->vd_driver->vd_fb_mmap(vd, offset, paddr, nprot,
1546 		    memattr));
1547 
1548 	return (ENXIO);
1549 }
1550 
1551 static int
1552 vtterm_ioctl(struct terminal *tm, u_long cmd, caddr_t data,
1553     struct thread *td)
1554 {
1555 	struct vt_window *vw = tm->tm_softc;
1556 	struct vt_device *vd = vw->vw_device;
1557 	keyboard_t *kbd;
1558 	int error, i, s;
1559 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
1560     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
1561 	int ival;
1562 
1563 	switch (cmd) {
1564 	case _IO('v', 4):
1565 		cmd = VT_RELDISP;
1566 		break;
1567 	case _IO('v', 5):
1568 		cmd = VT_ACTIVATE;
1569 		break;
1570 	case _IO('v', 6):
1571 		cmd = VT_WAITACTIVE;
1572 		break;
1573 	case _IO('K', 20):
1574 		cmd = KDSKBSTATE;
1575 		break;
1576 	case _IO('K', 67):
1577 		cmd = KDSETRAD;
1578 		break;
1579 	case _IO('K', 7):
1580 		cmd = KDSKBMODE;
1581 		break;
1582 	case _IO('K', 8):
1583 		cmd = KDMKTONE;
1584 		break;
1585 	case _IO('K', 63):
1586 		cmd = KIOCSOUND;
1587 		break;
1588 	case _IO('K', 66):
1589 		cmd = KDSETLED;
1590 		break;
1591 	case _IO('c', 110):
1592 		cmd = CONS_SETKBD;
1593 		break;
1594 	default:
1595 		goto skip_thunk;
1596 	}
1597 	ival = IOCPARM_IVAL(data);
1598 	data = (caddr_t)&ival;
1599 skip_thunk:
1600 #endif
1601 
1602 	switch (cmd) {
1603 	case KDSETRAD:		/* set keyboard repeat & delay rates (old) */
1604 		if (*(int *)data & ~0x7f)
1605 			return (EINVAL);
1606 	case GIO_KEYMAP:
1607 	case PIO_KEYMAP:
1608 	case GIO_DEADKEYMAP:
1609 	case PIO_DEADKEYMAP:
1610 	case GETFKEY:
1611 	case SETFKEY:
1612 	case KDGKBINFO:
1613 	case KDGKBTYPE:
1614 	case KDSKBSTATE:	/* set keyboard state (locks) */
1615 	case KDGKBSTATE:	/* get keyboard state (locks) */
1616 	case KDGETREPEAT:	/* get keyboard repeat & delay rates */
1617 	case KDSETREPEAT:	/* set keyboard repeat & delay rates (new) */
1618 	case KDSETLED:		/* set keyboard LED status */
1619 	case KDGETLED:		/* get keyboard LED status */
1620 	case KBADDKBD:		/* add/remove keyboard to/from mux */
1621 	case KBRELKBD: {
1622 		error = 0;
1623 
1624 		mtx_lock(&Giant);
1625 		kbd = kbd_get_keyboard(vd->vd_keyboard);
1626 		if (kbd != NULL)
1627 			error = kbdd_ioctl(kbd, cmd, data);
1628 		mtx_unlock(&Giant);
1629 		if (error == ENOIOCTL) {
1630 			if (cmd == KDGKBTYPE) {
1631 				/* always return something? XXX */
1632 				*(int *)data = 0;
1633 			} else {
1634 				return (ENODEV);
1635 			}
1636 		}
1637 		return (error);
1638 	}
1639 	case KDGKBMODE: {
1640 		int mode = -1;
1641 
1642 		mtx_lock(&Giant);
1643 		kbd = kbd_get_keyboard(vd->vd_keyboard);
1644 		if (kbd != NULL) {
1645 			kbdd_ioctl(kbd, KDGKBMODE, (void *)&mode);
1646 		}
1647 		mtx_unlock(&Giant);
1648 		DPRINTF(20, "mode %d, vw_kbdmode %d\n", mode, vw->vw_kbdmode);
1649 		*(int *)data = mode;
1650 		return (0);
1651 	}
1652 	case KDSKBMODE: {
1653 		int mode;
1654 
1655 		mode = *(int *)data;
1656 		switch (mode) {
1657 		case K_XLATE:
1658 		case K_RAW:
1659 		case K_CODE:
1660 			vw->vw_kbdmode = mode;
1661 			if (vw == vd->vd_curwindow) {
1662 				keyboard_t *kbd;
1663 				error = 0;
1664 
1665 				mtx_lock(&Giant);
1666 				kbd = kbd_get_keyboard(vd->vd_keyboard);
1667 				if (kbd != NULL) {
1668 					error = kbdd_ioctl(kbd, KDSKBMODE,
1669 					    (void *)&mode);
1670 				}
1671 				mtx_unlock(&Giant);
1672 			}
1673 			return (0);
1674 		default:
1675 			return (EINVAL);
1676 		}
1677 	}
1678 	case FBIOGTYPE:
1679 	case FBIO_GETWINORG:	/* get frame buffer window origin */
1680 	case FBIO_GETDISPSTART:	/* get display start address */
1681 	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
1682 	case FBIO_BLANK:	/* blank display */
1683 		if (vd->vd_driver->vd_fb_ioctl)
1684 			return (vd->vd_driver->vd_fb_ioctl(vd, cmd, data, td));
1685 		break;
1686 	case CONS_BLANKTIME:
1687 		/* XXX */
1688 		return (0);
1689 	case CONS_GET:
1690 		/* XXX */
1691 		*(int *)data = M_CG640x480;
1692 		return (0);
1693 	case CONS_BELLTYPE: 	/* set bell type sound */
1694 		if ((*(int *)data) & CONS_QUIET_BELL)
1695 			vd->vd_flags |= VDF_QUIET_BELL;
1696 		else
1697 			vd->vd_flags &= ~VDF_QUIET_BELL;
1698 		return (0);
1699 	case CONS_GETINFO: {
1700 		vid_info_t *vi = (vid_info_t *)data;
1701 
1702 		vi->m_num = vd->vd_curwindow->vw_number + 1;
1703 		/* XXX: other fields! */
1704 		return (0);
1705 	}
1706 	case CONS_GETVERS:
1707 		*(int *)data = 0x200;
1708 		return (0);
1709 	case CONS_MODEINFO:
1710 		/* XXX */
1711 		return (0);
1712 	case CONS_MOUSECTL: {
1713 		mouse_info_t *mouse = (mouse_info_t*)data;
1714 
1715 		/*
1716 		 * This has no effect on vt(4).  We don't draw any mouse
1717 		 * cursor.  Just ignore MOUSE_HIDE and MOUSE_SHOW to
1718 		 * prevent excessive errors.  All the other commands
1719 		 * should not be applied to individual TTYs, but only to
1720 		 * consolectl.
1721 		 */
1722 		switch (mouse->operation) {
1723 		case MOUSE_HIDE:
1724 			vd->vd_flags &= ~VDF_MOUSECURSOR;
1725 			return (0);
1726 		case MOUSE_SHOW:
1727 			vd->vd_mx = vd->vd_width / 2;
1728 			vd->vd_my = vd->vd_height / 2;
1729 			vd->vd_flags |= VDF_MOUSECURSOR;
1730 			return (0);
1731 		default:
1732 			return (EINVAL);
1733 		}
1734 	}
1735 	case PIO_VFONT: {
1736 		struct vt_font *vf;
1737 
1738 		error = vtfont_load((void *)data, &vf);
1739 		if (error != 0)
1740 			return (error);
1741 
1742 		error = vt_change_font(vw, vf);
1743 		if (error == 0) {
1744 			/* XXX: replace 0 with current bg color. */
1745 			vt_set_border(vw, vf, 0);
1746 		}
1747 		vtfont_unref(vf);
1748 		return (error);
1749 	}
1750 	case GIO_SCRNMAP: {
1751 		scrmap_t *sm = (scrmap_t *)data;
1752 		int i;
1753 
1754 		/* We don't have screen maps, so return a handcrafted one. */
1755 		for (i = 0; i < 256; i++)
1756 			sm->scrmap[i] = i;
1757 		return (0);
1758 	}
1759 	case KDSETMODE:
1760 		/* XXX */
1761 		return (0);
1762 	case KDENABIO:      	/* allow io operations */
1763 		error = priv_check(td, PRIV_IO);
1764 		if (error != 0)
1765 			return (error);
1766 		error = securelevel_gt(td->td_ucred, 0);
1767 		if (error != 0)
1768 			return (error);
1769 #if defined(__i386__)
1770 		td->td_frame->tf_eflags |= PSL_IOPL;
1771 #elif defined(__amd64__)
1772 		td->td_frame->tf_rflags |= PSL_IOPL;
1773 #endif
1774 		return (0);
1775 	case KDDISABIO:     	/* disallow io operations (default) */
1776 #if defined(__i386__)
1777 		td->td_frame->tf_eflags &= ~PSL_IOPL;
1778 #elif defined(__amd64__)
1779 		td->td_frame->tf_rflags &= ~PSL_IOPL;
1780 #endif
1781 		return (0);
1782 	case KDMKTONE:      	/* sound the bell */
1783 		vtterm_beep(tm, *(u_int *)data);
1784 		return (0);
1785 	case KIOCSOUND:     	/* make tone (*data) hz */
1786 		/* TODO */
1787 		return (0);
1788 	case CONS_SETKBD: 		/* set the new keyboard */
1789 		mtx_lock(&Giant);
1790 		error = 0;
1791 		if (vd->vd_keyboard != *(int *)data) {
1792 			kbd = kbd_get_keyboard(*(int *)data);
1793 			if (kbd == NULL) {
1794 				mtx_unlock(&Giant);
1795 				return (EINVAL);
1796 			}
1797 			i = kbd_allocate(kbd->kb_name, kbd->kb_unit,
1798 			    (void *)vd, vt_kbdevent, vd);
1799 			if (i >= 0) {
1800 				if (vd->vd_keyboard != -1) {
1801 					kbd_release(kbd, (void *)vd);
1802 				}
1803 				kbd = kbd_get_keyboard(i);
1804 				vd->vd_keyboard = i;
1805 
1806 				(void)kbdd_ioctl(kbd, KDSKBMODE,
1807 				    (caddr_t)&vd->vd_curwindow->vw_kbdmode);
1808 			} else {
1809 				error = EPERM;	/* XXX */
1810 			}
1811 		}
1812 		mtx_unlock(&Giant);
1813 		return (error);
1814 	case CONS_RELKBD: 		/* release the current keyboard */
1815 		mtx_lock(&Giant);
1816 		error = 0;
1817 		if (vd->vd_keyboard != -1) {
1818 			kbd = kbd_get_keyboard(vd->vd_keyboard);
1819 			if (kbd == NULL) {
1820 				mtx_unlock(&Giant);
1821 				return (EINVAL);
1822 			}
1823 			error = kbd_release(kbd, (void *)vd);
1824 			if (error == 0) {
1825 				vd->vd_keyboard = -1;
1826 			}
1827 		}
1828 		mtx_unlock(&Giant);
1829 		return (error);
1830 	case VT_ACTIVATE: {
1831 		int win;
1832 		win = *(int *)data - 1;
1833 		DPRINTF(5, "%s%d: VT_ACTIVATE ttyv%d ", SC_DRIVER_NAME,
1834 		    VT_UNIT(vw), win);
1835 		if ((win > VT_MAXWINDOWS) || (win < 0))
1836 			return (EINVAL);
1837 		return (vt_proc_window_switch(vd->vd_windows[win]));
1838 	}
1839 	case VT_GETACTIVE:
1840 		*(int *)data = vd->vd_curwindow->vw_number + 1;
1841 		return (0);
1842 	case VT_GETINDEX:
1843 		*(int *)data = vw->vw_number + 1;
1844 		return (0);
1845 	case VT_LOCKSWITCH:
1846 		/* TODO: Check current state, switching can be in progress. */
1847 		if ((*(int *)data) == 0x01)
1848 			vw->vw_flags |= VWF_VTYLOCK;
1849 		else if ((*(int *)data) == 0x02)
1850 			vw->vw_flags &= ~VWF_VTYLOCK;
1851 		else
1852 			return (EINVAL);
1853 		return (0);
1854 	case VT_OPENQRY:
1855 		VT_LOCK(vd);
1856 		for (i = 0; i < VT_MAXWINDOWS; i++) {
1857 			vw = vd->vd_windows[i];
1858 			if (vw == NULL)
1859 				continue;
1860 			if (!(vw->vw_flags & VWF_OPENED)) {
1861 				*(int *)data = vw->vw_number + 1;
1862 				VT_UNLOCK(vd);
1863 				return (0);
1864 			}
1865 		}
1866 		VT_UNLOCK(vd);
1867 		return (EINVAL);
1868 	case VT_WAITACTIVE:
1869 		error = 0;
1870 
1871 		i = *(unsigned int *)data;
1872 		if (i > VT_MAXWINDOWS)
1873 			return (EINVAL);
1874 		if (i != 0)
1875 			vw = vd->vd_windows[i - 1];
1876 
1877 		VT_LOCK(vd);
1878 		while (vd->vd_curwindow != vw && error == 0)
1879 			error = cv_wait_sig(&vd->vd_winswitch, &vd->vd_lock);
1880 		VT_UNLOCK(vd);
1881 		return (error);
1882 	case VT_SETMODE: {    	/* set screen switcher mode */
1883 		struct vt_mode *mode;
1884 		struct proc *p1;
1885 
1886 		mode = (struct vt_mode *)data;
1887 		DPRINTF(5, "%s%d: VT_SETMODE ", SC_DRIVER_NAME, VT_UNIT(vw));
1888 		if (vw->vw_smode.mode == VT_PROCESS) {
1889 			p1 = pfind(vw->vw_pid);
1890 			if (vw->vw_proc == p1 && vw->vw_proc != td->td_proc) {
1891 				if (p1)
1892 					PROC_UNLOCK(p1);
1893 				DPRINTF(5, "error EPERM\n");
1894 				return (EPERM);
1895 			}
1896 			if (p1)
1897 				PROC_UNLOCK(p1);
1898 		}
1899 		if (mode->mode == VT_AUTO) {
1900 			vw->vw_smode.mode = VT_AUTO;
1901 			vw->vw_proc = NULL;
1902 			vw->vw_pid = 0;
1903 			DPRINTF(5, "VT_AUTO, ");
1904 			if (vw == vw->vw_device->vd_windows[VT_CONSWINDOW])
1905 				cnavailable(vw->vw_terminal->consdev, TRUE);
1906 			/* were we in the middle of the vty switching process? */
1907 			if (finish_vt_rel(vw, TRUE, &s) == 0)
1908 				DPRINTF(5, "reset WAIT_REL, ");
1909 			if (finish_vt_acq(vw) == 0)
1910 				DPRINTF(5, "reset WAIT_ACQ, ");
1911 			return (0);
1912 		} else if (mode->mode == VT_PROCESS) {
1913 			if (!ISSIGVALID(mode->relsig) ||
1914 			    !ISSIGVALID(mode->acqsig) ||
1915 			    !ISSIGVALID(mode->frsig)) {
1916 				DPRINTF(5, "error EINVAL\n");
1917 				return (EINVAL);
1918 			}
1919 			DPRINTF(5, "VT_PROCESS %d, ", td->td_proc->p_pid);
1920 			bcopy(data, &vw->vw_smode, sizeof(struct vt_mode));
1921 			vw->vw_proc = td->td_proc;
1922 			vw->vw_pid = vw->vw_proc->p_pid;
1923 			if (vw == vw->vw_device->vd_windows[VT_CONSWINDOW])
1924 				cnavailable(vw->vw_terminal->consdev, FALSE);
1925 		} else {
1926 			DPRINTF(5, "VT_SETMODE failed, unknown mode %d\n",
1927 			    mode->mode);
1928 			return (EINVAL);
1929 		}
1930 		DPRINTF(5, "\n");
1931 		return (0);
1932 	}
1933 	case VT_GETMODE:	/* get screen switcher mode */
1934 		bcopy(&vw->vw_smode, data, sizeof(struct vt_mode));
1935 		return (0);
1936 
1937 	case VT_RELDISP:	/* screen switcher ioctl */
1938 		/*
1939 		 * This must be the current vty which is in the VT_PROCESS
1940 		 * switching mode...
1941 		 */
1942 		if ((vw != vd->vd_curwindow) || (vw->vw_smode.mode !=
1943 		    VT_PROCESS)) {
1944 			return (EINVAL);
1945 		}
1946 		/* ...and this process is controlling it. */
1947 		if (vw->vw_proc != td->td_proc) {
1948 			return (EPERM);
1949 		}
1950 		error = EINVAL;
1951 		switch(*(int *)data) {
1952 		case VT_FALSE:	/* user refuses to release screen, abort */
1953 			if ((error = finish_vt_rel(vw, FALSE, &s)) == 0)
1954 				DPRINTF(5, "%s%d: VT_RELDISP: VT_FALSE\n",
1955 				    SC_DRIVER_NAME, VT_UNIT(vw));
1956 			break;
1957 		case VT_TRUE:	/* user has released screen, go on */
1958 			/* finish_vt_rel(..., TRUE, ...) should not be locked */
1959 			if (vw->vw_flags & VWF_SWWAIT_REL) {
1960 				if ((error = finish_vt_rel(vw, TRUE, &s)) == 0)
1961 					DPRINTF(5, "%s%d: VT_RELDISP: VT_TRUE\n",
1962 					    SC_DRIVER_NAME, VT_UNIT(vw));
1963 			} else {
1964 				error = EINVAL;
1965 			}
1966 			return (error);
1967 		case VT_ACKACQ:	/* acquire acknowledged, switch completed */
1968 			if ((error = finish_vt_acq(vw)) == 0)
1969 				DPRINTF(5, "%s%d: VT_RELDISP: VT_ACKACQ\n",
1970 				    SC_DRIVER_NAME, VT_UNIT(vw));
1971 			break;
1972 		default:
1973 			break;
1974 		}
1975 		return (error);
1976 	}
1977 
1978 	return (ENOIOCTL);
1979 }
1980 
1981 static struct vt_window *
1982 vt_allocate_window(struct vt_device *vd, unsigned int window)
1983 {
1984 	struct vt_window *vw;
1985 	struct terminal *tm;
1986 	term_pos_t size;
1987 	struct winsize wsz;
1988 
1989 	vw = malloc(sizeof *vw, M_VT, M_WAITOK|M_ZERO);
1990 	vw->vw_device = vd;
1991 	vw->vw_number = window;
1992 	vw->vw_kbdmode = K_XLATE;
1993 
1994 	if ((vd->vd_flags & VDF_TEXTMODE) == 0)
1995 		vw->vw_font = vtfont_ref(&vt_font_default);
1996 
1997 	vt_termsize(vd, vw->vw_font, &size);
1998 	vt_winsize(vd, vw->vw_font, &wsz);
1999 	vtbuf_init(&vw->vw_buf, &size);
2000 
2001 	tm = vw->vw_terminal = terminal_alloc(&vt_termclass, vw);
2002 	terminal_set_winsize(tm, &wsz);
2003 	vd->vd_windows[window] = vw;
2004 	callout_init(&vw->vw_proc_dead_timer, 0);
2005 
2006 	return (vw);
2007 }
2008 
2009 void
2010 vt_upgrade(struct vt_device *vd)
2011 {
2012 	struct vt_window *vw;
2013 	unsigned int i;
2014 
2015 	if (!vty_enabled(VTY_VT))
2016 		return;
2017 
2018 	for (i = 0; i < VT_MAXWINDOWS; i++) {
2019 		vw = vd->vd_windows[i];
2020 		if (vw == NULL) {
2021 			/* New window. */
2022 			vw = vt_allocate_window(vd, i);
2023 		}
2024 		if (!(vw->vw_flags & VWF_READY)) {
2025 			callout_init(&vw->vw_proc_dead_timer, 0);
2026 			terminal_maketty(vw->vw_terminal, "v%r", VT_UNIT(vw));
2027 			vw->vw_flags |= VWF_READY;
2028 			if (vw->vw_flags & VWF_CONSOLE) {
2029 				/* For existing console window. */
2030 				EVENTHANDLER_REGISTER(shutdown_pre_sync,
2031 				    vt_window_switch, vw, SHUTDOWN_PRI_DEFAULT);
2032 			}
2033 		}
2034 
2035 	}
2036 	VT_LOCK(vd);
2037 	if (vd->vd_curwindow == NULL)
2038 		vd->vd_curwindow = vd->vd_windows[VT_CONSWINDOW];
2039 
2040 	if (!(vd->vd_flags & VDF_ASYNC)) {
2041 		/* Attach keyboard. */
2042 		vt_allocate_keyboard(vd);
2043 
2044 		/* Init 25 Hz timer. */
2045 		callout_init_mtx(&vd->vd_timer, &vd->vd_lock, 0);
2046 
2047 		/* Start timer when everything ready. */
2048 		vd->vd_flags |= VDF_ASYNC;
2049 		callout_reset(&vd->vd_timer, hz / VT_TIMERFREQ, vt_timer, vd);
2050 	}
2051 
2052 	VT_UNLOCK(vd);
2053 
2054 	/* Refill settings with new sizes. */
2055 	vt_resize(vd);
2056 }
2057 
2058 static void
2059 vt_resize(struct vt_device *vd)
2060 {
2061 	struct vt_window *vw;
2062 	int i;
2063 
2064 	for (i = 0; i < VT_MAXWINDOWS; i++) {
2065 		vw = vd->vd_windows[i];
2066 		VT_LOCK(vd);
2067 		/* Assign default font to window, if not textmode. */
2068 		if (!(vd->vd_flags & VDF_TEXTMODE) && vw->vw_font == NULL)
2069 			vw->vw_font = vtfont_ref(&vt_font_default);
2070 		VT_UNLOCK(vd);
2071 		/* Resize terminal windows */
2072 		while (vt_change_font(vw, vw->vw_font) == EBUSY) {
2073 			DPRINTF(100, "%s: vt_change_font() is busy, "
2074 			    "window %d\n", __func__, i);
2075 		}
2076 	}
2077 }
2078 
2079 void
2080 vt_allocate(struct vt_driver *drv, void *softc)
2081 {
2082 	struct vt_device *vd;
2083 
2084 	if (!vty_enabled(VTY_VT))
2085 		return;
2086 
2087 	if (main_vd->vd_driver == NULL) {
2088 		main_vd->vd_driver = drv;
2089 		printf("VT: initialize with new VT driver \"%s\".\n",
2090 		    drv->vd_name);
2091 	} else {
2092 		/*
2093 		 * Check if have rights to replace current driver. For example:
2094 		 * it is bad idea to replace KMS driver with generic VGA one.
2095 		 */
2096 		if (drv->vd_priority <= main_vd->vd_driver->vd_priority) {
2097 			printf("VT: Driver priority %d too low. Current %d\n ",
2098 			    drv->vd_priority, main_vd->vd_driver->vd_priority);
2099 			return;
2100 		}
2101 		printf("VT: Replacing driver \"%s\" with new \"%s\".\n",
2102 		    main_vd->vd_driver->vd_name, drv->vd_name);
2103 	}
2104 	vd = main_vd;
2105 	VT_LOCK(vd);
2106 
2107 	if (vd->vd_flags & VDF_ASYNC) {
2108 		/* Stop vt_flush periodic task. */
2109 		callout_drain(&vd->vd_timer);
2110 		/*
2111 		 * Mute current terminal until we done. vt_change_font (called
2112 		 * from vt_resize) will unmute it.
2113 		 */
2114 		terminal_mute(vd->vd_curwindow->vw_terminal, 1);
2115 	}
2116 
2117 	/*
2118 	 * Reset VDF_TEXTMODE flag, driver who require that flag (vt_vga) will
2119 	 * set it.
2120 	 */
2121 	vd->vd_flags &= ~VDF_TEXTMODE;
2122 
2123 	vd->vd_driver = drv;
2124 	vd->vd_softc = softc;
2125 	vd->vd_driver->vd_init(vd);
2126 	VT_UNLOCK(vd);
2127 
2128 	/* Update windows sizes and initialize last items. */
2129 	vt_upgrade(vd);
2130 
2131 #ifdef DEV_SPLASH
2132 	if (vd->vd_flags & VDF_SPLASH)
2133 		vtterm_splash(vd);
2134 #endif
2135 
2136 	if (vd->vd_flags & VDF_ASYNC) {
2137 		/* Allow to put chars now. */
2138 		terminal_mute(vd->vd_curwindow->vw_terminal, 0);
2139 		/* Rerun timer for screen updates. */
2140 		callout_schedule(&vd->vd_timer, hz / VT_TIMERFREQ);
2141 	}
2142 
2143 	/*
2144 	 * Register as console. If it already registered, cnadd() will ignore
2145 	 * it.
2146 	 */
2147 	termcn_cnregister(vd->vd_windows[VT_CONSWINDOW]->vw_terminal);
2148 }
2149 
2150 void
2151 vt_suspend()
2152 {
2153 
2154 	if (vt_suspendswitch == 0)
2155 		return;
2156 	/* Save current window. */
2157 	main_vd->vd_savedwindow = main_vd->vd_curwindow;
2158 	/* Ask holding process to free window and switch to console window */
2159 	vt_proc_window_switch(main_vd->vd_windows[VT_CONSWINDOW]);
2160 }
2161 
2162 void
2163 vt_resume()
2164 {
2165 
2166 	if (vt_suspendswitch == 0)
2167 		return;
2168 	/* Switch back to saved window */
2169 	if (main_vd->vd_savedwindow != NULL)
2170 		vt_proc_window_switch(main_vd->vd_savedwindow);
2171 	main_vd->vd_savedwindow = NULL;
2172 }
2173