xref: /freebsd/sys/dev/syscons/syscons.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
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$
29  */
30 
31 #include "sc.h"
32 #include "apm.h"
33 #include "opt_ddb.h"
34 #include "opt_devfs.h"
35 #include "opt_vesa.h"
36 #include "opt_vm86.h"
37 #include "opt_syscons.h"
38 
39 #if NSC > 0
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/reboot.h>
43 #include <sys/conf.h>
44 #include <sys/proc.h>
45 #include <sys/signalvar.h>
46 #include <sys/tty.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #ifdef	DEVFS
50 #include <sys/devfsext.h>
51 #endif
52 
53 #include <machine/bootinfo.h>
54 #include <machine/clock.h>
55 #include <machine/cons.h>
56 #include <machine/console.h>
57 #include <machine/mouse.h>
58 #include <machine/md_var.h>
59 #include <machine/psl.h>
60 #include <machine/frame.h>
61 #include <machine/pc/display.h>
62 #include <machine/pc/vesa.h>
63 #include <machine/apm_bios.h>
64 #include <machine/random.h>
65 
66 #include <vm/vm.h>
67 #include <vm/vm_param.h>
68 #include <vm/pmap.h>
69 
70 #include <i386/isa/isa.h>
71 #include <i386/isa/isa_device.h>
72 #include <i386/isa/timerreg.h>
73 #include <i386/isa/kbdtables.h>
74 #include <i386/isa/kbdio.h>
75 #include <i386/isa/videoio.h>
76 #include <i386/isa/syscons.h>
77 
78 #if !defined(MAXCONS)
79 #define MAXCONS 16
80 #endif
81 
82 #if !defined(SC_MAX_HISTORY_SIZE)
83 #define SC_MAX_HISTORY_SIZE	(1000 * MAXCONS)
84 #endif
85 
86 #if !defined(SC_HISTORY_SIZE)
87 #define SC_HISTORY_SIZE		(ROW * 4)
88 #endif
89 
90 #if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE
91 #undef SC_MAX_HISTORY_SIZE
92 #define SC_MAX_HISTORY_SIZE	(SC_HISTORY_SIZE * MAXCONS)
93 #endif
94 
95 #if !defined(SC_MOUSE_CHAR)
96 #define SC_MOUSE_CHAR		(0xd0)
97 #endif
98 
99 #define COLD 0
100 #define WARM 1
101 
102 #define DEFAULT_BLANKTIME	(5*60)		/* 5 minutes */
103 #define MAX_BLANKTIME		(7*24*60*60)	/* 7 days!? */
104 
105 /* for backward compatibility */
106 #define OLD_CONS_MOUSECTL	_IOWR('c', 10, old_mouse_info_t)
107 
108 typedef struct old_mouse_data {
109     int x;
110     int y;
111     int buttons;
112 } old_mouse_data_t;
113 
114 typedef struct old_mouse_info {
115     int operation;
116     union {
117 	struct old_mouse_data data;
118 	struct mouse_mode mode;
119     } u;
120 } old_mouse_info_t;
121 
122 /* XXX use sc_bcopy where video memory is concerned */
123 extern void generic_bcopy(const void *, void *, size_t);
124 
125 static default_attr user_default = {
126     (FG_LIGHTGREY | BG_BLACK) << 8,
127     (FG_BLACK | BG_LIGHTGREY) << 8
128 };
129 
130 static default_attr kernel_default = {
131     (FG_WHITE | BG_BLACK) << 8,
132     (FG_BLACK | BG_LIGHTGREY) << 8
133 };
134 
135 static  scr_stat    	main_console;
136 static  scr_stat    	*console[MAXCONS];
137 #ifdef DEVFS
138 static	void		*sc_devfs_token[MAXCONS];
139 static	void		*sc_mouse_devfs_token;
140 static	void		*sc_console_devfs_token;
141 #endif
142 	scr_stat    	*cur_console;
143 static  scr_stat    	*new_scp, *old_scp;
144 static  term_stat   	kernel_console;
145 static  default_attr    *current_default;
146 static  int     	flags = 0;
147 static  int		sc_port = IO_KBD;
148 static  KBDC		sc_kbdc = NULL;
149 static  char        	init_done = COLD;
150 static  u_short		sc_buffer[ROW*COL];
151 static  char		shutdown_in_progress = FALSE;
152 static  char        	font_loading_in_progress = FALSE;
153 static  char        	switch_in_progress = FALSE;
154 static  char        	write_in_progress = FALSE;
155 static  char        	blink_in_progress = FALSE;
156 static  int        	blinkrate = 0;
157 	u_int       	crtc_addr = MONO_BASE;
158 	char		crtc_type = KD_MONO;
159 	char        	crtc_vga = FALSE;
160 static	int		adp_flags = 0;
161 static  u_char      	shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
162 static  u_char		accents = 0;
163 static  u_char      	nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
164 static  const u_int     n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);
165 static  int     	delayed_next_scr = FALSE;
166 static  long        	scrn_blank_time = 0;    /* screen saver timeout value */
167 	int     	scrn_blanked = 0;       /* screen saver active flag */
168 static  long		scrn_time_stamp;
169 static	int		saver_mode = CONS_LKM_SAVER; /* LKM/user saver */
170 static	int		run_scrn_saver = FALSE;	/* should run the saver? */
171 static	int		scrn_idle = FALSE;	/* about to run the saver */
172 	u_char      	scr_map[256];
173 	u_char      	scr_rmap[256];
174 static	int		initial_video_mode;	/* initial video mode # */
175 static	int		bios_video_mode;	/* video mode # set by BIOS */
176 	int     	fonts_loaded = 0
177 #ifdef STD8X16FONT
178 	| FONT_16
179 #endif
180 	;
181 
182 	u_char		font_8[256*8];
183 	u_char		font_14[256*14];
184 #ifdef STD8X16FONT
185 extern
186 #endif
187 	u_char		font_16[256*16];
188 	u_char        	palette[256*3];
189 static	u_char 		*cut_buffer = NULL;
190 static	int		cut_buffer_size = 0;
191 static	int		mouse_level = 0;	/* sysmouse protocol level */
192 static	mousestatus_t	mouse_status = { 0, 0, 0, 0, 0, 0 };
193 static  u_short 	mouse_and_mask[16] = {
194 				0xc000, 0xe000, 0xf000, 0xf800,
195 				0xfc00, 0xfe00, 0xff00, 0xff80,
196 				0xfe00, 0x1e00, 0x1f00, 0x0f00,
197 				0x0f00, 0x0000, 0x0000, 0x0000
198 			};
199 static  u_short 	mouse_or_mask[16] = {
200 				0x0000, 0x4000, 0x6000, 0x7000,
201 				0x7800, 0x7c00, 0x7e00, 0x6800,
202 				0x0c00, 0x0c00, 0x0600, 0x0600,
203 				0x0000, 0x0000, 0x0000, 0x0000
204 			};
205 
206 	int		sc_history_size = SC_HISTORY_SIZE;
207 static	int		extra_history_size =
208 			    SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
209 
210 static void    		none_saver(int blank) { }
211 static void    		(*current_saver)(int blank) = none_saver;
212 static void    		(*default_saver)(int blank) = none_saver;
213 	int  		(*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
214 					 int flag, struct proc *p) = NULL;
215 
216 static int		sticky_splash = FALSE;
217 
218 /* OS specific stuff */
219 #ifdef not_yet_done
220 #define VIRTUAL_TTY(x)  (sccons[x] = ttymalloc(sccons[x]))
221 struct  CONSOLE_TTY 	(sccons[MAXCONS] = ttymalloc(sccons[MAXCONS]))
222 struct  MOUSE_TTY 	(sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1]))
223 struct  tty         	*sccons[MAXCONS+2];
224 #else
225 #define VIRTUAL_TTY(x)  &sccons[x]
226 #define CONSOLE_TTY 	&sccons[MAXCONS]
227 #define MOUSE_TTY 	&sccons[MAXCONS+1]
228 static struct tty     	sccons[MAXCONS+2];
229 #endif
230 #define SC_MOUSE 	128
231 #define SC_CONSOLE	255
232 u_short         	*Crtat;
233 static const int	nsccons = MAXCONS+2;
234 
235 #define WRAPHIST(scp, pointer, offset)\
236     ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\
237     + (offset)) % (scp->history_size)))
238 #define ISSIGVALID(sig)	((sig) > 0 && (sig) < NSIG)
239 
240 /* prototypes */
241 static int scattach(struct isa_device *dev);
242 static int scparam(struct tty *tp, struct termios *t);
243 static int scprobe(struct isa_device *dev);
244 static int scvidprobe(int unit, int flags);
245 static int sckbdprobe(int unit, int flags);
246 static void scstart(struct tty *tp);
247 static void scmousestart(struct tty *tp);
248 static void scinit(void);
249 static void scshutdown(int howto, void *arg);
250 static u_int scgetc(u_int flags);
251 #define SCGETC_CN	1
252 #define SCGETC_NONBLOCK	2
253 static void sccnupdate(scr_stat *scp);
254 static scr_stat *alloc_scp(void);
255 static void init_scp(scr_stat *scp);
256 static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark);
257 static int get_scr_num(void);
258 static timeout_t scrn_timer;
259 static void scrn_update(scr_stat *scp, int show_cursor);
260 static void scrn_saver(void (*saver)(int), int blank);
261 static void stop_scrn_saver(void (*saver)(int));
262 static int wait_scrn_saver_stop(void);
263 static int switch_scr(scr_stat *scp, u_int next_scr);
264 static void exchange_scr(void);
265 static void scan_esc(scr_stat *scp, u_char c);
266 static void ansi_put(scr_stat *scp, u_char *buf, int len);
267 static void draw_cursor_image(scr_stat *scp);
268 static void remove_cursor_image(scr_stat *scp);
269 static void move_crsr(scr_stat *scp, int x, int y);
270 static u_char *get_fstr(u_int c, u_int *len);
271 static void history_to_screen(scr_stat *scp);
272 static int history_up_line(scr_stat *scp);
273 static int history_down_line(scr_stat *scp);
274 static int mask2attr(struct term_stat *term);
275 static void set_keyboard(int command, int data);
276 static void update_leds(int which);
277 static void set_destructive_cursor(scr_stat *scp);
278 static void set_mouse_pos(scr_stat *scp);
279 static int skip_spc_right(scr_stat *scp, u_short *p);
280 static int skip_spc_left(scr_stat *scp, u_short *p);
281 static void mouse_cut(scr_stat *scp);
282 static void mouse_cut_start(scr_stat *scp);
283 static void mouse_cut_end(scr_stat *scp);
284 static void mouse_cut_word(scr_stat *scp);
285 static void mouse_cut_line(scr_stat *scp);
286 static void mouse_cut_extend(scr_stat *scp);
287 static void mouse_paste(scr_stat *scp);
288 static void draw_mouse_image(scr_stat *scp);
289 static void remove_mouse_image(scr_stat *scp);
290 static void draw_cutmarking(scr_stat *scp);
291 static void remove_cutmarking(scr_stat *scp);
292 static void do_bell(scr_stat *scp, int pitch, int duration);
293 static timeout_t blink_screen;
294 #ifdef SC_SPLASH_SCREEN
295 static void scsplash_init(scr_stat *scp);
296 static void scsplash_saver(int show);
297 #define scsplash_stick(stick)		(sticky_splash = (stick))
298 #else
299 #define scsplash_stick(stick)
300 #endif
301 
302 struct  isa_driver scdriver = {
303     scprobe, scattach, "sc", 1
304 };
305 
306 static	d_open_t	scopen;
307 static	d_close_t	scclose;
308 static	d_read_t	scread;
309 static	d_write_t	scwrite;
310 static	d_ioctl_t	scioctl;
311 	d_devtotty_t	scdevtotty;
312 static	d_mmap_t	scmmap;
313 
314 #define	CDEV_MAJOR	12
315 static	struct cdevsw	sc_cdevsw = {
316 	scopen,		scclose,	scread,		scwrite,
317 	scioctl,	nullstop,	noreset,	scdevtotty,
318 	ttpoll,		scmmap,		nostrategy,	"sc",
319 	NULL,		-1,		nodump,		nopsize,
320 	D_TTY,
321 };
322 
323 /*
324  * These functions need to be before calls to them so they can be inlined.
325  */
326 static void
327 draw_cursor_image(scr_stat *scp)
328 {
329     u_short cursor_image, *ptr = Crtat + (scp->cursor_pos - scp->scr_buf);
330     u_short prev_image;
331 
332     if (ISPIXELSC(scp)) {
333 	sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf,
334 	  scp->cursor_pos - scp->scr_buf, 1);
335 	return;
336     }
337 
338     /* do we have a destructive cursor ? */
339     if (flags & CHAR_CURSOR) {
340 	prev_image = scp->cursor_saveunder;
341 	cursor_image = *ptr & 0x00ff;
342 	if (cursor_image == DEAD_CHAR)
343 	    cursor_image = prev_image & 0x00ff;
344 	cursor_image |= *(scp->cursor_pos) & 0xff00;
345 	scp->cursor_saveunder = cursor_image;
346 	/* update the cursor bitmap if the char under the cursor has changed */
347 	if (prev_image != cursor_image)
348 	    set_destructive_cursor(scp);
349 	/* modify cursor_image */
350 	if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){
351 	    /*
352 	     * When the mouse pointer is at the same position as the cursor,
353 	     * the cursor bitmap needs to be updated even if the char under
354 	     * the cursor hasn't changed, because the mouse pionter may
355 	     * have moved by a few dots within the cursor cel.
356 	     */
357 	    if ((prev_image == cursor_image)
358 		    && (cursor_image != *(scp->cursor_pos)))
359 	        set_destructive_cursor(scp);
360 	    cursor_image &= 0xff00;
361 	    cursor_image |= DEAD_CHAR;
362 	}
363     } else {
364 	cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00;
365 	scp->cursor_saveunder = cursor_image;
366 	if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){
367 	    if ((cursor_image & 0x7000) == 0x7000) {
368 		cursor_image &= 0x8fff;
369 		if(!(cursor_image & 0x0700))
370 		    cursor_image |= 0x0700;
371 	    } else {
372 		cursor_image |= 0x7000;
373 		if ((cursor_image & 0x0700) == 0x0700)
374 		    cursor_image &= 0xf0ff;
375 	    }
376 	}
377     }
378     *ptr = cursor_image;
379 }
380 
381 static void
382 remove_cursor_image(scr_stat *scp)
383 {
384     if (ISPIXELSC(scp))
385 	sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf,
386 	  scp->cursor_oldpos - scp->scr_buf, 0);
387     else
388 	*(Crtat + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder;
389 }
390 
391 static void
392 move_crsr(scr_stat *scp, int x, int y)
393 {
394     if (x < 0)
395 	x = 0;
396     if (y < 0)
397 	y = 0;
398     if (x >= scp->xsize)
399 	x = scp->xsize-1;
400     if (y >= scp->ysize)
401 	y = scp->ysize-1;
402     scp->xpos = x;
403     scp->ypos = y;
404     scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos;
405 }
406 
407 static int
408 scprobe(struct isa_device *dev)
409 {
410     if (!scvidprobe(dev->id_unit, dev->id_flags)) {
411 	if (bootverbose)
412 	    printf("sc%d: no video adapter is found.\n", dev->id_unit);
413 	return (0);
414     }
415     (*biosvidsw.diag)(bootverbose);
416 #if defined(VESA) && defined(VM86)
417     if (vesa_load())
418 	return FALSE;
419     (*biosvidsw.diag)(bootverbose);
420 #endif
421 
422     sc_port = dev->id_iobase;
423     if (sckbdprobe(dev->id_unit, dev->id_flags))
424 	return (IO_KBDSIZE);
425     else
426         return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE);
427 }
428 
429 /* probe video adapters, return TRUE if found */
430 static int
431 scvidprobe(int unit, int flags)
432 {
433     video_adapter_t *adp;
434 
435     /* do this test only once */
436     if (init_done != COLD)
437 	return (crtc_type != -1);
438 
439     if ((*biosvidsw.init)() <= 0)
440 	return FALSE;
441     if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL)
442 	return FALSE;
443 
444     crtc_type = adp->va_type;
445     crtc_vga = (crtc_type == KD_VGA);
446     crtc_addr = adp->va_crtc_addr;
447     Crtat = (u_short *)adp->va_window;
448     adp_flags = adp->va_flags;
449     initial_video_mode = adp->va_initial_mode;
450     bios_video_mode = adp->va_initial_bios_mode;
451 
452     return TRUE;
453 }
454 
455 /* probe the keyboard, return TRUE if found */
456 static int
457 sckbdprobe(int unit, int flags)
458 {
459     int codeset;
460     int c = -1;
461     int m;
462     int res, id;
463 
464     sc_kbdc = kbdc_open(sc_port);
465 
466     if (!kbdc_lock(sc_kbdc, TRUE)) {
467 	/* driver error? */
468 	printf("sc%d: unable to lock the controller.\n", unit);
469         return ((flags & DETECT_KBD) ? FALSE : TRUE);
470     }
471 
472     /* discard anything left after UserConfig */
473     empty_both_buffers(sc_kbdc, 10);
474 
475     /* save the current keyboard controller command byte */
476     m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS;
477     c = get_controller_command_byte(sc_kbdc);
478     if (c == -1) {
479 	/* CONTROLLER ERROR */
480 	printf("sc%d: unable to get the current command byte value.\n", unit);
481 	goto fail;
482     }
483     if (bootverbose)
484 	printf("sc%d: the current keyboard controller command byte %04x\n",
485 	    unit, c);
486 #if 0
487     /* override the keyboard lock switch */
488     c |= KBD_OVERRIDE_KBD_LOCK;
489 #endif
490 
491     /*
492      * The keyboard may have been screwed up by the boot block.
493      * We may just be able to recover from error by testing the controller
494      * and the keyboard port. The controller command byte needs to be saved
495      * before this recovery operation, as some controllers seem to set
496      * the command byte to particular values.
497      */
498     test_controller(sc_kbdc);
499     test_kbd_port(sc_kbdc);
500 
501     /* enable the keyboard port, but disable the keyboard intr. */
502     if (!set_controller_command_byte(sc_kbdc,
503             KBD_KBD_CONTROL_BITS,
504             KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) {
505 	/* CONTROLLER ERROR
506 	 * there is very little we can do...
507 	 */
508 	printf("sc%d: unable to set the command byte.\n", unit);
509 	goto fail;
510      }
511 
512      /*
513       * Check if we have an XT keyboard before we attempt to reset it.
514       * The procedure assumes that the keyboard and the controller have
515       * been set up properly by BIOS and have not been messed up
516       * during the boot process.
517       */
518      codeset = -1;
519      if (flags & XT_KEYBD)
520 	 /* the user says there is a XT keyboard */
521 	 codeset = 1;
522 #ifdef DETECT_XT_KEYBOARD
523      else if ((c & KBD_TRANSLATION) == 0) {
524 	 /* SET_SCANCODE_SET is not always supported; ignore error */
525 	 if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0)
526 		 == KBD_ACK)
527 	     codeset = read_kbd_data(sc_kbdc);
528      }
529      if (bootverbose)
530          printf("sc%d: keyboard scancode set %d\n", unit, codeset);
531 #endif /* DETECT_XT_KEYBOARD */
532 
533     if (flags & KBD_NORESET) {
534         write_kbd_command(sc_kbdc, KBDC_ECHO);
535         if (read_kbd_data(sc_kbdc) != KBD_ECHO) {
536             empty_both_buffers(sc_kbdc, 10);
537             test_controller(sc_kbdc);
538             test_kbd_port(sc_kbdc);
539             if (bootverbose)
540                 printf("sc%d: failed to get response from the keyboard.\n",
541 		    unit);
542 	    goto fail;
543 	}
544     } else {
545         /* reset keyboard hardware */
546         if (!reset_kbd(sc_kbdc)) {
547             /* KEYBOARD ERROR
548              * Keyboard reset may fail either because the keyboard doen't
549              * exist, or because the keyboard doesn't pass the self-test,
550              * or the keyboard controller on the motherboard and the keyboard
551              * somehow fail to shake hands. It is just possible, particularly
552              * in the last case, that the keyoard controller may be left
553              * in a hung state. test_controller() and test_kbd_port() appear
554              * to bring the keyboard controller back (I don't know why and
555              * how, though.)
556              */
557             empty_both_buffers(sc_kbdc, 10);
558             test_controller(sc_kbdc);
559             test_kbd_port(sc_kbdc);
560             /* We could disable the keyboard port and interrupt... but,
561              * the keyboard may still exist (see above).
562              */
563             if (bootverbose)
564                 printf("sc%d: failed to reset the keyboard.\n", unit);
565             goto fail;
566         }
567     }
568 
569     /*
570      * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards
571      * such as those on the IBM ThinkPad laptop computers can be used
572      * with the standard console driver.
573      */
574     if (codeset == 1) {
575 	if (send_kbd_command_and_data(
576 	        sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
577 	    /* XT kbd doesn't need scan code translation */
578 	    c &= ~KBD_TRANSLATION;
579 	} else {
580 	    /* KEYBOARD ERROR
581 	     * The XT kbd isn't usable unless the proper scan code set
582 	     * is selected.
583 	     */
584 	    printf("sc%d: unable to set the XT keyboard mode.\n", unit);
585 	    goto fail;
586 	}
587     }
588     /* enable the keyboard port and intr. */
589     if (!set_controller_command_byte(sc_kbdc,
590             KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
591 	    (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
592 	        | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) {
593 	/* CONTROLLER ERROR
594 	 * This is serious; we are left with the disabled keyboard intr.
595 	 */
596 	printf("sc%d: unable to enable the keyboard port and intr.\n", unit);
597 	goto fail;
598     }
599 
600     /* Get the ID of the keyboard, if any */
601     empty_kbd_buffer(sc_kbdc, 5);
602     res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID);
603     if (res == KBD_ACK) {
604 	/* 10ms delay */
605 	DELAY(10000);
606 	id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc);
607 	if (bootverbose)
608 	    printf("sc%d: keyboard device ID: %04x\n", unit, id);
609     }
610 
611     kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS),
612     kbdc_lock(sc_kbdc, FALSE);
613     return TRUE;
614 
615 fail:
616     if (c != -1)
617         /* try to restore the command byte as before, if possible */
618         set_controller_command_byte(sc_kbdc, 0xff, c);
619     kbdc_set_device_mask(sc_kbdc,
620         (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS);
621     kbdc_lock(sc_kbdc, FALSE);
622     return FALSE;
623 }
624 
625 #if NAPM > 0
626 static int
627 scresume(void *dummy)
628 {
629 	shfts = ctls = alts = agrs = metas = accents = 0;
630 	return 0;
631 }
632 #endif
633 
634 static int
635 scattach(struct isa_device *dev)
636 {
637     scr_stat *scp;
638     video_info_t info;
639     dev_t cdev = makedev(CDEV_MAJOR, 0);
640 #ifdef DEVFS
641     int vc;
642 #endif
643 
644     scinit();
645     flags = dev->id_flags;
646     if (!ISFONTAVAIL(adp_flags))
647 	flags &= ~CHAR_CURSOR;
648 
649     scp = console[0];
650 
651     /* copy temporary buffer to final buffer */
652     scp->scr_buf = NULL;
653     sc_alloc_scr_buffer(scp, FALSE, FALSE);
654     bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short));
655 
656     /* cut buffer is available only when the mouse pointer is used */
657     if (ISMOUSEAVAIL(adp_flags))
658 	sc_alloc_cut_buffer(scp, FALSE);
659 
660     /* initialize history buffer & pointers */
661     sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE);
662 
663 #if defined(VESA) && defined(VM86)
664     if ((flags & VESA800X600)
665 	&& ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) {
666 	sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
667 	sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
668 	initial_video_mode = M_VESA_800x600;
669     }
670 #endif /* VESA && VM86 */
671 
672     /* initialize cursor stuff */
673     if (!ISGRAPHSC(scp))
674     	draw_cursor_image(scp);
675 
676     /* get screen update going */
677     scrn_timer((void *)TRUE);
678 
679     update_leds(scp->status);
680 
681     printf("sc%d: ", dev->id_unit);
682     switch(crtc_type) {
683     case KD_VGA:
684 	printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
685 	break;
686     case KD_EGA:
687 	printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
688 	break;
689     case KD_CGA:
690 	printf("CGA");
691 	break;
692     case KD_MONO:
693     case KD_HERCULES:
694     default:
695 	printf("MDA/Hercules");
696 	break;
697     }
698     printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags);
699 
700 #if NAPM > 0
701     scp->r_hook.ah_fun = scresume;
702     scp->r_hook.ah_arg = NULL;
703     scp->r_hook.ah_name = "system keyboard";
704     scp->r_hook.ah_order = APM_MID_ORDER;
705     apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook);
706 #endif
707 
708     at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC);
709 
710     cdevsw_add(&cdev, &sc_cdevsw, NULL);
711 
712 #ifdef DEVFS
713     for (vc = 0; vc < MAXCONS; vc++)
714         sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR,
715 				UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc);
716     sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR,
717 				UID_ROOT, GID_WHEEL, 0600, "sysmouse");
718     sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR,
719 				UID_ROOT, GID_WHEEL, 0600, "consolectl");
720 #endif
721     return 0;
722 }
723 
724 struct tty
725 *scdevtotty(dev_t dev)
726 {
727     int unit = minor(dev);
728 
729     if (init_done == COLD)
730 	return(NULL);
731     if (unit == SC_CONSOLE)
732 	return CONSOLE_TTY;
733     if (unit == SC_MOUSE)
734 	return MOUSE_TTY;
735     if (unit >= MAXCONS || unit < 0)
736 	return(NULL);
737     return VIRTUAL_TTY(unit);
738 }
739 
740 int
741 scopen(dev_t dev, int flag, int mode, struct proc *p)
742 {
743     struct tty *tp = scdevtotty(dev);
744 
745     if (!tp)
746 	return(ENXIO);
747 
748     tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart;
749     tp->t_param = scparam;
750     tp->t_dev = dev;
751     if (!(tp->t_state & TS_ISOPEN)) {
752 	ttychars(tp);
753         /* Use the current setting of the <-- key as default VERASE. */
754         /* If the Delete key is preferable, an stty is necessary     */
755         tp->t_cc[VERASE] = key_map.key[0x0e].map[0];
756 	tp->t_iflag = TTYDEF_IFLAG;
757 	tp->t_oflag = TTYDEF_OFLAG;
758 	tp->t_cflag = TTYDEF_CFLAG;
759 	tp->t_lflag = TTYDEF_LFLAG;
760 	tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
761 	scparam(tp, &tp->t_termios);
762 	(*linesw[tp->t_line].l_modem)(tp, 1);
763     	if (minor(dev) == SC_MOUSE)
764 	    mouse_level = 0;		/* XXX */
765     }
766     else
767 	if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
768 	    return(EBUSY);
769     if (minor(dev) < MAXCONS && !console[minor(dev)]) {
770 	console[minor(dev)] = alloc_scp();
771 	if (ISGRAPHSC(console[minor(dev)]))
772 	    sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16);
773     }
774     if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
775 	tp->t_winsize.ws_col = console[minor(dev)]->xsize;
776 	tp->t_winsize.ws_row = console[minor(dev)]->ysize;
777     }
778     return ((*linesw[tp->t_line].l_open)(dev, tp));
779 }
780 
781 int
782 scclose(dev_t dev, int flag, int mode, struct proc *p)
783 {
784     struct tty *tp = scdevtotty(dev);
785     struct scr_stat *scp;
786 
787     if (!tp)
788 	return(ENXIO);
789     if (minor(dev) < MAXCONS) {
790 	scp = sc_get_scr_stat(tp->t_dev);
791 	if (scp->status & SWITCH_WAIT_ACQ)
792 	    wakeup((caddr_t)&scp->smode);
793 #if not_yet_done
794 	if (scp == &main_console) {
795 	    scp->pid = 0;
796 	    scp->proc = NULL;
797 	    scp->smode.mode = VT_AUTO;
798 	}
799 	else {
800 	    free(scp->scr_buf, M_DEVBUF);
801 	    if (scp->history != NULL) {
802 		free(scp->history, M_DEVBUF);
803 		if (scp->history_size / scp->xsize
804 			> imax(sc_history_size, scp->ysize))
805 		    extra_history_size += scp->history_size / scp->xsize
806 			- imax(sc_history_size, scp->ysize);
807 	    }
808 	    free(scp, M_DEVBUF);
809 	    console[minor(dev)] = NULL;
810 	}
811 #else
812 	scp->pid = 0;
813 	scp->proc = NULL;
814 	scp->smode.mode = VT_AUTO;
815 #endif
816     }
817     spltty();
818     (*linesw[tp->t_line].l_close)(tp, flag);
819     ttyclose(tp);
820     spl0();
821     return(0);
822 }
823 
824 int
825 scread(dev_t dev, struct uio *uio, int flag)
826 {
827     struct tty *tp = scdevtotty(dev);
828 
829     if (!tp)
830 	return(ENXIO);
831     return((*linesw[tp->t_line].l_read)(tp, uio, flag));
832 }
833 
834 int
835 scwrite(dev_t dev, struct uio *uio, int flag)
836 {
837     struct tty *tp = scdevtotty(dev);
838 
839     if (!tp)
840 	return(ENXIO);
841     return((*linesw[tp->t_line].l_write)(tp, uio, flag));
842 }
843 
844 void
845 scintr(int unit)
846 {
847     static struct tty *cur_tty;
848     int c, len;
849     u_char *cp;
850 
851     /*
852      * Loop while there is still input to get from the keyboard.
853      * I don't think this is nessesary, and it doesn't fix
854      * the Xaccel-2.1 keyboard hang, but it can't hurt.		XXX
855      */
856     while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) {
857 
858 	cur_tty = VIRTUAL_TTY(get_scr_num());
859 	if (!(cur_tty->t_state & TS_ISOPEN))
860 	    if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN))
861 		continue;
862 
863 	switch (c & 0xff00) {
864 	case 0x0000: /* normal key */
865 	    (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
866 	    break;
867 	case FKEY:  /* function key, return string */
868 	    if (cp = get_fstr((u_int)c, (u_int *)&len)) {
869 	    	while (len-- >  0)
870 		    (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty);
871 	    }
872 	    break;
873 	case MKEY:  /* meta is active, prepend ESC */
874 	    (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
875 	    (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
876 	    break;
877 	case BKEY:  /* backtab fixed sequence (esc [ Z) */
878 	    (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
879 	    (*linesw[cur_tty->t_line].l_rint)('[', cur_tty);
880 	    (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty);
881 	    break;
882 	}
883     }
884 
885 #if 0
886     if (cur_console->status & MOUSE_ENABLED) {
887 	cur_console->status &= ~MOUSE_VISIBLE;
888 	remove_mouse_image(cur_console);
889     }
890 #else
891     if (cur_console->status & MOUSE_VISIBLE) {
892 	remove_mouse_image(cur_console);
893 	cur_console->status &= ~MOUSE_VISIBLE;
894     }
895 #endif
896 }
897 
898 static int
899 scparam(struct tty *tp, struct termios *t)
900 {
901     tp->t_ispeed = t->c_ispeed;
902     tp->t_ospeed = t->c_ospeed;
903     tp->t_cflag = t->c_cflag;
904     return 0;
905 }
906 
907 int
908 scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
909 {
910     int error;
911     u_int i;
912     struct tty *tp;
913     scr_stat *scp;
914     video_adapter_t *adp;
915     int s;
916 
917     tp = scdevtotty(dev);
918     if (!tp)
919 	return ENXIO;
920     scp = sc_get_scr_stat(tp->t_dev);
921 
922     /* If there is a user_ioctl function call that first */
923     if (sc_user_ioctl) {
924 	error = (*sc_user_ioctl)(dev, cmd, data, flag, p);
925 	if (error != ENOIOCTL)
926 	    return error;
927     }
928 
929     error = sc_vid_ioctl(tp, cmd, data, flag, p);
930     if (error != ENOIOCTL)
931 	return error;
932 
933     switch (cmd) {  		/* process console hardware related ioctl's */
934 
935     case GIO_ATTR:      	/* get current attributes */
936 	*(int*)data = (scp->term.cur_attr >> 8) & 0xFF;
937 	return 0;
938 
939     case GIO_COLOR:     	/* is this a color console ? */
940 	*(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0;
941 	return 0;
942 
943     case CONS_BLANKTIME:    	/* set screen saver timeout (0 = no saver) */
944 	if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME)
945             return EINVAL;
946 	s = spltty();
947 	scrn_blank_time = *(int *)data;
948 	run_scrn_saver = (scrn_blank_time != 0);
949 	splx(s);
950 	return 0;
951 
952     case CONS_CURSORTYPE:   	/* set cursor type blink/noblink */
953 	if ((*(int*)data) & 0x01)
954 	    flags |= BLINK_CURSOR;
955 	else
956 	    flags &= ~BLINK_CURSOR;
957 	if ((*(int*)data) & 0x02) {
958 	    if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
959 		return ENXIO;
960 	    flags |= CHAR_CURSOR;
961 	} else
962 	    flags &= ~CHAR_CURSOR;
963 	/*
964 	 * The cursor shape is global property; all virtual consoles
965 	 * are affected. Update the cursor in the current console...
966 	 */
967 	if (!ISGRAPHSC(cur_console)) {
968             remove_cursor_image(cur_console);
969 	    if (flags & CHAR_CURSOR)
970 	        set_destructive_cursor(cur_console);
971 	    draw_cursor_image(cur_console);
972 	}
973 	return 0;
974 
975     case CONS_BELLTYPE: 	/* set bell type sound/visual */
976 	if ((*(int *)data) & 0x01)
977 	    flags |= VISUAL_BELL;
978 	else
979 	    flags &= ~VISUAL_BELL;
980 	if ((*(int *)data) & 0x02)
981 	    flags |= QUIET_BELL;
982 	else
983 	    flags &= ~QUIET_BELL;
984 	return 0;
985 
986     case CONS_HISTORY:  	/* set history size */
987 	if (*(int *)data > 0) {
988 	    int lines;	/* buffer size to allocate */
989 	    int lines0;	/* current buffer size */
990 
991 	    lines = imax(*(int *)data, scp->ysize);
992 	    lines0 = (scp->history != NULL) ?
993 		      scp->history_size / scp->xsize : scp->ysize;
994 	    if (lines0 > imax(sc_history_size, scp->ysize))
995 		i = lines0 - imax(sc_history_size, scp->ysize);
996 	    else
997 		i = 0;
998 	    /*
999 	     * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
1000 	     * lines or scp->ysize lines, whichever is larger. A value
1001 	     * greater than that is allowed, subject to extra_history_size.
1002 	     */
1003 	    if (lines > imax(sc_history_size, scp->ysize))
1004 		if (lines - imax(sc_history_size, scp->ysize) >
1005 		    extra_history_size + i)
1006 		    return EINVAL;
1007             if (cur_console->status & BUFFER_SAVED)
1008                 return EBUSY;
1009 	    sc_alloc_history_buffer(scp, lines, i, TRUE);
1010 	    return 0;
1011 	}
1012 	else
1013 	    return EINVAL;
1014 
1015     case CONS_MOUSECTL:		/* control mouse arrow */
1016     case OLD_CONS_MOUSECTL:
1017     {
1018 	/* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
1019 	static butmap[8] = {
1020             MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP
1021 		| MOUSE_MSC_BUTTON3UP,
1022             MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1023             MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
1024             MOUSE_MSC_BUTTON3UP,
1025             MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
1026             MOUSE_MSC_BUTTON2UP,
1027             MOUSE_MSC_BUTTON1UP,
1028             0,
1029 	};
1030 	mouse_info_t *mouse = (mouse_info_t*)data;
1031 	mouse_info_t buf;
1032 
1033 	/* FIXME: */
1034 	if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags))
1035 	    return ENODEV;
1036 
1037 	if (cmd == OLD_CONS_MOUSECTL) {
1038 	    static unsigned char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
1039 	    old_mouse_info_t *old_mouse = (old_mouse_info_t *)data;
1040 
1041 	    mouse = &buf;
1042 	    mouse->operation = old_mouse->operation;
1043 	    switch (mouse->operation) {
1044 	    case MOUSE_MODE:
1045 		mouse->u.mode = old_mouse->u.mode;
1046 		break;
1047 	    case MOUSE_SHOW:
1048 	    case MOUSE_HIDE:
1049 		break;
1050 	    case MOUSE_MOVEABS:
1051 	    case MOUSE_MOVEREL:
1052 	    case MOUSE_ACTION:
1053 		mouse->u.data.x = old_mouse->u.data.x;
1054 		mouse->u.data.y = old_mouse->u.data.y;
1055 		mouse->u.data.z = 0;
1056 		mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7];
1057 		break;
1058 	    case MOUSE_GETINFO:
1059 		old_mouse->u.data.x = scp->mouse_xpos;
1060 		old_mouse->u.data.y = scp->mouse_ypos;
1061 		old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7];
1062 		break;
1063 	    default:
1064 		return EINVAL;
1065 	    }
1066 	}
1067 
1068 	switch (mouse->operation) {
1069 	case MOUSE_MODE:
1070 	    if (ISSIGVALID(mouse->u.mode.signal)) {
1071 		scp->mouse_signal = mouse->u.mode.signal;
1072 		scp->mouse_proc = p;
1073 		scp->mouse_pid = p->p_pid;
1074 	    }
1075 	    else {
1076 		scp->mouse_signal = 0;
1077 		scp->mouse_proc = NULL;
1078 		scp->mouse_pid = 0;
1079 	    }
1080 	    return 0;
1081 
1082 	case MOUSE_SHOW:
1083 	    if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) {
1084 		scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE);
1085 		scp->mouse_oldpos = scp->mouse_pos;
1086 		mark_all(scp);
1087 		return 0;
1088 	    }
1089 	    else
1090 		return EINVAL;
1091 	    break;
1092 
1093 	case MOUSE_HIDE:
1094 	    if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) {
1095 		scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
1096 		mark_all(scp);
1097 		return 0;
1098 	    }
1099 	    else
1100 		return EINVAL;
1101 	    break;
1102 
1103 	case MOUSE_MOVEABS:
1104 	    scp->mouse_xpos = mouse->u.data.x;
1105 	    scp->mouse_ypos = mouse->u.data.y;
1106 	    set_mouse_pos(scp);
1107 	    break;
1108 
1109 	case MOUSE_MOVEREL:
1110 	    scp->mouse_xpos += mouse->u.data.x;
1111 	    scp->mouse_ypos += mouse->u.data.y;
1112 	    set_mouse_pos(scp);
1113 	    break;
1114 
1115 	case MOUSE_GETINFO:
1116 	    mouse->u.data.x = scp->mouse_xpos;
1117 	    mouse->u.data.y = scp->mouse_ypos;
1118 	    mouse->u.data.z = 0;
1119 	    mouse->u.data.buttons = scp->mouse_buttons;
1120 	    return 0;
1121 
1122 	case MOUSE_ACTION:
1123 	case MOUSE_MOTION_EVENT:
1124 	    /* this should maybe only be settable from /dev/consolectl SOS */
1125 	    /* send out mouse event on /dev/sysmouse */
1126 
1127 	    mouse_status.dx += mouse->u.data.x;
1128 	    mouse_status.dy += mouse->u.data.y;
1129 	    mouse_status.dz += mouse->u.data.z;
1130 	    if (mouse->operation == MOUSE_ACTION)
1131 	        mouse_status.button = mouse->u.data.buttons;
1132 	    mouse_status.flags |=
1133 		((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ?
1134 		    MOUSE_POSCHANGED : 0)
1135 		| (mouse_status.obutton ^ mouse_status.button);
1136 	    if (mouse_status.flags == 0)
1137 		return 0;
1138 
1139 	    if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
1140 	    	cur_console->status |= MOUSE_VISIBLE;
1141 
1142 	    if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
1143 		u_char buf[MOUSE_SYS_PACKETSIZE];
1144 		int j;
1145 
1146 		/* the first five bytes are compatible with MouseSystems' */
1147 		buf[0] = MOUSE_MSC_SYNC
1148 		    | butmap[mouse_status.button & MOUSE_STDBUTTONS];
1149 		j = imax(imin(mouse->u.data.x, 255), -256);
1150 		buf[1] = j >> 1;
1151 		buf[3] = j - buf[1];
1152 		j = -imax(imin(mouse->u.data.y, 255), -256);
1153 		buf[2] = j >> 1;
1154 		buf[4] = j - buf[2];
1155 		for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++)
1156 	    		(*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
1157 		if (mouse_level >= 1) { 	/* extended part */
1158 		    j = imax(imin(mouse->u.data.z, 127), -128);
1159 		    buf[5] = (j >> 1) & 0x7f;
1160 		    buf[6] = (j - (j >> 1)) & 0x7f;
1161 		    /* buttons 4-10 */
1162 		    buf[7] = (~mouse_status.button >> 3) & 0x7f;
1163 		    for (j = MOUSE_MSC_PACKETSIZE;
1164 			 j < MOUSE_SYS_PACKETSIZE; j++)
1165 	    		(*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY);
1166 		}
1167 	    }
1168 
1169 	    if (cur_console->mouse_signal) {
1170 		cur_console->mouse_buttons = mouse->u.data.buttons;
1171     		/* has controlling process died? */
1172 		if (cur_console->mouse_proc &&
1173 		    (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
1174 		    	cur_console->mouse_signal = 0;
1175 			cur_console->mouse_proc = NULL;
1176 			cur_console->mouse_pid = 0;
1177 		}
1178 		else
1179 		    psignal(cur_console->mouse_proc, cur_console->mouse_signal);
1180 	    }
1181 	    else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) {
1182 		/* process button presses */
1183 		if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) &&
1184 		    ISTEXTSC(cur_console)) {
1185 		    cur_console->mouse_buttons = mouse->u.data.buttons;
1186 		    if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)
1187 			mouse_cut_start(cur_console);
1188 		    else
1189 			mouse_cut_end(cur_console);
1190 		    if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN ||
1191 			cur_console->mouse_buttons & MOUSE_BUTTON3DOWN)
1192 			mouse_paste(cur_console);
1193 		}
1194 	    }
1195 
1196 	    if (mouse->u.data.x != 0 || mouse->u.data.y != 0) {
1197 		cur_console->mouse_xpos += mouse->u.data.x;
1198 		cur_console->mouse_ypos += mouse->u.data.y;
1199 		set_mouse_pos(cur_console);
1200 	    }
1201 
1202 	    break;
1203 
1204 	case MOUSE_BUTTON_EVENT:
1205 	    if ((mouse->u.event.id & MOUSE_BUTTONS) == 0)
1206 		return EINVAL;
1207 	    if (mouse->u.event.value < 0)
1208 		return EINVAL;
1209 
1210 	    if (mouse->u.event.value > 0) {
1211 	        cur_console->mouse_buttons |= mouse->u.event.id;
1212 	        mouse_status.button |= mouse->u.event.id;
1213 	    } else {
1214 	        cur_console->mouse_buttons &= ~mouse->u.event.id;
1215 	        mouse_status.button &= ~mouse->u.event.id;
1216 	    }
1217 	    mouse_status.flags |= mouse_status.obutton ^ mouse_status.button;
1218 	    if (mouse_status.flags == 0)
1219 		return 0;
1220 
1221 	    if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
1222 	    	cur_console->status |= MOUSE_VISIBLE;
1223 
1224 	    if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
1225 		u_char buf[8];
1226 		int i;
1227 
1228 		buf[0] = MOUSE_MSC_SYNC
1229 			 | butmap[mouse_status.button & MOUSE_STDBUTTONS];
1230 		buf[7] = (~mouse_status.button >> 3) & 0x7f;
1231 		buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
1232 		for (i = 0;
1233 		     i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE
1234 					     : MOUSE_MSC_PACKETSIZE); i++)
1235 	    	    (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY);
1236 	    }
1237 
1238 	    if (cur_console->mouse_signal) {
1239 		if (cur_console->mouse_proc &&
1240 		    (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){
1241 		    	cur_console->mouse_signal = 0;
1242 			cur_console->mouse_proc = NULL;
1243 			cur_console->mouse_pid = 0;
1244 		}
1245 		else
1246 		    psignal(cur_console->mouse_proc, cur_console->mouse_signal);
1247 		break;
1248 	    }
1249 
1250 	    if (!ISTEXTSC(cur_console) || (cut_buffer == NULL))
1251 		break;
1252 
1253 	    switch (mouse->u.event.id) {
1254 	    case MOUSE_BUTTON1DOWN:
1255 	        switch (mouse->u.event.value % 4) {
1256 		case 0:	/* up */
1257 		    mouse_cut_end(cur_console);
1258 		    break;
1259 		case 1:
1260 		    mouse_cut_start(cur_console);
1261 		    break;
1262 		case 2:
1263 		    mouse_cut_word(cur_console);
1264 		    break;
1265 		case 3:
1266 		    mouse_cut_line(cur_console);
1267 		    break;
1268 		}
1269 		break;
1270 	    case MOUSE_BUTTON2DOWN:
1271 	        switch (mouse->u.event.value) {
1272 		case 0:	/* up */
1273 		    break;
1274 		default:
1275 		    mouse_paste(cur_console);
1276 		    break;
1277 		}
1278 		break;
1279 	    case MOUSE_BUTTON3DOWN:
1280 	        switch (mouse->u.event.value) {
1281 		case 0:	/* up */
1282 		    if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN))
1283 		        mouse_cut_end(cur_console);
1284 		    break;
1285 		default:
1286 		    mouse_cut_extend(cur_console);
1287 		    break;
1288 		}
1289 		break;
1290 	    }
1291 	    break;
1292 
1293 	default:
1294 	    return EINVAL;
1295 	}
1296 	/* make screensaver happy */
1297 	scsplash_stick(FALSE);
1298 	run_scrn_saver = FALSE;
1299 	return 0;
1300     }
1301 
1302     /* MOUSE_XXX: /dev/sysmouse ioctls */
1303     case MOUSE_GETHWINFO:	/* get device information */
1304     {
1305 	mousehw_t *hw = (mousehw_t *)data;
1306 
1307 	if (tp != MOUSE_TTY)
1308 	    return ENOTTY;
1309 	hw->buttons = 10;		/* XXX unknown */
1310 	hw->iftype = MOUSE_IF_SYSMOUSE;
1311 	hw->type = MOUSE_MOUSE;
1312 	hw->model = MOUSE_MODEL_GENERIC;
1313 	hw->hwid = 0;
1314 	return 0;
1315     }
1316 
1317     case MOUSE_GETMODE:		/* get protocol/mode */
1318     {
1319 	mousemode_t *mode = (mousemode_t *)data;
1320 
1321 	if (tp != MOUSE_TTY)
1322 	    return ENOTTY;
1323 	mode->level = mouse_level;
1324 	switch (mode->level) {
1325 	case 0:
1326 	    /* at this level, sysmouse emulates MouseSystems protocol */
1327 	    mode->protocol = MOUSE_PROTO_MSC;
1328 	    mode->rate = -1;		/* unknown */
1329 	    mode->resolution = -1;	/* unknown */
1330 	    mode->accelfactor = 0;	/* disabled */
1331 	    mode->packetsize = MOUSE_MSC_PACKETSIZE;
1332 	    mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
1333 	    mode->syncmask[1] = MOUSE_MSC_SYNC;
1334 	    break;
1335 
1336 	case 1:
1337 	    /* at this level, sysmouse uses its own protocol */
1338 	    mode->protocol = MOUSE_PROTO_SYSMOUSE;
1339 	    mode->rate = -1;
1340 	    mode->resolution = -1;
1341 	    mode->accelfactor = 0;
1342 	    mode->packetsize = MOUSE_SYS_PACKETSIZE;
1343 	    mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
1344 	    mode->syncmask[1] = MOUSE_SYS_SYNC;
1345 	    break;
1346 	}
1347 	return 0;
1348     }
1349 
1350     case MOUSE_SETMODE:		/* set protocol/mode */
1351     {
1352 	mousemode_t *mode = (mousemode_t *)data;
1353 
1354 	if (tp != MOUSE_TTY)
1355 	    return ENOTTY;
1356 	if ((mode->level < 0) || (mode->level > 1))
1357 	    return EINVAL;
1358 	mouse_level = mode->level;
1359 	return 0;
1360     }
1361 
1362     case MOUSE_GETLEVEL:	/* get operation level */
1363 	if (tp != MOUSE_TTY)
1364 	    return ENOTTY;
1365 	*(int *)data = mouse_level;
1366 	return 0;
1367 
1368     case MOUSE_SETLEVEL:	/* set operation level */
1369 	if (tp != MOUSE_TTY)
1370 	    return ENOTTY;
1371 	if ((*(int *)data  < 0) || (*(int *)data > 1))
1372 	    return EINVAL;
1373 	mouse_level = *(int *)data;
1374 	return 0;
1375 
1376     case MOUSE_GETSTATUS:	/* get accumulated mouse events */
1377 	if (tp != MOUSE_TTY)
1378 	    return ENOTTY;
1379 	s = spltty();
1380 	*(mousestatus_t *)data = mouse_status;
1381 	mouse_status.flags = 0;
1382 	mouse_status.obutton = mouse_status.button;
1383 	mouse_status.dx = 0;
1384 	mouse_status.dy = 0;
1385 	mouse_status.dz = 0;
1386 	splx(s);
1387 	return 0;
1388 
1389 #if notyet
1390     case MOUSE_GETVARS:		/* get internal mouse variables */
1391     case MOUSE_SETVARS:		/* set internal mouse variables */
1392 	if (tp != MOUSE_TTY)
1393 	    return ENOTTY;
1394 	return ENODEV;
1395 #endif
1396 
1397     case MOUSE_READSTATE:	/* read status from the device */
1398     case MOUSE_READDATA:	/* read data from the device */
1399 	if (tp != MOUSE_TTY)
1400 	    return ENOTTY;
1401 	return ENODEV;
1402 
1403     case CONS_GETINFO:  	/* get current (virtual) console info */
1404     {
1405 	vid_info_t *ptr = (vid_info_t*)data;
1406 	if (ptr->size == sizeof(struct vid_info)) {
1407 	    ptr->m_num = get_scr_num();
1408 	    ptr->mv_col = scp->xpos;
1409 	    ptr->mv_row = scp->ypos;
1410 	    ptr->mv_csz = scp->xsize;
1411 	    ptr->mv_rsz = scp->ysize;
1412 	    ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8;
1413 	    ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12;
1414 	    ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8;
1415 	    ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12;
1416 	    ptr->mv_grfc.fore = 0;      /* not supported */
1417 	    ptr->mv_grfc.back = 0;      /* not supported */
1418 	    ptr->mv_ovscan = scp->border;
1419 	    ptr->mk_keylock = scp->status & LOCK_KEY_MASK;
1420 	    return 0;
1421 	}
1422 	return EINVAL;
1423     }
1424 
1425     case CONS_GETVERS:  	/* get version number */
1426 	*(int*)data = 0x200;    /* version 2.0 */
1427 	return 0;
1428 
1429     case CONS_IDLE:		/* see if the screen has been idle */
1430 	/*
1431 	 * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE,
1432 	 * the user process may have been writing something on the
1433 	 * screen and syscons is not aware of it. Declare the screen
1434 	 * is NOT idle if it is in one of these modes. But there is
1435 	 * an exception to it; if a screen saver is running in the
1436 	 * graphics mode in the current screen, we should say that the
1437 	 * screen has been idle.
1438 	 */
1439 	*(int *)data = scrn_idle
1440 		       && (!ISGRAPHSC(cur_console)
1441 			   || (cur_console->status & SAVER_RUNNING));
1442 	return 0;
1443 
1444     case CONS_SAVERMODE:	/* set saver mode */
1445 	switch(*(int *)data) {
1446 	case CONS_USR_SAVER:
1447 	    /* if a LKM screen saver is running, stop it first. */
1448 	    scsplash_stick(FALSE);
1449 	    saver_mode = *(int *)data;
1450 	    s = spltty();
1451 	    if ((error = wait_scrn_saver_stop())) {
1452 		splx(s);
1453 		return error;
1454 	    }
1455 	    scp->status |= SAVER_RUNNING;
1456 	    scsplash_stick(TRUE);
1457 	    splx(s);
1458 	    break;
1459 	case CONS_LKM_SAVER:
1460 	    s = spltty();
1461 	    if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING))
1462 		scp->status &= ~SAVER_RUNNING;
1463 	    saver_mode = *(int *)data;
1464 	    splx(s);
1465 	    break;
1466 	default:
1467 	    return EINVAL;
1468 	}
1469 	return 0;
1470 
1471     case CONS_SAVERSTART:	/* immediately start/stop the screen saver */
1472 	/*
1473 	 * Note that this ioctl does not guarantee the screen saver
1474 	 * actually starts or stops. It merely attempts to do so...
1475 	 */
1476 	s = spltty();
1477 	run_scrn_saver = (*(int *)data != 0);
1478 	if (run_scrn_saver)
1479 	    scrn_time_stamp -= scrn_blank_time;
1480 	splx(s);
1481 	return 0;
1482 
1483     case VT_SETMODE:    	/* set screen switcher mode */
1484     {
1485 	struct vt_mode *mode;
1486 
1487 	mode = (struct vt_mode *)data;
1488 	if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) &&
1489 	    ISSIGVALID(mode->frsig)) {
1490 	    bcopy(data, &scp->smode, sizeof(struct vt_mode));
1491 	    if (scp->smode.mode == VT_PROCESS) {
1492 		scp->proc = p;
1493 		scp->pid = scp->proc->p_pid;
1494 	    }
1495 	    return 0;
1496 	} else
1497 	    return EINVAL;
1498     }
1499 
1500     case VT_GETMODE:    	/* get screen switcher mode */
1501 	bcopy(&scp->smode, data, sizeof(struct vt_mode));
1502 	return 0;
1503 
1504     case VT_RELDISP:    	/* screen switcher ioctl */
1505 	switch(*(int *)data) {
1506 	case VT_FALSE:  	/* user refuses to release screen, abort */
1507 	    if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
1508 		old_scp->status &= ~SWITCH_WAIT_REL;
1509 		switch_in_progress = FALSE;
1510 		return 0;
1511 	    }
1512 	    return EINVAL;
1513 
1514 	case VT_TRUE:   	/* user has released screen, go on */
1515 	    if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
1516 		scp->status &= ~SWITCH_WAIT_REL;
1517 		exchange_scr();
1518 		if (new_scp->smode.mode == VT_PROCESS) {
1519 		    new_scp->status |= SWITCH_WAIT_ACQ;
1520 		    psignal(new_scp->proc, new_scp->smode.acqsig);
1521 		}
1522 		else
1523 		    switch_in_progress = FALSE;
1524 		return 0;
1525 	    }
1526 	    return EINVAL;
1527 
1528 	case VT_ACKACQ: 	/* acquire acknowledged, switch completed */
1529 	    if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {
1530 		scp->status &= ~SWITCH_WAIT_ACQ;
1531 		switch_in_progress = FALSE;
1532 		return 0;
1533 	    }
1534 	    return EINVAL;
1535 
1536 	default:
1537 	    return EINVAL;
1538 	}
1539 	/* NOT REACHED */
1540 
1541     case VT_OPENQRY:    	/* return free virtual console */
1542 	for (i = 0; i < MAXCONS; i++) {
1543 	    tp = VIRTUAL_TTY(i);
1544 	    if (!(tp->t_state & TS_ISOPEN)) {
1545 		*(int *)data = i + 1;
1546 		return 0;
1547 	    }
1548 	}
1549 	return EINVAL;
1550 
1551     case VT_ACTIVATE:   	/* switch to screen *data */
1552 	return switch_scr(scp, *(int *)data - 1);
1553 
1554     case VT_WAITACTIVE: 	/* wait for switch to occur */
1555 	if (*(int *)data > MAXCONS || *(int *)data < 0)
1556 	    return EINVAL;
1557 	if (minor(dev) == *(int *)data - 1)
1558 	    return 0;
1559 	if (*(int *)data == 0) {
1560 	    if (scp == cur_console)
1561 		return 0;
1562 	}
1563 	else
1564 	    scp = console[*(int *)data - 1];
1565 	while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
1566 			     "waitvt", 0)) == ERESTART) ;
1567 	return error;
1568 
1569     case VT_GETACTIVE:
1570 	*(int *)data = get_scr_num()+1;
1571 	return 0;
1572 
1573     case KDENABIO:      	/* allow io operations */
1574 	error = suser(p->p_ucred, &p->p_acflag);
1575 	if (error != 0)
1576 	    return error;
1577 	if (securelevel > 0)
1578 	    return EPERM;
1579 	p->p_md.md_regs->tf_eflags |= PSL_IOPL;
1580 	return 0;
1581 
1582     case KDDISABIO:     	/* disallow io operations (default) */
1583 	p->p_md.md_regs->tf_eflags &= ~PSL_IOPL;
1584 	return 0;
1585 
1586     case KDSKBSTATE:    	/* set keyboard state (locks) */
1587 	if (*(int *)data & ~LOCK_KEY_MASK)
1588 	    return EINVAL;
1589 	scp->status &= ~LOCK_KEY_MASK;
1590 	scp->status |= *(int *)data;
1591 	if (scp == cur_console)
1592 	    update_leds(scp->status);
1593 	return 0;
1594 
1595     case KDGKBSTATE:    	/* get keyboard state (locks) */
1596 	*(int *)data = scp->status & LOCK_KEY_MASK;
1597 	return 0;
1598 
1599     case KDSETRAD:      	/* set keyboard repeat & delay rates */
1600 	if (*(int *)data & ~0x7f)
1601 	    return EINVAL;
1602 	if (sc_kbdc != NULL)
1603 	    set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data);
1604 	return 0;
1605 
1606     case KDSKBMODE:     	/* set keyboard mode */
1607 	switch (*(int *)data) {
1608 	case K_RAW: 		/* switch to RAW scancode mode */
1609 	    scp->status &= ~KBD_CODE_MODE;
1610 	    scp->status |= KBD_RAW_MODE;
1611 	    return 0;
1612 
1613 	case K_CODE: 		/* switch to CODE mode */
1614 	    scp->status &= ~KBD_RAW_MODE;
1615 	    scp->status |= KBD_CODE_MODE;
1616 	    return 0;
1617 
1618 	case K_XLATE:   	/* switch to XLT ascii mode */
1619 	    if (scp == cur_console && scp->status & KBD_RAW_MODE)
1620 		shfts = ctls = alts = agrs = metas = accents = 0;
1621 	    scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE);
1622 	    return 0;
1623 	default:
1624 	    return EINVAL;
1625 	}
1626 	/* NOT REACHED */
1627 
1628     case KDGKBMODE:     	/* get keyboard mode */
1629 	*(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW :
1630 		((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE);
1631 	return 0;
1632 
1633     case KDMKTONE:      	/* sound the bell */
1634 	if (*(int*)data)
1635 	    do_bell(scp, (*(int*)data)&0xffff,
1636 		    (((*(int*)data)>>16)&0xffff)*hz/1000);
1637 	else
1638 	    do_bell(scp, scp->bell_pitch, scp->bell_duration);
1639 	return 0;
1640 
1641     case KIOCSOUND:     	/* make tone (*data) hz */
1642 	if (scp == cur_console) {
1643 	    if (*(int*)data) {
1644 		int pitch = timer_freq / *(int*)data;
1645 
1646 		/* set command for counter 2, 2 byte write */
1647 		if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE))
1648 		    return EBUSY;
1649 
1650 		/* set pitch */
1651 		outb(TIMER_CNTR2, pitch);
1652 		outb(TIMER_CNTR2, (pitch>>8));
1653 
1654 		/* enable counter 2 output to speaker */
1655 		outb(IO_PPI, inb(IO_PPI) | 3);
1656 	    }
1657 	    else {
1658 		/* disable counter 2 output to speaker */
1659 		outb(IO_PPI, inb(IO_PPI) & 0xFC);
1660 		release_timer2();
1661 	    }
1662 	}
1663 	return 0;
1664 
1665     case KDGKBTYPE:     	/* get keyboard type */
1666 	*(int *)data = 0;  	/* type not known (yet) */
1667 	return 0;
1668 
1669     case KDSETLED:      	/* set keyboard LED status */
1670 	if (*(int *)data & ~LED_MASK)
1671 	    return EINVAL;
1672 	scp->status &= ~LED_MASK;
1673 	scp->status |= *(int *)data;
1674 	if (scp == cur_console)
1675 	    update_leds(scp->status);
1676 	return 0;
1677 
1678     case KDGETLED:      	/* get keyboard LED status */
1679 	*(int *)data = scp->status & LED_MASK;
1680 	return 0;
1681 
1682     case GETFKEY:       	/* get functionkey string */
1683 	if (*(u_short*)data < n_fkey_tab) {
1684 	    fkeyarg_t *ptr = (fkeyarg_t*)data;
1685 	    bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef,
1686 		  fkey_tab[ptr->keynum].len);
1687 	    ptr->flen = fkey_tab[ptr->keynum].len;
1688 	    return 0;
1689 	}
1690 	else
1691 	    return EINVAL;
1692 
1693     case SETFKEY:       	/* set functionkey string */
1694 	if (*(u_short*)data < n_fkey_tab) {
1695 	    fkeyarg_t *ptr = (fkeyarg_t*)data;
1696 	    bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str,
1697 		  min(ptr->flen, MAXFK));
1698 	    fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK);
1699 	    return 0;
1700 	}
1701 	else
1702 	    return EINVAL;
1703 
1704     case GIO_SCRNMAP:   	/* get output translation table */
1705 	bcopy(&scr_map, data, sizeof(scr_map));
1706 	return 0;
1707 
1708     case PIO_SCRNMAP:   	/* set output translation table */
1709 	bcopy(data, &scr_map, sizeof(scr_map));
1710 	for (i=0; i<sizeof(scr_map); i++)
1711 	    scr_rmap[scr_map[i]] = i;
1712 	return 0;
1713 
1714     case GIO_KEYMAP:    	/* get keyboard translation table */
1715 	bcopy(&key_map, data, sizeof(key_map));
1716 	return 0;
1717 
1718     case PIO_KEYMAP:    	/* set keyboard translation table */
1719 	accents = 0;
1720 	bzero(&accent_map, sizeof(accent_map));
1721 	bcopy(data, &key_map, sizeof(key_map));
1722 	return 0;
1723 
1724     case GIO_DEADKEYMAP:    	/* get accent key translation table */
1725 	bcopy(&accent_map, data, sizeof(accent_map));
1726 	return 0;
1727 
1728     case PIO_DEADKEYMAP:    	/* set accent key translation table */
1729 	accents = 0;
1730 	bcopy(data, &accent_map, sizeof(accent_map));
1731 	return 0;
1732 
1733     case PIO_FONT8x8:   	/* set 8x8 dot font */
1734 	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1735 	    return ENXIO;
1736 	bcopy(data, font_8, 8*256);
1737 	fonts_loaded |= FONT_8;
1738 	/*
1739 	 * FONT KLUDGE
1740 	 * Always use the font page #0. XXX
1741 	 * Don't load if the current font size is not 8x8.
1742 	 */
1743 	if (ISTEXTSC(cur_console) && (cur_console->font_size < 14))
1744 	    copy_font(cur_console, LOAD, 8, font_8);
1745 	return 0;
1746 
1747     case GIO_FONT8x8:   	/* get 8x8 dot font */
1748 	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1749 	    return ENXIO;
1750 	if (fonts_loaded & FONT_8) {
1751 	    bcopy(font_8, data, 8*256);
1752 	    return 0;
1753 	}
1754 	else
1755 	    return ENXIO;
1756 
1757     case PIO_FONT8x14:  	/* set 8x14 dot font */
1758 	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1759 	    return ENXIO;
1760 	bcopy(data, font_14, 14*256);
1761 	fonts_loaded |= FONT_14;
1762 	/*
1763 	 * FONT KLUDGE
1764 	 * Always use the font page #0. XXX
1765 	 * Don't load if the current font size is not 8x14.
1766 	 */
1767 	if (ISTEXTSC(cur_console)
1768 	    && (cur_console->font_size >= 14) && (cur_console->font_size < 16))
1769 	    copy_font(cur_console, LOAD, 14, font_14);
1770 	return 0;
1771 
1772     case GIO_FONT8x14:  	/* get 8x14 dot font */
1773 	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1774 	    return ENXIO;
1775 	if (fonts_loaded & FONT_14) {
1776 	    bcopy(font_14, data, 14*256);
1777 	    return 0;
1778 	}
1779 	else
1780 	    return ENXIO;
1781 
1782     case PIO_FONT8x16:  	/* set 8x16 dot font */
1783 	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1784 	    return ENXIO;
1785 	bcopy(data, font_16, 16*256);
1786 	fonts_loaded |= FONT_16;
1787 	/*
1788 	 * FONT KLUDGE
1789 	 * Always use the font page #0. XXX
1790 	 * Don't load if the current font size is not 8x16.
1791 	 */
1792 	if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16))
1793 	    copy_font(cur_console, LOAD, 16, font_16);
1794 	return 0;
1795 
1796     case GIO_FONT8x16:  	/* get 8x16 dot font */
1797 	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
1798 	    return ENXIO;
1799 	if (fonts_loaded & FONT_16) {
1800 	    bcopy(font_16, data, 16*256);
1801 	    return 0;
1802 	}
1803 	else
1804 	    return ENXIO;
1805     default:
1806 	break;
1807     }
1808 
1809     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1810     if (error != ENOIOCTL)
1811 	return(error);
1812     error = ttioctl(tp, cmd, data, flag);
1813     if (error != ENOIOCTL)
1814 	return(error);
1815     return(ENOTTY);
1816 }
1817 
1818 static void
1819 scstart(struct tty *tp)
1820 {
1821     struct clist *rbp;
1822     int s, len;
1823     u_char buf[PCBURST];
1824     scr_stat *scp = sc_get_scr_stat(tp->t_dev);
1825 
1826     if (scp->status & SLKED || blink_in_progress)
1827 	return; /* XXX who repeats the call when the above flags are cleared? */
1828     s = spltty();
1829     if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1830 	tp->t_state |= TS_BUSY;
1831 	rbp = &tp->t_outq;
1832 	while (rbp->c_cc) {
1833 	    len = q_to_b(rbp, buf, PCBURST);
1834 	    splx(s);
1835 	    ansi_put(scp, buf, len);
1836 	    s = spltty();
1837 	}
1838 	tp->t_state &= ~TS_BUSY;
1839 	ttwwakeup(tp);
1840     }
1841     splx(s);
1842 }
1843 
1844 static void
1845 scmousestart(struct tty *tp)
1846 {
1847     struct clist *rbp;
1848     int s;
1849     u_char buf[PCBURST];
1850 
1851     s = spltty();
1852     if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
1853 	tp->t_state |= TS_BUSY;
1854 	rbp = &tp->t_outq;
1855 	while (rbp->c_cc) {
1856 	    q_to_b(rbp, buf, PCBURST);
1857 	}
1858 	tp->t_state &= ~TS_BUSY;
1859 	ttwwakeup(tp);
1860     }
1861     splx(s);
1862 }
1863 
1864 void
1865 sccnprobe(struct consdev *cp)
1866 {
1867     struct isa_device *dvp;
1868 
1869     /*
1870      * Take control if we are the highest priority enabled display device.
1871      */
1872     dvp = find_display();
1873     if (dvp == NULL || dvp->id_driver != &scdriver) {
1874 	cp->cn_pri = CN_DEAD;
1875 	return;
1876     }
1877 
1878     if (!scvidprobe(dvp->id_unit, dvp->id_flags)) {
1879 	cp->cn_pri = CN_DEAD;
1880 	return;
1881     }
1882 
1883     /* initialize required fields */
1884     cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE);
1885     cp->cn_pri = CN_INTERNAL;
1886 
1887     sc_kbdc = kbdc_open(sc_port);
1888 }
1889 
1890 void
1891 sccninit(struct consdev *cp)
1892 {
1893     scinit();
1894 }
1895 
1896 void
1897 sccnputc(dev_t dev, int c)
1898 {
1899     u_char buf[1];
1900     int s;
1901     scr_stat *scp = console[0];
1902     term_stat save = scp->term;
1903 
1904     scp->term = kernel_console;
1905     current_default = &kernel_default;
1906     if (scp == cur_console && !ISGRAPHSC(scp))
1907 	remove_cursor_image(scp);
1908     buf[0] = c;
1909     ansi_put(scp, buf, 1);
1910     kernel_console = scp->term;
1911     current_default = &user_default;
1912     scp->term = save;
1913 
1914     s = spltty();	/* block scintr and scrn_timer */
1915     sccnupdate(scp);
1916     splx(s);
1917 }
1918 
1919 int
1920 sccngetc(dev_t dev)
1921 {
1922     int s = spltty();	/* block scintr and scrn_timer while we poll */
1923     int c;
1924 
1925     /*
1926      * Stop the screen saver and update the screen if necessary.
1927      * What if we have been running in the screen saver code... XXX
1928      */
1929     scsplash_stick(FALSE);
1930     run_scrn_saver = FALSE;
1931     sccnupdate(cur_console);
1932 
1933     c = scgetc(SCGETC_CN);
1934     splx(s);
1935     return(c);
1936 }
1937 
1938 int
1939 sccncheckc(dev_t dev)
1940 {
1941     int s = spltty();	/* block scintr and scrn_timer while we poll */
1942     int c;
1943 
1944     scsplash_stick(FALSE);
1945     run_scrn_saver = FALSE;
1946     sccnupdate(cur_console);
1947 
1948     c = scgetc(SCGETC_CN | SCGETC_NONBLOCK);
1949     splx(s);
1950     return(c == NOKEY ? -1 : c);	/* c == -1 can't happen */
1951 }
1952 
1953 static void
1954 sccnupdate(scr_stat *scp)
1955 {
1956     /* this is a cut-down version of scrn_timer()... */
1957 
1958     if (font_loading_in_progress)
1959 	return;
1960 
1961     if (panicstr || shutdown_in_progress) {
1962 	scsplash_stick(FALSE);
1963 	run_scrn_saver = FALSE;
1964     } else if (scp != cur_console) {
1965 	return;
1966     }
1967 
1968     if (!run_scrn_saver)
1969 	scrn_idle = FALSE;
1970     if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
1971 	if (scp->status & SAVER_RUNNING)
1972             stop_scrn_saver(current_saver);
1973 
1974     if (scp != cur_console || blink_in_progress || switch_in_progress)
1975 	return;
1976 
1977     if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
1978 	scrn_update(scp, TRUE);
1979 }
1980 
1981 scr_stat
1982 *sc_get_scr_stat(dev_t dev)
1983 {
1984     int unit = minor(dev);
1985 
1986     if (unit == SC_CONSOLE)
1987 	return console[0];
1988     if (unit >= MAXCONS || unit < 0)
1989 	return(NULL);
1990     return console[unit];
1991 }
1992 
1993 static int
1994 get_scr_num()
1995 {
1996     int i = 0;
1997 
1998     while ((i < MAXCONS) && (cur_console != console[i]))
1999 	i++;
2000     return i < MAXCONS ? i : 0;
2001 }
2002 
2003 static void
2004 scrn_timer(void *arg)
2005 {
2006     struct timeval tv;
2007     scr_stat *scp;
2008     int s;
2009 
2010     /* don't do anything when we are touching font */
2011     if (font_loading_in_progress) {
2012 	if (arg)
2013 	    timeout(scrn_timer, (void *)TRUE, hz / 10);
2014 	return;
2015     }
2016     s = spltty();
2017 
2018     /*
2019      * With release 2.1 of the Xaccel server, the keyboard is left
2020      * hanging pretty often. Apparently an interrupt from the
2021      * keyboard is lost, and I don't know why (yet).
2022      * This ugly hack calls scintr if input is ready for the keyboard
2023      * and conveniently hides the problem.			XXX
2024      */
2025     /* Try removing anything stuck in the keyboard controller; whether
2026      * it's a keyboard scan code or mouse data. `scintr()' doesn't
2027      * read the mouse data directly, but `kbdio' routines will, as a
2028      * side effect.
2029      */
2030     if (kbdc_lock(sc_kbdc, TRUE)) {
2031 	/*
2032 	 * We have seen the lock flag is not set. Let's reset the flag early;
2033 	 * otherwise `update_led()' failes which may want the lock
2034 	 * during `scintr()'.
2035 	 */
2036 	kbdc_lock(sc_kbdc, FALSE);
2037 	if (kbdc_data_ready(sc_kbdc))
2038 	    scintr(0);
2039     }
2040 
2041     scp = cur_console;
2042 
2043     /* should we stop the screen saver? */
2044     getmicrouptime(&tv);
2045     if (panicstr || shutdown_in_progress) {
2046 	scsplash_stick(FALSE);
2047 	run_scrn_saver = FALSE;
2048     }
2049     if (run_scrn_saver) {
2050 	scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time);
2051     } else {
2052 	scrn_time_stamp = tv.tv_sec;
2053 	scrn_idle = FALSE;
2054 	if (scrn_blank_time > 0)
2055 	    run_scrn_saver = TRUE;
2056     }
2057     if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
2058 	if (scp->status & SAVER_RUNNING)
2059             stop_scrn_saver(current_saver);
2060 
2061     /* should we just return ? */
2062     if (blink_in_progress || switch_in_progress) {
2063 	if (arg)
2064 	    timeout(scrn_timer, (void *)TRUE, hz / 10);
2065 	splx(s);
2066 	return;
2067     }
2068 
2069     /* Update the screen */
2070     if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
2071 	scrn_update(scp, TRUE);
2072 
2073     /* should we activate the screen saver? */
2074     if ((saver_mode == CONS_LKM_SAVER) && scrn_idle)
2075 	if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING))
2076 	    scrn_saver(current_saver, TRUE);
2077 
2078     if (arg)
2079 	timeout(scrn_timer, (void *)TRUE, hz / 25);
2080     splx(s);
2081 }
2082 
2083 static void
2084 scrn_update(scr_stat *scp, int show_cursor)
2085 {
2086     /* update screen image */
2087     if (scp->start <= scp->end)
2088         sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0);
2089 
2090     /* we are not to show the cursor and the mouse pointer... */
2091     if (!show_cursor) {
2092         scp->end = 0;
2093         scp->start = scp->xsize*scp->ysize - 1;
2094 	return;
2095     }
2096 
2097     /* update "pseudo" mouse pointer image */
2098     if (scp->status & MOUSE_VISIBLE) {
2099         /* did mouse move since last time ? */
2100         if (scp->status & MOUSE_MOVED) {
2101             /* do we need to remove old mouse pointer image ? */
2102             if (scp->mouse_cut_start != NULL ||
2103                 (scp->mouse_pos-scp->scr_buf) <= scp->start ||
2104                 (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) {
2105                 remove_mouse_image(scp);
2106             }
2107             scp->status &= ~MOUSE_MOVED;
2108             draw_mouse_image(scp);
2109         }
2110         else {
2111             /* mouse didn't move, has it been overwritten ? */
2112             if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start &&
2113                 (scp->mouse_pos - scp->scr_buf) <= scp->end) {
2114                 draw_mouse_image(scp);
2115             }
2116         }
2117     }
2118 
2119     /* update cursor image */
2120     if (scp->status & CURSOR_ENABLED) {
2121         /* did cursor move since last time ? */
2122         if (scp->cursor_pos != scp->cursor_oldpos) {
2123             /* do we need to remove old cursor image ? */
2124             if ((scp->cursor_oldpos - scp->scr_buf) < scp->start ||
2125                 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) {
2126                 remove_cursor_image(scp);
2127             }
2128             scp->cursor_oldpos = scp->cursor_pos;
2129             draw_cursor_image(scp);
2130         }
2131         else {
2132             /* cursor didn't move, has it been overwritten ? */
2133             if (scp->cursor_pos - scp->scr_buf >= scp->start &&
2134                 scp->cursor_pos - scp->scr_buf <= scp->end) {
2135                 draw_cursor_image(scp);
2136             } else {
2137                 /* if its a blinking cursor, we may have to update it */
2138                 if (flags & BLINK_CURSOR)
2139                     draw_cursor_image(scp);
2140             }
2141         }
2142         blinkrate++;
2143     }
2144 
2145     if (scp->mouse_cut_start != NULL)
2146         draw_cutmarking(scp);
2147 
2148     scp->end = 0;
2149     scp->start = scp->xsize*scp->ysize - 1;
2150 }
2151 
2152 int
2153 add_scrn_saver(void (*this_saver)(int))
2154 {
2155 #ifdef SC_SPLASH_SCREEN
2156     if (current_saver == scsplash) {
2157 	scsplash_stick(FALSE);
2158         stop_scrn_saver(scsplash);
2159     }
2160 #endif
2161 
2162     if (current_saver != default_saver)
2163 	return EBUSY;
2164     run_scrn_saver = FALSE;
2165     saver_mode = CONS_LKM_SAVER;
2166     current_saver = this_saver;
2167     return 0;
2168 }
2169 
2170 int
2171 remove_scrn_saver(void (*this_saver)(int))
2172 {
2173     if (current_saver != this_saver)
2174 	return EINVAL;
2175 
2176     /*
2177      * In order to prevent `current_saver' from being called by
2178      * the timeout routine `scrn_timer()' while we manipulate
2179      * the saver list, we shall set `current_saver' to `none_saver'
2180      * before stopping the current saver, rather than blocking by `splXX()'.
2181      */
2182     current_saver = none_saver;
2183     if (scrn_blanked > 0)
2184         stop_scrn_saver(this_saver);
2185 
2186     if (scrn_blanked > 0)
2187 	return EBUSY;	/* XXX */
2188 
2189     current_saver = default_saver;
2190     return 0;
2191 }
2192 
2193 static void
2194 scrn_saver(void (*saver)(int), int blank)
2195 {
2196     static int busy = FALSE;
2197 
2198     if (busy)
2199 	return;
2200     busy = TRUE;
2201     (*saver)(blank);
2202     busy = FALSE;
2203 }
2204 
2205 static void
2206 stop_scrn_saver(void (*saver)(int))
2207 {
2208     scrn_saver(saver, FALSE);
2209     run_scrn_saver = FALSE;
2210     /* the screen saver may have chosen not to stop after all... */
2211     if (scrn_blanked > 0)
2212 	return;
2213 
2214     mark_all(cur_console);
2215     if (delayed_next_scr)
2216 	switch_scr(cur_console, delayed_next_scr - 1);
2217     wakeup((caddr_t)&scrn_blanked);
2218 }
2219 
2220 static int
2221 wait_scrn_saver_stop(void)
2222 {
2223     int error = 0;
2224 
2225     while (scrn_blanked > 0) {
2226 	run_scrn_saver = FALSE;
2227 	error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0);
2228 	run_scrn_saver = FALSE;
2229 	if (error != ERESTART)
2230 	    break;
2231     }
2232     return error;
2233 }
2234 
2235 void
2236 sc_clear_screen(scr_stat *scp)
2237 {
2238     move_crsr(scp, 0, 0);
2239     scp->cursor_oldpos = scp->cursor_pos;
2240     fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
2241 	  scp->xsize * scp->ysize);
2242     mark_all(scp);
2243     remove_cutmarking(scp);
2244 }
2245 
2246 static int
2247 switch_scr(scr_stat *scp, u_int next_scr)
2248 {
2249     /* delay switch if actively updating screen */
2250     if (scrn_blanked > 0 || write_in_progress || blink_in_progress) {
2251 	scsplash_stick(FALSE);
2252 	run_scrn_saver = FALSE;
2253 	delayed_next_scr = next_scr+1;
2254 	return 0;
2255     }
2256 
2257     if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid)))
2258 	switch_in_progress = FALSE;
2259 
2260     if (next_scr >= MAXCONS || switch_in_progress ||
2261 	(cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) {
2262 	do_bell(scp, BELL_PITCH, BELL_DURATION);
2263 	return EINVAL;
2264     }
2265 
2266     /* is the wanted virtual console open ? */
2267     if (next_scr) {
2268 	struct tty *tp = VIRTUAL_TTY(next_scr);
2269 	if (!(tp->t_state & TS_ISOPEN)) {
2270 	    do_bell(scp, BELL_PITCH, BELL_DURATION);
2271 	    return EINVAL;
2272 	}
2273     }
2274 
2275     switch_in_progress = TRUE;
2276     old_scp = cur_console;
2277     new_scp = console[next_scr];
2278     wakeup((caddr_t)&new_scp->smode);
2279     if (new_scp == old_scp) {
2280 	switch_in_progress = FALSE;
2281 	delayed_next_scr = FALSE;
2282 	return 0;
2283     }
2284 
2285     /* has controlling process died? */
2286     if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid)))
2287 	old_scp->smode.mode = VT_AUTO;
2288     if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid)))
2289 	new_scp->smode.mode = VT_AUTO;
2290 
2291     /* check the modes and switch appropriately */
2292     if (old_scp->smode.mode == VT_PROCESS) {
2293 	old_scp->status |= SWITCH_WAIT_REL;
2294 	psignal(old_scp->proc, old_scp->smode.relsig);
2295     }
2296     else {
2297 	exchange_scr();
2298 	if (new_scp->smode.mode == VT_PROCESS) {
2299 	    new_scp->status |= SWITCH_WAIT_ACQ;
2300 	    psignal(new_scp->proc, new_scp->smode.acqsig);
2301 	}
2302 	else
2303 	    switch_in_progress = FALSE;
2304     }
2305     return 0;
2306 }
2307 
2308 static void
2309 exchange_scr(void)
2310 {
2311     move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
2312     cur_console = new_scp;
2313     if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) {
2314 	if (adp_flags & V_ADP_MODECHANGE)
2315 	    set_mode(new_scp);
2316     }
2317     move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
2318     if (ISTEXTSC(new_scp) && (flags & CHAR_CURSOR))
2319 	set_destructive_cursor(new_scp);
2320     if (ISGRAPHSC(old_scp))
2321 	load_palette(new_scp, palette);
2322     if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE ||
2323         old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE)
2324 	shfts = ctls = alts = agrs = metas = accents = 0;
2325     set_border(new_scp, new_scp->border);
2326     update_leds(new_scp->status);
2327     delayed_next_scr = FALSE;
2328     mark_all(new_scp);
2329 
2330     /* FIXME: the screen size may be larger than a 64K segment. */
2331     if (ISPIXELSC(new_scp))
2332 	bzero(Crtat, new_scp->xpixel*new_scp->ypixel/8);
2333 }
2334 
2335 static void
2336 scan_esc(scr_stat *scp, u_char c)
2337 {
2338     static u_char ansi_col[16] =
2339 	{0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
2340     int i, n;
2341     u_short *src, *dst, count;
2342 
2343     if (scp->term.esc == 1) {	/* seen ESC */
2344 	switch (c) {
2345 
2346 	case '7':   /* Save cursor position */
2347 	    scp->saved_xpos = scp->xpos;
2348 	    scp->saved_ypos = scp->ypos;
2349 	    break;
2350 
2351 	case '8':   /* Restore saved cursor position */
2352 	    if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0)
2353 		move_crsr(scp, scp->saved_xpos, scp->saved_ypos);
2354 	    break;
2355 
2356 	case '[':   /* Start ESC [ sequence */
2357 	    scp->term.esc = 2;
2358 	    scp->term.last_param = -1;
2359 	    for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
2360 		scp->term.param[i] = 1;
2361 	    scp->term.num_param = 0;
2362 	    return;
2363 
2364 	case 'M':   /* Move cursor up 1 line, scroll if at top */
2365 	    if (scp->ypos > 0)
2366 		move_crsr(scp, scp->xpos, scp->ypos - 1);
2367 	    else {
2368 		bcopy(scp->scr_buf, scp->scr_buf + scp->xsize,
2369 		       (scp->ysize - 1) * scp->xsize * sizeof(u_short));
2370 		fillw(scp->term.cur_color | scr_map[0x20],
2371 		      scp->scr_buf, scp->xsize);
2372     		mark_all(scp);
2373 	    }
2374 	    break;
2375 #if notyet
2376 	case 'Q':
2377 	    scp->term.esc = 4;
2378 	    return;
2379 #endif
2380 	case 'c':   /* Clear screen & home */
2381 	    sc_clear_screen(scp);
2382 	    break;
2383 
2384 	case '(':   /* iso-2022: designate 94 character set to G0 */
2385 	    scp->term.esc = 5;
2386 	    return;
2387 	}
2388     }
2389     else if (scp->term.esc == 2) {	/* seen ESC [ */
2390 	if (c >= '0' && c <= '9') {
2391 	    if (scp->term.num_param < MAX_ESC_PAR) {
2392 	    if (scp->term.last_param != scp->term.num_param) {
2393 		scp->term.last_param = scp->term.num_param;
2394 		scp->term.param[scp->term.num_param] = 0;
2395 	    }
2396 	    else
2397 		scp->term.param[scp->term.num_param] *= 10;
2398 	    scp->term.param[scp->term.num_param] += c - '0';
2399 	    return;
2400 	    }
2401 	}
2402 	scp->term.num_param = scp->term.last_param + 1;
2403 	switch (c) {
2404 
2405 	case ';':
2406 	    if (scp->term.num_param < MAX_ESC_PAR)
2407 		return;
2408 	    break;
2409 
2410 	case '=':
2411 	    scp->term.esc = 3;
2412 	    scp->term.last_param = -1;
2413 	    for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
2414 		scp->term.param[i] = 1;
2415 	    scp->term.num_param = 0;
2416 	    return;
2417 
2418 	case 'A':   /* up n rows */
2419 	    n = scp->term.param[0]; if (n < 1) n = 1;
2420 	    move_crsr(scp, scp->xpos, scp->ypos - n);
2421 	    break;
2422 
2423 	case 'B':   /* down n rows */
2424 	    n = scp->term.param[0]; if (n < 1) n = 1;
2425 	    move_crsr(scp, scp->xpos, scp->ypos + n);
2426 	    break;
2427 
2428 	case 'C':   /* right n columns */
2429 	    n = scp->term.param[0]; if (n < 1) n = 1;
2430 	    move_crsr(scp, scp->xpos + n, scp->ypos);
2431 	    break;
2432 
2433 	case 'D':   /* left n columns */
2434 	    n = scp->term.param[0]; if (n < 1) n = 1;
2435 	    move_crsr(scp, scp->xpos - n, scp->ypos);
2436 	    break;
2437 
2438 	case 'E':   /* cursor to start of line n lines down */
2439 	    n = scp->term.param[0]; if (n < 1) n = 1;
2440 	    move_crsr(scp, 0, scp->ypos + n);
2441 	    break;
2442 
2443 	case 'F':   /* cursor to start of line n lines up */
2444 	    n = scp->term.param[0]; if (n < 1) n = 1;
2445 	    move_crsr(scp, 0, scp->ypos - n);
2446 	    break;
2447 
2448 	case 'f':   /* Cursor move */
2449 	case 'H':
2450 	    if (scp->term.num_param == 0)
2451 		move_crsr(scp, 0, 0);
2452 	    else if (scp->term.num_param == 2)
2453 		move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1);
2454 	    break;
2455 
2456 	case 'J':   /* Clear all or part of display */
2457 	    if (scp->term.num_param == 0)
2458 		n = 0;
2459 	    else
2460 		n = scp->term.param[0];
2461 	    switch (n) {
2462 	    case 0: /* clear form cursor to end of display */
2463 		fillw(scp->term.cur_color | scr_map[0x20],
2464 		      scp->cursor_pos,
2465 		      scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos);
2466     		mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2467     		mark_for_update(scp, scp->xsize * scp->ysize - 1);
2468 		remove_cutmarking(scp);
2469 		break;
2470 	    case 1: /* clear from beginning of display to cursor */
2471 		fillw(scp->term.cur_color | scr_map[0x20],
2472 		      scp->scr_buf,
2473 		      scp->cursor_pos - scp->scr_buf);
2474     		mark_for_update(scp, 0);
2475     		mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2476 		remove_cutmarking(scp);
2477 		break;
2478 	    case 2: /* clear entire display */
2479 		fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf,
2480 		      scp->xsize * scp->ysize);
2481 		mark_all(scp);
2482 		remove_cutmarking(scp);
2483 		break;
2484 	    }
2485 	    break;
2486 
2487 	case 'K':   /* Clear all or part of line */
2488 	    if (scp->term.num_param == 0)
2489 		n = 0;
2490 	    else
2491 		n = scp->term.param[0];
2492 	    switch (n) {
2493 	    case 0: /* clear form cursor to end of line */
2494 		fillw(scp->term.cur_color | scr_map[0x20],
2495 		      scp->cursor_pos,
2496 		      scp->xsize - scp->xpos);
2497     		mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2498     		mark_for_update(scp, scp->cursor_pos - scp->scr_buf +
2499 				scp->xsize - scp->xpos);
2500 		break;
2501 	    case 1: /* clear from beginning of line to cursor */
2502 		fillw(scp->term.cur_color | scr_map[0x20],
2503 		      scp->cursor_pos - scp->xpos,
2504 		      scp->xpos + 1);
2505     		mark_for_update(scp, scp->ypos * scp->xsize);
2506     		mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2507 		break;
2508 	    case 2: /* clear entire line */
2509 		fillw(scp->term.cur_color | scr_map[0x20],
2510 		      scp->cursor_pos - scp->xpos,
2511 		      scp->xsize);
2512     		mark_for_update(scp, scp->ypos * scp->xsize);
2513     		mark_for_update(scp, (scp->ypos + 1) * scp->xsize);
2514 		break;
2515 	    }
2516 	    break;
2517 
2518 	case 'L':   /* Insert n lines */
2519 	    n = scp->term.param[0]; if (n < 1) n = 1;
2520 	    if (n > scp->ysize - scp->ypos)
2521 		n = scp->ysize - scp->ypos;
2522 	    src = scp->scr_buf + scp->ypos * scp->xsize;
2523 	    dst = src + n * scp->xsize;
2524 	    count = scp->ysize - (scp->ypos + n);
2525 	    bcopy(src, dst, count * scp->xsize * sizeof(u_short));
2526 	    fillw(scp->term.cur_color | scr_map[0x20], src,
2527 		  n * scp->xsize);
2528 	    mark_for_update(scp, scp->ypos * scp->xsize);
2529 	    mark_for_update(scp, scp->xsize * scp->ysize - 1);
2530 	    break;
2531 
2532 	case 'M':   /* Delete n lines */
2533 	    n = scp->term.param[0]; if (n < 1) n = 1;
2534 	    if (n > scp->ysize - scp->ypos)
2535 		n = scp->ysize - scp->ypos;
2536 	    dst = scp->scr_buf + scp->ypos * scp->xsize;
2537 	    src = dst + n * scp->xsize;
2538 	    count = scp->ysize - (scp->ypos + n);
2539 	    bcopy(src, dst, count * scp->xsize * sizeof(u_short));
2540 	    src = dst + count * scp->xsize;
2541 	    fillw(scp->term.cur_color | scr_map[0x20], src,
2542 		  n * scp->xsize);
2543 	    mark_for_update(scp, scp->ypos * scp->xsize);
2544 	    mark_for_update(scp, scp->xsize * scp->ysize - 1);
2545 	    break;
2546 
2547 	case 'P':   /* Delete n chars */
2548 	    n = scp->term.param[0]; if (n < 1) n = 1;
2549 	    if (n > scp->xsize - scp->xpos)
2550 		n = scp->xsize - scp->xpos;
2551 	    dst = scp->cursor_pos;
2552 	    src = dst + n;
2553 	    count = scp->xsize - (scp->xpos + n);
2554 	    bcopy(src, dst, count * sizeof(u_short));
2555 	    src = dst + count;
2556 	    fillw(scp->term.cur_color | scr_map[0x20], src, n);
2557 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2558 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count);
2559 	    break;
2560 
2561 	case '@':   /* Insert n chars */
2562 	    n = scp->term.param[0]; if (n < 1) n = 1;
2563 	    if (n > scp->xsize - scp->xpos)
2564 		n = scp->xsize - scp->xpos;
2565 	    src = scp->cursor_pos;
2566 	    dst = src + n;
2567 	    count = scp->xsize - (scp->xpos + n);
2568 	    bcopy(src, dst, count * sizeof(u_short));
2569 	    fillw(scp->term.cur_color | scr_map[0x20], src, n);
2570 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2571 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count);
2572 	    break;
2573 
2574 	case 'S':   /* scroll up n lines */
2575 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2576 	    if (n > scp->ysize)
2577 		n = scp->ysize;
2578 	    bcopy(scp->scr_buf + (scp->xsize * n),
2579 		   scp->scr_buf,
2580 		   scp->xsize * (scp->ysize - n) * sizeof(u_short));
2581 	    fillw(scp->term.cur_color | scr_map[0x20],
2582 		  scp->scr_buf + scp->xsize * (scp->ysize - n),
2583 		  scp->xsize * n);
2584     	    mark_all(scp);
2585 	    break;
2586 
2587 	case 'T':   /* scroll down n lines */
2588 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2589 	    if (n > scp->ysize)
2590 		n = scp->ysize;
2591 	    bcopy(scp->scr_buf,
2592 		  scp->scr_buf + (scp->xsize * n),
2593 		  scp->xsize * (scp->ysize - n) *
2594 		  sizeof(u_short));
2595 	    fillw(scp->term.cur_color | scr_map[0x20],
2596 		  scp->scr_buf, scp->xsize * n);
2597     	    mark_all(scp);
2598 	    break;
2599 
2600 	case 'X':   /* erase n characters in line */
2601 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2602 	    if (n > scp->xsize - scp->xpos)
2603 		n = scp->xsize - scp->xpos;
2604 	    fillw(scp->term.cur_color | scr_map[0x20],
2605 		  scp->cursor_pos, n);
2606 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2607 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n);
2608 	    break;
2609 
2610 	case 'Z':   /* move n tabs backwards */
2611 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2612 	    if ((i = scp->xpos & 0xf8) == scp->xpos)
2613 		i -= 8*n;
2614 	    else
2615 		i -= 8*(n-1);
2616 	    if (i < 0)
2617 		i = 0;
2618 	    move_crsr(scp, i, scp->ypos);
2619 	    break;
2620 
2621 	case '`':   /* move cursor to column n */
2622 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2623 	    move_crsr(scp, n - 1, scp->ypos);
2624 	    break;
2625 
2626 	case 'a':   /* move cursor n columns to the right */
2627 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2628 	    move_crsr(scp, scp->xpos + n, scp->ypos);
2629 	    break;
2630 
2631 	case 'd':   /* move cursor to row n */
2632 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2633 	    move_crsr(scp, scp->xpos, n - 1);
2634 	    break;
2635 
2636 	case 'e':   /* move cursor n rows down */
2637 	    n = scp->term.param[0]; if (n < 1)  n = 1;
2638 	    move_crsr(scp, scp->xpos, scp->ypos + n);
2639 	    break;
2640 
2641 	case 'm':   /* change attribute */
2642 	    if (scp->term.num_param == 0) {
2643 		scp->term.attr_mask = NORMAL_ATTR;
2644 		scp->term.cur_attr =
2645 		    scp->term.cur_color = scp->term.std_color;
2646 		break;
2647 	    }
2648 	    for (i = 0; i < scp->term.num_param; i++) {
2649 		switch (n = scp->term.param[i]) {
2650 		case 0: /* back to normal */
2651 		    scp->term.attr_mask = NORMAL_ATTR;
2652 		    scp->term.cur_attr =
2653 			scp->term.cur_color = scp->term.std_color;
2654 		    break;
2655 		case 1: /* bold */
2656 		    scp->term.attr_mask |= BOLD_ATTR;
2657 		    scp->term.cur_attr = mask2attr(&scp->term);
2658 		    break;
2659 		case 4: /* underline */
2660 		    scp->term.attr_mask |= UNDERLINE_ATTR;
2661 		    scp->term.cur_attr = mask2attr(&scp->term);
2662 		    break;
2663 		case 5: /* blink */
2664 		    scp->term.attr_mask |= BLINK_ATTR;
2665 		    scp->term.cur_attr = mask2attr(&scp->term);
2666 		    break;
2667 		case 7: /* reverse video */
2668 		    scp->term.attr_mask |= REVERSE_ATTR;
2669 		    scp->term.cur_attr = mask2attr(&scp->term);
2670 		    break;
2671 		case 30: case 31: /* set fg color */
2672 		case 32: case 33: case 34:
2673 		case 35: case 36: case 37:
2674 		    scp->term.attr_mask |= FOREGROUND_CHANGED;
2675 		    scp->term.cur_color =
2676 			(scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8);
2677 		    scp->term.cur_attr = mask2attr(&scp->term);
2678 		    break;
2679 		case 40: case 41: /* set bg color */
2680 		case 42: case 43: case 44:
2681 		case 45: case 46: case 47:
2682 		    scp->term.attr_mask |= BACKGROUND_CHANGED;
2683 		    scp->term.cur_color =
2684 			(scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12);
2685 		    scp->term.cur_attr = mask2attr(&scp->term);
2686 		    break;
2687 		}
2688 	    }
2689 	    break;
2690 
2691 	case 's':   /* Save cursor position */
2692 	    scp->saved_xpos = scp->xpos;
2693 	    scp->saved_ypos = scp->ypos;
2694 	    break;
2695 
2696 	case 'u':   /* Restore saved cursor position */
2697 	    if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0)
2698 		move_crsr(scp, scp->saved_xpos, scp->saved_ypos);
2699 	    break;
2700 
2701 	case 'x':
2702 	    if (scp->term.num_param == 0)
2703 		n = 0;
2704 	    else
2705 		n = scp->term.param[0];
2706 	    switch (n) {
2707 	    case 0:     /* reset attributes */
2708 		scp->term.attr_mask = NORMAL_ATTR;
2709 		scp->term.cur_attr =
2710 		    scp->term.cur_color = scp->term.std_color =
2711 		    current_default->std_color;
2712 		scp->term.rev_color = current_default->rev_color;
2713 		break;
2714 	    case 1:     /* set ansi background */
2715 		scp->term.attr_mask &= ~BACKGROUND_CHANGED;
2716 		scp->term.cur_color = scp->term.std_color =
2717 		    (scp->term.std_color & 0x0F00) |
2718 		    (ansi_col[(scp->term.param[1])&0x0F]<<12);
2719 		scp->term.cur_attr = mask2attr(&scp->term);
2720 		break;
2721 	    case 2:     /* set ansi foreground */
2722 		scp->term.attr_mask &= ~FOREGROUND_CHANGED;
2723 		scp->term.cur_color = scp->term.std_color =
2724 		    (scp->term.std_color & 0xF000) |
2725 		    (ansi_col[(scp->term.param[1])&0x0F]<<8);
2726 		scp->term.cur_attr = mask2attr(&scp->term);
2727 		break;
2728 	    case 3:     /* set ansi attribute directly */
2729 		scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED);
2730 		scp->term.cur_color = scp->term.std_color =
2731 		    (scp->term.param[1]&0xFF)<<8;
2732 		scp->term.cur_attr = mask2attr(&scp->term);
2733 		break;
2734 	    case 5:     /* set ansi reverse video background */
2735 		scp->term.rev_color =
2736 		    (scp->term.rev_color & 0x0F00) |
2737 		    (ansi_col[(scp->term.param[1])&0x0F]<<12);
2738 		scp->term.cur_attr = mask2attr(&scp->term);
2739 		break;
2740 	    case 6:     /* set ansi reverse video foreground */
2741 		scp->term.rev_color =
2742 		    (scp->term.rev_color & 0xF000) |
2743 		    (ansi_col[(scp->term.param[1])&0x0F]<<8);
2744 		scp->term.cur_attr = mask2attr(&scp->term);
2745 		break;
2746 	    case 7:     /* set ansi reverse video directly */
2747 		scp->term.rev_color =
2748 		    (scp->term.param[1]&0xFF)<<8;
2749 		scp->term.cur_attr = mask2attr(&scp->term);
2750 		break;
2751 	    }
2752 	    break;
2753 
2754 	case 'z':   /* switch to (virtual) console n */
2755 	    if (scp->term.num_param == 1)
2756 		switch_scr(scp, scp->term.param[0]);
2757 	    break;
2758 	}
2759     }
2760     else if (scp->term.esc == 3) {	/* seen ESC [0-9]+ = */
2761 	if (c >= '0' && c <= '9') {
2762 	    if (scp->term.num_param < MAX_ESC_PAR) {
2763 	    if (scp->term.last_param != scp->term.num_param) {
2764 		scp->term.last_param = scp->term.num_param;
2765 		scp->term.param[scp->term.num_param] = 0;
2766 	    }
2767 	    else
2768 		scp->term.param[scp->term.num_param] *= 10;
2769 	    scp->term.param[scp->term.num_param] += c - '0';
2770 	    return;
2771 	    }
2772 	}
2773 	scp->term.num_param = scp->term.last_param + 1;
2774 	switch (c) {
2775 
2776 	case ';':
2777 	    if (scp->term.num_param < MAX_ESC_PAR)
2778 		return;
2779 	    break;
2780 
2781 	case 'A':   /* set display border color */
2782 	    if (scp->term.num_param == 1) {
2783 		scp->border=scp->term.param[0] & 0xff;
2784 		if (scp == cur_console)
2785 		    set_border(cur_console, scp->border);
2786             }
2787 	    break;
2788 
2789 	case 'B':   /* set bell pitch and duration */
2790 	    if (scp->term.num_param == 2) {
2791 		scp->bell_pitch = scp->term.param[0];
2792 		scp->bell_duration = scp->term.param[1];
2793 	    }
2794 	    break;
2795 
2796 	case 'C':   /* set cursor type & shape */
2797 	    if (scp->term.num_param == 1) {
2798 		if (scp->term.param[0] & 0x01)
2799 		    flags |= BLINK_CURSOR;
2800 		else
2801 		    flags &= ~BLINK_CURSOR;
2802 		if ((scp->term.param[0] & 0x02)
2803 		    && ISFONTAVAIL(get_adapter(scp)->va_flags))
2804 		    flags |= CHAR_CURSOR;
2805 		else
2806 		    flags &= ~CHAR_CURSOR;
2807 	    }
2808 	    else if (scp->term.num_param == 2) {
2809 		scp->cursor_start = scp->term.param[0] & 0x1F;
2810 		scp->cursor_end = scp->term.param[1] & 0x1F;
2811 	    }
2812 	    /*
2813 	     * The cursor shape is global property; all virtual consoles
2814 	     * are affected. Update the cursor in the current console...
2815 	     */
2816 	    if (!ISGRAPHSC(cur_console)) {
2817 		remove_cursor_image(cur_console);
2818 		if (flags & CHAR_CURSOR)
2819 	            set_destructive_cursor(cur_console);
2820 		draw_cursor_image(cur_console);
2821 	    }
2822 	    break;
2823 
2824 	case 'F':   /* set ansi foreground */
2825 	    if (scp->term.num_param == 1) {
2826 		scp->term.attr_mask &= ~FOREGROUND_CHANGED;
2827 		scp->term.cur_color = scp->term.std_color =
2828 		    (scp->term.std_color & 0xF000)
2829 		    | ((scp->term.param[0] & 0x0F) << 8);
2830 		scp->term.cur_attr = mask2attr(&scp->term);
2831 	    }
2832 	    break;
2833 
2834 	case 'G':   /* set ansi background */
2835 	    if (scp->term.num_param == 1) {
2836 		scp->term.attr_mask &= ~BACKGROUND_CHANGED;
2837 		scp->term.cur_color = scp->term.std_color =
2838 		    (scp->term.std_color & 0x0F00)
2839 		    | ((scp->term.param[0] & 0x0F) << 12);
2840 		scp->term.cur_attr = mask2attr(&scp->term);
2841 	    }
2842 	    break;
2843 
2844 	case 'H':   /* set ansi reverse video foreground */
2845 	    if (scp->term.num_param == 1) {
2846 		scp->term.rev_color =
2847 		    (scp->term.rev_color & 0xF000)
2848 		    | ((scp->term.param[0] & 0x0F) << 8);
2849 		scp->term.cur_attr = mask2attr(&scp->term);
2850 	    }
2851 	    break;
2852 
2853 	case 'I':   /* set ansi reverse video background */
2854 	    if (scp->term.num_param == 1) {
2855 		scp->term.rev_color =
2856 		    (scp->term.rev_color & 0x0F00)
2857 		    | ((scp->term.param[0] & 0x0F) << 12);
2858 		scp->term.cur_attr = mask2attr(&scp->term);
2859 	    }
2860 	    break;
2861 	}
2862     }
2863 #if notyet
2864     else if (scp->term.esc == 4) {	/* seen ESC Q */
2865 	/* to be filled */
2866     }
2867 #endif
2868     else if (scp->term.esc == 5) {	/* seen ESC ( */
2869 	switch (c) {
2870 	case 'B':   /* iso-2022: desginate ASCII into G0 */
2871 	    break;
2872 	/* other items to be filled */
2873 	default:
2874 	    break;
2875 	}
2876     }
2877     scp->term.esc = 0;
2878 }
2879 
2880 static void
2881 ansi_put(scr_stat *scp, u_char *buf, int len)
2882 {
2883     u_char *ptr = buf;
2884 
2885     /* make screensaver happy */
2886     if (!sticky_splash && scp == cur_console)
2887 	run_scrn_saver = FALSE;
2888 
2889     write_in_progress++;
2890 outloop:
2891     if (scp->term.esc) {
2892 	scan_esc(scp, *ptr++);
2893 	len--;
2894     }
2895     else if (PRINTABLE(*ptr)) {     /* Print only printables */
2896  	int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos);
2897  	u_short cur_attr = scp->term.cur_attr;
2898  	u_short *cursor_pos = scp->cursor_pos;
2899 	do {
2900 	    /*
2901 	     * gcc-2.6.3 generates poor (un)sign extension code.  Casting the
2902 	     * pointers in the following to volatile should have no effect,
2903 	     * but in fact speeds up this inner loop from 26 to 18 cycles
2904 	     * (+ cache misses) on i486's.
2905 	     */
2906 #define	UCVP(ucp)	((u_char volatile *)(ucp))
2907 	    *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr;
2908 	    ptr++;
2909 	    cnt--;
2910 	} while (cnt && PRINTABLE(*ptr));
2911 	len -= (cursor_pos - scp->cursor_pos);
2912 	scp->xpos += (cursor_pos - scp->cursor_pos);
2913 	mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2914 	mark_for_update(scp, cursor_pos - scp->scr_buf);
2915 	scp->cursor_pos = cursor_pos;
2916 	if (scp->xpos >= scp->xsize) {
2917 	    scp->xpos = 0;
2918 	    scp->ypos++;
2919 	}
2920     }
2921     else  {
2922 	switch(*ptr) {
2923 	case 0x07:
2924 	    do_bell(scp, scp->bell_pitch, scp->bell_duration);
2925 	    break;
2926 
2927 	case 0x08:      /* non-destructive backspace */
2928 	    if (scp->cursor_pos > scp->scr_buf) {
2929 	    	mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2930 		scp->cursor_pos--;
2931 	    	mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2932 		if (scp->xpos > 0)
2933 		    scp->xpos--;
2934 		else {
2935 		    scp->xpos += scp->xsize - 1;
2936 		    scp->ypos--;
2937 		}
2938 	    }
2939 	    break;
2940 
2941 	case 0x09:  /* non-destructive tab */
2942 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2943 	    scp->cursor_pos += (8 - scp->xpos % 8u);
2944 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2945 	    if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) {
2946 	        scp->xpos = 0;
2947 	        scp->ypos++;
2948 	    }
2949 	    break;
2950 
2951 	case 0x0a:  /* newline, same pos */
2952 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2953 	    scp->cursor_pos += scp->xsize;
2954 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2955 	    scp->ypos++;
2956 	    break;
2957 
2958 	case 0x0c:  /* form feed, clears screen */
2959 	    sc_clear_screen(scp);
2960 	    break;
2961 
2962 	case 0x0d:  /* return, return to pos 0 */
2963 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2964 	    scp->cursor_pos -= scp->xpos;
2965 	    mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
2966 	    scp->xpos = 0;
2967 	    break;
2968 
2969 	case 0x1b:  /* start escape sequence */
2970 	    scp->term.esc = 1;
2971 	    scp->term.num_param = 0;
2972 	    break;
2973 	}
2974 	ptr++; len--;
2975     }
2976     /* do we have to scroll ?? */
2977     if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) {
2978 	remove_cutmarking(scp);
2979 	if (scp->history) {
2980 	    bcopy(scp->scr_buf, scp->history_head,
2981 		   scp->xsize * sizeof(u_short));
2982 	    scp->history_head += scp->xsize;
2983 	    if (scp->history_head + scp->xsize >
2984 		scp->history + scp->history_size)
2985 		scp->history_head = scp->history;
2986 	}
2987 	bcopy(scp->scr_buf + scp->xsize, scp->scr_buf,
2988 	       scp->xsize * (scp->ysize - 1) * sizeof(u_short));
2989 	fillw(scp->term.cur_color | scr_map[0x20],
2990 	      scp->scr_buf + scp->xsize * (scp->ysize - 1),
2991 	      scp->xsize);
2992 	scp->cursor_pos -= scp->xsize;
2993 	scp->ypos--;
2994     	mark_all(scp);
2995     }
2996     if (len)
2997 	goto outloop;
2998     write_in_progress--;
2999     if (delayed_next_scr)
3000 	switch_scr(scp, delayed_next_scr - 1);
3001 }
3002 
3003 static void
3004 scinit(void)
3005 {
3006     int col;
3007     int row;
3008     u_int i;
3009 
3010     if (init_done != COLD)
3011 	return;
3012     init_done = WARM;
3013 
3014     /* extract the hardware cursor location and move it out of the way */
3015     (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row);
3016     (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1);
3017 
3018     /* set up the first console */
3019     current_default = &user_default;
3020     console[0] = &main_console;
3021     init_scp(console[0]);
3022     cur_console = console[0];
3023 
3024     /* copy screen to temporary buffer */
3025     if (ISTEXTSC(console[0]))
3026 	    generic_bcopy(Crtat, sc_buffer,
3027 		   console[0]->xsize * console[0]->ysize * sizeof(u_short));
3028 
3029     console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos
3030 	= sc_buffer;
3031     if (col >= console[0]->xsize)
3032 	col = 0;
3033     if (row >= console[0]->ysize)
3034 	row = console[0]->ysize - 1;
3035     console[0]->xpos = col;
3036     console[0]->ypos = row;
3037     console[0]->cursor_pos = console[0]->cursor_oldpos =
3038 	sc_buffer + row*console[0]->xsize + col;
3039     console[0]->cursor_saveunder = *console[0]->cursor_pos;
3040     for (i=1; i<MAXCONS; i++)
3041 	console[i] = NULL;
3042     kernel_console.esc = 0;
3043     kernel_console.attr_mask = NORMAL_ATTR;
3044     kernel_console.cur_attr =
3045 	kernel_console.cur_color = kernel_console.std_color =
3046 	kernel_default.std_color;
3047     kernel_console.rev_color = kernel_default.rev_color;
3048 
3049     /* initialize mapscrn arrays to a one to one map */
3050     for (i=0; i<sizeof(scr_map); i++) {
3051 	scr_map[i] = scr_rmap[i] = i;
3052     }
3053 
3054     /* Save font and palette */
3055     if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) {
3056 	if (fonts_loaded & FONT_16) {
3057 	    copy_font(cur_console, LOAD, 16, font_16);
3058 	} else {
3059 	    copy_font(cur_console, SAVE, 16, font_16);
3060 	    fonts_loaded = FONT_16;
3061 	    set_destructive_cursor(cur_console);
3062 	}
3063 	/*
3064 	 * FONT KLUDGE
3065 	 * Always use the font page #0. XXX
3066 	 */
3067 	(*biosvidsw.show_font)(cur_console->adp, 0);
3068     }
3069     save_palette(cur_console, palette);
3070 
3071 #ifdef SC_SPLASH_SCREEN
3072     /* put up the splash. */
3073     scsplash_init(cur_console);
3074 #endif
3075 }
3076 
3077 static void
3078 scshutdown(int howto, void *arg)
3079 {
3080     scsplash_stick(FALSE);
3081     run_scrn_saver = FALSE;
3082     if (!cold && cur_console->smode.mode == VT_AUTO
3083 	&& console[0]->smode.mode == VT_AUTO)
3084 	switch_scr(cur_console, 0);
3085     shutdown_in_progress = TRUE;
3086 }
3087 
3088 int
3089 sc_clean_up(scr_stat *scp)
3090 {
3091     int error;
3092 
3093     if ((error = wait_scrn_saver_stop()))
3094 	return error;
3095     scp->status &= ~MOUSE_VISIBLE;
3096     remove_cutmarking(scp);
3097     return 0;
3098 }
3099 
3100 void
3101 sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear)
3102 {
3103     if (scp->scr_buf)
3104 	free(scp->scr_buf, M_DEVBUF);
3105     scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
3106 				     M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3107 
3108     if (clear) {
3109         /* clear the screen and move the text cursor to the top-left position */
3110 	sc_clear_screen(scp);
3111     } else {
3112 	/* retain the current cursor position, but adjust pointers */
3113 	move_crsr(scp, scp->xpos, scp->ypos);
3114 	scp->cursor_oldpos = scp->cursor_pos;
3115     }
3116 
3117     /* move the mouse cursor at the center of the screen */
3118     sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
3119 }
3120 
3121 void
3122 sc_alloc_cut_buffer(scr_stat *scp, int wait)
3123 {
3124     if ((cut_buffer == NULL)
3125 	|| (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
3126 	if (cut_buffer != NULL)
3127 	    free(cut_buffer, M_DEVBUF);
3128 	cut_buffer_size = scp->xsize * scp->ysize + 1;
3129 	cut_buffer = (u_char *)malloc(cut_buffer_size,
3130 				    M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3131 	if (cut_buffer != NULL)
3132 	    cut_buffer[0] = '\0';
3133     }
3134 }
3135 
3136 void
3137 sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait)
3138 {
3139     u_short *usp;
3140 
3141     if (lines < scp->ysize)
3142 	lines = scp->ysize;
3143 
3144     usp = scp->history;
3145     scp->history = NULL;
3146     if (usp != NULL) {
3147 	free(usp, M_DEVBUF);
3148 	if (extra > 0)
3149 	    extra_history_size += extra;
3150     }
3151 
3152     scp->history_size = lines * scp->xsize;
3153     if (lines > imax(sc_history_size, scp->ysize))
3154 	extra_history_size -= lines - imax(sc_history_size, scp->ysize);
3155     usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
3156 			    M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
3157     if (usp != NULL)
3158 	bzero(usp, scp->history_size * sizeof(u_short));
3159     scp->history_head = scp->history_pos = usp;
3160     scp->history = usp;
3161 }
3162 
3163 static scr_stat
3164 *alloc_scp()
3165 {
3166     scr_stat *scp;
3167 
3168     scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK);
3169     init_scp(scp);
3170     sc_alloc_scr_buffer(scp, TRUE, TRUE);
3171     if (ISMOUSEAVAIL(get_adapter(scp)->va_flags))
3172 	sc_alloc_cut_buffer(scp, TRUE);
3173     sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE);
3174 /* SOS
3175     if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE)
3176 	set_mode(scp);
3177 */
3178     sc_clear_screen(scp);
3179     scp->cursor_saveunder = *scp->cursor_pos;
3180     return scp;
3181 }
3182 
3183 static void
3184 init_scp(scr_stat *scp)
3185 {
3186     video_info_t info;
3187 
3188     scp->adp = V_ADP_PRIMARY;
3189     (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info);
3190 
3191     scp->status = 0;
3192     scp->mode = scp->initial_mode = initial_video_mode;
3193     scp->scr_buf = NULL;
3194     if (info.vi_flags & V_INFO_GRAPHICS) {
3195 	scp->status |= GRAPHICS_MODE;
3196 	scp->xpixel = info.vi_width;
3197 	scp->ypixel = info.vi_height;
3198 	scp->xsize = info.vi_width/8;
3199 	scp->ysize = info.vi_height/info.vi_cheight;
3200 	scp->font_size = FONT_NONE;
3201     } else {
3202 	scp->xsize = info.vi_width;
3203 	scp->ysize = info.vi_height;
3204 	scp->xpixel = scp->xsize*8;
3205 	scp->ypixel = scp->ysize*info.vi_cheight;
3206 	scp->font_size = info.vi_cheight;
3207     }
3208     scp->xoff = scp->yoff = 0;
3209     scp->xpos = scp->ypos = 0;
3210     scp->saved_xpos = scp->saved_ypos = -1;
3211     scp->start = scp->xsize * scp->ysize;
3212     scp->end = 0;
3213     scp->term.esc = 0;
3214     scp->term.attr_mask = NORMAL_ATTR;
3215     scp->term.cur_attr =
3216 	scp->term.cur_color = scp->term.std_color =
3217 	current_default->std_color;
3218     scp->term.rev_color = current_default->rev_color;
3219     scp->border = BG_BLACK;
3220     scp->cursor_start = *(u_int8_t *)pa_to_va(0x461);
3221     scp->cursor_end = *(u_int8_t *)pa_to_va(0x460);
3222     scp->mouse_xpos = scp->xsize*8/2;
3223     scp->mouse_ypos = scp->ysize*scp->font_size/2;
3224     scp->mouse_cut_start = scp->mouse_cut_end = NULL;
3225     scp->mouse_signal = 0;
3226     scp->mouse_pid = 0;
3227     scp->mouse_proc = NULL;
3228     scp->bell_pitch = BELL_PITCH;
3229     scp->bell_duration = BELL_DURATION;
3230     scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
3231     scp->status |= CURSOR_ENABLED;
3232     scp->pid = 0;
3233     scp->proc = NULL;
3234     scp->smode.mode = VT_AUTO;
3235     scp->history_head = scp->history_pos = scp->history = NULL;
3236     scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize;
3237 }
3238 
3239 static u_char
3240 *get_fstr(u_int c, u_int *len)
3241 {
3242     u_int i;
3243 
3244     if (!(c & FKEY))
3245 	return(NULL);
3246     i = (c & 0xFF) - F_FN;
3247     if (i > n_fkey_tab)
3248 	return(NULL);
3249     *len = fkey_tab[i].len;
3250     return(fkey_tab[i].str);
3251 }
3252 
3253 static void
3254 history_to_screen(scr_stat *scp)
3255 {
3256     int i;
3257 
3258     for (i=0; i<scp->ysize; i++)
3259 	bcopy(scp->history + (((scp->history_pos - scp->history) +
3260 	       scp->history_size-((i+1)*scp->xsize))%scp->history_size),
3261 	       scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)),
3262 	       scp->xsize * sizeof(u_short));
3263     mark_all(scp);
3264 }
3265 
3266 static int
3267 history_up_line(scr_stat *scp)
3268 {
3269     if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) !=
3270 	scp->history_head) {
3271 	scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize);
3272 	history_to_screen(scp);
3273 	return 0;
3274     }
3275     else
3276 	return -1;
3277 }
3278 
3279 static int
3280 history_down_line(scr_stat *scp)
3281 {
3282     if (scp->history_pos != scp->history_head) {
3283 	scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize);
3284 	history_to_screen(scp);
3285 	return 0;
3286     }
3287     else
3288 	return -1;
3289 }
3290 
3291 /*
3292  * scgetc(flags) - get character from keyboard.
3293  * If flags & SCGETC_CN, then avoid harmful side effects.
3294  * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else
3295  * return NOKEY if there is nothing there.
3296  */
3297 static u_int
3298 scgetc(u_int flags)
3299 {
3300     struct key_t *key;
3301     u_char scancode, keycode;
3302     u_int state, action;
3303     int c;
3304     static u_char esc_flag = 0, compose = 0;
3305     static u_int chr = 0;
3306 
3307 next_code:
3308     /* first see if there is something in the keyboard port */
3309     if (flags & SCGETC_NONBLOCK) {
3310 	c = read_kbd_data_no_wait(sc_kbdc);
3311 	if (c == -1)
3312 	    return(NOKEY);
3313     } else {
3314 	do {
3315 	    c = read_kbd_data(sc_kbdc);
3316 	} while(c == -1);
3317     }
3318     scancode = (u_char)c;
3319 
3320     /* make screensaver happy */
3321     if (!(scancode & 0x80)) {
3322 	scsplash_stick(FALSE);
3323 	run_scrn_saver = FALSE;
3324     }
3325 
3326     if (!(flags & SCGETC_CN)) {
3327 	/* do the /dev/random device a favour */
3328 	add_keyboard_randomness(scancode);
3329 
3330 	if (cur_console->status & KBD_RAW_MODE)
3331 	    return scancode;
3332     }
3333 
3334     keycode = scancode & 0x7F;
3335     switch (esc_flag) {
3336     case 0x00:      /* normal scancode */
3337 	switch(scancode) {
3338 	case 0xB8:  /* left alt (compose key) */
3339 	    if (compose) {
3340 		compose = 0;
3341 		if (chr > 255) {
3342 		    do_bell(cur_console,
3343 			BELL_PITCH, BELL_DURATION);
3344 		    chr = 0;
3345 		}
3346 	    }
3347 	    break;
3348 	case 0x38:
3349 	    if (!compose) {
3350 		compose = 1;
3351 		chr = 0;
3352 	    }
3353 	    break;
3354 	case 0xE0:
3355 	case 0xE1:
3356 	    esc_flag = scancode;
3357 	    goto next_code;
3358 	}
3359 	break;
3360     case 0xE0:      /* 0xE0 prefix */
3361 	esc_flag = 0;
3362 	switch (keycode) {
3363 	case 0x1C:  /* right enter key */
3364 	    keycode = 0x59;
3365 	    break;
3366 	case 0x1D:  /* right ctrl key */
3367 	    keycode = 0x5A;
3368 	    break;
3369 	case 0x35:  /* keypad divide key */
3370 	    keycode = 0x5B;
3371 	    break;
3372 	case 0x37:  /* print scrn key */
3373 	    keycode = 0x5C;
3374 	    break;
3375 	case 0x38:  /* right alt key (alt gr) */
3376 	    keycode = 0x5D;
3377 	    break;
3378 	case 0x47:  /* grey home key */
3379 	    keycode = 0x5E;
3380 	    break;
3381 	case 0x48:  /* grey up arrow key */
3382 	    keycode = 0x5F;
3383 	    break;
3384 	case 0x49:  /* grey page up key */
3385 	    keycode = 0x60;
3386 	    break;
3387 	case 0x4B:  /* grey left arrow key */
3388 	    keycode = 0x61;
3389 	    break;
3390 	case 0x4D:  /* grey right arrow key */
3391 	    keycode = 0x62;
3392 	    break;
3393 	case 0x4F:  /* grey end key */
3394 	    keycode = 0x63;
3395 	    break;
3396 	case 0x50:  /* grey down arrow key */
3397 	    keycode = 0x64;
3398 	    break;
3399 	case 0x51:  /* grey page down key */
3400 	    keycode = 0x65;
3401 	    break;
3402 	case 0x52:  /* grey insert key */
3403 	    keycode = 0x66;
3404 	    break;
3405 	case 0x53:  /* grey delete key */
3406 	    keycode = 0x67;
3407 	    break;
3408 
3409 	/* the following 3 are only used on the MS "Natural" keyboard */
3410 	case 0x5b:  /* left Window key */
3411 	    keycode = 0x69;
3412 	    break;
3413 	case 0x5c:  /* right Window key */
3414 	    keycode = 0x6a;
3415 	    break;
3416 	case 0x5d:  /* menu key */
3417 	    keycode = 0x6b;
3418 	    break;
3419 	default:    /* ignore everything else */
3420 	    goto next_code;
3421 	}
3422 	break;
3423     case 0xE1:      /* 0xE1 prefix */
3424 	esc_flag = 0;
3425 	if (keycode == 0x1D)
3426 	    esc_flag = 0x1D;
3427 	goto next_code;
3428 	/* NOT REACHED */
3429     case 0x1D:      /* pause / break */
3430 	esc_flag = 0;
3431 	if (keycode != 0x45)
3432 	    goto next_code;
3433 	keycode = 0x68;
3434 	break;
3435     }
3436 
3437     if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE))
3438 	return (keycode | (scancode & 0x80));
3439 
3440     /* if scroll-lock pressed allow history browsing */
3441     if (cur_console->history && cur_console->status & SLKED) {
3442 	int i;
3443 
3444 	cur_console->status &= ~CURSOR_ENABLED;
3445 	if (!(cur_console->status & BUFFER_SAVED)) {
3446 	    cur_console->status |= BUFFER_SAVED;
3447 	    cur_console->history_save = cur_console->history_head;
3448 
3449 	    /* copy screen into top of history buffer */
3450 	    for (i=0; i<cur_console->ysize; i++) {
3451 		bcopy(cur_console->scr_buf + (cur_console->xsize * i),
3452 		       cur_console->history_head,
3453 		       cur_console->xsize * sizeof(u_short));
3454 		cur_console->history_head += cur_console->xsize;
3455 		if (cur_console->history_head + cur_console->xsize >
3456 		    cur_console->history + cur_console->history_size)
3457 		    cur_console->history_head=cur_console->history;
3458 	    }
3459 	    cur_console->history_pos = cur_console->history_head;
3460 	    history_to_screen(cur_console);
3461 	}
3462 	switch (scancode) {
3463 	case 0x47:  /* home key */
3464 	    cur_console->history_pos = cur_console->history_head;
3465 	    history_to_screen(cur_console);
3466 	    goto next_code;
3467 
3468 	case 0x4F:  /* end key */
3469 	    cur_console->history_pos =
3470 		WRAPHIST(cur_console, cur_console->history_head,
3471 			 cur_console->xsize*cur_console->ysize);
3472 	    history_to_screen(cur_console);
3473 	    goto next_code;
3474 
3475 	case 0x48:  /* up arrow key */
3476 	    if (history_up_line(cur_console))
3477 		do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3478 	    goto next_code;
3479 
3480 	case 0x50:  /* down arrow key */
3481 	    if (history_down_line(cur_console))
3482 		do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3483 	    goto next_code;
3484 
3485 	case 0x49:  /* page up key */
3486 	    for (i=0; i<cur_console->ysize; i++)
3487 	    if (history_up_line(cur_console)) {
3488 		do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3489 		break;
3490 	    }
3491 	    goto next_code;
3492 
3493 	case 0x51:  /* page down key */
3494 	    for (i=0; i<cur_console->ysize; i++)
3495 	    if (history_down_line(cur_console)) {
3496 		do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3497 		break;
3498 	    }
3499 	    goto next_code;
3500 	}
3501     }
3502 
3503     if (compose) {
3504 	switch (scancode) {
3505 	/* key pressed process it */
3506 	case 0x47: case 0x48: case 0x49:    /* keypad 7,8,9 */
3507 	    chr = (scancode - 0x40) + chr*10;
3508 	    goto next_code;
3509 	case 0x4B: case 0x4C: case 0x4D:    /* keypad 4,5,6 */
3510 	    chr = (scancode - 0x47) + chr*10;
3511 	    goto next_code;
3512 	case 0x4F: case 0x50: case 0x51:    /* keypad 1,2,3 */
3513 	    chr = (scancode - 0x4E) + chr*10;
3514 	    goto next_code;
3515 	case 0x52:              /* keypad 0 */
3516 	    chr *= 10;
3517 	    goto next_code;
3518 
3519 	/* key release, no interest here */
3520 	case 0xC7: case 0xC8: case 0xC9:    /* keypad 7,8,9 */
3521 	case 0xCB: case 0xCC: case 0xCD:    /* keypad 4,5,6 */
3522 	case 0xCF: case 0xD0: case 0xD1:    /* keypad 1,2,3 */
3523 	case 0xD2:              /* keypad 0 */
3524 	    goto next_code;
3525 
3526 	case 0x38:              /* left alt key */
3527 	    break;
3528 	default:
3529 	    if (chr) {
3530 		compose = chr = 0;
3531 		do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3532 		goto next_code;
3533 	    }
3534 	    break;
3535 	}
3536     }
3537 
3538     state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0));
3539     if ((!agrs && (cur_console->status & ALKED))
3540 	|| (agrs && !(cur_console->status & ALKED)))
3541 	keycode += ALTGR_OFFSET;
3542     key = &key_map.key[keycode];
3543     if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED))
3544 	 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) )
3545 	state ^= 1;
3546 
3547     /* Check for make/break */
3548     action = key->map[state];
3549     if (scancode & 0x80) {      /* key released */
3550 	if (key->spcl & (0x80>>state)) {
3551 	    switch (action) {
3552 	    case LSH:
3553 		shfts &= ~1;
3554 		break;
3555 	    case RSH:
3556 		shfts &= ~2;
3557 		break;
3558 	    case LCTR:
3559 		ctls &= ~1;
3560 		break;
3561 	    case RCTR:
3562 		ctls &= ~2;
3563 		break;
3564 	    case LALT:
3565 		alts &= ~1;
3566 		break;
3567 	    case RALT:
3568 		alts &= ~2;
3569 		break;
3570 	    case NLK:
3571 		nlkcnt = 0;
3572 		break;
3573 	    case CLK:
3574 		clkcnt = 0;
3575 		break;
3576 	    case SLK:
3577 		slkcnt = 0;
3578 		break;
3579 	    case ASH:
3580 		agrs = 0;
3581 		break;
3582 	    case ALK:
3583 		alkcnt = 0;
3584 		break;
3585 	    case META:
3586 		metas = 0;
3587 		break;
3588 	    }
3589 	}
3590 	if (chr && !compose) {
3591 	    action = chr;
3592 	    chr = 0;
3593 	    return(action);
3594 	}
3595     } else {
3596 	/* key pressed */
3597 	if (key->spcl & (0x80>>state)) {
3598 	    switch (action) {
3599 	    /* LOCKING KEYS */
3600 	    case NLK:
3601 		if (!nlkcnt) {
3602 		    nlkcnt++;
3603 		    if (cur_console->status & NLKED)
3604 			cur_console->status &= ~NLKED;
3605 		    else
3606 			cur_console->status |= NLKED;
3607 		    update_leds(cur_console->status);
3608 		}
3609 		break;
3610 	    case CLK:
3611 		if (!clkcnt) {
3612 		    clkcnt++;
3613 		    if (cur_console->status & CLKED)
3614 			cur_console->status &= ~CLKED;
3615 		    else
3616 			cur_console->status |= CLKED;
3617 		    update_leds(cur_console->status);
3618 		}
3619 		break;
3620 	    case SLK:
3621 		if (!slkcnt) {
3622 		    slkcnt++;
3623 		    if (cur_console->status & SLKED) {
3624 			cur_console->status &= ~SLKED;
3625 			if (cur_console->status & BUFFER_SAVED){
3626 			    int i;
3627 			    u_short *ptr = cur_console->history_save;
3628 
3629 			    for (i=0; i<cur_console->ysize; i++) {
3630 				bcopy(ptr,
3631 				       cur_console->scr_buf +
3632 				       (cur_console->xsize*i),
3633 				       cur_console->xsize * sizeof(u_short));
3634 				ptr += cur_console->xsize;
3635 				if (ptr + cur_console->xsize >
3636 				    cur_console->history +
3637 				    cur_console->history_size)
3638 				    ptr = cur_console->history;
3639 			    }
3640 			    cur_console->status &= ~BUFFER_SAVED;
3641 			    cur_console->history_head=cur_console->history_save;
3642 			    cur_console->status |= CURSOR_ENABLED;
3643 			    mark_all(cur_console);
3644 			}
3645 			scstart(VIRTUAL_TTY(get_scr_num()));
3646 		    }
3647 		    else
3648 			cur_console->status |= SLKED;
3649 		    update_leds(cur_console->status);
3650 		}
3651 		break;
3652 	    case ALK:
3653 		if (!alkcnt) {
3654 		    alkcnt++;
3655 		    if (cur_console->status & ALKED)
3656 			cur_console->status &= ~ALKED;
3657 		    else
3658 			cur_console->status |= ALKED;
3659 		    update_leds(cur_console->status);
3660 		}
3661 		break;
3662 
3663 	    /* NON-LOCKING KEYS */
3664 	    case NOP:
3665 		break;
3666 	    case SPSC:
3667 		/* force activatation/deactivation of the screen saver */
3668 		accents = 0;
3669 		if (scrn_blanked <= 0) {
3670 		    run_scrn_saver = TRUE;
3671 		    scrn_time_stamp -= scrn_blank_time;
3672 		}
3673 #ifdef SC_SPLASH_SCREEN
3674 		if (cold) {
3675 		    /*
3676 		     * While devices are being probed, the screen saver need
3677 		     * to be invoked explictly. XXX
3678 		     */
3679 		    if (scrn_blanked > 0) {
3680 			scsplash_stick(FALSE);
3681 			stop_scrn_saver(current_saver);
3682 		    } else {
3683 			if (!ISGRAPHSC(cur_console)) {
3684 			    scsplash_stick(TRUE);
3685 			    scrn_saver(current_saver, TRUE);
3686 			}
3687 		    }
3688 		}
3689 #endif
3690 		break;
3691 	    case RBT:
3692 #ifndef SC_DISABLE_REBOOT
3693 		accents = 0;
3694 		shutdown_nice();
3695 #endif
3696 		break;
3697 	    case SUSP:
3698 #if NAPM > 0
3699 		accents = 0;
3700 		apm_suspend(PMST_SUSPEND);
3701 #endif
3702 		break;
3703 
3704 	    case STBY:
3705 #if NAPM > 0
3706 		accents = 0;
3707 		apm_suspend(PMST_STANDBY);
3708 #endif
3709 		break;
3710 
3711 	    case DBG:
3712 #ifdef DDB          /* try to switch to console 0 */
3713 		accents = 0;
3714 		/*
3715 		 * TRY to make sure the screen saver is stopped,
3716 		 * and the screen is updated before switching to
3717 		 * the vty0.
3718 		 */
3719 		scrn_timer((void *)FALSE);
3720 		if (cur_console->smode.mode == VT_AUTO &&
3721 		    console[0]->smode.mode == VT_AUTO)
3722 		    switch_scr(cur_console, 0);
3723 		Debugger("manual escape to debugger");
3724 #else
3725 		printf("No debugger in kernel\n");
3726 #endif
3727 		break;
3728 	    case LSH:
3729 		shfts |= 1;
3730 		break;
3731 	    case RSH:
3732 		shfts |= 2;
3733 		break;
3734 	    case LCTR:
3735 		ctls |= 1;
3736 		break;
3737 	    case RCTR:
3738 		ctls |= 2;
3739 		break;
3740 	    case LALT:
3741 		alts |= 1;
3742 		break;
3743 	    case RALT:
3744 		alts |= 2;
3745 		break;
3746 	    case ASH:
3747 		agrs = 1;
3748 		break;
3749 	    case META:
3750 		metas = 1;
3751 		break;
3752 	    case NEXT:
3753 		{
3754 		int next, this = get_scr_num();
3755 		accents = 0;
3756 		for (next = this+1; next != this; next = (next+1)%MAXCONS) {
3757 		    struct tty *tp = VIRTUAL_TTY(next);
3758 		    if (tp->t_state & TS_ISOPEN) {
3759 			switch_scr(cur_console, next);
3760 			break;
3761 		    }
3762 		}
3763 		}
3764 		break;
3765 	    case BTAB:
3766 		accents = 0;
3767 		return(BKEY);
3768 	    default:
3769 		if (action >= F_ACC && action <= L_ACC) {
3770 		    /* turn it into an index */
3771 		    action -= F_ACC - 1;
3772 		    if ((action > accent_map.n_accs)
3773 			|| (accent_map.acc[action - 1].accchar == 0)) {
3774 			/*
3775 			 * The index is out of range or pointing to an
3776 			 * empty entry.
3777 			 */
3778 			accents = 0;
3779 			do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3780 		    }
3781 		    /*
3782 		     * If the same accent key has been hit twice,
3783 		     * produce the accent char itself.
3784 		     */
3785 		    if (action == accents) {
3786 			action = accent_map.acc[accents - 1].accchar;
3787 			accents = 0;
3788 			if (metas)
3789 			    action |= MKEY;
3790 			return (action);
3791 		    }
3792 		    /* remember the index and wait for the next key stroke */
3793 		    accents = action;
3794 		    break;
3795 		}
3796 		if (accents > 0) {
3797 		    accents = 0;
3798 		    do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3799 		}
3800 		if (action >= F_SCR && action <= L_SCR) {
3801 		    switch_scr(cur_console, action - F_SCR);
3802 		    break;
3803 		}
3804 		if (action >= F_FN && action <= L_FN)
3805 		    action |= FKEY;
3806 		return(action);
3807 	    }
3808 	}
3809 	else {
3810 	    if (accents) {
3811 		struct acc_t *acc;
3812 		int i;
3813 
3814 		acc = &accent_map.acc[accents - 1];
3815 		accents = 0;
3816 		/*
3817 		 * If the accent key is followed by the space key,
3818 		 * produce the accent char itself.
3819 		 */
3820 		if (action == ' ') {
3821 		    action = acc->accchar;
3822 		    if (metas)
3823 			action |= MKEY;
3824 		    return (action);
3825 		}
3826 		for (i = 0; i < NUM_ACCENTCHARS; ++i) {
3827 		    if (acc->map[i][0] == 0)	/* end of the map entry */
3828 			break;
3829 		    if (acc->map[i][0] == action) {
3830 			action = acc->map[i][1];
3831 			if (metas)
3832 			    action |= MKEY;
3833 			return (action);
3834 		    }
3835 		}
3836 		do_bell(cur_console, BELL_PITCH, BELL_DURATION);
3837 		goto next_code;
3838 	    }
3839 	    if (metas)
3840 		action |= MKEY;
3841 	    return(action);
3842 	}
3843     }
3844     goto next_code;
3845 }
3846 
3847 int
3848 scmmap(dev_t dev, int offset, int nprot)
3849 {
3850     if (offset > 0x20000 - PAGE_SIZE)
3851 	return -1;
3852     return i386_btop((VIDEOMEM + offset));
3853 }
3854 
3855 /*
3856  * Calculate hardware attributes word using logical attributes mask and
3857  * hardware colors
3858  */
3859 
3860 static int
3861 mask2attr(struct term_stat *term)
3862 {
3863     int attr, mask = term->attr_mask;
3864 
3865     if (mask & REVERSE_ATTR) {
3866 	attr = ((mask & FOREGROUND_CHANGED) ?
3867 		((term->cur_color & 0xF000) >> 4) :
3868 		(term->rev_color & 0x0F00)) |
3869 	       ((mask & BACKGROUND_CHANGED) ?
3870 		((term->cur_color & 0x0F00) << 4) :
3871 		(term->rev_color & 0xF000));
3872     } else
3873 	attr = term->cur_color;
3874 
3875     /* XXX: underline mapping for Hercules adapter can be better */
3876     if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
3877 	attr ^= 0x0800;
3878     if (mask & BLINK_ATTR)
3879 	attr ^= 0x8000;
3880 
3881     return attr;
3882 }
3883 
3884 static void
3885 set_keyboard(int command, int data)
3886 {
3887     int s;
3888 
3889     if (sc_kbdc == NULL)
3890 	return;
3891 
3892     /* prevent the timeout routine from polling the keyboard */
3893     if (!kbdc_lock(sc_kbdc, TRUE))
3894 	return;
3895 
3896     /* disable the keyboard and mouse interrupt */
3897     s = spltty();
3898 #if 0
3899     c = get_controller_command_byte(sc_kbdc);
3900     if ((c == -1)
3901 	|| !set_controller_command_byte(sc_kbdc,
3902             kbdc_get_device_mask(sc_kbdc),
3903             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
3904                 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
3905 	/* CONTROLLER ERROR */
3906         kbdc_lock(sc_kbdc, FALSE);
3907 	splx(s);
3908 	return;
3909     }
3910     /*
3911      * Now that the keyboard controller is told not to generate
3912      * the keyboard and mouse interrupts, call `splx()' to allow
3913      * the other tty interrupts. The clock interrupt may also occur,
3914      * but the timeout routine (`scrn_timer()') will be blocked
3915      * by the lock flag set via `kbdc_lock()'
3916      */
3917     splx(s);
3918 #endif
3919 
3920     if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK)
3921         send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD);
3922 
3923 #if 0
3924     /* restore the interrupts */
3925     if (!set_controller_command_byte(sc_kbdc,
3926             kbdc_get_device_mask(sc_kbdc),
3927 	    c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
3928 	/* CONTROLLER ERROR */
3929     }
3930 #else
3931     splx(s);
3932 #endif
3933     kbdc_lock(sc_kbdc, FALSE);
3934 }
3935 
3936 static void
3937 update_leds(int which)
3938 {
3939     static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
3940 
3941     /* replace CAPS led with ALTGR led for ALTGR keyboards */
3942     if (key_map.n_keys > ALTGR_OFFSET) {
3943 	if (which & ALKED)
3944 	    which |= CLKED;
3945 	else
3946 	    which &= ~CLKED;
3947     }
3948 
3949     set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]);
3950 }
3951 
3952 int
3953 set_mode(scr_stat *scp)
3954 {
3955     video_info_t info;
3956     video_adapter_t *adp;
3957 
3958     /* reject unsupported mode */
3959     if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
3960 	return 1;
3961 
3962     /* if this vty is not currently showing, do nothing */
3963     if (scp != cur_console)
3964 	return 0;
3965 
3966     /* setup video hardware for the given mode */
3967     adp = get_adapter(scp);
3968     (*biosvidsw.set_mode)(scp->adp, scp->mode);
3969     Crtat = (u_short *)adp->va_window;
3970 
3971     if (!(scp->status & GRAPHICS_MODE)) {
3972 	/* load appropriate font */
3973 	if (!(scp->status & PIXEL_MODE)
3974 	    && ISFONTAVAIL(get_adapter(scp)->va_flags)) {
3975 	    if (scp->font_size < 14) {
3976 		if (fonts_loaded & FONT_8)
3977 		    copy_font(scp, LOAD, 8, font_8);
3978 	    } else if (scp->font_size >= 16) {
3979 		if (fonts_loaded & FONT_16)
3980 		    copy_font(scp, LOAD, 16, font_16);
3981 	    } else {
3982 		if (fonts_loaded & FONT_14)
3983 		    copy_font(scp, LOAD, 14, font_14);
3984 	    }
3985 	    /*
3986 	    * FONT KLUDGE:
3987 	    * This is an interim kludge to display correct font.
3988 	    * Always use the font page #0 on the video plane 2.
3989 	    * Somehow we cannot show the font in other font pages on
3990 	    * some video cards... XXX
3991 	    */
3992 	    (*biosvidsw.show_font)(scp->adp, 0);
3993 	}
3994 	mark_all(scp);
3995     }
3996     set_border(scp, scp->border);
3997 
3998     /* move hardware cursor out of the way */
3999     (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
4000 
4001     return 0;
4002 }
4003 
4004 void
4005 copy_font(scr_stat *scp, int operation, int font_size, u_char *buf)
4006 {
4007     /*
4008      * FONT KLUDGE:
4009      * This is an interim kludge to display correct font.
4010      * Always use the font page #0 on the video plane 2.
4011      * Somehow we cannot show the font in other font pages on
4012      * some video cards... XXX
4013      */
4014     font_loading_in_progress = TRUE;
4015     if (operation == LOAD) {
4016 	(*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256);
4017 	if (flags & CHAR_CURSOR)
4018 	    set_destructive_cursor(scp);
4019     } else if (operation == SAVE) {
4020 	(*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256);
4021     }
4022     font_loading_in_progress = FALSE;
4023 }
4024 
4025 static void
4026 set_destructive_cursor(scr_stat *scp)
4027 {
4028     u_char cursor[32];
4029     u_char *font_buffer;
4030     int font_size;
4031     int i;
4032 
4033     if (!ISFONTAVAIL(get_adapter(scp)->va_flags) || !ISTEXTSC(scp))
4034 	return;
4035 
4036     if (scp->font_size < 14) {
4037 	font_buffer = font_8;
4038 	font_size = 8;
4039     } else if (scp->font_size >= 16) {
4040 	font_buffer = font_16;
4041 	font_size = 16;
4042     } else {
4043 	font_buffer = font_14;
4044 	font_size = 14;
4045     }
4046 
4047     if (scp->status & MOUSE_VISIBLE) {
4048 	if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR)
4049     	    bcopy(&scp->mouse_cursor[0], cursor, scp->font_size);
4050 	else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1)
4051     	    bcopy(&scp->mouse_cursor[32], cursor, scp->font_size);
4052 	else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2)
4053     	    bcopy(&scp->mouse_cursor[64], cursor, scp->font_size);
4054 	else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3)
4055     	    bcopy(&scp->mouse_cursor[96], cursor, scp->font_size);
4056 	else
4057 	    bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size),
4058  	       	   cursor, scp->font_size);
4059     }
4060     else
4061     	bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size),
4062  	       cursor, scp->font_size);
4063     for (i=0; i<32; i++)
4064 	if ((i >= scp->cursor_start && i <= scp->cursor_end) ||
4065 	    (scp->cursor_start >= scp->font_size && i == scp->font_size - 1))
4066 	    cursor[i] |= 0xff;
4067 #if 1
4068     while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ;
4069 #endif
4070     font_loading_in_progress = TRUE;
4071     (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1);
4072     font_loading_in_progress = FALSE;
4073 }
4074 
4075 void
4076 sc_move_mouse(scr_stat *scp, int x, int y)
4077 {
4078     scp->mouse_xpos = x;
4079     scp->mouse_ypos = y;
4080     scp->mouse_pos = scp->mouse_oldpos =
4081 	scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8;
4082 }
4083 
4084 static void
4085 set_mouse_pos(scr_stat *scp)
4086 {
4087     static int last_xpos = -1, last_ypos = -1;
4088 
4089     if (scp->mouse_xpos < 0)
4090 	scp->mouse_xpos = 0;
4091     if (scp->mouse_ypos < 0)
4092 	scp->mouse_ypos = 0;
4093     if (!ISTEXTSC(scp)) {
4094         if (scp->mouse_xpos > scp->xpixel-1)
4095 	    scp->mouse_xpos = scp->xpixel-1;
4096         if (scp->mouse_ypos > scp->ypixel-1)
4097 	    scp->mouse_ypos = scp->ypixel-1;
4098 	return;
4099     }
4100     if (scp->mouse_xpos > (scp->xsize*8)-1)
4101 	scp->mouse_xpos = (scp->xsize*8)-1;
4102     if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1)
4103 	scp->mouse_ypos = (scp->ysize*scp->font_size)-1;
4104 
4105     if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) {
4106 	scp->status |= MOUSE_MOVED;
4107 
4108     	scp->mouse_pos = scp->scr_buf +
4109 	    ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8);
4110 
4111 	if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
4112 	    mouse_cut(scp);
4113     }
4114 }
4115 
4116 #define isspace(c)	(((c) & 0xff) == ' ')
4117 
4118 static int
4119 skip_spc_right(scr_stat *scp, u_short *p)
4120 {
4121     int i;
4122 
4123     for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
4124 	if (!isspace(*p))
4125 	    break;
4126 	++p;
4127     }
4128     return i;
4129 }
4130 
4131 static int
4132 skip_spc_left(scr_stat *scp, u_short *p)
4133 {
4134     int i;
4135 
4136     for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) {
4137 	if (!isspace(*p))
4138 	    break;
4139 	--p;
4140     }
4141     return i;
4142 }
4143 
4144 static void
4145 mouse_cut(scr_stat *scp)
4146 {
4147     u_short *end;
4148     u_short *p;
4149     int i = 0;
4150     int j = 0;
4151 
4152     scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ?
4153 	scp->mouse_pos + 1 : scp->mouse_pos;
4154     end = (scp->mouse_cut_start > scp->mouse_cut_end) ?
4155 	scp->mouse_cut_start : scp->mouse_cut_end;
4156     for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ?
4157 	    scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) {
4158 	cut_buffer[i] = *p & 0xff;
4159 	/* remember the position of the last non-space char */
4160 	if (!isspace(cut_buffer[i++]))
4161 	    j = i;
4162 	/* trim trailing blank when crossing lines */
4163 	if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) {
4164 	    cut_buffer[j++] = '\r';
4165 	    i = j;
4166 	}
4167     }
4168     cut_buffer[i] = '\0';
4169 
4170     /* scan towards the end of the last line */
4171     --p;
4172     for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) {
4173 	if (!isspace(*p))
4174 	    break;
4175 	++p;
4176     }
4177     /* if there is nothing but blank chars, trim them, but mark towards eol */
4178     if (i >= scp->xsize) {
4179 	if (scp->mouse_cut_start > scp->mouse_cut_end)
4180 	    scp->mouse_cut_start = p;
4181 	else
4182 	    scp->mouse_cut_end = p;
4183 	cut_buffer[j++] = '\r';
4184 	cut_buffer[j] = '\0';
4185     }
4186 
4187     mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf);
4188     mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf);
4189 }
4190 
4191 static void
4192 mouse_cut_start(scr_stat *scp)
4193 {
4194     int i;
4195 
4196     if (scp->status & MOUSE_VISIBLE) {
4197 	if (scp->mouse_pos == scp->mouse_cut_start &&
4198 	    scp->mouse_cut_start == scp->mouse_cut_end - 1) {
4199 	    cut_buffer[0] = '\0';
4200 	    remove_cutmarking(scp);
4201 	} else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) {
4202 	    /* if the pointer is on trailing blank chars, mark towards eol */
4203 	    i = skip_spc_left(scp, scp->mouse_pos) + 1;
4204 	    scp->mouse_cut_start = scp->scr_buf +
4205 	        ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i;
4206 	    scp->mouse_cut_end = scp->scr_buf +
4207 	        ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize;
4208 	    cut_buffer[0] = '\r';
4209 	    cut_buffer[1] = '\0';
4210 	    scp->status |= MOUSE_CUTTING;
4211 	} else {
4212 	    scp->mouse_cut_start = scp->mouse_pos;
4213 	    scp->mouse_cut_end = scp->mouse_cut_start + 1;
4214 	    cut_buffer[0] = *scp->mouse_cut_start & 0xff;
4215 	    cut_buffer[1] = '\0';
4216 	    scp->status |= MOUSE_CUTTING;
4217 	}
4218     	mark_all(scp);
4219 	/* delete all other screens cut markings */
4220 	for (i=0; i<MAXCONS; i++) {
4221 	    if (console[i] == NULL || console[i] == scp)
4222 		continue;
4223 	    remove_cutmarking(console[i]);
4224 	}
4225     }
4226 }
4227 
4228 static void
4229 mouse_cut_end(scr_stat *scp)
4230 {
4231     if (scp->status & MOUSE_VISIBLE) {
4232 	scp->status &= ~MOUSE_CUTTING;
4233     }
4234 }
4235 
4236 static void
4237 mouse_cut_word(scr_stat *scp)
4238 {
4239     u_short *p;
4240     u_short *sol;
4241     u_short *eol;
4242     int i;
4243 
4244     /*
4245      * Because we don't have locale information in the kernel,
4246      * we only distinguish space char and non-space chars.  Punctuation
4247      * chars, symbols and other regular chars are all treated alike.
4248      */
4249     if (scp->status & MOUSE_VISIBLE) {
4250 	sol = scp->scr_buf
4251 	    + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
4252 	eol = sol + scp->xsize;
4253 	if (isspace(*scp->mouse_pos)) {
4254 	    for (p = scp->mouse_pos; p >= sol; --p)
4255 	        if (!isspace(*p))
4256 		    break;
4257 	    scp->mouse_cut_start = ++p;
4258 	    for (p = scp->mouse_pos; p < eol; ++p)
4259 	        if (!isspace(*p))
4260 		    break;
4261 	    scp->mouse_cut_end = p;
4262 	} else {
4263 	    for (p = scp->mouse_pos; p >= sol; --p)
4264 	        if (isspace(*p))
4265 		    break;
4266 	    scp->mouse_cut_start = ++p;
4267 	    for (p = scp->mouse_pos; p < eol; ++p)
4268 	        if (isspace(*p))
4269 		    break;
4270 	    scp->mouse_cut_end = p;
4271 	}
4272 	for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
4273 	    cut_buffer[i++] = *p & 0xff;
4274 	cut_buffer[i] = '\0';
4275 	scp->status |= MOUSE_CUTTING;
4276     }
4277 }
4278 
4279 static void
4280 mouse_cut_line(scr_stat *scp)
4281 {
4282     u_short *p;
4283     int i;
4284 
4285     if (scp->status & MOUSE_VISIBLE) {
4286 	scp->mouse_cut_start = scp->scr_buf
4287 	    + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize;
4288 	scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize;
4289 	for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p)
4290 	    cut_buffer[i++] = *p & 0xff;
4291 	cut_buffer[i++] = '\r';
4292 	cut_buffer[i] = '\0';
4293 	scp->status |= MOUSE_CUTTING;
4294     }
4295 }
4296 
4297 static void
4298 mouse_cut_extend(scr_stat *scp)
4299 {
4300     if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING)
4301 	&& (scp->mouse_cut_start != NULL)) {
4302 	mouse_cut(scp);
4303 	scp->status |= MOUSE_CUTTING;
4304     }
4305 }
4306 
4307 static void
4308 mouse_paste(scr_stat *scp)
4309 {
4310     if (scp->status & MOUSE_VISIBLE) {
4311 	struct tty *tp;
4312 	u_char *ptr = cut_buffer;
4313 
4314 	tp = VIRTUAL_TTY(get_scr_num());
4315 	while (*ptr)
4316 	    (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp);
4317     }
4318 }
4319 
4320 static void
4321 draw_mouse_image(scr_stat *scp)
4322 {
4323     u_short buffer[32];
4324     u_short xoffset, yoffset;
4325     u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf);
4326     u_char *font_buffer;
4327     int font_size;
4328     int i;
4329 
4330     if (scp->font_size < 14) {
4331 	font_buffer = font_8;
4332 	font_size = 8;
4333     } else if (scp->font_size >= 16) {
4334 	font_buffer = font_16;
4335 	font_size = 16;
4336     } else {
4337 	font_buffer = font_14;
4338 	font_size = 14;
4339     }
4340 
4341     xoffset = scp->mouse_xpos % 8;
4342     yoffset = scp->mouse_ypos % scp->font_size;
4343 
4344     /* prepare mousepointer char's bitmaps */
4345     bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size),
4346 	   &scp->mouse_cursor[0], font_size);
4347     bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size),
4348 	   &scp->mouse_cursor[32], font_size);
4349     bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size),
4350 	   &scp->mouse_cursor[64], font_size);
4351     bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size),
4352 	   &scp->mouse_cursor[96], font_size);
4353     for (i=0; i<font_size; i++) {
4354 	buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32];
4355 	buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96];
4356     }
4357 
4358     /* now and-or in the mousepointer image */
4359     for (i=0; i<16; i++) {
4360 	buffer[i+yoffset] =
4361 	    ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset))
4362 	    | (mouse_or_mask[i] >> xoffset);
4363     }
4364     for (i=0; i<font_size; i++) {
4365 	scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8;
4366 	scp->mouse_cursor[i+32] = buffer[i] & 0xff;
4367 	scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8;
4368 	scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff;
4369     }
4370 
4371     scp->mouse_oldpos = scp->mouse_pos;
4372 
4373 #if 1
4374     /* wait for vertical retrace to avoid jitter on some videocards */
4375     while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ;
4376 #endif
4377     font_loading_in_progress = TRUE;
4378     (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor,
4379 			   SC_MOUSE_CHAR, 4);
4380     font_loading_in_progress = FALSE;
4381 
4382     *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR;
4383     *(crt_pos+scp->xsize) =
4384 	(*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2);
4385     if (scp->mouse_xpos < (scp->xsize-1)*8) {
4386     	*(crt_pos + 1) = (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1);
4387     	*(crt_pos+scp->xsize + 1) =
4388 	    (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3);
4389     }
4390     mark_for_update(scp, scp->mouse_pos - scp->scr_buf);
4391     mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf);
4392 }
4393 
4394 static void
4395 remove_mouse_image(scr_stat *scp)
4396 {
4397     u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf);
4398 
4399     if (!ISTEXTSC(scp))
4400 	return;
4401     *(crt_pos) = *(scp->mouse_oldpos);
4402     *(crt_pos+1) = *(scp->mouse_oldpos+1);
4403     *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize);
4404     *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1);
4405     mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf);
4406     mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf);
4407 }
4408 
4409 static void
4410 draw_cutmarking(scr_stat *scp)
4411 {
4412     u_short *ptr;
4413     u_short och, nch;
4414 
4415     for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) {
4416 	nch = och = *(Crtat + (ptr - scp->scr_buf));
4417 	/* are we outside the selected area ? */
4418 	if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ?
4419 	            scp->mouse_cut_end : scp->mouse_cut_start) ||
4420 	     ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ?
4421 	            scp->mouse_cut_start : scp->mouse_cut_end)) {
4422 	    if (ptr != scp->cursor_pos)
4423 		nch = (och & 0xff) | (*ptr & 0xff00);
4424 	}
4425 	else {
4426 	    /* are we clear of the cursor image ? */
4427 	    if (ptr != scp->cursor_pos)
4428 		nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4;
4429 	    else {
4430 		if (flags & CHAR_CURSOR)
4431 		    nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4;
4432 		else
4433 		    if (!(flags & BLINK_CURSOR))
4434 		        nch = (och & 0xff) | (*ptr & 0xff00);
4435 	    }
4436 	}
4437 	if (nch != och)
4438 	    *(Crtat + (ptr - scp->scr_buf)) = nch;
4439     }
4440 }
4441 
4442 static void
4443 remove_cutmarking(scr_stat *scp)
4444 {
4445     scp->mouse_cut_start = scp->mouse_cut_end = NULL;
4446     scp->status &= ~MOUSE_CUTTING;
4447     mark_all(scp);
4448 }
4449 
4450 static void
4451 do_bell(scr_stat *scp, int pitch, int duration)
4452 {
4453     if (cold || shutdown_in_progress)
4454 	return;
4455 
4456     if (scp != cur_console && (flags & QUIET_BELL))
4457 	return;
4458 
4459     if (flags & VISUAL_BELL) {
4460 	if (blink_in_progress)
4461 	    return;
4462 	blink_in_progress = 4;
4463 	if (scp != cur_console)
4464 	    blink_in_progress += 2;
4465 	blink_screen(cur_console);
4466     } else {
4467 	if (scp != cur_console)
4468 	    pitch *= 2;
4469 	sysbeep(pitch, duration);
4470     }
4471 }
4472 
4473 static void
4474 blink_screen(void *arg)
4475 {
4476     scr_stat *scp = arg;
4477 
4478     if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) {
4479 	blink_in_progress = FALSE;
4480     	mark_all(scp);
4481 	if (delayed_next_scr)
4482 	    switch_scr(scp, delayed_next_scr - 1);
4483     }
4484     else {
4485 	if (blink_in_progress & 1)
4486 	    fillw(kernel_default.std_color | scr_map[0x20],
4487 		  Crtat, scp->xsize * scp->ysize);
4488 	else
4489 	    fillw(kernel_default.rev_color | scr_map[0x20],
4490 		  Crtat, scp->xsize * scp->ysize);
4491 	blink_in_progress--;
4492 	timeout(blink_screen, scp, hz / 10);
4493     }
4494 }
4495 
4496 void
4497 sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
4498 {
4499     u_char *font;
4500     u_char *d, *e;
4501     u_char *f;
4502     int font_size;
4503     int line_length;
4504     int xsize;
4505     int i, j;
4506 
4507     if (ISTEXTSC(scp)) {
4508 	generic_bcopy(p+from, Crtat+from, (to-from+1)*sizeof (u_short));
4509     } else /* if ISPIXELSC(scp) */ {
4510 	if (mark)
4511 	    mark = 255;
4512 	font_size = scp->font_size;
4513 	if (font_size < 14)
4514 	    font = font_8;
4515 	else if (font_size >= 16)
4516 	    font = font_16;
4517 	else
4518 	    font = font_14;
4519 	line_length = scp->xpixel/8;
4520 	xsize = scp->xsize;
4521 	d = (u_char *)Crtat
4522 	    + scp->xoff + scp->yoff*font_size*line_length
4523 	    + (from%xsize) + font_size*line_length*(from/xsize);
4524 	for (i = from ; i <= to ; i++) {
4525 	    e = d;
4526 	    f = &font[(p[i] & 0x00ff)*font_size];
4527 	    for (j = 0 ; j < font_size; j++, f++) {
4528 	        *e = mark^*f;
4529 		e += line_length;
4530 	    }
4531 	    d++;
4532 	    if ((i % xsize) == xsize - 1)
4533 		d += scp->xoff*2 + (font_size - 1)*line_length;
4534 	}
4535     }
4536 }
4537 
4538 #ifdef SC_SPLASH_SCREEN
4539 
4540 static void
4541 scsplash_init(scr_stat *scp)
4542 {
4543     video_info_t info;
4544 
4545     /*
4546      * We currently assume the splash screen always use
4547      * VGA_CG320 mode and abort installation if this mode is not
4548      * supported with this video card. XXX
4549      */
4550     if ((*biosvidsw.get_info)(scp->adp, M_VGA_CG320, &info))
4551 	return;
4552 
4553     if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) {
4554 	default_saver = scsplash_saver;
4555 	scrn_blank_time = DEFAULT_BLANKTIME;
4556 	run_scrn_saver = TRUE;
4557 	if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) {
4558 	    scsplash_stick(TRUE);
4559 	    scsplash_saver(TRUE);
4560 	}
4561     }
4562 }
4563 
4564 static void
4565 scsplash_saver(int show)
4566 {
4567     if (show)
4568 	scsplash(TRUE);
4569     else if (!sticky_splash)
4570 	scsplash(FALSE);
4571 }
4572 
4573 #endif /* SC_SPLASH_SCREEN */
4574 
4575 #endif /* NSC */
4576