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