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