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