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