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