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