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