diff --git a/lkm/syscons/blank/blank_saver.c b/lkm/syscons/blank/blank_saver.c
index 451dc9a4b241..d5f4cf0bf560 100644
--- a/lkm/syscons/blank/blank_saver.c
+++ b/lkm/syscons/blank/blank_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: blank_saver.c,v 1.10 1997/07/15 14:49:09 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
diff --git a/lkm/syscons/daemon/daemon_saver.c b/lkm/syscons/daemon/daemon_saver.c
index f3cf3dce7736..688df41f274a 100644
--- a/lkm/syscons/daemon/daemon_saver.c
+++ b/lkm/syscons/daemon/daemon_saver.c
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: daemon_saver.c,v 1.8 1998/01/16 17:58:43 bde Exp $
+ *	$Id: daemon_saver.c,v 1.9 1998/08/06 09:14:20 yokota Exp $
  */
 
 #include <sys/param.h>
@@ -205,7 +205,7 @@ daemon_saver(int blank)
 			/* clear the screen and set the border color */
 			fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
 			      Crtat, scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			xlen = ylen = tlen = 0;
 		}
 		if (scrn_blanked++ < 2)
@@ -322,7 +322,7 @@ daemon_saver(int blank)
 		draw_string(txpos, typos, toff, (char *)message, tlen);
 	} else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/lkm/syscons/fade/fade_saver.c b/lkm/syscons/fade/fade_saver.c
index 341f7e8d240c..41176e76e092 100644
--- a/lkm/syscons/fade/fade_saver.c
+++ b/lkm/syscons/fade/fade_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995-1997 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: fade_saver.c,v 1.11 1997/07/15 14:49:25 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -84,7 +84,7 @@ fade_saver(int blank)
 	else {
 		switch (crtc_type) {
 		case KD_VGA:
-			load_palette(palette);
+			load_palette(cur_console, palette);
 			count = 0;
 			break;
 		case KD_EGA:
diff --git a/lkm/syscons/green/green_saver.c b/lkm/syscons/green/green_saver.c
index b8c82958ac34..667866284681 100644
--- a/lkm/syscons/green/green_saver.c
+++ b/lkm/syscons/green/green_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: green_saver.c,v 1.10 1997/07/15 14:49:29 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
diff --git a/lkm/syscons/saver.h b/lkm/syscons/saver.h
index 7118e4588e22..96cc010e9b81 100644
--- a/lkm/syscons/saver.h
+++ b/lkm/syscons/saver.h
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995-1997 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,12 +25,12 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *  $Id: saver.h,v 1.9 1997/07/15 14:48:11 yokota Exp $
+ *	$Id$
  */
-
 #include <machine/apm_bios.h>
 #include <machine/console.h>
 
+#include <i386/isa/videoio.h>
 #include <i386/isa/syscons.h>
 
 extern scr_stat	*cur_console;
diff --git a/lkm/syscons/snake/snake_saver.c b/lkm/syscons/snake/snake_saver.c
index c3fa1fe7ce38..c5011d04bac2 100644
--- a/lkm/syscons/snake/snake_saver.c
+++ b/lkm/syscons/snake/snake_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: snake_saver.c,v 1.16 1998/01/16 17:58:50 bde Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -63,7 +63,7 @@ snake_saver(int blank)
 		if (scrn_blanked <= 0) {
 			fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20],
 			      Crtat, scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			dirx = (scp->xpos ? 1 : -1);
 			diry = (scp->ypos ?
 				scp->xsize : -scp->xsize);
@@ -99,7 +99,7 @@ snake_saver(int blank)
 	}
 	else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/lkm/syscons/star/star_saver.c b/lkm/syscons/star/star_saver.c
index 517a5579968f..8ac65bdba71c 100644
--- a/lkm/syscons/star/star_saver.c
+++ b/lkm/syscons/star/star_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: star_saver.c,v 1.13 1998/01/16 17:58:55 bde Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -62,7 +62,7 @@ star_saver(int blank)
 			scrn_blanked = 1;
 			fillw((FG_LIGHTGREY|BG_BLACK)<<8|scr_map[0x20], Crtat,
 			      scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			for(i=0; i<NUM_STARS; i++) {
 				stars[i][0] =
 					random() % (scp->xsize*scp->ysize);
@@ -80,7 +80,7 @@ star_saver(int blank)
 	}
 	else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 2d8c4a883224..8b20f861bacc 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
 # LINT -- config file for checking all the sources, tries to pull in
 #	as much of the source tree as it can.
 #
-#	$Id: LINT,v 1.464 1998/09/15 10:01:13 gibbs Exp $
+#	$Id: LINT,v 1.465 1998/09/15 11:44:43 phk Exp $
 #
 # NB: You probably don't want to try running a kernel built from this
 # file.  Instead, you should start from GENERIC, and add options from
@@ -803,6 +803,9 @@ options		SC_HISTORY_SIZE=200	# number of history buffer lines
 options		SC_DISABLE_REBOOT	# disable reboot key sequence
 # If the screen flickers badly when the mouse pointer is moved, try this.
 options		SC_BAD_FLICKER
+# To include support for VESA video modes
+# Dont use together with SMP!!
+options		VESA			# needs VM86 defined too!!
 
 #
 # `flags' for sc0:
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 5302df40d509..6a0847003632 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
-#	$Id: files.i386,v 1.202 1998/09/08 20:57:46 sos Exp $
+#	$Id: files.i386,v 1.203 1998/09/15 10:01:13 gibbs Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -240,6 +240,10 @@ i386/isa/spigot.c		optional	spigot	device-driver
 i386/isa/spkr.c			optional	speaker	device-driver
 i386/isa/stallion.c		optional	stl	device-driver
 i386/isa/syscons.c		optional	sc	device-driver
+i386/isa/scvidctl.c		optional	sc	device-driver
+i386/isa/scvesactl.c		optional	sc	device-driver
+i386/isa/videoio.c		optional	sc	device-driver
+i386/isa/vesa.c			optional	sc	device-driver
 i386/isa/tw.c			optional	tw	device-driver
 #i386/isa/ultra14f.c		optional	uha	device-driver
 i386/isa/wd.c			optional	wdc	device-driver
diff --git a/sys/conf/options.i386 b/sys/conf/options.i386
index c07d086cbdf4..21c45983b680 100644
--- a/sys/conf/options.i386
+++ b/sys/conf/options.i386
@@ -1,4 +1,4 @@
-#	$Id: options.i386,v 1.85 1998/09/08 18:09:50 brian Exp $
+#	$Id: options.i386,v 1.86 1998/09/15 10:01:14 gibbs Exp $
 
 BOUNCEPAGES		opt_bounce.h
 DISABLE_PSE
@@ -77,6 +77,8 @@ SC_DISABLE_REBOOT	opt_syscons.h
 SC_MOUSE_CHAR		opt_syscons.h
 SC_BAD_FLICKER		opt_syscons.h
 
+VESA			opt_vesa.h
+
 PSM_HOOKAPM		opt_psm.h
 PSM_RESETAFTERSUSPEND	opt_psm.h
 PSM_DEBUG		opt_psm.h
diff --git a/sys/dev/kbd/kbdtables.h b/sys/dev/kbd/kbdtables.h
index d36b39a33e7a..61376f48b919 100644
--- a/sys/dev/kbd/kbdtables.h
+++ b/sys/dev/kbd/kbdtables.h
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1992-1995 S�ren Schmidt
+ * Copyright (c) 1992-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: kbdtables.h,v 1.39 1998/01/28 08:45:18 yokota Exp $
+ *	$Id$
  */
 
 #define SET8 0x80       	/* set eight bit on */
diff --git a/sys/dev/syscons/blank/blank_saver.c b/sys/dev/syscons/blank/blank_saver.c
index 451dc9a4b241..d5f4cf0bf560 100644
--- a/sys/dev/syscons/blank/blank_saver.c
+++ b/sys/dev/syscons/blank/blank_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: blank_saver.c,v 1.10 1997/07/15 14:49:09 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
diff --git a/sys/dev/syscons/daemon/daemon_saver.c b/sys/dev/syscons/daemon/daemon_saver.c
index f3cf3dce7736..688df41f274a 100644
--- a/sys/dev/syscons/daemon/daemon_saver.c
+++ b/sys/dev/syscons/daemon/daemon_saver.c
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: daemon_saver.c,v 1.8 1998/01/16 17:58:43 bde Exp $
+ *	$Id: daemon_saver.c,v 1.9 1998/08/06 09:14:20 yokota Exp $
  */
 
 #include <sys/param.h>
@@ -205,7 +205,7 @@ daemon_saver(int blank)
 			/* clear the screen and set the border color */
 			fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
 			      Crtat, scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			xlen = ylen = tlen = 0;
 		}
 		if (scrn_blanked++ < 2)
@@ -322,7 +322,7 @@ daemon_saver(int blank)
 		draw_string(txpos, typos, toff, (char *)message, tlen);
 	} else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/sys/dev/syscons/fade/fade_saver.c b/sys/dev/syscons/fade/fade_saver.c
index 341f7e8d240c..41176e76e092 100644
--- a/sys/dev/syscons/fade/fade_saver.c
+++ b/sys/dev/syscons/fade/fade_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995-1997 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: fade_saver.c,v 1.11 1997/07/15 14:49:25 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -84,7 +84,7 @@ fade_saver(int blank)
 	else {
 		switch (crtc_type) {
 		case KD_VGA:
-			load_palette(palette);
+			load_palette(cur_console, palette);
 			count = 0;
 			break;
 		case KD_EGA:
diff --git a/sys/dev/syscons/green/green_saver.c b/sys/dev/syscons/green/green_saver.c
index b8c82958ac34..667866284681 100644
--- a/sys/dev/syscons/green/green_saver.c
+++ b/sys/dev/syscons/green/green_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: green_saver.c,v 1.10 1997/07/15 14:49:29 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
diff --git a/sys/dev/syscons/scvesactl.c b/sys/dev/syscons/scvesactl.c
new file mode 100644
index 000000000000..9678177d4011
--- /dev/null
+++ b/sys/dev/syscons/scvesactl.c
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "sc.h"
+#include "opt_vesa.h"
+#include "opt_vm86.h"
+
+#if (NSC > 0 && defined(VESA) && defined(VM86)) || defined(VESA_MODULE)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+
+#include <machine/apm_bios.h>
+#include <machine/console.h>
+#include <machine/pc/vesa.h>
+
+#include <i386/isa/videoio.h>
+#include <i386/isa/syscons.h>
+
+static int (*prev_user_ioctl)(dev_t dev, int cmd, caddr_t data, int flag, 
+			      struct proc *p);
+
+extern struct tty *scdevtotty(dev_t dev);
+
+int
+vesa_ioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
+{
+	scr_stat *scp;
+	struct tty *tp;
+	video_info_t info;
+	video_adapter_t *adp;
+	int mode;
+	int error;
+	int s;
+
+	tp = scdevtotty(dev);
+	if (!tp)
+		return ENXIO;
+	scp = sc_get_scr_stat(tp->t_dev);
+
+	switch (cmd) {
+	case SW_VESA_USER:
+
+		mode = (int)data;
+		if ((*biosvidsw.get_info)(scp->adp, mode, &info))
+			return ENODEV;
+		if (info.vi_flags & V_INFO_GRAPHICS)
+			goto vesa_graphics;
+		else
+			goto vesa_text;
+
+	/* text modes */
+	case SW_VESA_C80x60:
+	case SW_VESA_C132x25:
+	case SW_VESA_C132x43:
+	case SW_VESA_C132x50:
+	case SW_VESA_C132x60:
+		adp = get_adapter(scp);
+		if (!(adp->va_flags & V_ADP_MODECHANGE))
+			return ENODEV;
+		mode = (cmd & 0xff) + M_VESA_BASE;
+vesa_text:
+		return sc_set_text_mode(scp, tp, mode, 0, 0, 0);
+
+	/* graphics modes */
+	case SW_VESA_32K_320: 	case SW_VESA_64K_320: 
+	case SW_VESA_FULL_320:
+
+	case SW_VESA_CG640x400:
+
+	case SW_VESA_CG640x480:
+	case SW_VESA_32K_640:	case SW_VESA_64K_640:
+	case SW_VESA_FULL_640:
+
+	case SW_VESA_800x600:	case SW_VESA_CG800x600:
+	case SW_VESA_32K_800:	case SW_VESA_64K_800:
+	case SW_VESA_FULL_800:
+
+	case SW_VESA_1024x768:	case SW_VESA_CG1024x768:
+	case SW_VESA_32K_1024:	case SW_VESA_64K_1024:
+	case SW_VESA_FULL_1024:
+
+	case SW_VESA_1280x1024:	case SW_VESA_CG1280x1024:
+	case SW_VESA_32K_1280:	case SW_VESA_64K_1280:
+	case SW_VESA_FULL_1280:
+		adp = get_adapter(scp);
+		if (!(adp->va_flags & V_ADP_MODECHANGE))
+			return ENODEV;
+		mode = (cmd & 0xff) + M_VESA_BASE;
+vesa_graphics:
+		return sc_set_graphics_mode(scp, tp, mode);
+	}
+
+	if (prev_user_ioctl)
+		return (*prev_user_ioctl)(dev, cmd, data, flag, p);
+	else
+		return ENOIOCTL;
+}
+
+int
+vesa_load_ioctl(void)
+{
+	if (prev_user_ioctl)
+		return EBUSY;
+	prev_user_ioctl = sc_user_ioctl;
+	sc_user_ioctl = vesa_ioctl;
+	return 0;
+}
+
+int
+vesa_unload_ioctl(void)
+{
+	if (sc_user_ioctl != vesa_ioctl)
+		return EBUSY;
+	sc_user_ioctl = prev_user_ioctl;
+	prev_user_ioctl = NULL;
+	return 0;
+}
+
+#endif /* (NSC > 0 && VESA && VM86) || VESA_MODULE */
diff --git a/sys/dev/syscons/scvidctl.c b/sys/dev/syscons/scvidctl.c
new file mode 100644
index 000000000000..464933edb112
--- /dev/null
+++ b/sys/dev/syscons/scvidctl.c
@@ -0,0 +1,486 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "sc.h"
+#include "opt_syscons.h"
+
+#if NSC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+
+#include <machine/apm_bios.h>
+#include <machine/console.h>
+
+#include <i386/isa/videoio.h>
+#include <i386/isa/syscons.h>
+
+/* video ioctl */
+
+extern scr_stat *cur_console;
+extern u_short *Crtat;
+extern int fonts_loaded;
+extern int sc_history_size;
+extern u_char palette[];
+
+int
+sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
+		 int fontsize)
+{
+    video_adapter_t *adp;
+    video_info_t info;
+    int error;
+    int s;
+    int i;
+
+    if ((*biosvidsw.get_info)(scp->adp, mode, &info))
+	return ENODEV;
+    adp = get_adapter(scp);
+ 
+    /* adjust argument values */
+    if (fontsize <= 0)
+	fontsize = info.vi_cheight;
+    if (fontsize < 14) {
+	fontsize = 8;
+	if (!(fonts_loaded & FONT_8))
+	    return EINVAL;
+    } else if (fontsize >= 16) {
+	fontsize = 16;
+	if (!(fonts_loaded & FONT_16))
+	    return EINVAL;
+    } else {
+	fontsize = 14;
+	if (!(fonts_loaded & FONT_14))
+	    return EINVAL;
+    }
+    if ((xsize <= 0) || (xsize > info.vi_width))
+	xsize = info.vi_width;
+    if ((ysize <= 0) || (ysize > info.vi_height))
+	ysize = info.vi_height;
+
+    /* stop screen saver, etc */
+    s = spltty();
+    if ((error = sc_clean_up(scp))) {
+	splx(s);
+	return error;
+    }
+
+    /* set up scp */
+    if (scp->history != NULL)
+	i = imax(scp->history_size / scp->xsize 
+		 - imax(sc_history_size, scp->ysize), 0);
+    else
+	i = 0;
+    /*
+     * This is a kludge to fend off scrn_update() while we
+     * muck around with scp. XXX
+     */
+    scp->status |= UNKNOWN_MODE;
+    scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE);
+    scp->mode = mode;
+    scp->font_size = fontsize;
+    scp->xsize = xsize;
+    scp->ysize = ysize;
+    scp->xpixel = scp->xsize*8;
+    scp->ypixel = scp->ysize*fontsize;
+
+    /* allocate buffers */
+    sc_alloc_scr_buffer(scp, TRUE, TRUE);
+    if (ISMOUSEAVAIL(adp->va_flags))
+	sc_alloc_cut_buffer(scp, FALSE);
+    sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
+    splx(s);
+
+    if (scp == cur_console)
+	set_mode(scp);
+    scp->status &= ~UNKNOWN_MODE;
+
+    if (tp == NULL)
+	return 0;
+    if (tp->t_winsize.ws_col != scp->xsize
+	|| tp->t_winsize.ws_row != scp->ysize) {
+	tp->t_winsize.ws_col = scp->xsize;
+	tp->t_winsize.ws_row = scp->ysize;
+	pgsignal(tp->t_pgrp, SIGWINCH, 1);
+    }
+
+    return 0;
+}
+
+int
+sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
+{
+    video_adapter_t *adp;
+    video_info_t info;
+    int error;
+    int s;
+
+    if ((*biosvidsw.get_info)(scp->adp, mode, &info))
+	return ENODEV;
+    adp = get_adapter(scp);
+
+    /* stop screen saver, etc */
+    s = spltty();
+    if ((error = sc_clean_up(scp))) {
+	splx(s);
+	return error;
+    }
+
+    /* set up scp */
+    scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE);
+    scp->status &= ~PIXEL_MODE;
+    scp->mode = mode;
+    scp->xpixel = info.vi_width;
+    scp->ypixel = info.vi_height;
+    scp->xsize = info.vi_width/8;
+    scp->ysize = info.vi_height/info.vi_cheight;
+    scp->font_size = FONT_NONE;
+    /* move the mouse cursor at the center of the screen */
+    sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
+    splx(s);
+
+    if (scp == cur_console)
+	set_mode(scp);
+    /* clear_graphics();*/
+    scp->status &= ~UNKNOWN_MODE;
+
+    if (tp == NULL)
+	return 0;
+    if (tp->t_winsize.ws_xpixel != scp->xpixel
+	|| tp->t_winsize.ws_ypixel != scp->ypixel) {
+	tp->t_winsize.ws_xpixel = scp->xpixel;
+	tp->t_winsize.ws_ypixel = scp->ypixel;
+	pgsignal(tp->t_pgrp, SIGWINCH, 1);
+    }
+
+    return 0;
+}
+
+int
+sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 
+		  int fontsize)
+{
+    video_adapter_t *adp;
+    video_info_t info;
+    int error;
+    int s;
+    int i;
+
+    if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
+	return ENODEV;		/* this shouldn't happen */
+    adp = get_adapter(scp);
+
+#ifdef SC_VIDEO_DEBUG
+    if (scp->scr_buf != NULL) {
+	printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n",
+	       scp->mode, xsize, ysize, fontsize);
+    }
+#endif
+
+    /* adjust argument values */
+    if ((fontsize <= 0) || (fontsize == FONT_NONE))
+	fontsize = info.vi_cheight;
+    if (fontsize < 14) {
+	fontsize = 8;
+	if (!(fonts_loaded & FONT_8))
+	    return EINVAL;
+    } else if (fontsize >= 16) {
+	fontsize = 16;
+	if (!(fonts_loaded & FONT_16))
+	    return EINVAL;
+    } else {
+	fontsize = 14;
+	if (!(fonts_loaded & FONT_14))
+	    return EINVAL;
+    }
+    if (xsize <= 0)
+	xsize = info.vi_width/8;
+    if (ysize <= 0)
+	ysize = info.vi_height/fontsize;
+
+#ifdef SC_VIDEO_DEBUG
+    if (scp->scr_buf != NULL) {
+	printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n",
+	       scp->mode, xsize, ysize, fontsize);
+	printf("set_pixel_mode(): Crtat:%x, %dx%d, xoff:%d, yoff:%d\n",
+	       Crtat, info.vi_width, info.vi_height, 
+	       (info.vi_width/8 - xsize)/2,
+	       (info.vi_height/fontsize - ysize)/2);
+    }
+#endif
+
+    /* stop screen saver, etc */
+    s = spltty();
+    if ((error = sc_clean_up(scp))) {
+	splx(s);
+	return error;
+    }
+
+    /* set up scp */
+    if (scp->history != NULL)
+	i = imax(scp->history_size / scp->xsize 
+		 - imax(sc_history_size, scp->ysize), 0);
+    else
+	i = 0;
+    scp->status |= (UNKNOWN_MODE | PIXEL_MODE);
+    scp->status &= ~(GRAPHICS_MODE | MOUSE_ENABLED);
+    scp->xsize = xsize;
+    scp->ysize = ysize;
+    scp->font_size = fontsize;
+    scp->xoff = (scp->xpixel/8 - xsize)/2;
+    scp->yoff = (scp->ypixel/fontsize - ysize)/2;
+
+    /* allocate buffers */
+    sc_alloc_scr_buffer(scp, TRUE, TRUE);
+    if (ISMOUSEAVAIL(adp->va_flags))
+	sc_alloc_cut_buffer(scp, FALSE);
+    sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
+    splx(s);
+
+    /* FIXME */
+    if (scp == cur_console)
+	bzero(Crtat, scp->xpixel*scp->ypixel/8);
+
+    scp->status &= ~UNKNOWN_MODE;
+
+#ifdef SC_VIDEO_DEBUG
+    printf("set_pixel_mode(): status:%x\n", scp->status);
+#endif
+
+    if (tp == NULL)
+	return 0;
+    if (tp->t_winsize.ws_col != scp->xsize
+	|| tp->t_winsize.ws_row != scp->ysize) {
+	tp->t_winsize.ws_col = scp->xsize;
+	tp->t_winsize.ws_row = scp->ysize;
+	pgsignal(tp->t_pgrp, SIGWINCH, 1);
+    }
+
+    return 0;
+}
+
+int
+sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+    scr_stat *scp;
+    video_adapter_t *adp;
+    int error;
+    int s;
+
+    scp = sc_get_scr_stat(tp->t_dev);
+
+    switch (cmd) {
+
+    case CONS_CURRENT:  	/* get current adapter type */
+	adp = get_adapter(scp);
+	*(int *)data = adp->va_type;
+	return 0;
+
+    case CONS_CURRENTADP:	/* get current adapter index */
+	*(int *)data = scp->adp;
+	return 0;
+
+    case CONS_ADPINFO:		/* adapter information */
+	adp = (*biosvidsw.adapter)(((video_adapter_t *)data)->va_index);
+	if (adp == NULL)
+	    return ENODEV;
+	bcopy(adp, data, sizeof(*adp));
+	return 0;
+
+    case CONS_GET:      	/* get current video mode */
+	*(int *)data = scp->mode;
+	return 0;
+
+    case CONS_MODEINFO:		/* get mode information */
+	return ((*biosvidsw.get_info)(scp->adp, 
+		    ((video_info_t *)data)->vi_mode, (video_info_t *)data) 
+		? ENODEV : 0);
+
+    case CONS_FINDMODE:		/* find a matching video mode */
+	return ((*biosvidsw.query_mode)(scp->adp, (video_info_t *)data) 
+		? ENODEV : 0);
+
+    case CONS_SETWINORG:
+	return ((*biosvidsw.set_win_org)(scp->adp, *(u_int *)data) 
+		   ? ENODEV : 0);
+
+    /* VGA TEXT MODES */
+    case SW_VGA_C40x25:
+    case SW_VGA_C80x25: case SW_VGA_M80x25:
+    case SW_VGA_C80x30: case SW_VGA_M80x30:
+    case SW_VGA_C80x50: case SW_VGA_M80x50:
+    case SW_VGA_C80x60: case SW_VGA_M80x60:
+    case SW_B40x25:     case SW_C40x25:
+    case SW_B80x25:     case SW_C80x25:
+    case SW_ENH_B40x25: case SW_ENH_C40x25:
+    case SW_ENH_B80x25: case SW_ENH_C80x25:
+    case SW_ENH_B80x43: case SW_ENH_C80x43:
+    case SW_EGAMONO80x25:
+	adp = get_adapter(scp);
+	if (!(adp->va_flags & V_ADP_MODECHANGE))
+ 	    return ENODEV;
+	return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0);
+
+    /* GRAPHICS MODES */
+    case SW_BG320:     case SW_BG640:
+    case SW_CG320:     case SW_CG320_D:   case SW_CG640_E:
+    case SW_CG640x350: case SW_ENH_CG640:
+    case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:
+    case SW_VGA_MODEX:
+	adp = get_adapter(scp);
+	if (!(adp->va_flags & V_ADP_MODECHANGE))
+	    return ENODEV;
+	return sc_set_graphics_mode(scp, tp, cmd & 0xff);
+
+    case KDSETMODE:     	/* set current mode of this (virtual) console */
+	switch (*data) {
+	case KD_TEXT:   	/* switch to TEXT (known) mode */
+	    /*
+	     * If scp->mode is of graphics modes, we don't know which
+	     * text mode to switch back to...
+	     */
+	    if (scp->status & GRAPHICS_MODE)
+		return EINVAL;
+	    /* restore fonts & palette ! */
+#if 0
+	    adp = get_adapter(scp);
+	    if (ISFONTAVAIL(adp->va_flags) 
+		&& !(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
+		/*
+		 * FONT KLUDGE
+		 * Don't load fonts for now... XXX
+		 */
+		if (fonts_loaded & FONT_8)
+		    copy_font(scp, LOAD, 8, font_8);
+		if (fonts_loaded & FONT_14)
+		    copy_font(scp, LOAD, 14, font_14);
+		if (fonts_loaded & FONT_16)
+		    copy_font(scp, LOAD, 16, font_16);
+	    }
+#endif
+	    load_palette(scp, palette);
+
+	    /* move hardware cursor out of the way */
+	    (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
+
+	    /* FALL THROUGH */
+
+	case KD_TEXT1:  	/* switch to TEXT (known) mode */
+	    /*
+	     * If scp->mode is of graphics modes, we don't know which
+	     * text/pixel mode to switch back to...
+	     */
+	    if (scp->status & GRAPHICS_MODE)
+		return EINVAL;
+	    s = spltty();
+	    if ((error = sc_clean_up(scp))) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= UNKNOWN_MODE;
+	    splx(s);
+	    /* no restore fonts & palette */
+	    if (scp == cur_console) {
+		set_mode(scp);
+		/* FIXME */
+		if (scp->status & PIXEL_MODE)
+		    bzero(Crtat, scp->xpixel*scp->ypixel/8);
+	    }
+	    sc_clear_screen(scp);
+	    scp->status &= ~UNKNOWN_MODE;
+	    return 0;
+
+	case KD_PIXEL:		/* pixel (raster) display */
+	    if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
+		return EINVAL;
+	    if (!(scp->status & PIXEL_MODE))
+		return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 
+					 scp->font_size);
+	    s = spltty();
+	    if ((error = sc_clean_up(scp))) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= (UNKNOWN_MODE | PIXEL_MODE);
+	    splx(s);
+	    if (scp == cur_console) {
+		set_mode(scp);
+		load_palette(scp, palette);
+		/* FIXME */
+		bzero(Crtat, scp->xpixel*scp->ypixel/8);
+	    }
+	    sc_clear_screen(scp);
+	    scp->status &= ~UNKNOWN_MODE;
+	    return 0;
+
+	case KD_GRAPHICS:	/* switch to GRAPHICS (unknown) mode */
+	    s = spltty();
+	    if ((error = sc_clean_up(scp))) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= UNKNOWN_MODE;
+	    splx(s);
+	    return 0;
+
+	default:
+	    return EINVAL;
+	}
+	/* NOT REACHED */
+
+    case KDRASTER:		/* set pixel (raster) display mode */
+	if (ISUNKNOWNSC(scp) || ISTEXTSC(scp))
+	    return ENODEV;
+	return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 
+				 ((int *)data)[2]);
+
+    case KDGETMODE:     	/* get current mode of this (virtual) console */
+	/* 
+	 * From the user program's point of view, KD_PIXEL is the same 
+	 * as KD_TEXT... 
+	 */
+	*data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT;
+	return 0;
+
+    case KDSBORDER:     	/* set border color of this (virtual) console */
+	scp->border = *data;
+	if (scp == cur_console)
+	    set_border(cur_console, scp->border);
+	return 0;
+    }
+
+    return ENOIOCTL;
+}
+
+#endif /* NSC > 0 */
diff --git a/sys/dev/syscons/snake/snake_saver.c b/sys/dev/syscons/snake/snake_saver.c
index c3fa1fe7ce38..c5011d04bac2 100644
--- a/sys/dev/syscons/snake/snake_saver.c
+++ b/sys/dev/syscons/snake/snake_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: snake_saver.c,v 1.16 1998/01/16 17:58:50 bde Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -63,7 +63,7 @@ snake_saver(int blank)
 		if (scrn_blanked <= 0) {
 			fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20],
 			      Crtat, scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			dirx = (scp->xpos ? 1 : -1);
 			diry = (scp->ypos ?
 				scp->xsize : -scp->xsize);
@@ -99,7 +99,7 @@ snake_saver(int blank)
 	}
 	else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/sys/dev/syscons/star/star_saver.c b/sys/dev/syscons/star/star_saver.c
index 517a5579968f..8ac65bdba71c 100644
--- a/sys/dev/syscons/star/star_saver.c
+++ b/sys/dev/syscons/star/star_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: star_saver.c,v 1.13 1998/01/16 17:58:55 bde Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -62,7 +62,7 @@ star_saver(int blank)
 			scrn_blanked = 1;
 			fillw((FG_LIGHTGREY|BG_BLACK)<<8|scr_map[0x20], Crtat,
 			      scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			for(i=0; i<NUM_STARS; i++) {
 				stars[i][0] =
 					random() % (scp->xsize*scp->ysize);
@@ -80,7 +80,7 @@ star_saver(int blank)
 	}
 	else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index ebc243f52ba7..50e0f199c0fb 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1992-1997 S�ren Schmidt
+ * Copyright (c) 1992-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,13 +25,15 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *  $Id: syscons.c,v 1.276 1998/08/23 08:26:41 bde Exp $
+ *	$Id$
  */
 
 #include "sc.h"
 #include "apm.h"
 #include "opt_ddb.h"
 #include "opt_devfs.h"
+#include "opt_vesa.h"
+#include "opt_vm86.h"
 #include "opt_syscons.h"
 
 #if NSC > 0
@@ -57,9 +59,9 @@
 #include <machine/psl.h>
 #include <machine/frame.h>
 #include <machine/pc/display.h>
+#include <machine/pc/vesa.h>
 #include <machine/apm_bios.h>
 #include <machine/random.h>
-#include <machine/bootinfo.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -70,6 +72,7 @@
 #include <i386/isa/timerreg.h>
 #include <i386/isa/kbdtables.h>
 #include <i386/isa/kbdio.h>
+#include <i386/isa/videoio.h>
 #include <i386/isa/syscons.h>
 
 #if !defined(MAXCONS)
@@ -96,11 +99,6 @@
 #define COLD 0
 #define WARM 1
 
-#define VESA_MODE(x)		((x) >= M_VESA_BASE)
-
-#define MODE_MAP_SIZE		(M_VGA_CG320 + 1)
-#define MODE_PARAM_SIZE		64
-
 #define DEFAULT_BLANKTIME	(5*60)		/* 5 minutes */
 #define MAX_BLANKTIME		(7*24*60*60)	/* 7 days!? */
 
@@ -159,6 +157,7 @@ static  int        	blinkrate = 0;
 	u_int       	crtc_addr = MONO_BASE;
 	char		crtc_type = KD_MONO;
 	char        	crtc_vga = FALSE;
+static	int		adp_flags = 0;
 static  u_char      	shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
 static  u_char		accents = 0;
 static  u_char      	nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
@@ -172,7 +171,7 @@ static	int		run_scrn_saver = FALSE;	/* should run the saver? */
 static	int		scrn_idle = FALSE;	/* about to run the saver */
 	u_char      	scr_map[256];
 	u_char      	scr_rmap[256];
-	char        	*video_mode_ptr = NULL;
+static	int		initial_video_mode;	/* initial video mode # */
 static	int		bios_video_mode;	/* video mode # set by BIOS */
 	int     	fonts_loaded = 0
 #ifdef STD8X16FONT
@@ -180,19 +179,15 @@ static	int		bios_video_mode;	/* video mode # set by BIOS */
 #endif
 	;
 
-	char        	font_8[256*8];
-	char		font_14[256*14];
+	u_char		font_8[256*8];
+	u_char		font_14[256*14];
 #ifdef STD8X16FONT
 extern
 #endif
-	unsigned char	font_16[256*16];
-	char        	palette[256*3];
-static  char		*mode_map[MODE_MAP_SIZE];
-static  char		vgaregs[MODE_PARAM_SIZE];
-static  char		vgaregs2[MODE_PARAM_SIZE];
-static  int		rows_offset = 1;
-static	char 		*cut_buffer;
-static	int		cut_buffer_size;
+	u_char		font_16[256*16];
+	u_char        	palette[256*3];
+static	u_char 		*cut_buffer = NULL;
+static	int		cut_buffer_size = 0;
 static	int		mouse_level = 0;	/* sysmouse protocol level */
 static	mousestatus_t	mouse_status = { 0, 0, 0, 0, 0, 0 };
 static  u_short 	mouse_and_mask[16] = {
@@ -208,13 +203,14 @@ static  u_short 	mouse_or_mask[16] = {
 				0x0000, 0x0000, 0x0000, 0x0000
 			};
 
-static int		extra_history_size = 
+	int		sc_history_size = SC_HISTORY_SIZE;
+static	int		extra_history_size = 
 			    SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
 
 static void    		none_saver(int blank) { }
 static void    		(*current_saver)(int blank) = none_saver;
 static void    		(*default_saver)(int blank) = none_saver;
-int  			(*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
+	int  		(*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
 					 int flag, struct proc *p) = NULL;
 
 static int		sticky_splash = FALSE;
@@ -233,8 +229,6 @@ static struct tty     	sccons[MAXCONS+2];
 #endif
 #define SC_MOUSE 	128
 #define SC_CONSOLE	255
-#define MONO_BUF    	pa_to_va(0xB0000)
-#define CGA_BUF     	pa_to_va(0xB8000)
 u_short         	*Crtat;
 static const int	nsccons = MAXCONS+2;
 
@@ -243,9 +237,6 @@ static const int	nsccons = MAXCONS+2;
     + (offset)) % (scp->history_size)))
 #define ISSIGVALID(sig)	((sig) > 0 && (sig) < NSIG)
 
-/* this should really be in `rtc.h' */
-#define RTC_EQUIPMENT		0x14
-
 /* prototypes */
 static int scattach(struct isa_device *dev);
 static int scparam(struct tty *tp, struct termios *t);
@@ -256,30 +247,26 @@ static void scstart(struct tty *tp);
 static void scmousestart(struct tty *tp);
 static void scinit(void);
 static void scshutdown(int howto, void *arg);
-static void map_mode_table(char *map[], char *table, int max);
-static int map_mode_num(int mode);
-static char *get_mode_param(scr_stat *scp, int mode);
 static u_int scgetc(u_int flags);
 #define SCGETC_CN	1
 #define SCGETC_NONBLOCK	2
 static void sccnupdate(scr_stat *scp);
-static scr_stat *get_scr_stat(dev_t dev);
 static scr_stat *alloc_scp(void);
 static void init_scp(scr_stat *scp);
 static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark);
 static int get_scr_num(void);
 static timeout_t scrn_timer;
 static void scrn_update(scr_stat *scp, int show_cursor);
+static void scrn_saver(void (*saver)(int), int blank);
 static void stop_scrn_saver(void (*saver)(int));
 static int wait_scrn_saver_stop(void);
-static void clear_screen(scr_stat *scp);
 static int switch_scr(scr_stat *scp, u_int next_scr);
 static void exchange_scr(void);
-static void move_crsr(scr_stat *scp, int x, int y);
 static void scan_esc(scr_stat *scp, u_char c);
+static void ansi_put(scr_stat *scp, u_char *buf, int len);
 static void draw_cursor_image(scr_stat *scp); 
 static void remove_cursor_image(scr_stat *scp); 
-static void ansi_put(scr_stat *scp, u_char *buf, int len);
+static void move_crsr(scr_stat *scp, int x, int y);
 static u_char *get_fstr(u_int c, u_int *len);
 static void history_to_screen(scr_stat *scp);
 static int history_up_line(scr_stat *scp);
@@ -287,16 +274,6 @@ static int history_down_line(scr_stat *scp);
 static int mask2attr(struct term_stat *term);
 static void set_keyboard(int command, int data);
 static void update_leds(int which);
-static void set_vgaregs(char *modetable);
-static void read_vgaregs(char *buf);
-#define COMP_IDENTICAL	0
-#define COMP_SIMILAR	1
-#define COMP_DIFFERENT	2
-static int comp_vgaregs(u_char *buf1, u_char *buf2);
-static void dump_vgaregs(u_char *buf);
-#define PARAM_BUFSIZE	6
-static void set_font_mode(u_char *buf);
-static void set_normal_mode(u_char *buf);
 static void set_destructive_cursor(scr_stat *scp);
 static void set_mouse_pos(scr_stat *scp);
 static int skip_spc_right(scr_stat *scp, u_short *p);
@@ -312,12 +289,11 @@ static void draw_mouse_image(scr_stat *scp);
 static void remove_mouse_image(scr_stat *scp); 
 static void draw_cutmarking(scr_stat *scp); 
 static void remove_cutmarking(scr_stat *scp); 
-static void save_palette(void);
 static void do_bell(scr_stat *scp, int pitch, int duration);
 static timeout_t blink_screen;
 #ifdef SC_SPLASH_SCREEN
-static void scsplash_init(void);
-static void scsplash(int show);
+static void scsplash_init(scr_stat *scp);
+static void scsplash_saver(int show);
 #define scsplash_stick(stick)		(sticky_splash = (stick))
 #else
 #define scsplash_stick(stick)
@@ -332,7 +308,7 @@ static	d_close_t	scclose;
 static	d_read_t	scread;
 static	d_write_t	scwrite;
 static	d_ioctl_t	scioctl;
-static	d_devtotty_t	scdevtotty;
+	d_devtotty_t	scdevtotty;
 static	d_mmap_t	scmmap;
 
 #define	CDEV_MAJOR	12
@@ -353,7 +329,7 @@ draw_cursor_image(scr_stat *scp)
     u_short cursor_image, *ptr = Crtat + (scp->cursor_pos - scp->scr_buf);
     u_short prev_image;
 
-    if (VESA_MODE(scp->mode)) {
+    if (ISPIXELSC(scp)) {
 	sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, 
 	  scp->cursor_pos - scp->scr_buf, 1);
 	return;
@@ -405,7 +381,7 @@ draw_cursor_image(scr_stat *scp)
 static void
 remove_cursor_image(scr_stat *scp)
 {
-    if (VESA_MODE(scp->mode))
+    if (ISPIXELSC(scp))
 	sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 
 	  scp->cursor_oldpos - scp->scr_buf, 0);
     else
@@ -436,6 +412,12 @@ scprobe(struct isa_device *dev)
 	    printf("sc%d: no video adapter is found.\n", dev->id_unit);
 	return (0);
     }
+    (*biosvidsw.diag)(bootverbose);
+#if defined(VESA) && defined(VM86)
+    if (vesa_load())
+	return FALSE;
+    (*biosvidsw.diag)(bootverbose);
+#endif
 
     sc_port = dev->id_iobase;
     if (sckbdprobe(dev->id_unit, dev->id_flags))
@@ -448,99 +430,24 @@ scprobe(struct isa_device *dev)
 static int
 scvidprobe(int unit, int flags)
 {
-    /* 
-     * XXX don't try to `printf' anything here, the console may not have 
-     * been configured yet. 
-     */
-    u_short volatile *cp;
-    u_short was;
-    u_int pa;
-    u_int segoff;
+    video_adapter_t *adp;
 
     /* do this test only once */
     if (init_done != COLD)
-	return (Crtat != 0);
+	return (crtc_type != -1);
 
-    /*
-     * Finish defaulting crtc variables for a mono screen.  Crtat is a
-     * bogus common variable so that it can be shared with pcvt, so it
-     * can't be statically initialized.  XXX.
-     */
-    Crtat = (u_short *)MONO_BUF;
-    crtc_type = KD_MONO;
-    /* If CGA memory seems to work, switch to color.  */
-    cp = (u_short *)CGA_BUF;
-    was = *cp;
-    *cp = (u_short) 0xA55A;
-    bios_video_mode = *(u_char *)pa_to_va(0x449);
-    if (bootinfo.bi_vesa == 0x102) {
-	bios_video_mode = bootinfo.bi_vesa;
-	Crtat  = (u_short *)pa_to_va(0xA0000);
-	crtc_addr = COLOR_BASE;
-	crtc_type = KD_VGA;
-        bzero(Crtat, 800*600/8);
-    } else if (*cp == 0xA55A) {
-	Crtat = (u_short *)CGA_BUF;
-	crtc_addr = COLOR_BASE;
-	crtc_type = KD_CGA;
-    } else {
-        cp = Crtat;
-	was = *cp;
-	*cp = (u_short) 0xA55A;
-	if (*cp != 0xA55A) {
-	    /* no screen at all, bail out */
-	    Crtat = 0;
-	    return FALSE;
-	}
-    }
-    *cp = was;
+    if ((*biosvidsw.init)() <= 0)
+	return FALSE;
+    if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL)
+	return FALSE;
 
-    if (!VESA_MODE(bios_video_mode)) {
-	/* 
-	 * Check rtc and BIOS date area.
-	 * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy
-	 * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are
-	 * zeros for EGA and VGA. However, the EGA/VGA BIOS will set 
-	 * these bits in BIOSDATA_EQUIPMENT according to the monitor
-	 * type detected.
-	 */
-	switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) {	/* bit 4 and 5 */
-	case 0: /* EGA/VGA, or nothing */
-	    crtc_type = KD_EGA;
-	    /* the color adapter may be in the 40x25 mode... XXX */
-	    break;
-	case 1: /* CGA 40x25 */
-	    /* switch to the 80x25 mode? XXX */
-	    /* FALL THROUGH */
-	case 2: /* CGA 80x25 */
-	    /* `crtc_type' has already been set... */
-	    /* crtc_type = KD_CGA; */
-	    break;
-	case 3: /* MDA */
-	    /* `crtc_type' has already been set... */
-	    /* crtc_type = KD_MONO; */
-	    break;
-	}
-
-	/* is this a VGA or higher ? */
-	outb(crtc_addr, 7);
-	if (inb(crtc_addr) == 7) {
-
-	    crtc_type = KD_VGA;
-	    crtc_vga = TRUE;
-	    read_vgaregs(vgaregs);
-
-	    /* Get the BIOS video mode pointer */
-	    segoff = *(u_int *)pa_to_va(0x4a8);
-	    pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff);
-	    if (ISMAPPED(pa, sizeof(u_int))) {
-		segoff = *(u_int *)pa_to_va(pa);
-		pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff);       
-		if (ISMAPPED(pa, MODE_PARAM_SIZE))
-		    video_mode_ptr = (char *)pa_to_va(pa);
-	    }
-	}
-    }
+    crtc_type = adp->va_type;
+    crtc_vga = (crtc_type == KD_VGA);
+    crtc_addr = adp->va_crtc_addr;
+    Crtat = (u_short *)adp->va_window;
+    adp_flags = adp->va_flags;
+    initial_video_mode = adp->va_initial_mode;
+    bios_video_mode = adp->va_initial_bios_mode;
 
     return TRUE;
 }
@@ -728,48 +635,42 @@ static int
 scattach(struct isa_device *dev)
 {
     scr_stat *scp;
+    video_info_t info;
     dev_t cdev = makedev(CDEV_MAJOR, 0);
-    char *p;
 #ifdef DEVFS
     int vc;
 #endif
 
     scinit();
     flags = dev->id_flags;
-    if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode))
+    if (!ISFONTAVAIL(adp_flags))
 	flags &= ~CHAR_CURSOR;
 
     scp = console[0];
 
-    if (crtc_type == KD_VGA) {
-	cut_buffer_size = scp->xsize * scp->ysize + 1;
-    	cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT);
-	if (cut_buffer != NULL)
-	    cut_buffer[0] = '\0';
-    }
-
-    scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
-				     M_DEVBUF, M_NOWAIT);
-
     /* copy temporary buffer to final buffer */
-    bcopy(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short));
+    scp->scr_buf = NULL;
+    sc_alloc_scr_buffer(scp, FALSE, FALSE);
+    bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short));
 
-    scp->cursor_pos = scp->cursor_oldpos =
-	scp->scr_buf + scp->xpos + scp->ypos * scp->xsize;
-    scp->mouse_pos = scp->mouse_oldpos = 
-	scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize +
-	    		scp->mouse_xpos/8);
+    /* cut buffer is available only when the mouse pointer is used */
+    if (ISMOUSEAVAIL(adp_flags))
+	sc_alloc_cut_buffer(scp, FALSE);
 
     /* initialize history buffer & pointers */
-    scp->history_head = scp->history_pos = 
-	(u_short *)malloc(scp->history_size*sizeof(u_short),
-			  M_DEVBUF, M_NOWAIT);
-    if (scp->history_head != NULL)
-        bzero(scp->history_head, scp->history_size*sizeof(u_short));
-    scp->history = scp->history_head;
+    sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE);
+
+#if defined(VESA) && defined(VM86)
+    if ((flags & VESA800X600) 
+	&& ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) {
+	sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
+	sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
+	initial_video_mode = M_VESA_800x600;
+    }
+#endif /* VESA && VM86 */
 
     /* initialize cursor stuff */
-    if (!(scp->status & UNKNOWN_MODE))
+    if (!ISGRAPHSC(scp))
     	draw_cursor_image(scp);
 
     /* get screen update going */
@@ -777,42 +678,13 @@ scattach(struct isa_device *dev)
 
     update_leds(scp->status);
 
-    if ((crtc_type == KD_VGA) && bootverbose) {
-        printf("sc%d: BIOS video mode:%d\n", dev->id_unit, bios_video_mode);
-        printf("sc%d: VGA registers upon power-up\n", dev->id_unit);
-        dump_vgaregs(vgaregs);
-        printf("sc%d: video mode:%d\n", dev->id_unit, scp->mode);
-        printf("sc%d: VGA registers in BIOS for mode:%d\n", 
-		dev->id_unit, scp->mode);
-        dump_vgaregs(vgaregs2);
-	p = get_mode_param(scp, scp->mode);
-        if (p != NULL) {
-            printf("sc%d: VGA registers to be used for mode:%d\n", 
-		dev->id_unit, scp->mode);
-            dump_vgaregs(p);
-        }
-        printf("sc%d: rows_offset:%d\n", dev->id_unit, rows_offset);
-    }
-    if ((crtc_type == KD_VGA) && !VESA_MODE(bios_video_mode) 
-	&& (video_mode_ptr == NULL))
-        printf("sc%d: WARNING: video mode switching is only partially supported\n",
-	        dev->id_unit); 
-
     printf("sc%d: ", dev->id_unit);
     switch(crtc_type) {
     case KD_VGA:
-	if (VESA_MODE(bios_video_mode))
-	    printf("Graphics display (VESA mode = 0x%x)", bios_video_mode);
-	else if (crtc_addr == MONO_BASE)
-	    printf("VGA mono");
-	else
-	    printf("VGA color");
+	printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
 	break;
     case KD_EGA:
-	if (crtc_addr == MONO_BASE)
-	    printf("EGA mono");
-	else
-	    printf("EGA color");
+	printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
 	break;
     case KD_CGA:
 	printf("CGA");
@@ -820,7 +692,7 @@ scattach(struct isa_device *dev)
     case KD_MONO:
     case KD_HERCULES:
     default:
-	printf("MDA/hercules");
+	printf("MDA/Hercules");
 	break;
     }
     printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags);
@@ -896,6 +768,8 @@ scopen(dev_t dev, int flag, int mode, struct proc *p)
 	    return(EBUSY);
     if (minor(dev) < MAXCONS && !console[minor(dev)]) {
 	console[minor(dev)] = alloc_scp();
+	if (ISGRAPHSC(console[minor(dev)]))
+	    sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16);
     }
     if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
 	tp->t_winsize.ws_col = console[minor(dev)]->xsize;
@@ -913,7 +787,7 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
     if (!tp)
 	return(ENXIO);
     if (minor(dev) < MAXCONS) {
-	scp = get_scr_stat(tp->t_dev);
+	scp = sc_get_scr_stat(tp->t_dev);
 	if (scp->status & SWITCH_WAIT_ACQ)
 	    wakeup((caddr_t)&scp->smode);
 #if not_yet_done
@@ -927,9 +801,9 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
 	    if (scp->history != NULL) {
 		free(scp->history, M_DEVBUF);
 		if (scp->history_size / scp->xsize
-			> imax(SC_HISTORY_SIZE, scp->ysize))
+			> imax(sc_history_size, scp->ysize))
 		    extra_history_size += scp->history_size / scp->xsize 
-			- imax(SC_HISTORY_SIZE, scp->ysize);
+			- imax(sc_history_size, scp->ysize);
 	    }
 	    free(scp, M_DEVBUF);
 	    console[minor(dev)] = NULL;
@@ -1008,10 +882,17 @@ scintr(int unit)
 	}
     }
 
+#if 0
     if (cur_console->status & MOUSE_ENABLED) {
 	cur_console->status &= ~MOUSE_VISIBLE;
 	remove_mouse_image(cur_console);
     }
+#else
+    if (cur_console->status & MOUSE_VISIBLE) {
+	remove_mouse_image(cur_console);
+	cur_console->status &= ~MOUSE_VISIBLE;
+    }
+#endif
 }
 
 static int
@@ -1030,21 +911,25 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
     u_int i;
     struct tty *tp;
     scr_stat *scp;
-    u_short *usp;
-    char *mp;
+    video_adapter_t *adp;
     int s;
 
     tp = scdevtotty(dev);
     if (!tp)
 	return ENXIO;
-    scp = get_scr_stat(tp->t_dev);
+    scp = sc_get_scr_stat(tp->t_dev);
 
     /* If there is a user_ioctl function call that first */
     if (sc_user_ioctl) {
-	if (error = (*sc_user_ioctl)(dev, cmd, data, flag, p))
+	error = (*sc_user_ioctl)(dev, cmd, data, flag, p);
+	if (error != ENOIOCTL)
 	    return error;
     }
 
+    error = sc_vid_ioctl(tp, cmd, data, flag, p);
+    if (error != ENOIOCTL)
+	return error;
+
     switch (cmd) {  		/* process console hardware related ioctl's */
 
     case GIO_ATTR:      	/* get current attributes */
@@ -1052,18 +937,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case GIO_COLOR:     	/* is this a color console ? */
-	if (crtc_addr == COLOR_BASE)
-	    *(int*)data = 1;
-	else
-	    *(int*)data = 0;
-	return 0;
-
-    case CONS_CURRENT:  	/* get current adapter type */
-	*(int *)data = crtc_type;
-	return 0;
-
-    case CONS_GET:      	/* get current video mode */
-	*(int*)data = scp->mode;
+	*(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0;
 	return 0;
 
     case CONS_BLANKTIME:    	/* set screen saver timeout (0 = no saver) */
@@ -1081,7 +955,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	else
 	    flags &= ~BLINK_CURSOR;
 	if ((*(int*)data) & 0x02) {
-	    if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode))
+	    if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 		return ENXIO;
 	    flags |= CHAR_CURSOR;
 	} else
@@ -1090,7 +964,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * The cursor shape is global property; all virtual consoles
 	 * are affected. Update the cursor in the current console...
 	 */
-	if (!(cur_console->status & UNKNOWN_MODE)) {
+	if (!ISGRAPHSC(cur_console)) {
             remove_cursor_image(cur_console);
 	    if (flags & CHAR_CURSOR)
 	        set_destructive_cursor(cur_console);
@@ -1117,37 +991,22 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    lines = imax(*(int *)data, scp->ysize);
 	    lines0 = (scp->history != NULL) ? 
 		      scp->history_size / scp->xsize : scp->ysize;
+	    if (lines0 > imax(sc_history_size, scp->ysize))
+		i = lines0 - imax(sc_history_size, scp->ysize);
+	    else
+		i = 0;
 	    /*
 	     * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
 	     * lines or scp->ysize lines, whichever is larger. A value 
 	     * greater than that is allowed, subject to extra_history_size.
 	     */
-	    if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size)
-                return EINVAL;
+	    if (lines > imax(sc_history_size, scp->ysize))
+		if (lines - imax(sc_history_size, scp->ysize) >
+		    extra_history_size + i)
+		    return EINVAL;
             if (cur_console->status & BUFFER_SAVED)
                 return EBUSY;
-	    usp = scp->history;
-	    scp->history = NULL;
-	    if (usp != NULL)
-		free(usp, M_DEVBUF);
-	    scp->history_size = lines * scp->xsize;
-	    /*
-	     * extra_history_size += 
-	     *    (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ? 
-	     *     lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
-	     * extra_history_size -= 
-	     *    (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ? 
-	     *	   lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
-	     * lines0 >= ysize && lines >= ysize... Hey, the above can be 
-	     * reduced to the following...
-	     */
-	    extra_history_size += 
-		imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE);
-	    usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
-				    M_DEVBUF, M_WAITOK);
-	    bzero(usp, scp->history_size * sizeof(u_short));
-	    scp->history_head = scp->history_pos = usp;
-	    scp->history = usp;
+	    sc_alloc_history_buffer(scp, lines, i, TRUE);
 	    return 0;
 	}
 	else
@@ -1171,7 +1030,8 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	mouse_info_t *mouse = (mouse_info_t*)data;
 	mouse_info_t buf;
 
-	if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode))
+	/* FIXME: */
+	if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags))
 	    return ENODEV;
 	
 	if (cmd == OLD_CONS_MOUSECTL) {
@@ -1220,7 +1080,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    return 0;
 
 	case MOUSE_SHOW:
-	    if (!(scp->status & MOUSE_ENABLED)) {
+	    if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) {
 		scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE);
 		scp->mouse_oldpos = scp->mouse_pos;
 		mark_all(scp);
@@ -1231,7 +1091,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    break;
 
 	case MOUSE_HIDE:
-	    if (scp->status & MOUSE_ENABLED) {
+	    if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) {
 		scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
 		mark_all(scp);
 		return 0;
@@ -1276,7 +1136,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    if (mouse_status.flags == 0)
 		return 0;
 
-	    if (cur_console->status & MOUSE_ENABLED)
+	    if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
 	    	cur_console->status |= MOUSE_VISIBLE;
 
 	    if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
@@ -1321,7 +1181,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) {
 		/* process button presses */
 		if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && 
-		    !(cur_console->status & UNKNOWN_MODE)) {
+		    ISTEXTSC(cur_console)) {
 		    cur_console->mouse_buttons = mouse->u.data.buttons;
 		    if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)
 			mouse_cut_start(cur_console);
@@ -1358,7 +1218,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    if (mouse_status.flags == 0)
 		return 0;
 
-	    if (cur_console->status & MOUSE_ENABLED)
+	    if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
 	    	cur_console->status |= MOUSE_VISIBLE;
 
 	    if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
@@ -1387,7 +1247,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 		break;
 	    }
 
-	    if ((cur_console->status & UNKNOWN_MODE) || (cut_buffer == NULL))
+	    if (!ISTEXTSC(cur_console) || (cut_buffer == NULL))
 		break;
 
 	    switch (mouse->u.event.id) {
@@ -1567,18 +1427,41 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case CONS_IDLE:		/* see if the screen has been idle */
-	*(int *)data = (scrn_idle && !(cur_console->status & UNKNOWN_MODE));
+	/*
+	 * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE,
+	 * the user process may have been writing something on the
+	 * screen and syscons is not aware of it. Declare the screen
+	 * is NOT idle if it is in one of these modes. But there is
+	 * an exception to it; if a screen saver is running in the 
+	 * graphics mode in the current screen, we should say that the
+	 * screen has been idle.
+	 */
+	*(int *)data = scrn_idle 
+		       && (!ISGRAPHSC(cur_console)
+			   || (cur_console->status & SAVER_RUNNING));
 	return 0;
 
     case CONS_SAVERMODE:	/* set saver mode */
 	switch(*(int *)data) {
 	case CONS_USR_SAVER:
-	    /* if a LKM screen saver is running, it will eventually stop... */
+	    /* if a LKM screen saver is running, stop it first. */
+	    scsplash_stick(FALSE);
 	    saver_mode = *(int *)data;
+	    s = spltty();
+	    if ((error = wait_scrn_saver_stop())) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= SAVER_RUNNING;
 	    scsplash_stick(TRUE);
+	    splx(s);
 	    break;
 	case CONS_LKM_SAVER:
+	    s = spltty();
+	    if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING))
+		scp->status &= ~SAVER_RUNNING;
 	    saver_mode = *(int *)data;
+	    splx(s);
 	    break;
 	default:
 	    return EINVAL;
@@ -1597,226 +1480,6 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	splx(s);
 	return 0;
 
-    /* VGA TEXT MODES */
-    case SW_VGA_C40x25:
-    case SW_VGA_C80x25: case SW_VGA_M80x25:
-    case SW_VGA_C80x30: case SW_VGA_M80x30:
-    case SW_VGA_C80x50: case SW_VGA_M80x50:
-    case SW_VGA_C80x60: case SW_VGA_M80x60:
-    case SW_B40x25:     case SW_C40x25:
-    case SW_B80x25:     case SW_C80x25:
-    case SW_ENH_B40x25: case SW_ENH_C40x25:
-    case SW_ENH_B80x25: case SW_ENH_C80x25:
-    case SW_ENH_B80x43: case SW_ENH_C80x43:
-    case SW_EGAMONO80x25:
-
-	if (crtc_type != KD_VGA)
- 	    return ENODEV;
- 	mp = get_mode_param(scp, cmd & 0xff);
- 	if (mp == NULL)
- 	    return ENODEV;
- 
-	s = spltty();
-	if ((error = wait_scrn_saver_stop())) {
-	    splx(s);
-	    return error;
-	}
-
-	scp->status &= ~MOUSE_VISIBLE;
-	remove_cutmarking(scp);
-	if (scp->history != NULL)
-	    i = imax(scp->history_size / scp->xsize 
-		     - imax(SC_HISTORY_SIZE, scp->ysize), 0);
-	else
-	    i = 0;
-	switch (cmd & 0xff) {
-	case M_VGA_C80x60: case M_VGA_M80x60:
-	    if (!(fonts_loaded & FONT_8)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    /*
-	     * This is a kludge to fend off scrn_update() while we
-	     * muck around with scp. XXX
-	     */
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 60;
-	    scp->font_size = 8;
-	    break;
-	case M_VGA_C80x50: case M_VGA_M80x50:
-	    if (!(fonts_loaded & FONT_8)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 50;
-	    scp->font_size = 8;
-	    break;
-	case M_ENH_B80x43: case M_ENH_C80x43:
-	    if (!(fonts_loaded & FONT_8)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 43;
-	    scp->font_size = 8;
-	    break;
-	case M_VGA_C80x30: case M_VGA_M80x30:
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 30;
-	    scp->font_size = mp[2];
-	    break;
-	case M_ENH_C40x25: case M_ENH_B40x25:
-	case M_ENH_C80x25: case M_ENH_B80x25:
-	case M_EGAMONO80x25:
-	    if (!(fonts_loaded & FONT_14)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    /* FALL THROUGH */
-	default:
-	    if ((cmd & 0xff) > M_VGA_CG320) {
-		splx(s);
-		return EINVAL;
-	    }
-	    scp->status |= UNKNOWN_MODE;
-            scp->xsize = mp[0];
-            scp->ysize = mp[1] + rows_offset;
-	    scp->font_size = mp[2];
-	    break;
-	}
-
-	scp->mode = cmd & 0xff;
-	scp->xpixel = scp->xsize * 8;
-	scp->ypixel = scp->ysize * scp->font_size;
-	free(scp->scr_buf, M_DEVBUF);
-	scp->scr_buf = (u_short *)
-	    malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_WAITOK);
-	/* move the text cursor to the home position */
-	move_crsr(scp, 0, 0);
-	/* move the mouse cursor at the center of the screen */
-	scp->mouse_xpos = scp->xpixel / 2;
-	scp->mouse_ypos = scp->ypixel / 2;
-    	scp->mouse_pos = scp->mouse_oldpos = 
-	    scp->scr_buf + (scp->mouse_ypos / scp->font_size) * scp->xsize 
-	    + scp->mouse_xpos / 8;
-	/* allocate a larger cut buffer if necessary */
-	if ((cut_buffer == NULL)
-	    || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
-	    if (cut_buffer != NULL)
-		free(cut_buffer, M_DEVBUF);
-	    cut_buffer_size = scp->xsize * scp->ysize + 1;
-	    cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT);
-	    if (cut_buffer != NULL)
-		cut_buffer[0] = '\0';
-	}
-	splx(s);
-
-	usp = scp->history;
-	scp->history = NULL;
-	if (usp != NULL) {
-	    free(usp, M_DEVBUF);
-	    extra_history_size += i;
-	}
-	scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
-	usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 
-				M_DEVBUF, M_NOWAIT);
-	if (usp != NULL)
-	    bzero(usp, scp->history_size * sizeof(u_short));
-	scp->history_head = scp->history_pos = usp;
-	scp->history = usp;
-	if (scp == cur_console)
-	    set_mode(scp);
-	clear_screen(scp);
-	scp->status &= ~UNKNOWN_MODE;
-
-	if (tp->t_winsize.ws_col != scp->xsize
-	    || tp->t_winsize.ws_row != scp->ysize) {
-	    tp->t_winsize.ws_col = scp->xsize;
-	    tp->t_winsize.ws_row = scp->ysize;
-	    pgsignal(tp->t_pgrp, SIGWINCH, 1);
-	}
-	return 0;
-
-    /* GRAPHICS MODES */
-    case SW_BG320:     case SW_BG640:
-    case SW_CG320:     case SW_CG320_D:   case SW_CG640_E:
-    case SW_CG640x350: case SW_ENH_CG640:
-    case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:
-
-	if (crtc_type != KD_VGA)
-	    return ENODEV;
-	mp = get_mode_param(scp, cmd & 0xff);
-	if (mp == NULL)
-	    return ENODEV;
-
-	s = spltty();
-	if ((error = wait_scrn_saver_stop())) {
-	    splx(s);
-	    return error;
-	}
-
-	scp->status &= ~MOUSE_VISIBLE;
-	remove_cutmarking(scp);
-	scp->status |= UNKNOWN_MODE;    /* graphics mode */
-	scp->mode = cmd & 0xFF;
-	scp->xpixel = mp[0] * 8;
-	scp->ypixel = (mp[1] + rows_offset) * mp[2];
-	scp->font_size = FONT_NONE;
-	/* move the mouse cursor at the center of the screen */
-	scp->mouse_xpos = scp->xpixel / 2;
-	scp->mouse_ypos = scp->ypixel / 2;
-	splx(s);
-
-	if (scp == cur_console)
-	    set_mode(scp);
-	/* clear_graphics();*/
-
-	if (tp->t_winsize.ws_xpixel != scp->xpixel
-	    || tp->t_winsize.ws_ypixel != scp->ypixel) {
-	    tp->t_winsize.ws_xpixel = scp->xpixel;
-	    tp->t_winsize.ws_ypixel = scp->ypixel;
-	    pgsignal(tp->t_pgrp, SIGWINCH, 1);
-	}
-	return 0;
-
-    case SW_VGA_MODEX:
-	if (crtc_type != KD_VGA)
-	    return ENODEV;
-	mp = get_mode_param(scp, cmd & 0xff);
-	if (mp == NULL)
-	    return ENODEV;
-
-	s = spltty();
-	if ((error = wait_scrn_saver_stop())) {
-	    splx(s);
-	    return error;
-	}
-
-	scp->status &= ~MOUSE_VISIBLE;
-	remove_cutmarking(scp);
-	scp->status |= UNKNOWN_MODE;    /* graphics mode */
-	scp->mode = cmd & 0xFF;
-	scp->xpixel = 320;
-	scp->ypixel = 240;
-	scp->font_size = FONT_NONE;
-	splx(s);
-
-	if (scp == cur_console)
-	    set_mode(scp);
-	/* clear_graphics();*/
-	if (tp->t_winsize.ws_xpixel != scp->xpixel
-	    || tp->t_winsize.ws_ypixel != scp->ypixel) {
-	    tp->t_winsize.ws_xpixel = scp->xpixel;
-	    tp->t_winsize.ws_ypixel = scp->ypixel;
-	    pgsignal(tp->t_pgrp, SIGWINCH, 1);
-	}
-	return 0;
-
     case VT_SETMODE:    	/* set screen switcher mode */
     {
 	struct vt_mode *mode;
@@ -1839,7 +1502,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case VT_RELDISP:    	/* screen switcher ioctl */
-	switch(*data) {
+	switch(*(int *)data) {
 	case VT_FALSE:  	/* user refuses to release screen, abort */
 	    if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
 		old_scp->status &= ~SWITCH_WAIT_REL;
@@ -1879,32 +1542,32 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	for (i = 0; i < MAXCONS; i++) {
 	    tp = VIRTUAL_TTY(i);
 	    if (!(tp->t_state & TS_ISOPEN)) {
-		*data = i + 1;
+		*(int *)data = i + 1;
 		return 0;
 	    }
 	}
 	return EINVAL;
 
     case VT_ACTIVATE:   	/* switch to screen *data */
-	return switch_scr(scp, (*data) - 1);
+	return switch_scr(scp, *(int *)data - 1);
 
     case VT_WAITACTIVE: 	/* wait for switch to occur */
-	if (*data > MAXCONS || *data < 0)
+	if (*(int *)data > MAXCONS || *(int *)data < 0)
 	    return EINVAL;
-	if (minor(dev) == (*data) - 1)
+	if (minor(dev) == *(int *)data - 1)
 	    return 0;
-	if (*data == 0) {
+	if (*(int *)data == 0) {
 	    if (scp == cur_console)
 		return 0;
 	}
 	else
-	    scp = console[(*data) - 1];
+	    scp = console[*(int *)data - 1];
 	while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
 			     "waitvt", 0)) == ERESTART) ;
 	return error;
 
     case VT_GETACTIVE:
-	*data = get_scr_num()+1;
+	*(int *)data = get_scr_num()+1;
 	return 0;
 
     case KDENABIO:      	/* allow io operations */
@@ -1920,102 +1583,28 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	p->p_md.md_regs->tf_eflags &= ~PSL_IOPL;
 	return 0;
 
-    case KDSETMODE:     	/* set current mode of this (virtual) console */
-	switch (*data) {
-	case KD_TEXT:   	/* switch to TEXT (known) mode */
-	    /* restore fonts & palette ! */
-	    if (crtc_type == KD_VGA) {
-		if (!VESA_MODE(scp->mode)) {
-#if 0
-		    /*
-		     * FONT KLUDGE
-		     * Don't load fonts for now... XXX
-		     */
-		    if (fonts_loaded & FONT_8)
-			copy_font(LOAD, FONT_8, font_8);
-		    if (fonts_loaded & FONT_14)
-			copy_font(LOAD, FONT_14, font_14);
-		    if (fonts_loaded & FONT_16)
-			copy_font(LOAD, FONT_16, font_16);
-#endif
-		}
-		load_palette(palette);
-	    }
-
-	    /* move hardware cursor out of the way */
-	    outb(crtc_addr, 14);
-	    outb(crtc_addr + 1, 0xff);
-	    outb(crtc_addr, 15);
-	    outb(crtc_addr + 1, 0xff);
-
-	    /* FALL THROUGH */
-
-	case KD_TEXT1:  	/* switch to TEXT (known) mode */
-	    s = spltty();
-	    if ((error = wait_scrn_saver_stop())) {
-		splx(s);
-		return error;
-	    }
-	    scp->status &= ~MOUSE_VISIBLE;
-	    remove_cutmarking(scp);
-	    scp->status |= UNKNOWN_MODE;
-	    splx(s);
-	    /* no restore fonts & palette */
-	    if (crtc_type == KD_VGA)
-		set_mode(scp);
-	    scp->status &= ~UNKNOWN_MODE;
-	    clear_screen(scp);
-	    return 0;
-
-	case KD_GRAPHICS:	/* switch to GRAPHICS (unknown) mode */
-	    s = spltty();
-	    if ((error = wait_scrn_saver_stop())) {
-		splx(s);
-		return error;
-	    }
-	    scp->status &= ~MOUSE_VISIBLE;
-	    remove_cutmarking(scp);
-	    scp->status |= UNKNOWN_MODE;
-	    splx(s);
-	    return 0;
-	default:
-	    return EINVAL;
-	}
-	/* NOT REACHED */
-
-    case KDGETMODE:     	/* get current mode of this (virtual) console */
-	*data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT;
-	return 0;
-
-    case KDSBORDER:     	/* set border color of this (virtual) console */
-	scp->border = *data;
-	if (scp == cur_console)
-	    set_border(scp->border);
-	return 0;
-
     case KDSKBSTATE:    	/* set keyboard state (locks) */
-	if (*data >= 0 && *data <= LOCK_KEY_MASK) {
-	    scp->status &= ~LOCK_KEY_MASK;
-	    scp->status |= *data;
-	    if (scp == cur_console)
-		update_leds(scp->status);
-	    return 0;
-	}
-	return EINVAL;
+	if (*(int *)data & ~LOCK_KEY_MASK)
+	    return EINVAL;
+	scp->status &= ~LOCK_KEY_MASK;
+	scp->status |= *(int *)data;
+	if (scp == cur_console)
+	    update_leds(scp->status);
+	return 0;
 
     case KDGKBSTATE:    	/* get keyboard state (locks) */
-	*data = scp->status & LOCK_KEY_MASK;
+	*(int *)data = scp->status & LOCK_KEY_MASK;
 	return 0;
 
     case KDSETRAD:      	/* set keyboard repeat & delay rates */
-	if (*data & 0x80)
+	if (*(int *)data & ~0x7f)
 	    return EINVAL;
 	if (sc_kbdc != NULL) 
-	    set_keyboard(KBDC_SET_TYPEMATIC, *data);
+	    set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data);
 	return 0;
 
     case KDSKBMODE:     	/* set keyboard mode */
-	switch (*data) {
+	switch (*(int *)data) {
 	case K_RAW: 		/* switch to RAW scancode mode */
 	    scp->status &= ~KBD_CODE_MODE;
 	    scp->status |= KBD_RAW_MODE;
@@ -2037,7 +1626,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	/* NOT REACHED */
 
     case KDGKBMODE:     	/* get keyboard mode */
-	*data = (scp->status & KBD_RAW_MODE) ? K_RAW : 
+	*(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : 
 		((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE);
 	return 0;
 
@@ -2074,21 +1663,20 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case KDGKBTYPE:     	/* get keyboard type */
-	*data = 0;  		/* type not known (yet) */
+	*(int *)data = 0;  	/* type not known (yet) */
 	return 0;
 
     case KDSETLED:      	/* set keyboard LED status */
-	if (*data >= 0 && *data <= LED_MASK) {
-	    scp->status &= ~LED_MASK;
-	    scp->status |= *data;
-	    if (scp == cur_console)
-		update_leds(scp->status);
-	    return 0;
-	}
-	return EINVAL;
+	if (*(int *)data & ~LED_MASK)
+	    return EINVAL;
+	scp->status &= ~LED_MASK;
+	scp->status |= *(int *)data;
+	if (scp == cur_console)
+	    update_leds(scp->status);
+	return 0;
 
     case KDGETLED:      	/* get keyboard LED status */
-	*data = scp->status & LED_MASK;
+	*(int *)data = scp->status & LED_MASK;
 	return 0;
 
     case GETFKEY:       	/* get functionkey string */
@@ -2143,7 +1731,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case PIO_FONT8x8:   	/* set 8x8 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	bcopy(data, font_8, 8*256);
 	fonts_loaded |= FONT_8;
@@ -2152,17 +1740,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * Always use the font page #0. XXX
 	 * Don't load if the current font size is not 8x8.
 	 */
-	if (!VESA_MODE(cur_console->mode) 
-	    && !(cur_console->status & UNKNOWN_MODE)
-	    && (cur_console->font_size < 14)) {
-	    copy_font(LOAD, FONT_8, font_8);
-	    if (flags & CHAR_CURSOR)
-	        set_destructive_cursor(cur_console);
-	}
+	if (ISTEXTSC(cur_console) && (cur_console->font_size < 14))
+	    copy_font(cur_console, LOAD, 8, font_8);
 	return 0;
 
     case GIO_FONT8x8:   	/* get 8x8 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	if (fonts_loaded & FONT_8) {
 	    bcopy(font_8, data, 8*256);
@@ -2172,7 +1755,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    return ENXIO;
 
     case PIO_FONT8x14:  	/* set 8x14 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	bcopy(data, font_14, 14*256);
 	fonts_loaded |= FONT_14;
@@ -2181,17 +1764,13 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * Always use the font page #0. XXX
 	 * Don't load if the current font size is not 8x14.
 	 */
-	if (!VESA_MODE(cur_console->mode) 
-	    && !(cur_console->status & UNKNOWN_MODE)
-	    && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) {
-	    copy_font(LOAD, FONT_14, font_14);
-	    if (flags & CHAR_CURSOR)
-	        set_destructive_cursor(cur_console);
-	}
+	if (ISTEXTSC(cur_console)
+	    && (cur_console->font_size >= 14) && (cur_console->font_size < 16))
+	    copy_font(cur_console, LOAD, 14, font_14);
 	return 0;
 
     case GIO_FONT8x14:  	/* get 8x14 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	if (fonts_loaded & FONT_14) {
 	    bcopy(font_14, data, 14*256);
@@ -2201,7 +1780,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    return ENXIO;
 
     case PIO_FONT8x16:  	/* set 8x16 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	bcopy(data, font_16, 16*256);
 	fonts_loaded |= FONT_16;
@@ -2210,17 +1789,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * Always use the font page #0. XXX
 	 * Don't load if the current font size is not 8x16.
 	 */
-	if (!VESA_MODE(cur_console->mode) 
-	    && !(cur_console->status & UNKNOWN_MODE)
-	    && (cur_console->font_size >= 16)) {
-	    copy_font(LOAD, FONT_16, font_16);
-	    if (flags & CHAR_CURSOR)
-	        set_destructive_cursor(cur_console);
-	}
+	if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16))
+	    copy_font(cur_console, LOAD, 16, font_16);
 	return 0;
 
     case GIO_FONT8x16:  	/* get 8x16 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	if (fonts_loaded & FONT_16) {
 	    bcopy(font_16, data, 16*256);
@@ -2247,7 +1821,7 @@ scstart(struct tty *tp)
     struct clist *rbp;
     int s, len;
     u_char buf[PCBURST];
-    scr_stat *scp = get_scr_stat(tp->t_dev);
+    scr_stat *scp = sc_get_scr_stat(tp->t_dev);
 
     if (scp->status & SLKED || blink_in_progress)
 	return; /* XXX who repeats the call when the above flags are cleared? */
@@ -2329,7 +1903,7 @@ sccnputc(dev_t dev, int c)
 
     scp->term = kernel_console;
     current_default = &kernel_default;
-    if (scp == cur_console && !(scp->status & UNKNOWN_MODE))
+    if (scp == cur_console && !ISGRAPHSC(scp))
 	remove_cursor_image(scp);
     buf[0] = c;
     ansi_put(scp, buf, 1);
@@ -2384,25 +1958,28 @@ sccnupdate(scr_stat *scp)
     if (font_loading_in_progress)
 	return;
 
-    if (panicstr) {
+    if (panicstr || shutdown_in_progress) {
 	scsplash_stick(FALSE);
 	run_scrn_saver = FALSE;
+    } else if (scp != cur_console) {
+	return;
     }
+
     if (!run_scrn_saver)
 	scrn_idle = FALSE;
     if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
-	if (scrn_blanked > 0)
+	if (scp->status & SAVER_RUNNING)
             stop_scrn_saver(current_saver);
 
     if (scp != cur_console || blink_in_progress || switch_in_progress)
 	return;
 
-    if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0)
+    if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
 	scrn_update(scp, TRUE);
 }
 
-static scr_stat
-*get_scr_stat(dev_t dev)
+scr_stat
+*sc_get_scr_stat(dev_t dev)
 {
     int unit = minor(dev);
 
@@ -2461,6 +2038,8 @@ scrn_timer(void *arg)
 	    scintr(0);
     }
 
+    scp = cur_console;
+
     /* should we stop the screen saver? */
     getmicrouptime(&tv);
     if (panicstr || shutdown_in_progress) {
@@ -2476,7 +2055,7 @@ scrn_timer(void *arg)
 	    run_scrn_saver = TRUE;
     }
     if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
-	if (scrn_blanked > 0)
+	if (scp->status & SAVER_RUNNING)
             stop_scrn_saver(current_saver);
 
     /* should we just return ? */
@@ -2488,14 +2067,13 @@ scrn_timer(void *arg)
     }
 
     /* Update the screen */
-    scp = cur_console;
-    if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0)
+    if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
 	scrn_update(scp, TRUE);
 
     /* should we activate the screen saver? */
     if ((saver_mode == CONS_LKM_SAVER) && scrn_idle)
-	if ((scp->status & UNKNOWN_MODE) == 0 || scrn_blanked > 0)
-	    (*current_saver)(TRUE);
+	if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING))
+	    scrn_saver(current_saver, TRUE);
 
     if (arg)
 	timeout(scrn_timer, (void *)TRUE, hz / 25);
@@ -2583,9 +2161,9 @@ add_scrn_saver(void (*this_saver)(int))
 
     if (current_saver != default_saver)
 	return EBUSY;
-    current_saver = this_saver;
+    run_scrn_saver = FALSE;
     saver_mode = CONS_LKM_SAVER;
-    run_scrn_saver = (scrn_blank_time > 0);
+    current_saver = this_saver;
     return 0;
 }
 
@@ -2612,10 +2190,22 @@ remove_scrn_saver(void (*this_saver)(int))
     return 0;
 }
 
+static void
+scrn_saver(void (*saver)(int), int blank)
+{
+    static int busy = FALSE;
+
+    if (busy)
+	return;
+    busy = TRUE;
+    (*saver)(blank);
+    busy = FALSE;
+}
+
 static void
 stop_scrn_saver(void (*saver)(int))
 {
-    (*saver)(FALSE);
+    scrn_saver(saver, FALSE);
     run_scrn_saver = FALSE;
     /* the screen saver may have chosen not to stop after all... */
     if (scrn_blanked > 0)
@@ -2632,8 +2222,8 @@ wait_scrn_saver_stop(void)
 {
     int error = 0;
 
-    run_scrn_saver = FALSE;
     while (scrn_blanked > 0) {
+	run_scrn_saver = FALSE;
 	error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0);
 	run_scrn_saver = FALSE;
 	if (error != ERESTART)
@@ -2642,8 +2232,8 @@ wait_scrn_saver_stop(void)
     return error;
 }
 
-static void
-clear_screen(scr_stat *scp)
+void
+sc_clear_screen(scr_stat *scp)
 {
     move_crsr(scp, 0, 0);
     scp->cursor_oldpos = scp->cursor_pos;
@@ -2668,8 +2258,7 @@ switch_scr(scr_stat *scp, u_int next_scr)
 	switch_in_progress = FALSE;
 
     if (next_scr >= MAXCONS || switch_in_progress ||
-	(cur_console->smode.mode == VT_AUTO
-	 && cur_console->status & UNKNOWN_MODE)) {
+	(cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) {
 	do_bell(scp, BELL_PITCH, BELL_DURATION);
 	return EINVAL;
     }
@@ -2721,25 +2310,26 @@ exchange_scr(void)
 {
     move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
     cur_console = new_scp;
-    if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){
-	if (crtc_type == KD_VGA)
+    if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) {
+	if (adp_flags & V_ADP_MODECHANGE)
 	    set_mode(new_scp);
     }
     move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
-    if (!(new_scp->status & UNKNOWN_MODE) && (flags & CHAR_CURSOR))
+    if (ISTEXTSC(new_scp) && (flags & CHAR_CURSOR))
 	set_destructive_cursor(new_scp);
-    if ((old_scp->status & UNKNOWN_MODE) && crtc_type == KD_VGA)
-	load_palette(palette);
+    if (ISGRAPHSC(old_scp))
+	load_palette(new_scp, palette);
     if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE ||
         old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE)
 	shfts = ctls = alts = agrs = metas = accents = 0;
-    set_border(new_scp->border);
+    set_border(new_scp, new_scp->border);
     update_leds(new_scp->status);
     delayed_next_scr = FALSE;
     mark_all(new_scp);
-    if (new_scp->mode == 0x102) {
-	bzero(Crtat, 800*600/8);
-    }
+
+    /* FIXME: the screen size may be larger than a 64K segment. */
+    if (ISPIXELSC(new_scp))
+	bzero(Crtat, new_scp->xpixel*new_scp->ypixel/8);
 }
 
 static void
@@ -2788,7 +2378,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    return;
 #endif
 	case 'c':   /* Clear screen & home */
-	    clear_screen(scp);
+	    sc_clear_screen(scp);
 	    break;
 
 	case '(':   /* iso-2022: designate 94 character set to G0 */
@@ -2874,7 +2464,7 @@ scan_esc(scr_stat *scp, u_char c)
 		      scp->cursor_pos,
 		      scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos);
     		mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
-    		mark_for_update(scp, scp->xsize * scp->ysize);
+    		mark_for_update(scp, scp->xsize * scp->ysize - 1);
 		remove_cutmarking(scp);
 		break;
 	    case 1: /* clear from beginning of display to cursor */
@@ -2936,7 +2526,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    fillw(scp->term.cur_color | scr_map[0x20], src,
 		  n * scp->xsize);
 	    mark_for_update(scp, scp->ypos * scp->xsize);
-	    mark_for_update(scp, scp->xsize * scp->ysize);
+	    mark_for_update(scp, scp->xsize * scp->ysize - 1);
 	    break;
 
 	case 'M':   /* Delete n lines */
@@ -2951,7 +2541,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    fillw(scp->term.cur_color | scr_map[0x20], src,
 		  n * scp->xsize);
 	    mark_for_update(scp, scp->ypos * scp->xsize);
-	    mark_for_update(scp, scp->xsize * scp->ysize);
+	    mark_for_update(scp, scp->xsize * scp->ysize - 1);
 	    break;
 
 	case 'P':   /* Delete n chars */
@@ -3192,7 +2782,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    if (scp->term.num_param == 1) {
 		scp->border=scp->term.param[0] & 0xff;
 		if (scp == cur_console)
-		    set_border(scp->border);
+		    set_border(cur_console, scp->border);
             }
 	    break;
 
@@ -3209,8 +2799,8 @@ scan_esc(scr_stat *scp, u_char c)
 		    flags |= BLINK_CURSOR;
 		else
 		    flags &= ~BLINK_CURSOR;
-		if ((scp->term.param[0] & 0x02) && 
-		    crtc_type == KD_VGA && !VESA_MODE(bios_video_mode))
+		if ((scp->term.param[0] & 0x02) 
+		    && ISFONTAVAIL(get_adapter(scp)->va_flags)) 
 		    flags |= CHAR_CURSOR;
 		else
 		    flags &= ~CHAR_CURSOR;
@@ -3223,9 +2813,9 @@ scan_esc(scr_stat *scp, u_char c)
 	     * The cursor shape is global property; all virtual consoles
 	     * are affected. Update the cursor in the current console...
 	     */
-	    if (!(cur_console->status & UNKNOWN_MODE)) {
+	    if (!ISGRAPHSC(cur_console)) {
 		remove_cursor_image(cur_console);
-		if (crtc_type == KD_VGA && (flags & CHAR_CURSOR))
+		if (flags & CHAR_CURSOR)
 	            set_destructive_cursor(cur_console);
 		draw_cursor_image(cur_console);
 	    }
@@ -3366,7 +2956,7 @@ outloop:
 	    break;
 
 	case 0x0c:  /* form feed, clears screen */
-	    clear_screen(scp);
+	    sc_clear_screen(scp);
 	    break;
 
 	case 0x0d:  /* return, return to pos 0 */
@@ -3413,42 +3003,17 @@ outloop:
 static void
 scinit(void)
 {
-    u_int hw_cursor;
+    int col;
+    int row;
     u_int i;
 
     if (init_done != COLD)
 	return;
     init_done = WARM;
 
-    /*
-     * Ensure a zero start address.  This is mainly to recover after
-     * switching from pcvt using userconfig().  The registers are w/o
-     * for old hardware so it's too hard to relocate the active screen
-     * memory.
-     */
-    outb(crtc_addr, 12);
-    outb(crtc_addr + 1, 0);
-    outb(crtc_addr, 13);
-    outb(crtc_addr + 1, 0);
-
-    /* extract cursor location */
-    outb(crtc_addr, 14);
-    hw_cursor = inb(crtc_addr + 1) << 8;
-    outb(crtc_addr, 15);
-    hw_cursor |= inb(crtc_addr + 1);
-
-    /*
-     * Validate cursor location.  It may be off the screen.  Then we must
-     * not use it for the initial buffer offset.
-     */
-    if (hw_cursor >= ROW * COL)
-	hw_cursor = (ROW - 1) * COL;
-
-    /* move hardware cursor out of the way */
-    outb(crtc_addr, 14);
-    outb(crtc_addr + 1, 0xff);
-    outb(crtc_addr, 15);
-    outb(crtc_addr + 1, 0xff);
+    /* extract the hardware cursor location and move it out of the way */
+    (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row);
+    (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1);
 
     /* set up the first console */
     current_default = &user_default;
@@ -3456,51 +3021,22 @@ scinit(void)
     init_scp(console[0]);
     cur_console = console[0];
 
-    /* discard the video mode table if we are not familiar with it... */
-    if (video_mode_ptr) {
-        bzero(mode_map, sizeof(mode_map));
-	bcopy(video_mode_ptr + MODE_PARAM_SIZE*console[0]->mode, 
-	      vgaregs2, sizeof(vgaregs2));
-        switch (comp_vgaregs(vgaregs, video_mode_ptr 
-                    + MODE_PARAM_SIZE*console[0]->mode)) {
-        case COMP_IDENTICAL:
-            map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
-            /* 
-             * This is a kludge for Toshiba DynaBook SS433 whose BIOS video
-             * mode table entry has the actual # of rows at the offset 1; 
-	     * BIOSes from other manufacturers store the # of rows - 1 there. 
-	     * XXX
-             */
-	    rows_offset = vgaregs[1] + 1 
-		- video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1];
-            break;
-        case COMP_SIMILAR:
-            map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
-            mode_map[console[0]->mode] = vgaregs;
-	    rows_offset = vgaregs[1] + 1 
-		- video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1];
-            vgaregs[1] -= rows_offset - 1;
-            break;
-        case COMP_DIFFERENT:
-        default:
-            video_mode_ptr = NULL;
-            mode_map[console[0]->mode] = vgaregs;
-	    rows_offset = 1;
-            break;
-        }
-    }
-
     /* copy screen to temporary buffer */
-    if (!VESA_MODE(console[0]->mode))
+    if (ISTEXTSC(console[0]))
 	    generic_bcopy(Crtat, sc_buffer,
 		   console[0]->xsize * console[0]->ysize * sizeof(u_short));
 
     console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos
 	= sc_buffer;
-    console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor;
+    if (col >= console[0]->xsize)
+	col = 0;
+    if (row >= console[0]->ysize)
+	row = console[0]->ysize - 1;
+    console[0]->xpos = col;
+    console[0]->ypos = row;
+    console[0]->cursor_pos = console[0]->cursor_oldpos =
+	sc_buffer + row*console[0]->xsize + col;
     console[0]->cursor_saveunder = *console[0]->cursor_pos;
-    console[0]->xpos = hw_cursor % COL;
-    console[0]->ypos = hw_cursor / COL;
     for (i=1; i<MAXCONS; i++)
 	console[i] = NULL;
     kernel_console.esc = 0;
@@ -3515,28 +3051,26 @@ scinit(void)
 	scr_map[i] = scr_rmap[i] = i;
     }
 
-    /* Save font and palette if VGA */
-    if (crtc_type == KD_VGA) {
-	if (!VESA_MODE(bios_video_mode)) {
-	    if (fonts_loaded & FONT_16) {
-		copy_font(LOAD, FONT_16, font_16);
-	    } else {
-		copy_font(SAVE, FONT_16, font_16);
-		fonts_loaded = FONT_16;
-	    }
-	    set_destructive_cursor(console[0]);
+    /* Save font and palette */
+    if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) {
+	if (fonts_loaded & FONT_16) {
+	    copy_font(cur_console, LOAD, 16, font_16);
+	} else {
+	    copy_font(cur_console, SAVE, 16, font_16);
+	    fonts_loaded = FONT_16;
+	    set_destructive_cursor(cur_console);
 	}
-	save_palette();
+	/*
+	 * FONT KLUDGE
+	 * Always use the font page #0. XXX
+	 */
+	(*biosvidsw.show_font)(cur_console->adp, 0);
     }
+    save_palette(cur_console, palette);
 
 #ifdef SC_SPLASH_SCREEN
-    /* 
-     * If not booting verbosely, put up the splash.
-     * Note that the splash screen is not currently supported in 
-     * the VESA mode.
-     */
-    if (!(boothowto & RB_VERBOSE) && !VESA_MODE(bios_video_mode))
-	scsplash_init();
+    /* put up the splash. */
+    scsplash_init(cur_console);
 #endif
 }
 
@@ -3551,52 +3085,79 @@ scshutdown(int howto, void *arg)
     shutdown_in_progress = TRUE;
 }
 
-static void
-map_mode_table(char *map[], char *table, int max)
+int
+sc_clean_up(scr_stat *scp)
 {
-    int i;
+    int error;
 
-    for(i = 0; i < max; ++i)
-	map[i] = table + i*MODE_PARAM_SIZE;
-    for(; i < MODE_MAP_SIZE; ++i)
-	map[i] = NULL;
+    if ((error = wait_scrn_saver_stop()))
+	return error;
+    scp->status &= ~MOUSE_VISIBLE;
+    remove_cutmarking(scp);
+    return 0;
 }
 
-static int
-map_mode_num(int mode)
+void
+sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear)
 {
-    static struct {
-        int from;
-        int to;
-    } mode_map[] = {
-        { M_ENH_B80x43, M_ENH_B80x25 },
-        { M_ENH_C80x43, M_ENH_C80x25 },
-        { M_VGA_M80x30, M_VGA_M80x25 },
-        { M_VGA_C80x30, M_VGA_C80x25 },
-        { M_VGA_M80x50, M_VGA_M80x25 },
-        { M_VGA_C80x50, M_VGA_C80x25 },
-        { M_VGA_M80x60, M_VGA_M80x25 },
-        { M_VGA_C80x60, M_VGA_C80x25 },
-        { M_VGA_MODEX,  M_VGA_CG320 },
-    };
-    int i;
+    if (scp->scr_buf)
+	free(scp->scr_buf, M_DEVBUF);
+    scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 
+				     M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
 
-    for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
-        if (mode_map[i].from == mode)
-            return mode_map[i].to;
+    if (clear) {
+        /* clear the screen and move the text cursor to the top-left position */
+	sc_clear_screen(scp);
+    } else {
+	/* retain the current cursor position, but adjust pointers */
+	move_crsr(scp, scp->xpos, scp->ypos);
+	scp->cursor_oldpos = scp->cursor_pos;
     }
-    return mode;
+
+    /* move the mouse cursor at the center of the screen */
+    sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
 }
 
-static char 
-*get_mode_param(scr_stat *scp, int mode)
+void
+sc_alloc_cut_buffer(scr_stat *scp, int wait)
 {
-    if (mode >= MODE_MAP_SIZE)
-	mode = map_mode_num(mode);
-    if (mode < MODE_MAP_SIZE)
-	return mode_map[mode];
-    else
-	return NULL;
+    if ((cut_buffer == NULL)
+	|| (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
+	if (cut_buffer != NULL)
+	    free(cut_buffer, M_DEVBUF);
+	cut_buffer_size = scp->xsize * scp->ysize + 1;
+	cut_buffer = (u_char *)malloc(cut_buffer_size, 
+				    M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
+	if (cut_buffer != NULL)
+	    cut_buffer[0] = '\0';
+    }
+}
+
+void
+sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait)
+{
+    u_short *usp;
+
+    if (lines < scp->ysize)
+	lines = scp->ysize;
+
+    usp = scp->history;
+    scp->history = NULL;
+    if (usp != NULL) {
+	free(usp, M_DEVBUF);
+	if (extra > 0)
+	    extra_history_size += extra;
+    }
+
+    scp->history_size = lines * scp->xsize;
+    if (lines > imax(sc_history_size, scp->ysize))
+	extra_history_size -= lines - imax(sc_history_size, scp->ysize);
+    usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 
+			    M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
+    if (usp != NULL)
+	bzero(usp, scp->history_size * sizeof(u_short));
+    scp->history_head = scp->history_pos = usp;
+    scp->history = usp;
 }
 
 static scr_stat
@@ -3606,22 +3167,15 @@ static scr_stat
 
     scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK);
     init_scp(scp);
-    scp->scr_buf = scp->cursor_pos = scp->cursor_oldpos =
-	(u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
-			  M_DEVBUF, M_WAITOK);
-    scp->mouse_pos = scp->mouse_oldpos = 
-	scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize +
-			scp->mouse_xpos/8);
-    scp->history_head = scp->history_pos =
-	(u_short *)malloc(scp->history_size*sizeof(u_short),
-			  M_DEVBUF, M_WAITOK);
-    bzero(scp->history_head, scp->history_size*sizeof(u_short));
-    scp->history = scp->history_head;
+    sc_alloc_scr_buffer(scp, TRUE, TRUE);
+    if (ISMOUSEAVAIL(get_adapter(scp)->va_flags))
+	sc_alloc_cut_buffer(scp, TRUE);
+    sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE);
 /* SOS
-    if (crtc_type == KD_VGA && video_mode_ptr)
+    if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE)
 	set_mode(scp);
 */
-    clear_screen(scp);
+    sc_clear_screen(scp);
     scp->cursor_saveunder = *scp->cursor_pos;
     return scp;
 }
@@ -3629,43 +3183,29 @@ static scr_stat
 static void
 init_scp(scr_stat *scp)
 {
-    switch(crtc_type) {
-    case KD_VGA:
-	if (VESA_MODE(bios_video_mode))
-	    scp->mode = bios_video_mode;
-	else if (crtc_addr == MONO_BASE)
-	    scp->mode = M_VGA_M80x25;
-	else
-	    scp->mode = M_VGA_C80x25;
-	scp->font_size = 16;
-	break;
-    case KD_CGA:
-	if (crtc_addr == MONO_BASE)
-	    scp->mode = M_B80x25;
-	else
-	    scp->mode = M_C80x25;
-	scp->font_size = 8;
-	break;
-    case KD_EGA:
-	if (crtc_addr == MONO_BASE)
-	    scp->mode = M_B80x25;
-	else
-	    scp->mode = M_C80x25;
-	scp->font_size = 14;
-	break;
-    case KD_MONO:
-    case KD_HERCULES:
-    default:
-	scp->mode = M_EGAMONO80x25;
-	scp->font_size = 14;
-	break;
-    }
-    scp->initial_mode = scp->mode;
+    video_info_t info;
 
-    scp->xsize = COL;
-    scp->ysize = ROW;
-    scp->xpixel = scp->xsize * 8;
-    scp->ypixel = scp->ysize * scp->font_size;
+    scp->adp = V_ADP_PRIMARY;
+    (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info);
+
+    scp->status = 0;
+    scp->mode = scp->initial_mode = initial_video_mode;
+    scp->scr_buf = NULL;
+    if (info.vi_flags & V_INFO_GRAPHICS) {
+	scp->status |= GRAPHICS_MODE;
+	scp->xpixel = info.vi_width;
+	scp->ypixel = info.vi_height;
+	scp->xsize = info.vi_width/8;
+	scp->ysize = info.vi_height/info.vi_cheight;
+	scp->font_size = FONT_NONE;
+    } else {
+	scp->xsize = info.vi_width;
+	scp->ysize = info.vi_height;
+	scp->xpixel = scp->xsize*8;
+	scp->ypixel = scp->ysize*info.vi_cheight;
+	scp->font_size = info.vi_cheight;
+    }
+    scp->xoff = scp->yoff = 0;
     scp->xpos = scp->ypos = 0;
     scp->saved_xpos = scp->saved_ypos = -1;
     scp->start = scp->xsize * scp->ysize;
@@ -3677,8 +3217,8 @@ init_scp(scr_stat *scp)
 	current_default->std_color;
     scp->term.rev_color = current_default->rev_color;
     scp->border = BG_BLACK;
-    scp->cursor_start = *(char *)pa_to_va(0x461);
-    scp->cursor_end = *(char *)pa_to_va(0x460);
+    scp->cursor_start = *(u_int8_t *)pa_to_va(0x461);
+    scp->cursor_end = *(u_int8_t *)pa_to_va(0x460);
     scp->mouse_xpos = scp->xsize*8/2;
     scp->mouse_ypos = scp->ysize*scp->font_size/2;
     scp->mouse_cut_start = scp->mouse_cut_end = NULL;
@@ -3687,13 +3227,13 @@ init_scp(scr_stat *scp)
     scp->mouse_proc = NULL;
     scp->bell_pitch = BELL_PITCH;
     scp->bell_duration = BELL_DURATION;
-    scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
+    scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
     scp->status |= CURSOR_ENABLED;
     scp->pid = 0;
     scp->proc = NULL;
     scp->smode.mode = VT_AUTO;
     scp->history_head = scp->history_pos = scp->history = NULL;
-    scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
+    scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize;
 }
 
 static u_char
@@ -4140,9 +3680,9 @@ next_code:
 			scsplash_stick(FALSE);
 			stop_scrn_saver(current_saver);
 		    } else {
-			if ((cur_console->status & UNKNOWN_MODE) == 0) {
+			if (!ISGRAPHSC(cur_console)) {
 			    scsplash_stick(TRUE);
-			    (*current_saver)(TRUE);
+			    scrn_saver(current_saver, TRUE);
 			}
 		    }
 		}
@@ -4409,475 +3949,100 @@ update_leds(int which)
     set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]);
 }
 
-void
+int
 set_mode(scr_stat *scp)
 {
-    char special_modetable[MODE_PARAM_SIZE];
-    char *mp;
-    int s;
-    int i;
+    video_info_t info;
+    video_adapter_t *adp;
 
+    /* reject unsupported mode */
+    if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
+	return 1;
+
+    /* if this vty is not currently showing, do nothing */
     if (scp != cur_console)
-	return;
-
-    /* 
-     * even if mode switching is disabled, we can change back
-     * to the initial mode or the custom mode based on the initial
-     * mode if we have saved register values upon start-up.
-     */
-    mp = get_mode_param(scp, scp->mode);
-    if (mp == NULL)
-	return;
-    bcopy(mp, &special_modetable, sizeof(special_modetable));
+	return 0;
 
     /* setup video hardware for the given mode */
-    switch (scp->mode) {
-    case M_VGA_C80x60: case M_VGA_M80x60:
-	special_modetable[2]  = 0x08;
-	special_modetable[19] = 0x47;
-	goto special_480l;
+    adp = get_adapter(scp);
+    (*biosvidsw.set_mode)(scp->adp, scp->mode);
+    Crtat = (u_short *)adp->va_window;
 
-    case M_VGA_C80x30: case M_VGA_M80x30:
-	special_modetable[19] = 0x4f;
-special_480l:
-	special_modetable[9] |= 0xc0;
-	special_modetable[16] = 0x08;
-	special_modetable[17] = 0x3e;
-	special_modetable[26] = 0xea;
-	special_modetable[28] = 0xdf;
-	special_modetable[31] = 0xe7;
-	special_modetable[32] = 0x04;
-	goto setup_mode;
-
-    case M_ENH_C80x43: case M_ENH_B80x43:
-	special_modetable[28] = 87;
-	goto special_80x50;
-
-    case M_VGA_C80x50: case M_VGA_M80x50:
-special_80x50:
-	special_modetable[2] = 8;
-	special_modetable[19] = 7;
-	goto setup_mode;
-
-    case M_VGA_C40x25: case M_VGA_C80x25:
-    case M_VGA_M80x25:
-    case M_B40x25:     case M_C40x25:
-    case M_B80x25:     case M_C80x25:
-    case M_ENH_B40x25: case M_ENH_C40x25:
-    case M_ENH_B80x25: case M_ENH_C80x25:
-    case M_EGAMONO80x25:
-
-setup_mode:
-	set_vgaregs(special_modetable);
-	scp->font_size = special_modetable[2];
-
-	/* set font type (size) */
-	if (scp->font_size < 14) {
-	    if (fonts_loaded & FONT_8)
-		copy_font(LOAD, FONT_8, font_8);
-	    i = 0x0a;				/* font 2 */
-	} else if (scp->font_size >= 16) {
-	    if (fonts_loaded & FONT_16)
-		copy_font(LOAD, FONT_16, font_16);
-	    i = 0x00;				/* font 0 */
-	} else {
-	    if (fonts_loaded & FONT_14)
-		copy_font(LOAD, FONT_14, font_14);
-	    i = 0x05;				/* font 1 */
+    if (!(scp->status & GRAPHICS_MODE)) {
+	/* load appropriate font */
+	if (!(scp->status & PIXEL_MODE) 
+	    && ISFONTAVAIL(get_adapter(scp)->va_flags)) {
+	    if (scp->font_size < 14) {
+		if (fonts_loaded & FONT_8)
+		    copy_font(scp, LOAD, 8, font_8);
+	    } else if (scp->font_size >= 16) {
+		if (fonts_loaded & FONT_16)
+		    copy_font(scp, LOAD, 16, font_16);
+	    } else {
+		if (fonts_loaded & FONT_14)
+		    copy_font(scp, LOAD, 14, font_14);
+	    }
+	    /*
+	    * FONT KLUDGE:
+	    * This is an interim kludge to display correct font.
+	    * Always use the font page #0 on the video plane 2.
+	    * Somehow we cannot show the font in other font pages on
+	    * some video cards... XXX
+	    */ 
+	    (*biosvidsw.show_font)(scp->adp, 0);
 	}
-	/*
-	 * FONT KLUDGE:
-	 * This is an interim kludge to display correct font.
-	 * Always use the font page #0 on the video plane 2.
-	 * Somehow we cannot show the font in other font pages on
-	 * some video cards... XXX
-	 */
-	i = 0x00;
-	s = splhigh();
-	outb(TSIDX, 0x00); outb(TSREG, 0x01);
-	outb(TSIDX, 0x03); outb(TSREG, i);
-	outb(TSIDX, 0x00); outb(TSREG, 0x03);
-	splx(s);
+	mark_all(scp);
+    }
+    set_border(scp, scp->border);
+
+    /* move hardware cursor out of the way */
+    (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
+
+    return 0;
+}
+
+void
+copy_font(scr_stat *scp, int operation, int font_size, u_char *buf)
+{
+    /*
+     * FONT KLUDGE:
+     * This is an interim kludge to display correct font.
+     * Always use the font page #0 on the video plane 2.
+     * Somehow we cannot show the font in other font pages on
+     * some video cards... XXX
+     */ 
+    font_loading_in_progress = TRUE;
+    if (operation == LOAD) {
+	(*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256);
 	if (flags & CHAR_CURSOR)
 	    set_destructive_cursor(scp);
-	mark_all(scp);
-	break;
-
-    case M_VGA_MODEX:
-	/* "unchain" the VGA mode */
-	special_modetable[5-1+0x04] &= 0xf7;
-	special_modetable[5-1+0x04] |= 0x04;
-	/* turn off doubleword mode */
-	special_modetable[10+0x14] &= 0xbf;
-	/* turn off word adressing */
-	special_modetable[10+0x17] |= 0x40;
-	/* set logical screen width */
-	special_modetable[10+0x13] = 80;
-	/* set 240 lines */
-	special_modetable[10+0x11] = 0x2c;
-	special_modetable[10+0x06] = 0x0d;
-	special_modetable[10+0x07] = 0x3e;
-	special_modetable[10+0x10] = 0xea;
-	special_modetable[10+0x11] = 0xac;
-	special_modetable[10+0x12] = 0xdf;
-	special_modetable[10+0x15] = 0xe7;
-	special_modetable[10+0x16] = 0x06;
-	/* set vertical sync polarity to reflect aspect ratio */
-	special_modetable[9] = 0xe3;
-	goto setup_grmode;
-
-    case M_BG320:     case M_CG320:     case M_BG640:
-    case M_CG320_D:   case M_CG640_E:
-    case M_CG640x350: case M_ENH_CG640:
-    case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
-
-setup_grmode:
-	set_vgaregs(special_modetable);
-	scp->font_size = FONT_NONE;
-	break;
-
-    default:
-	/* call user defined function XXX */
-	break;
+    } else if (operation == SAVE) {
+	(*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256);
     }
-
-    /* set border color for this (virtual) console */
-    set_border(scp->border);
-    return;
-}
-
-void
-set_border(u_char color)
-{
-    switch (crtc_type) {
-    case KD_EGA:
-    case KD_VGA:
-        inb(crtc_addr + 6);		/* reset flip-flop */
-        outb(ATC, 0x31); outb(ATC, color);
-	break;
-    case KD_CGA:
-	outb(crtc_addr + 5, color & 0x0f); /* color select register */
-	break;
-    case KD_MONO:
-    case KD_HERCULES:
-    default:
-	break;
-    }
-}
-
-static void
-set_vgaregs(char *modetable)
-{
-    int i, s = splhigh();
-
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);   	/* stop sequencer */
-    for (i=0; i<4; i++) {           		/* program sequencer */
-	outb(TSIDX, i+1);
-	outb(TSREG, modetable[i+5]);
-    }
-    outb(MISC, modetable[9]);       		/* set dot-clock */
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);   	/* start sequencer */
-    outb(crtc_addr, 0x11);
-    outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F);
-    for (i=0; i<25; i++) {          		/* program crtc */
-	outb(crtc_addr, i);
-	if (i == 14 || i == 15)     		/* no hardware cursor */
-	    outb(crtc_addr+1, 0xff);
-	else
-	    outb(crtc_addr+1, modetable[i+10]);
-    }
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    for (i=0; i<20; i++) {          		/* program attribute ctrl */
-	outb(ATC, i);
-	outb(ATC, modetable[i+35]);
-    }
-    for (i=0; i<9; i++) {           		/* program graph data ctrl */
-	outb(GDCIDX, i);
-	outb(GDCREG, modetable[i+55]);
-    }
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-    splx(s);
-}
-
-static void
-read_vgaregs(char *buf)
-{
-    int i, j;
-    int s;
-
-    bzero(buf, MODE_PARAM_SIZE);
-
-    s = splhigh();
-
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);   	/* stop sequencer */
-    for (i=0, j=5; i<4; i++) {           
-	outb(TSIDX, i+1);
-	buf[j++] = inb(TSREG);
-    }
-    buf[9] = inb(MISC + 10);      		/* dot-clock */
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);   	/* start sequencer */
-
-    for (i=0, j=10; i<25; i++) {       		/* crtc */
-	outb(crtc_addr, i);
-	buf[j++] = inb(crtc_addr+1);
-    }
-    for (i=0, j=35; i<20; i++) {          	/* attribute ctrl */
-        inb(crtc_addr+6);           		/* reset flip-flop */
-	outb(ATC, i);
-	buf[j++] = inb(ATC + 1);
-    }
-    for (i=0, j=55; i<9; i++) {           	/* graph data ctrl */
-	outb(GDCIDX, i);
-	buf[j++] = inb(GDCREG);
-    }
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-
-    buf[0] = *(char *)pa_to_va(0x44a);		/* COLS */
-    buf[1] = *(char *)pa_to_va(0x484);		/* ROWS */
-    buf[2] = *(char *)pa_to_va(0x485);		/* POINTS */
-    buf[3] = *(char *)pa_to_va(0x44c);
-    buf[4] = *(char *)pa_to_va(0x44d);
-
-    splx(s);
-}
-
-static int 
-comp_vgaregs(u_char *buf1, u_char *buf2)
-{
-    static struct {
-        u_char mask;
-    } params[MODE_PARAM_SIZE] = {
-	0xff, 0x00, 0xff, 		/* COLS, ROWS, POINTS */
-	0xff, 0xff, 			/* page length */
-	0xfe, 0xff, 0xff, 0xff,		/* sequencer registers */
-	0xf3,				/* misc register */
-	0xff, 0xff, 0xff, 0x7f, 0xff,	/* CRTC */
-	0xff, 0xff, 0xff, 0x7f, 0xff,
-	0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0xff, 0x7f, 0xff, 0xff,
-	0x7f, 0xff, 0xff, 0xef, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff,	/* attribute controller registers */
-	0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xf0,
-	0xff, 0xff, 0xff, 0xff, 0xff,	/* GDC register */
-	0xff, 0xff, 0xff, 0xff, 
-    }; 
-    int identical = TRUE;
-    int i;
-
-    for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
-	if (params[i].mask == 0)	/* don't care */
-	    continue;
-	if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
-	    return COMP_DIFFERENT;
-	if (buf1[i] != buf2[i])
-	    identical = FALSE;
-    }
-    return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
-
-#if 0
-    for(i = 0; i < 20; ++i) {
-	if (*buf1++ != *buf2++)
-	    return COMP_DIFFERENT;
-    }
-    buf1 += 2;  /* skip the cursor shape */
-    buf2 += 2;
-    for(i = 22; i < 24; ++i) {
-	if (*buf1++ != *buf2++)
-	    return COMP_DIFFERENT;
-    }
-    buf1 += 2;  /* skip the cursor position */
-    buf2 += 2;
-    for(i = 26; i < MODE_PARAM_SIZE; ++i) {
-	if (*buf1++ != *buf2++)
-	    return COMP_DIFFERENT;
-    }
-    return COMP_IDENTICAL;
-#endif
-}
-
-static void
-dump_vgaregs(u_char *buf)
-{
-    int i;
-
-    for(i = 0; i < MODE_PARAM_SIZE;) {
-	printf("%02x ", buf[i]);
-	if ((++i % 16) == 0)
-	    printf("\n");
-    }
-}
-
-static void
-set_font_mode(u_char *buf)
-{
-    int s = splhigh();
-
-    font_loading_in_progress = TRUE;
-
-    /* save register values */
-    outb(TSIDX, 0x02); buf[0] = inb(TSREG);
-    outb(TSIDX, 0x04); buf[1] = inb(TSREG);
-    outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
-    outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
-    outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
-    inb(crtc_addr + 6);
-    outb(ATC, 0x10); buf[5] = inb(ATC + 1);
-
-    /* setup vga for loading fonts */
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
-    inb(crtc_addr+6);               		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-
-#if SLOW_VGA
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);
-#endif
-    outb(TSIDX, 0x02); outb(TSREG, 0x04);
-    outb(TSIDX, 0x04); outb(TSREG, 0x07);
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);
-#endif
-    outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
-    outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
-    outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
-#else
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0100);
-#endif
-    outw(TSIDX, 0x0402);
-    outw(TSIDX, 0x0704);
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0300);
-#endif
-    outw(GDCIDX, 0x0204);
-    outw(GDCIDX, 0x0005);
-    outw(GDCIDX, 0x0406);               /* addr = a0000, 64kb */
-#endif
-    splx(s);
-}
-
-static void
-set_normal_mode(u_char *buf)
-{
-    char *modetable;
-    int s = splhigh();
-
-    /* setup vga for normal operation mode again */
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x10); outb(ATC, buf[5]);
-    inb(crtc_addr+6);               		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-
-#if SLOW_VGA
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);
-#endif
-    outb(TSIDX, 0x02); outb(TSREG, buf[0]);
-    outb(TSIDX, 0x04); outb(TSREG, buf[1]);
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);
-#endif
-    outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
-    outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
-    if (crtc_addr == MONO_BASE) {
-	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
-    } else {
-	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
-    }
-#else
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0100);
-#endif
-    outw(TSIDX, 0x0002 | (buf[0] << 8));
-    outw(TSIDX, 0x0004 | (buf[1] << 8));
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0300);
-#endif
-    outw(GDCIDX, 0x0004 | (buf[2] << 8));
-    outw(GDCIDX, 0x0005 | (buf[3] << 8));
-    if (crtc_addr == MONO_BASE)
-        outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
-    else
-        outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
-#endif
-
     font_loading_in_progress = FALSE;
-    splx(s);
-}
-
-void
-copy_font(int operation, int font_type, char* font_image)
-{
-    int ch, line, segment, fontsize;
-    u_char buf[PARAM_BUFSIZE];
-    u_char val;
-
-    switch (font_type) {
-    default:
-    case FONT_8:
-	segment = 0x8000;
-	fontsize = 8;
-	break;
-    case FONT_14:
-	segment = 0x4000;
-	fontsize = 14;
-	break;
-    case FONT_16:
-	segment = 0x0000;
-	fontsize = 16;
-	break;
-    }
-    /*
-     * FONT KLUDGE
-     * Always use the font page #0. XXX
-     */
-    segment = 0x0000;
-    outb(TSIDX, 0x01); val = inb(TSREG);        /* disable screen */
-    outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
-    set_font_mode(buf);
-    for (ch=0; ch < 256; ch++)
-	for (line=0; line < fontsize; line++)
-	if (operation)
-	    *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) =
-		    font_image[(ch*fontsize)+line];
-	else
-	    font_image[(ch*fontsize)+line] =
-	    *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line);
-    set_normal_mode(buf);
-    outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */
 }
 
 static void
 set_destructive_cursor(scr_stat *scp)
 {
-    u_char buf[PARAM_BUFSIZE];
     u_char cursor[32];
-    caddr_t address;
+    u_char *font_buffer;
+    int font_size;
     int i;
-    char *font_buffer;
+
+    if (!ISFONTAVAIL(get_adapter(scp)->va_flags) || !ISTEXTSC(scp))
+	return;
 
     if (scp->font_size < 14) {
 	font_buffer = font_8;
-	address = (caddr_t)VIDEOMEM + 0x8000;
-    }
-    else if (scp->font_size >= 16) {
+	font_size = 8;
+    } else if (scp->font_size >= 16) {
 	font_buffer = font_16;
-	address = (caddr_t)VIDEOMEM;
-    }
-    else {
+	font_size = 16;
+    } else {
 	font_buffer = font_14;
-	address = (caddr_t)VIDEOMEM + 0x4000;
+	font_size = 14;
     }
-    /*
-     * FONT KLUDGE
-     * Always use the font page #0. XXX
-     */
-    address = (caddr_t)VIDEOMEM;
 
     if (scp->status & MOUSE_VISIBLE) {
 	if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR)
@@ -4902,9 +4067,18 @@ set_destructive_cursor(scr_stat *scp)
 #if 1
     while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ;
 #endif
-    set_font_mode(buf);
-    generic_bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32);
-    set_normal_mode(buf);
+    font_loading_in_progress = TRUE;
+    (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1);
+    font_loading_in_progress = FALSE;
+}
+
+void
+sc_move_mouse(scr_stat *scp, int x, int y)
+{
+    scp->mouse_xpos = x;
+    scp->mouse_ypos = y;
+    scp->mouse_pos = scp->mouse_oldpos = 
+	scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8;
 }
 
 static void
@@ -4916,7 +4090,7 @@ set_mouse_pos(scr_stat *scp)
 	scp->mouse_xpos = 0;
     if (scp->mouse_ypos < 0)
 	scp->mouse_ypos = 0;
-    if (scp->status & UNKNOWN_MODE) {
+    if (!ISTEXTSC(scp)) {
         if (scp->mouse_xpos > scp->xpixel-1)
 	    scp->mouse_xpos = scp->xpixel-1;
         if (scp->mouse_ypos > scp->ypixel-1)
@@ -5146,35 +4320,26 @@ mouse_paste(scr_stat *scp)
 static void
 draw_mouse_image(scr_stat *scp)
 {
-    caddr_t address;
-    int i;
-    char *font_buffer;
-    u_char buf[PARAM_BUFSIZE];
     u_short buffer[32];
     u_short xoffset, yoffset;
     u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf);
-    int font_size = scp->font_size;
+    u_char *font_buffer;
+    int font_size;
+    int i;
 
-    if (font_size < 14) {
+    if (scp->font_size < 14) {
 	font_buffer = font_8;
-	address = (caddr_t)VIDEOMEM + 0x8000;
-    }
-    else if (font_size >= 16) {
+	font_size = 8;
+    } else if (scp->font_size >= 16) {
 	font_buffer = font_16;
-	address = (caddr_t)VIDEOMEM;
-    }
-    else {
+	font_size = 16;
+    } else {
 	font_buffer = font_14;
-	address = (caddr_t)VIDEOMEM + 0x4000;
+	font_size = 14;
     }
-    /*
-     * FONT KLUDGE
-     * Always use the font page #0. XXX
-     */
-    address = (caddr_t)VIDEOMEM;
 
     xoffset = scp->mouse_xpos % 8;
-    yoffset = scp->mouse_ypos % font_size;
+    yoffset = scp->mouse_ypos % scp->font_size;
 
     /* prepare mousepointer char's bitmaps */
     bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size),
@@ -5209,9 +4374,11 @@ draw_mouse_image(scr_stat *scp)
     /* wait for vertical retrace to avoid jitter on some videocards */
     while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ;
 #endif
-    set_font_mode(buf);
-    generic_bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + SC_MOUSE_CHAR * 32, 128);
-    set_normal_mode(buf);
+    font_loading_in_progress = TRUE;
+    (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, 
+			   SC_MOUSE_CHAR, 4); 
+    font_loading_in_progress = FALSE;
+
     *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR;
     *(crt_pos+scp->xsize) = 
 	(*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2);
@@ -5229,6 +4396,8 @@ remove_mouse_image(scr_stat *scp)
 {
     u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf);
 
+    if (!ISTEXTSC(scp))
+	return;
     *(crt_pos) = *(scp->mouse_oldpos);
     *(crt_pos+1) = *(scp->mouse_oldpos+1);
     *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize);
@@ -5278,30 +4447,6 @@ remove_cutmarking(scr_stat *scp)
     mark_all(scp);
 }
 
-static void
-save_palette(void)
-{
-    int i;
-
-    outb(PALRADR, 0x00);
-    for (i=0x00; i<0x300; i++)
-	palette[i] = inb(PALDATA);
-    inb(crtc_addr+6);           /* reset flip/flop */
-}
-
-void
-load_palette(char *palette)
-{
-    int i;
-
-    outb(PIXMASK, 0xFF);            /* no pixelmask */
-    outb(PALWADR, 0x00);
-    for (i=0x00; i<0x300; i++)
-	 outb(PALDATA, palette[i]);
-    inb(crtc_addr+6);           /* reset flip/flop */
-    outb(ATC, 0x20);            /* enable palette */
-}
-
 static void
 do_bell(scr_stat *scp, int pitch, int duration)
 {
@@ -5330,7 +4475,7 @@ blink_screen(void *arg)
 {
     scr_stat *scp = arg;
 
-    if ((scp->status & UNKNOWN_MODE) || (blink_in_progress <= 1)) {
+    if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) {
 	blink_in_progress = FALSE;
     	mark_all(scp);
 	if (delayed_next_scr)
@@ -5351,25 +4496,41 @@ blink_screen(void *arg)
 void 
 sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
 {
-    if (!VESA_MODE(scp->mode)) {
-	generic_bcopy(p+from, Crtat+from, (to-from+1)*sizeof (u_short));
-    } else if (scp->mode == 0x102) {
-	u_char *d, *e;
-	int i,j;
+    u_char *font;
+    u_char *d, *e;
+    u_char *f;
+    int font_size;
+    int line_length;
+    int xsize;
+    int i, j;
 
+    if (ISTEXTSC(scp)) {
+	generic_bcopy(p+from, Crtat+from, (to-from+1)*sizeof (u_short));
+    } else /* if ISPIXELSC(scp) */ {
 	if (mark)
-		mark = 255;
-	d = (u_char *)Crtat;
-	d += 10 + 6*16*100 + (from%80) + 16*100*(from/80);
+	    mark = 255;
+	font_size = scp->font_size;
+	if (font_size < 14)
+	    font = font_8;
+	else if (font_size >= 16)
+	    font = font_16;
+	else
+	    font = font_14;
+	line_length = scp->xpixel/8;
+	xsize = scp->xsize;
+	d = (u_char *)Crtat 
+	    + scp->xoff + scp->yoff*font_size*line_length 
+	    + (from%xsize) + font_size*line_length*(from/xsize);
 	for (i = from ; i <= to ; i++) {
 	    e = d;
-	    for (j = 0 ; j < 16; j++) {
-	        *e = mark^font_16[(p[i]&0xff)*16+j];
-		e+=100;
+	    f = &font[(p[i] & 0x00ff)*font_size];
+	    for (j = 0 ; j < font_size; j++, f++) {
+	        *e = mark^*f;
+		e += line_length;
 	    }
 	    d++;
-	    if ((i % 80) == 79)
-		d += 20 + 15*100;
+	    if ((i % xsize) == xsize - 1)
+		d += scp->xoff*2 + (font_size - 1)*line_length;
 	}
     }
 }
@@ -5377,34 +4538,36 @@ sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
 #ifdef SC_SPLASH_SCREEN
 
 static void
-scsplash_init(void)
+scsplash_init(scr_stat *scp)
 {
+    video_info_t info;
+
     /* 
      * We currently assume the splash screen always use
      * VGA_CG320 mode and abort installation if this mode is not
      * supported with this video card. XXX
      */
-    if (crtc_type != KD_VGA || get_mode_param(cur_console, M_VGA_CG320) == NULL)
+    if ((*biosvidsw.get_info)(scp->adp, M_VGA_CG320, &info))
 	return;
 
-    if (splash_load() == 0 && add_scrn_saver(scsplash) == 0) {
-	default_saver = scsplash;
+    if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) {
+	default_saver = scsplash_saver;
 	scrn_blank_time = DEFAULT_BLANKTIME;
 	run_scrn_saver = TRUE;
-	if (!(boothowto & RB_CONFIG)) {
+	if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) {
 	    scsplash_stick(TRUE);
-	    scsplash(TRUE);
+	    scsplash_saver(TRUE);
 	}
     }
 }
 
 static void
-scsplash(int show)
+scsplash_saver(int show)
 {
     if (show)
-	splash(TRUE);
+	scsplash(TRUE);
     else if (!sticky_splash)
-	splash(FALSE);
+	scsplash(FALSE);
 }
 
 #endif /* SC_SPLASH_SCREEN */
diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h
index b23a2ae7c5da..315946b57305 100644
--- a/sys/dev/syscons/syscons.h
+++ b/sys/dev/syscons/syscons.h
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995-1997 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: syscons.h,v 1.38 1998/08/03 09:09:35 yokota Exp $
+ *	$Id$
  */
 
 #ifndef _I386_ISA_SYSCONS_H_
@@ -65,6 +65,9 @@
 #define MOUSE_MOVED	0x01000
 #define MOUSE_CUTTING	0x02000
 #define MOUSE_VISIBLE	0x04000
+#define GRAPHICS_MODE	0x08000
+#define PIXEL_MODE	0x10000
+#define SAVER_RUNNING	0x20000
 
 /* configuration flags */
 #define VISUAL_BELL	0x00001
@@ -74,6 +77,7 @@
 #define XT_KEYBD	0x00010
 #define KBD_NORESET	0x00020
 #define QUIET_BELL	0x00040
+#define VESA800X600	0x00080
 
 /* attribute flags */
 #define NORMAL_ATTR             0x00
@@ -84,9 +88,6 @@
 #define FOREGROUND_CHANGED      0x10
 #define BACKGROUND_CHANGED      0x20
 
-/* video hardware memory addresses */
-#define VIDEOMEM	0x000A0000
-
 /* misc defines */
 #define FALSE		0
 #define TRUE		1
@@ -104,20 +105,6 @@
 #define FONT_14		4
 #define FONT_16		8
 
-/* defines related to hardware addresses */
-#define	MONO_BASE	0x3B4			/* crt controller base mono */
-#define	COLOR_BASE	0x3D4			/* crt controller base color */
-#define MISC		0x3C2			/* misc output register */
-#define ATC		IO_VGA+0x00		/* attribute controller */
-#define TSIDX		IO_VGA+0x04		/* timing sequencer idx */
-#define TSREG		IO_VGA+0x05		/* timing sequencer data */
-#define PIXMASK		IO_VGA+0x06		/* pixel write mask */
-#define PALRADR		IO_VGA+0x07		/* palette read address */
-#define PALWADR		IO_VGA+0x08		/* palette write address */
-#define PALDATA		IO_VGA+0x09		/* palette data register */
-#define GDCIDX		IO_VGA+0x0E		/* graph data controller idx */
-#define GDCREG		IO_VGA+0x0F		/* graph data controller data */
-
 /* special characters */
 #define cntlc		0x03
 #define cntld		0x04
@@ -141,6 +128,7 @@ typedef struct term_stat {
 } term_stat;
 
 typedef struct scr_stat {
+	int		adp;			/* video adapter index */
 	u_short 	*scr_buf;		/* buffer when off screen */
 	int 		xpos;			/* current X position */
 	int 		ypos;			/* current Y position */
@@ -150,6 +138,8 @@ typedef struct scr_stat {
 	int 		ysize;			/* Y text size */
 	int 		xpixel;			/* X graphics size */
 	int 		ypixel;			/* Y graphics size */
+	int		xoff;			/* X offset in pixel mode */
+	int		yoff;			/* Y offset in pixel mode */
 	int		font_size;		/* fontsize in Y direction */
 	int		start;			/* modified area start */
 	int		end;			/* modified area end */
@@ -186,7 +176,8 @@ typedef struct scr_stat {
 	int		history_size;		/* size of history buffer */
 	struct apmhook  r_hook;			/* reconfiguration support */
 #ifdef SC_SPLASH_SCREEN
-	u_char		splash_save_mode;	/* saved mode for splash screen */
+	int		splash_save_mode;	/* saved mode for splash screen */
+	int		splash_save_status;	/* saved status for splash screen */
 #endif
 } scr_stat;
 
@@ -195,18 +186,59 @@ typedef struct default_attr {
 	int             rev_color;              /* reverse hardware color */
 } default_attr;
 
+
+#define ISTEXTSC(scp)	(!((scp)->status 				\
+			  & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE)))
+#define ISGRAPHSC(scp)	(((scp)->status 				\
+			  & (UNKNOWN_MODE | GRAPHICS_MODE)))
+#define ISPIXELSC(scp)	(((scp)->status 				\
+			  & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE))\
+			  == PIXEL_MODE)
+#define ISUNKNOWNSC(scp) ((scp)->status & UNKNOWN_MODE)
+
+#define ISFONTAVAIL(af)	((af) & V_ADP_FONT)
+#define ISMOUSEAVAIL(af) ((af) & V_ADP_FONT)
+#define ISPALAVAIL(af)	((af) & V_ADP_PALETTE)
+
 /* misc prototypes used by different syscons related LKM's */
-void set_border(u_char color);
-void set_mode(scr_stat *scp);
-void copy_font(int operation, int font_type, char* font_image);
-void load_palette(char *palette);
+
+/* syscons.c */
+extern int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, int flag, 
+			    struct proc *p);
+
+int set_mode(scr_stat *scp);
+scr_stat *sc_get_scr_stat(dev_t dev);
+
+void copy_font(scr_stat *scp, int operation, int font_size, u_char *font_image);
+#define save_palette(scp, pal)	(*biosvidsw.save_palette)((scp)->adp, pal)
+#define load_palette(scp, pal)	(*biosvidsw.load_palette)((scp)->adp, pal)
+#define set_border(scp, col)	(*biosvidsw.set_border)((scp)->adp, col)
+#define get_adapter(scp)	(*biosvidsw.adapter)((scp)->adp)
+
 int add_scrn_saver(void (*this)(int));
 int remove_scrn_saver(void (*this)(int));
 
+void sc_clear_screen(scr_stat *scp);
+void sc_move_mouse(scr_stat *scp, int x, int y);
+int sc_clean_up(scr_stat *scp);
+void sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear);
+void sc_alloc_cut_buffer(scr_stat *scp, int wait);
+void sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait);
+
+/* scvidctl.c */
+int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode,
+		     int xsize, int ysize, int fontsize);
+int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode);
+int sc_set_pixel_mode(scr_stat *scp, struct tty *tp,
+		      int xsize, int ysize, int fontsize);
+int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, 
+		 struct proc *p);
+
 #ifdef SC_SPLASH_SCREEN
-void splash(int);
-int splash_load(void);
-int splash_unload(void);
+/* splash.c */
+void scsplash(int);
+int scsplash_load(scr_stat *scp);
+int scsplash_unload(scr_stat *scp);
 #endif
 
 #endif /* !_I386_ISA_SYSCONS_H_ */
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index 2d8c4a883224..8b20f861bacc 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
 # LINT -- config file for checking all the sources, tries to pull in
 #	as much of the source tree as it can.
 #
-#	$Id: LINT,v 1.464 1998/09/15 10:01:13 gibbs Exp $
+#	$Id: LINT,v 1.465 1998/09/15 11:44:43 phk Exp $
 #
 # NB: You probably don't want to try running a kernel built from this
 # file.  Instead, you should start from GENERIC, and add options from
@@ -803,6 +803,9 @@ options		SC_HISTORY_SIZE=200	# number of history buffer lines
 options		SC_DISABLE_REBOOT	# disable reboot key sequence
 # If the screen flickers badly when the mouse pointer is moved, try this.
 options		SC_BAD_FLICKER
+# To include support for VESA video modes
+# Dont use together with SMP!!
+options		VESA			# needs VM86 defined too!!
 
 #
 # `flags' for sc0:
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 2d8c4a883224..8b20f861bacc 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
 # LINT -- config file for checking all the sources, tries to pull in
 #	as much of the source tree as it can.
 #
-#	$Id: LINT,v 1.464 1998/09/15 10:01:13 gibbs Exp $
+#	$Id: LINT,v 1.465 1998/09/15 11:44:43 phk Exp $
 #
 # NB: You probably don't want to try running a kernel built from this
 # file.  Instead, you should start from GENERIC, and add options from
@@ -803,6 +803,9 @@ options		SC_HISTORY_SIZE=200	# number of history buffer lines
 options		SC_DISABLE_REBOOT	# disable reboot key sequence
 # If the screen flickers badly when the mouse pointer is moved, try this.
 options		SC_BAD_FLICKER
+# To include support for VESA video modes
+# Dont use together with SMP!!
+options		VESA			# needs VM86 defined too!!
 
 #
 # `flags' for sc0:
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index 5302df40d509..6a0847003632 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
-#	$Id: files.i386,v 1.202 1998/09/08 20:57:46 sos Exp $
+#	$Id: files.i386,v 1.203 1998/09/15 10:01:13 gibbs Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -240,6 +240,10 @@ i386/isa/spigot.c		optional	spigot	device-driver
 i386/isa/spkr.c			optional	speaker	device-driver
 i386/isa/stallion.c		optional	stl	device-driver
 i386/isa/syscons.c		optional	sc	device-driver
+i386/isa/scvidctl.c		optional	sc	device-driver
+i386/isa/scvesactl.c		optional	sc	device-driver
+i386/isa/videoio.c		optional	sc	device-driver
+i386/isa/vesa.c			optional	sc	device-driver
 i386/isa/tw.c			optional	tw	device-driver
 #i386/isa/ultra14f.c		optional	uha	device-driver
 i386/isa/wd.c			optional	wdc	device-driver
diff --git a/sys/i386/conf/options.i386 b/sys/i386/conf/options.i386
index c07d086cbdf4..21c45983b680 100644
--- a/sys/i386/conf/options.i386
+++ b/sys/i386/conf/options.i386
@@ -1,4 +1,4 @@
-#	$Id: options.i386,v 1.85 1998/09/08 18:09:50 brian Exp $
+#	$Id: options.i386,v 1.86 1998/09/15 10:01:14 gibbs Exp $
 
 BOUNCEPAGES		opt_bounce.h
 DISABLE_PSE
@@ -77,6 +77,8 @@ SC_DISABLE_REBOOT	opt_syscons.h
 SC_MOUSE_CHAR		opt_syscons.h
 SC_BAD_FLICKER		opt_syscons.h
 
+VESA			opt_vesa.h
+
 PSM_HOOKAPM		opt_psm.h
 PSM_RESETAFTERSUSPEND	opt_psm.h
 PSM_DEBUG		opt_psm.h
diff --git a/sys/i386/include/console.h b/sys/i386/include/console.h
index 7503746c8420..3373e608eabf 100644
--- a/sys/i386/include/console.h
+++ b/sys/i386/include/console.h
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: console.h,v 1.37 1998/07/06 06:29:06 imp Exp $
+ *	$Id: console.h,v 1.38 1998/08/03 11:30:28 yokota Exp $
  */
 
 #ifndef	_MACHINE_CONSOLE_H_
@@ -51,6 +51,7 @@
 #define KDGETLED	_IOR('K', 65, int)
 #define KDSETLED	_IO('K', 66 /*, int */)
 #define KDSETRAD	_IO('K', 67 /*, int */)
+#define KDRASTER	_IOW('K', 100, scr_size_t)
 
 #define GETFKEY		_IOWR('k', 0, fkeyarg_t)
 #define SETFKEY		_IOWR('k', 1, fkeyarg_t)
@@ -84,6 +85,11 @@
 #define GIO_FONT8x16	_IOR('c', 69, fnt16_t)
 #define CONS_GETINFO    _IOWR('c', 73, vid_info_t)
 #define CONS_GETVERS	_IOR('c', 74, int)
+#define CONS_CURRENTADP	_IOR('c', 100, int)
+#define CONS_ADPINFO	_IOWR('c', 101, video_adapter_t)
+#define CONS_MODEINFO	_IOWR('c', 102, video_info_t)
+#define CONS_FINDMODE	_IOWR('c', 103, video_info_t)
+#define CONS_SETWINORG	_IO('c', 104 /* u_int */) 
 
 /* CONS_SAVERMODE */
 #define CONS_LKM_SAVER	0
@@ -169,6 +175,7 @@ struct mouse_info {
 #define KD_TEXT0	0		/* ditto			*/
 #define KD_TEXT1	2		/* set text mode !restore fonts */
 #define KD_GRAPHICS	1		/* set graphics mode 		*/
+#define KD_PIXEL	3		/* set pixel mode		*/
 
 #define K_RAW		0		/* keyboard returns scancodes	*/
 #define K_XLATE		1		/* keyboard returns ascii 	*/
@@ -263,6 +270,55 @@ struct ssaver	{
 	long	time;
 };
 
+/* adapter infromation block */
+struct video_adapter {
+    int			va_index;
+    int			va_type;
+    int			va_flags;
+#define V_ADP_COLOR	(1<<0)
+#define V_ADP_MODECHANGE (1<<1)
+#define V_ADP_STATESAVE	(1<<2)
+#define V_ADP_STATELOAD	(1<<3)
+#define V_ADP_FONT	(1<<4)
+#define V_ADP_PALETTE	(1<<5)
+#define V_ADP_BORDER	(1<<6)
+#define V_ADP_VESA	(1<<7)
+    int			va_crtc_addr;
+    u_int		va_window;	/* virtual address */
+    size_t		va_window_size;
+    size_t		va_window_gran;
+    u_int		va_buffer;	/* virtual address */
+    size_t		va_buffer_size;
+    int			va_initial_mode;
+    int			va_initial_bios_mode;
+    int			va_mode;
+};
+
+#define V_ADP_PRIMARY		0
+#define V_ADP_SECONDARY		1
+
+/* video mode information block */
+struct video_info {
+    int			vi_mode;
+    int			vi_flags;
+#define V_INFO_COLOR	(1<<0)
+#define V_INFO_GRAPHICS	(1<<1)
+#define V_INFO_LENEAR	(1<<2)
+#define V_INFO_VESA	(1<<3)
+    int			vi_width;
+    int			vi_height;
+    int			vi_cwidth;
+    int			vi_cheight;
+    int			vi_depth;
+    int			vi_planes;
+    u_int		vi_window;	/* physical address */
+    size_t		vi_window_size;
+    size_t		vi_window_gran;
+    u_int		vi_buffer;	/* physical address */
+    size_t		vi_buffer_size;
+    /* XXX pixel format, memory model,... */
+};
+
 typedef struct accentmap accentmap_t;
 typedef struct fkeytab fkeytab_t;
 typedef struct fkeyarg fkeyarg_t;
@@ -273,6 +329,9 @@ typedef struct {char fnt8x8[8*256];} fnt8_t;
 typedef struct {char fnt8x14[14*256];} fnt14_t;
 typedef struct {char fnt8x16[16*256];} fnt16_t;
 typedef struct ssaver ssaver_t;
+typedef struct video_adapter video_adapter_t;
+typedef struct video_info video_info_t;
+typedef struct {int scr_size[3];} scr_size_t;
 
 /* defines for "special" keys (spcl bit set in keymap) */
 #define NOP		0x00		/* nothing (dead key)		*/
@@ -378,8 +437,6 @@ typedef struct ssaver ssaver_t;
 #define M_HGC_P1	0xe1	/* hercules graphics - page 1 @ B8000 */
 #define M_MCA_MODE	0xff	/* monochrome adapter mode */
 
-#define M_VESA_BASE	0x100	/* VESA mode number base */
-
 #define SW_PC98_80x25	_IO('S', M_PC98_80x25)
 #define SW_PC98_80x30	_IO('S', M_PC98_80x30)
 #define SW_B40x25 	_IO('S', M_B40x25)
@@ -421,4 +478,68 @@ typedef struct ssaver ssaver_t;
 #define SW_VGA_CG640	_IO('S', M_VGA_CG640)
 #define SW_VGA_MODEX	_IO('S', M_VGA_MODEX)
 
+#define M_VESA_BASE		0x100	/* VESA mode number base */
+
+#define M_VESA_CG640x400	0x100	/* 640x400, 256 color */
+#define M_VESA_CG640x480	0x101	/* 640x480, 256 color */
+#define M_VESA_800x600		0x102	/* 800x600, 16 color */
+#define M_VESA_CG800x600	0x103	/* 800x600, 256 color */
+#define M_VESA_1024x768		0x104	/* 1024x768, 16 color */
+#define M_VESA_CG1024x768	0x105	/* 1024x768, 256 color */
+#define M_VESA_1280x1024	0x106	/* 1280x1024, 16 color */
+#define M_VESA_CG1280x1024	0x107	/* 1280x1024, 256 color */
+#define M_VESA_C80x60		0x108	/* 8x8 font */
+#define M_VESA_C132x25		0x109	/* 8x16 font */
+#define M_VESA_C132x43		0x10a	/* 8x14 font */
+#define M_VESA_C132x50		0x10b	/* 8x8 font */
+#define M_VESA_C132x60		0x10c	/* 8x8 font */
+#define M_VESA_32K_320		0x10d	/* 320x200, 5:5:5 */
+#define M_VESA_64K_320		0x10e	/* 320x200, 5:6:5 */
+#define M_VESA_FULL_320		0x10f	/* 320x200, 8:8:8 */
+#define M_VESA_32K_640		0x110	/* 640x480, 5:5:5 */
+#define M_VESA_64K_640		0x111	/* 640x480, 5:6:5 */
+#define M_VESA_FULL_640		0x112	/* 640x480, 8:8:8 */
+#define M_VESA_32K_800		0x113	/* 800x600, 5:5:5 */
+#define M_VESA_64K_800		0x114	/* 800x600, 5:6:5 */
+#define M_VESA_FULL_800		0x115	/* 800x600, 8:8:8 */
+#define M_VESA_32K_1024		0x116	/* 1024x768, 5:5:5 */
+#define M_VESA_64K_1024		0x117	/* 1024x768, 5:6:5 */
+#define M_VESA_FULL_1024	0x118	/* 1024x768, 8:8:8 */
+#define M_VESA_32K_1280		0x119	/* 1280x1024, 5:5:5 */
+#define M_VESA_64K_1280		0x11a	/* 1280x1024, 5:6:5 */
+#define M_VESA_FULL_1280	0x11b	/* 1280x1024, 8:8:8 */
+#define M_VESA_MODE_MAX		0x1ff
+#define M_VESA_USER		0x1ff
+
+#define SW_VESA_CG640x400	_IO('V', M_VESA_CG640x400 - M_VESA_BASE)
+#define SW_VESA_CG640x480	_IO('V', M_VESA_CG640x480 - M_VESA_BASE)
+#define SW_VESA_800x600		_IO('V', M_VESA_800x600 - M_VESA_BASE)
+#define SW_VESA_CG800x600	_IO('V', M_VESA_CG800x600 - M_VESA_BASE)
+#define SW_VESA_1024x768	_IO('V', M_VESA_1024x768 - M_VESA_BASE)
+#define SW_VESA_CG1024x768	_IO('V', M_VESA_CG1024x768 - M_VESA_BASE)
+#define SW_VESA_1280x1024	_IO('V', M_VESA_1280x1024 - M_VESA_BASE)
+#define SW_VESA_CG1280x1024	_IO('V', M_VESA_CG1280x1024 - M_VESA_BASE)
+#define SW_VESA_C80x60		_IO('V', M_VESA_C80x60 - M_VESA_BASE)
+#define SW_VESA_C132x25		_IO('V', M_VESA_C132x25 - M_VESA_BASE)
+#define SW_VESA_C132x43		_IO('V', M_VESA_C132x43 - M_VESA_BASE)
+#define SW_VESA_C132x50		_IO('V', M_VESA_C132x50 - M_VESA_BASE)
+#define SW_VESA_C132x60		_IO('V', M_VESA_C132x60 - M_VESA_BASE)
+#define SW_VESA_32K_320		_IO('V', M_VESA_32K_320 - M_VESA_BASE)
+#define SW_VESA_64K_320		_IO('V', M_VESA_64K_320 - M_VESA_BASE)
+#define SW_VESA_FULL_320	_IO('V', M_VESA_FULL_320 - M_VESA_BASE)
+#define SW_VESA_32K_640		_IO('V', M_VESA_32K_640 - M_VESA_BASE)
+#define SW_VESA_64K_640		_IO('V', M_VESA_64K_640 - M_VESA_BASE)
+#define SW_VESA_FULL_640	_IO('V', M_VESA_FULL_640 - M_VESA_BASE)
+#define SW_VESA_32K_800		_IO('V', M_VESA_32K_800 - M_VESA_BASE)
+#define SW_VESA_64K_800		_IO('V', M_VESA_64K_800 - M_VESA_BASE)
+#define SW_VESA_FULL_800	_IO('V', M_VESA_FULL_800 - M_VESA_BASE)
+#define SW_VESA_32K_1024	_IO('V', M_VESA_32K_1024 - M_VESA_BASE)
+#define SW_VESA_64K_1024	_IO('V', M_VESA_64K_1024 - M_VESA_BASE)
+#define SW_VESA_FULL_1024	_IO('V', M_VESA_FULL_1024 - M_VESA_BASE)
+#define SW_VESA_32K_1280	_IO('V', M_VESA_32K_1280 - M_VESA_BASE)
+#define SW_VESA_64K_1280	_IO('V', M_VESA_64K_1280 - M_VESA_BASE)
+#define SW_VESA_FULL_1280	_IO('V', M_VESA_FULL_1280 - M_VESA_BASE)
+#define SW_VESA_USER		_IO('V', M_VESA_USER - M_VESA_BASE)
+
 #endif /* !_MACHINE_CONSOLE_H_ */
+
diff --git a/sys/i386/include/pc/vesa.h b/sys/i386/include/pc/vesa.h
new file mode 100644
index 000000000000..4fa38eee14b3
--- /dev/null
+++ b/sys/i386/include/pc/vesa.h
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#ifndef _MACHINE_PC_VESA_H
+#define _MACHINE_PC_VESA_H
+
+struct vesa_info
+{
+    /* mandatory fields */
+    u_int8_t		v_sig[4] __attribute__ ((packed));	/* VESA */
+    u_int16_t		v_version __attribute__ ((packed));	/* ver in BCD */
+    u_int32_t		v_oemstr __attribute__ ((packed));	/* OEM string */
+    u_int32_t		v_flags __attribute__ ((packed));	/* flags */
+#define V_DAC8		(1<<0)
+#define V_NONVGA	(1<<1)
+#define V_SNOW		(1<<2)
+    u_int32_t		v_modetable __attribute__ ((packed));	/* modes */
+    u_int16_t		v_memsize __attribute__ ((packed));	/* in 64K */
+    /* 2.0 */
+    u_int16_t		v_revision __attribute__ ((packed));	/* software rev */
+    u_int32_t		v_venderstr __attribute__ ((packed));	/* vender */
+    u_int32_t		v_prodstr __attribute__ ((packed));	/* product name */
+    u_int32_t		v_revstr __attribute__ ((packed));	/* product rev */
+};
+
+struct vesa_mode 
+{
+    /* mandatory fields */
+    u_int16_t		v_modeattr;
+#define V_MODESUPP	(1<<0)	/* VESA mode attributes */
+#define V_MODEOPTINFO	(1<<1)
+#define V_MODEBIOSOUT	(1<<2)
+#define V_MODECOLOR	(1<<3)
+#define V_MODEGRAPHICS	(1<<4)
+#define V_MODENONVGA	(1<<5)
+#define V_MODENONBANK	(1<<6)
+#define V_MODELFB	(1<<7)
+#define V_MODEVESA	(1<<16)	/* Private attributes */
+    u_int8_t		v_waattr;
+    u_int8_t		v_wbattr;
+#define V_WATTREXIST	(1<<0)
+#define V_WATTRREAD	(1<<1)
+#define V_WATTRWRITE	(1<<2)
+    u_int16_t		v_wgran;
+    u_int16_t		v_wsize;
+    u_int16_t		v_waseg;
+    u_int16_t		v_wbseg;
+    u_int32_t		v_posfunc;
+    u_int16_t		v_bpscanline;
+    /* fields optional for 1.0/1.1 implementations */
+    u_int16_t		v_width;
+    u_int16_t		v_height;
+    u_int8_t		v_cwidth;
+    u_int8_t		v_cheight;
+    u_int8_t		v_planes;
+    u_int8_t		v_bpp;
+    u_int8_t		v_banks;
+    u_int8_t		v_memmodel;
+#define V_MMTEXT	0
+#define V_MMCGA		1
+#define V_MMHGC		2
+#define V_MMEGA		3
+#define V_MMPACKED	4
+#define V_MMSEQU256	5
+#define V_MMDIRCOLOR	6
+#define V_MMYUV		7
+    u_int8_t		v_banksize;
+    u_int8_t		v_ipages;
+    u_int8_t		v_reserved0;
+    /* fields for 1.2+ implementations */
+    u_int8_t		v_redmasksize;
+    u_int8_t		v_redfieldpos;
+    u_int8_t		v_greenmasksize;
+    u_int8_t		v_greenfieldpos;
+    u_int8_t		v_bluemasksize;
+    u_int8_t		v_bluefieldpos;
+    u_int8_t		v_resmasksize;
+    u_int8_t		v_resfieldpos;
+    u_int8_t		v_dircolormode;
+    /* 2.0 implementations */
+    u_int32_t		v_lfb;
+    u_int32_t		v_offscreen;
+    u_int8_t		v_offscreensize;
+};
+
+#ifdef KERNEL
+
+#define VESA_MODE(x)	((x) >= M_VESA_BASE)
+
+int vesa_load_ioctl(void);
+int vesa_unload_ioctl(void);
+
+#ifndef VESA_MODULE
+int vesa_load(void);
+#endif
+
+#endif /* KERNEL */
+
+#endif /* !_MACHINE_PC_VESA_H */
diff --git a/sys/i386/isa/kbdtables.h b/sys/i386/isa/kbdtables.h
index d36b39a33e7a..61376f48b919 100644
--- a/sys/i386/isa/kbdtables.h
+++ b/sys/i386/isa/kbdtables.h
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1992-1995 S�ren Schmidt
+ * Copyright (c) 1992-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: kbdtables.h,v 1.39 1998/01/28 08:45:18 yokota Exp $
+ *	$Id$
  */
 
 #define SET8 0x80       	/* set eight bit on */
diff --git a/sys/i386/isa/pcaudio.c b/sys/i386/isa/pcaudio.c
index 25b5237a76dc..e2b0c6557835 100644
--- a/sys/i386/isa/pcaudio.c
+++ b/sys/i386/isa/pcaudio.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1994 S�ren Schmidt
+ * Copyright (c) 1994-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: pcaudio.c,v 1.41 1998/06/07 17:10:48 dfr Exp $
+ *	$Id$
  */
 
 #include "pca.h"
diff --git a/sys/i386/isa/scvesactl.c b/sys/i386/isa/scvesactl.c
new file mode 100644
index 000000000000..9678177d4011
--- /dev/null
+++ b/sys/i386/isa/scvesactl.c
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "sc.h"
+#include "opt_vesa.h"
+#include "opt_vm86.h"
+
+#if (NSC > 0 && defined(VESA) && defined(VM86)) || defined(VESA_MODULE)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+
+#include <machine/apm_bios.h>
+#include <machine/console.h>
+#include <machine/pc/vesa.h>
+
+#include <i386/isa/videoio.h>
+#include <i386/isa/syscons.h>
+
+static int (*prev_user_ioctl)(dev_t dev, int cmd, caddr_t data, int flag, 
+			      struct proc *p);
+
+extern struct tty *scdevtotty(dev_t dev);
+
+int
+vesa_ioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
+{
+	scr_stat *scp;
+	struct tty *tp;
+	video_info_t info;
+	video_adapter_t *adp;
+	int mode;
+	int error;
+	int s;
+
+	tp = scdevtotty(dev);
+	if (!tp)
+		return ENXIO;
+	scp = sc_get_scr_stat(tp->t_dev);
+
+	switch (cmd) {
+	case SW_VESA_USER:
+
+		mode = (int)data;
+		if ((*biosvidsw.get_info)(scp->adp, mode, &info))
+			return ENODEV;
+		if (info.vi_flags & V_INFO_GRAPHICS)
+			goto vesa_graphics;
+		else
+			goto vesa_text;
+
+	/* text modes */
+	case SW_VESA_C80x60:
+	case SW_VESA_C132x25:
+	case SW_VESA_C132x43:
+	case SW_VESA_C132x50:
+	case SW_VESA_C132x60:
+		adp = get_adapter(scp);
+		if (!(adp->va_flags & V_ADP_MODECHANGE))
+			return ENODEV;
+		mode = (cmd & 0xff) + M_VESA_BASE;
+vesa_text:
+		return sc_set_text_mode(scp, tp, mode, 0, 0, 0);
+
+	/* graphics modes */
+	case SW_VESA_32K_320: 	case SW_VESA_64K_320: 
+	case SW_VESA_FULL_320:
+
+	case SW_VESA_CG640x400:
+
+	case SW_VESA_CG640x480:
+	case SW_VESA_32K_640:	case SW_VESA_64K_640:
+	case SW_VESA_FULL_640:
+
+	case SW_VESA_800x600:	case SW_VESA_CG800x600:
+	case SW_VESA_32K_800:	case SW_VESA_64K_800:
+	case SW_VESA_FULL_800:
+
+	case SW_VESA_1024x768:	case SW_VESA_CG1024x768:
+	case SW_VESA_32K_1024:	case SW_VESA_64K_1024:
+	case SW_VESA_FULL_1024:
+
+	case SW_VESA_1280x1024:	case SW_VESA_CG1280x1024:
+	case SW_VESA_32K_1280:	case SW_VESA_64K_1280:
+	case SW_VESA_FULL_1280:
+		adp = get_adapter(scp);
+		if (!(adp->va_flags & V_ADP_MODECHANGE))
+			return ENODEV;
+		mode = (cmd & 0xff) + M_VESA_BASE;
+vesa_graphics:
+		return sc_set_graphics_mode(scp, tp, mode);
+	}
+
+	if (prev_user_ioctl)
+		return (*prev_user_ioctl)(dev, cmd, data, flag, p);
+	else
+		return ENOIOCTL;
+}
+
+int
+vesa_load_ioctl(void)
+{
+	if (prev_user_ioctl)
+		return EBUSY;
+	prev_user_ioctl = sc_user_ioctl;
+	sc_user_ioctl = vesa_ioctl;
+	return 0;
+}
+
+int
+vesa_unload_ioctl(void)
+{
+	if (sc_user_ioctl != vesa_ioctl)
+		return EBUSY;
+	sc_user_ioctl = prev_user_ioctl;
+	prev_user_ioctl = NULL;
+	return 0;
+}
+
+#endif /* (NSC > 0 && VESA && VM86) || VESA_MODULE */
diff --git a/sys/i386/isa/scvidctl.c b/sys/i386/isa/scvidctl.c
new file mode 100644
index 000000000000..464933edb112
--- /dev/null
+++ b/sys/i386/isa/scvidctl.c
@@ -0,0 +1,486 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "sc.h"
+#include "opt_syscons.h"
+
+#if NSC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+
+#include <machine/apm_bios.h>
+#include <machine/console.h>
+
+#include <i386/isa/videoio.h>
+#include <i386/isa/syscons.h>
+
+/* video ioctl */
+
+extern scr_stat *cur_console;
+extern u_short *Crtat;
+extern int fonts_loaded;
+extern int sc_history_size;
+extern u_char palette[];
+
+int
+sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
+		 int fontsize)
+{
+    video_adapter_t *adp;
+    video_info_t info;
+    int error;
+    int s;
+    int i;
+
+    if ((*biosvidsw.get_info)(scp->adp, mode, &info))
+	return ENODEV;
+    adp = get_adapter(scp);
+ 
+    /* adjust argument values */
+    if (fontsize <= 0)
+	fontsize = info.vi_cheight;
+    if (fontsize < 14) {
+	fontsize = 8;
+	if (!(fonts_loaded & FONT_8))
+	    return EINVAL;
+    } else if (fontsize >= 16) {
+	fontsize = 16;
+	if (!(fonts_loaded & FONT_16))
+	    return EINVAL;
+    } else {
+	fontsize = 14;
+	if (!(fonts_loaded & FONT_14))
+	    return EINVAL;
+    }
+    if ((xsize <= 0) || (xsize > info.vi_width))
+	xsize = info.vi_width;
+    if ((ysize <= 0) || (ysize > info.vi_height))
+	ysize = info.vi_height;
+
+    /* stop screen saver, etc */
+    s = spltty();
+    if ((error = sc_clean_up(scp))) {
+	splx(s);
+	return error;
+    }
+
+    /* set up scp */
+    if (scp->history != NULL)
+	i = imax(scp->history_size / scp->xsize 
+		 - imax(sc_history_size, scp->ysize), 0);
+    else
+	i = 0;
+    /*
+     * This is a kludge to fend off scrn_update() while we
+     * muck around with scp. XXX
+     */
+    scp->status |= UNKNOWN_MODE;
+    scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE);
+    scp->mode = mode;
+    scp->font_size = fontsize;
+    scp->xsize = xsize;
+    scp->ysize = ysize;
+    scp->xpixel = scp->xsize*8;
+    scp->ypixel = scp->ysize*fontsize;
+
+    /* allocate buffers */
+    sc_alloc_scr_buffer(scp, TRUE, TRUE);
+    if (ISMOUSEAVAIL(adp->va_flags))
+	sc_alloc_cut_buffer(scp, FALSE);
+    sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
+    splx(s);
+
+    if (scp == cur_console)
+	set_mode(scp);
+    scp->status &= ~UNKNOWN_MODE;
+
+    if (tp == NULL)
+	return 0;
+    if (tp->t_winsize.ws_col != scp->xsize
+	|| tp->t_winsize.ws_row != scp->ysize) {
+	tp->t_winsize.ws_col = scp->xsize;
+	tp->t_winsize.ws_row = scp->ysize;
+	pgsignal(tp->t_pgrp, SIGWINCH, 1);
+    }
+
+    return 0;
+}
+
+int
+sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
+{
+    video_adapter_t *adp;
+    video_info_t info;
+    int error;
+    int s;
+
+    if ((*biosvidsw.get_info)(scp->adp, mode, &info))
+	return ENODEV;
+    adp = get_adapter(scp);
+
+    /* stop screen saver, etc */
+    s = spltty();
+    if ((error = sc_clean_up(scp))) {
+	splx(s);
+	return error;
+    }
+
+    /* set up scp */
+    scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE);
+    scp->status &= ~PIXEL_MODE;
+    scp->mode = mode;
+    scp->xpixel = info.vi_width;
+    scp->ypixel = info.vi_height;
+    scp->xsize = info.vi_width/8;
+    scp->ysize = info.vi_height/info.vi_cheight;
+    scp->font_size = FONT_NONE;
+    /* move the mouse cursor at the center of the screen */
+    sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
+    splx(s);
+
+    if (scp == cur_console)
+	set_mode(scp);
+    /* clear_graphics();*/
+    scp->status &= ~UNKNOWN_MODE;
+
+    if (tp == NULL)
+	return 0;
+    if (tp->t_winsize.ws_xpixel != scp->xpixel
+	|| tp->t_winsize.ws_ypixel != scp->ypixel) {
+	tp->t_winsize.ws_xpixel = scp->xpixel;
+	tp->t_winsize.ws_ypixel = scp->ypixel;
+	pgsignal(tp->t_pgrp, SIGWINCH, 1);
+    }
+
+    return 0;
+}
+
+int
+sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 
+		  int fontsize)
+{
+    video_adapter_t *adp;
+    video_info_t info;
+    int error;
+    int s;
+    int i;
+
+    if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
+	return ENODEV;		/* this shouldn't happen */
+    adp = get_adapter(scp);
+
+#ifdef SC_VIDEO_DEBUG
+    if (scp->scr_buf != NULL) {
+	printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n",
+	       scp->mode, xsize, ysize, fontsize);
+    }
+#endif
+
+    /* adjust argument values */
+    if ((fontsize <= 0) || (fontsize == FONT_NONE))
+	fontsize = info.vi_cheight;
+    if (fontsize < 14) {
+	fontsize = 8;
+	if (!(fonts_loaded & FONT_8))
+	    return EINVAL;
+    } else if (fontsize >= 16) {
+	fontsize = 16;
+	if (!(fonts_loaded & FONT_16))
+	    return EINVAL;
+    } else {
+	fontsize = 14;
+	if (!(fonts_loaded & FONT_14))
+	    return EINVAL;
+    }
+    if (xsize <= 0)
+	xsize = info.vi_width/8;
+    if (ysize <= 0)
+	ysize = info.vi_height/fontsize;
+
+#ifdef SC_VIDEO_DEBUG
+    if (scp->scr_buf != NULL) {
+	printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n",
+	       scp->mode, xsize, ysize, fontsize);
+	printf("set_pixel_mode(): Crtat:%x, %dx%d, xoff:%d, yoff:%d\n",
+	       Crtat, info.vi_width, info.vi_height, 
+	       (info.vi_width/8 - xsize)/2,
+	       (info.vi_height/fontsize - ysize)/2);
+    }
+#endif
+
+    /* stop screen saver, etc */
+    s = spltty();
+    if ((error = sc_clean_up(scp))) {
+	splx(s);
+	return error;
+    }
+
+    /* set up scp */
+    if (scp->history != NULL)
+	i = imax(scp->history_size / scp->xsize 
+		 - imax(sc_history_size, scp->ysize), 0);
+    else
+	i = 0;
+    scp->status |= (UNKNOWN_MODE | PIXEL_MODE);
+    scp->status &= ~(GRAPHICS_MODE | MOUSE_ENABLED);
+    scp->xsize = xsize;
+    scp->ysize = ysize;
+    scp->font_size = fontsize;
+    scp->xoff = (scp->xpixel/8 - xsize)/2;
+    scp->yoff = (scp->ypixel/fontsize - ysize)/2;
+
+    /* allocate buffers */
+    sc_alloc_scr_buffer(scp, TRUE, TRUE);
+    if (ISMOUSEAVAIL(adp->va_flags))
+	sc_alloc_cut_buffer(scp, FALSE);
+    sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
+    splx(s);
+
+    /* FIXME */
+    if (scp == cur_console)
+	bzero(Crtat, scp->xpixel*scp->ypixel/8);
+
+    scp->status &= ~UNKNOWN_MODE;
+
+#ifdef SC_VIDEO_DEBUG
+    printf("set_pixel_mode(): status:%x\n", scp->status);
+#endif
+
+    if (tp == NULL)
+	return 0;
+    if (tp->t_winsize.ws_col != scp->xsize
+	|| tp->t_winsize.ws_row != scp->ysize) {
+	tp->t_winsize.ws_col = scp->xsize;
+	tp->t_winsize.ws_row = scp->ysize;
+	pgsignal(tp->t_pgrp, SIGWINCH, 1);
+    }
+
+    return 0;
+}
+
+int
+sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+    scr_stat *scp;
+    video_adapter_t *adp;
+    int error;
+    int s;
+
+    scp = sc_get_scr_stat(tp->t_dev);
+
+    switch (cmd) {
+
+    case CONS_CURRENT:  	/* get current adapter type */
+	adp = get_adapter(scp);
+	*(int *)data = adp->va_type;
+	return 0;
+
+    case CONS_CURRENTADP:	/* get current adapter index */
+	*(int *)data = scp->adp;
+	return 0;
+
+    case CONS_ADPINFO:		/* adapter information */
+	adp = (*biosvidsw.adapter)(((video_adapter_t *)data)->va_index);
+	if (adp == NULL)
+	    return ENODEV;
+	bcopy(adp, data, sizeof(*adp));
+	return 0;
+
+    case CONS_GET:      	/* get current video mode */
+	*(int *)data = scp->mode;
+	return 0;
+
+    case CONS_MODEINFO:		/* get mode information */
+	return ((*biosvidsw.get_info)(scp->adp, 
+		    ((video_info_t *)data)->vi_mode, (video_info_t *)data) 
+		? ENODEV : 0);
+
+    case CONS_FINDMODE:		/* find a matching video mode */
+	return ((*biosvidsw.query_mode)(scp->adp, (video_info_t *)data) 
+		? ENODEV : 0);
+
+    case CONS_SETWINORG:
+	return ((*biosvidsw.set_win_org)(scp->adp, *(u_int *)data) 
+		   ? ENODEV : 0);
+
+    /* VGA TEXT MODES */
+    case SW_VGA_C40x25:
+    case SW_VGA_C80x25: case SW_VGA_M80x25:
+    case SW_VGA_C80x30: case SW_VGA_M80x30:
+    case SW_VGA_C80x50: case SW_VGA_M80x50:
+    case SW_VGA_C80x60: case SW_VGA_M80x60:
+    case SW_B40x25:     case SW_C40x25:
+    case SW_B80x25:     case SW_C80x25:
+    case SW_ENH_B40x25: case SW_ENH_C40x25:
+    case SW_ENH_B80x25: case SW_ENH_C80x25:
+    case SW_ENH_B80x43: case SW_ENH_C80x43:
+    case SW_EGAMONO80x25:
+	adp = get_adapter(scp);
+	if (!(adp->va_flags & V_ADP_MODECHANGE))
+ 	    return ENODEV;
+	return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0);
+
+    /* GRAPHICS MODES */
+    case SW_BG320:     case SW_BG640:
+    case SW_CG320:     case SW_CG320_D:   case SW_CG640_E:
+    case SW_CG640x350: case SW_ENH_CG640:
+    case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:
+    case SW_VGA_MODEX:
+	adp = get_adapter(scp);
+	if (!(adp->va_flags & V_ADP_MODECHANGE))
+	    return ENODEV;
+	return sc_set_graphics_mode(scp, tp, cmd & 0xff);
+
+    case KDSETMODE:     	/* set current mode of this (virtual) console */
+	switch (*data) {
+	case KD_TEXT:   	/* switch to TEXT (known) mode */
+	    /*
+	     * If scp->mode is of graphics modes, we don't know which
+	     * text mode to switch back to...
+	     */
+	    if (scp->status & GRAPHICS_MODE)
+		return EINVAL;
+	    /* restore fonts & palette ! */
+#if 0
+	    adp = get_adapter(scp);
+	    if (ISFONTAVAIL(adp->va_flags) 
+		&& !(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
+		/*
+		 * FONT KLUDGE
+		 * Don't load fonts for now... XXX
+		 */
+		if (fonts_loaded & FONT_8)
+		    copy_font(scp, LOAD, 8, font_8);
+		if (fonts_loaded & FONT_14)
+		    copy_font(scp, LOAD, 14, font_14);
+		if (fonts_loaded & FONT_16)
+		    copy_font(scp, LOAD, 16, font_16);
+	    }
+#endif
+	    load_palette(scp, palette);
+
+	    /* move hardware cursor out of the way */
+	    (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
+
+	    /* FALL THROUGH */
+
+	case KD_TEXT1:  	/* switch to TEXT (known) mode */
+	    /*
+	     * If scp->mode is of graphics modes, we don't know which
+	     * text/pixel mode to switch back to...
+	     */
+	    if (scp->status & GRAPHICS_MODE)
+		return EINVAL;
+	    s = spltty();
+	    if ((error = sc_clean_up(scp))) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= UNKNOWN_MODE;
+	    splx(s);
+	    /* no restore fonts & palette */
+	    if (scp == cur_console) {
+		set_mode(scp);
+		/* FIXME */
+		if (scp->status & PIXEL_MODE)
+		    bzero(Crtat, scp->xpixel*scp->ypixel/8);
+	    }
+	    sc_clear_screen(scp);
+	    scp->status &= ~UNKNOWN_MODE;
+	    return 0;
+
+	case KD_PIXEL:		/* pixel (raster) display */
+	    if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
+		return EINVAL;
+	    if (!(scp->status & PIXEL_MODE))
+		return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 
+					 scp->font_size);
+	    s = spltty();
+	    if ((error = sc_clean_up(scp))) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= (UNKNOWN_MODE | PIXEL_MODE);
+	    splx(s);
+	    if (scp == cur_console) {
+		set_mode(scp);
+		load_palette(scp, palette);
+		/* FIXME */
+		bzero(Crtat, scp->xpixel*scp->ypixel/8);
+	    }
+	    sc_clear_screen(scp);
+	    scp->status &= ~UNKNOWN_MODE;
+	    return 0;
+
+	case KD_GRAPHICS:	/* switch to GRAPHICS (unknown) mode */
+	    s = spltty();
+	    if ((error = sc_clean_up(scp))) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= UNKNOWN_MODE;
+	    splx(s);
+	    return 0;
+
+	default:
+	    return EINVAL;
+	}
+	/* NOT REACHED */
+
+    case KDRASTER:		/* set pixel (raster) display mode */
+	if (ISUNKNOWNSC(scp) || ISTEXTSC(scp))
+	    return ENODEV;
+	return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 
+				 ((int *)data)[2]);
+
+    case KDGETMODE:     	/* get current mode of this (virtual) console */
+	/* 
+	 * From the user program's point of view, KD_PIXEL is the same 
+	 * as KD_TEXT... 
+	 */
+	*data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT;
+	return 0;
+
+    case KDSBORDER:     	/* set border color of this (virtual) console */
+	scp->border = *data;
+	if (scp == cur_console)
+	    set_border(cur_console, scp->border);
+	return 0;
+    }
+
+    return ENOIOCTL;
+}
+
+#endif /* NSC > 0 */
diff --git a/sys/i386/isa/syscons.c b/sys/i386/isa/syscons.c
index ebc243f52ba7..50e0f199c0fb 100644
--- a/sys/i386/isa/syscons.c
+++ b/sys/i386/isa/syscons.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1992-1997 S�ren Schmidt
+ * Copyright (c) 1992-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,13 +25,15 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *  $Id: syscons.c,v 1.276 1998/08/23 08:26:41 bde Exp $
+ *	$Id$
  */
 
 #include "sc.h"
 #include "apm.h"
 #include "opt_ddb.h"
 #include "opt_devfs.h"
+#include "opt_vesa.h"
+#include "opt_vm86.h"
 #include "opt_syscons.h"
 
 #if NSC > 0
@@ -57,9 +59,9 @@
 #include <machine/psl.h>
 #include <machine/frame.h>
 #include <machine/pc/display.h>
+#include <machine/pc/vesa.h>
 #include <machine/apm_bios.h>
 #include <machine/random.h>
-#include <machine/bootinfo.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -70,6 +72,7 @@
 #include <i386/isa/timerreg.h>
 #include <i386/isa/kbdtables.h>
 #include <i386/isa/kbdio.h>
+#include <i386/isa/videoio.h>
 #include <i386/isa/syscons.h>
 
 #if !defined(MAXCONS)
@@ -96,11 +99,6 @@
 #define COLD 0
 #define WARM 1
 
-#define VESA_MODE(x)		((x) >= M_VESA_BASE)
-
-#define MODE_MAP_SIZE		(M_VGA_CG320 + 1)
-#define MODE_PARAM_SIZE		64
-
 #define DEFAULT_BLANKTIME	(5*60)		/* 5 minutes */
 #define MAX_BLANKTIME		(7*24*60*60)	/* 7 days!? */
 
@@ -159,6 +157,7 @@ static  int        	blinkrate = 0;
 	u_int       	crtc_addr = MONO_BASE;
 	char		crtc_type = KD_MONO;
 	char        	crtc_vga = FALSE;
+static	int		adp_flags = 0;
 static  u_char      	shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
 static  u_char		accents = 0;
 static  u_char      	nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
@@ -172,7 +171,7 @@ static	int		run_scrn_saver = FALSE;	/* should run the saver? */
 static	int		scrn_idle = FALSE;	/* about to run the saver */
 	u_char      	scr_map[256];
 	u_char      	scr_rmap[256];
-	char        	*video_mode_ptr = NULL;
+static	int		initial_video_mode;	/* initial video mode # */
 static	int		bios_video_mode;	/* video mode # set by BIOS */
 	int     	fonts_loaded = 0
 #ifdef STD8X16FONT
@@ -180,19 +179,15 @@ static	int		bios_video_mode;	/* video mode # set by BIOS */
 #endif
 	;
 
-	char        	font_8[256*8];
-	char		font_14[256*14];
+	u_char		font_8[256*8];
+	u_char		font_14[256*14];
 #ifdef STD8X16FONT
 extern
 #endif
-	unsigned char	font_16[256*16];
-	char        	palette[256*3];
-static  char		*mode_map[MODE_MAP_SIZE];
-static  char		vgaregs[MODE_PARAM_SIZE];
-static  char		vgaregs2[MODE_PARAM_SIZE];
-static  int		rows_offset = 1;
-static	char 		*cut_buffer;
-static	int		cut_buffer_size;
+	u_char		font_16[256*16];
+	u_char        	palette[256*3];
+static	u_char 		*cut_buffer = NULL;
+static	int		cut_buffer_size = 0;
 static	int		mouse_level = 0;	/* sysmouse protocol level */
 static	mousestatus_t	mouse_status = { 0, 0, 0, 0, 0, 0 };
 static  u_short 	mouse_and_mask[16] = {
@@ -208,13 +203,14 @@ static  u_short 	mouse_or_mask[16] = {
 				0x0000, 0x0000, 0x0000, 0x0000
 			};
 
-static int		extra_history_size = 
+	int		sc_history_size = SC_HISTORY_SIZE;
+static	int		extra_history_size = 
 			    SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
 
 static void    		none_saver(int blank) { }
 static void    		(*current_saver)(int blank) = none_saver;
 static void    		(*default_saver)(int blank) = none_saver;
-int  			(*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
+	int  		(*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
 					 int flag, struct proc *p) = NULL;
 
 static int		sticky_splash = FALSE;
@@ -233,8 +229,6 @@ static struct tty     	sccons[MAXCONS+2];
 #endif
 #define SC_MOUSE 	128
 #define SC_CONSOLE	255
-#define MONO_BUF    	pa_to_va(0xB0000)
-#define CGA_BUF     	pa_to_va(0xB8000)
 u_short         	*Crtat;
 static const int	nsccons = MAXCONS+2;
 
@@ -243,9 +237,6 @@ static const int	nsccons = MAXCONS+2;
     + (offset)) % (scp->history_size)))
 #define ISSIGVALID(sig)	((sig) > 0 && (sig) < NSIG)
 
-/* this should really be in `rtc.h' */
-#define RTC_EQUIPMENT		0x14
-
 /* prototypes */
 static int scattach(struct isa_device *dev);
 static int scparam(struct tty *tp, struct termios *t);
@@ -256,30 +247,26 @@ static void scstart(struct tty *tp);
 static void scmousestart(struct tty *tp);
 static void scinit(void);
 static void scshutdown(int howto, void *arg);
-static void map_mode_table(char *map[], char *table, int max);
-static int map_mode_num(int mode);
-static char *get_mode_param(scr_stat *scp, int mode);
 static u_int scgetc(u_int flags);
 #define SCGETC_CN	1
 #define SCGETC_NONBLOCK	2
 static void sccnupdate(scr_stat *scp);
-static scr_stat *get_scr_stat(dev_t dev);
 static scr_stat *alloc_scp(void);
 static void init_scp(scr_stat *scp);
 static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark);
 static int get_scr_num(void);
 static timeout_t scrn_timer;
 static void scrn_update(scr_stat *scp, int show_cursor);
+static void scrn_saver(void (*saver)(int), int blank);
 static void stop_scrn_saver(void (*saver)(int));
 static int wait_scrn_saver_stop(void);
-static void clear_screen(scr_stat *scp);
 static int switch_scr(scr_stat *scp, u_int next_scr);
 static void exchange_scr(void);
-static void move_crsr(scr_stat *scp, int x, int y);
 static void scan_esc(scr_stat *scp, u_char c);
+static void ansi_put(scr_stat *scp, u_char *buf, int len);
 static void draw_cursor_image(scr_stat *scp); 
 static void remove_cursor_image(scr_stat *scp); 
-static void ansi_put(scr_stat *scp, u_char *buf, int len);
+static void move_crsr(scr_stat *scp, int x, int y);
 static u_char *get_fstr(u_int c, u_int *len);
 static void history_to_screen(scr_stat *scp);
 static int history_up_line(scr_stat *scp);
@@ -287,16 +274,6 @@ static int history_down_line(scr_stat *scp);
 static int mask2attr(struct term_stat *term);
 static void set_keyboard(int command, int data);
 static void update_leds(int which);
-static void set_vgaregs(char *modetable);
-static void read_vgaregs(char *buf);
-#define COMP_IDENTICAL	0
-#define COMP_SIMILAR	1
-#define COMP_DIFFERENT	2
-static int comp_vgaregs(u_char *buf1, u_char *buf2);
-static void dump_vgaregs(u_char *buf);
-#define PARAM_BUFSIZE	6
-static void set_font_mode(u_char *buf);
-static void set_normal_mode(u_char *buf);
 static void set_destructive_cursor(scr_stat *scp);
 static void set_mouse_pos(scr_stat *scp);
 static int skip_spc_right(scr_stat *scp, u_short *p);
@@ -312,12 +289,11 @@ static void draw_mouse_image(scr_stat *scp);
 static void remove_mouse_image(scr_stat *scp); 
 static void draw_cutmarking(scr_stat *scp); 
 static void remove_cutmarking(scr_stat *scp); 
-static void save_palette(void);
 static void do_bell(scr_stat *scp, int pitch, int duration);
 static timeout_t blink_screen;
 #ifdef SC_SPLASH_SCREEN
-static void scsplash_init(void);
-static void scsplash(int show);
+static void scsplash_init(scr_stat *scp);
+static void scsplash_saver(int show);
 #define scsplash_stick(stick)		(sticky_splash = (stick))
 #else
 #define scsplash_stick(stick)
@@ -332,7 +308,7 @@ static	d_close_t	scclose;
 static	d_read_t	scread;
 static	d_write_t	scwrite;
 static	d_ioctl_t	scioctl;
-static	d_devtotty_t	scdevtotty;
+	d_devtotty_t	scdevtotty;
 static	d_mmap_t	scmmap;
 
 #define	CDEV_MAJOR	12
@@ -353,7 +329,7 @@ draw_cursor_image(scr_stat *scp)
     u_short cursor_image, *ptr = Crtat + (scp->cursor_pos - scp->scr_buf);
     u_short prev_image;
 
-    if (VESA_MODE(scp->mode)) {
+    if (ISPIXELSC(scp)) {
 	sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, 
 	  scp->cursor_pos - scp->scr_buf, 1);
 	return;
@@ -405,7 +381,7 @@ draw_cursor_image(scr_stat *scp)
 static void
 remove_cursor_image(scr_stat *scp)
 {
-    if (VESA_MODE(scp->mode))
+    if (ISPIXELSC(scp))
 	sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 
 	  scp->cursor_oldpos - scp->scr_buf, 0);
     else
@@ -436,6 +412,12 @@ scprobe(struct isa_device *dev)
 	    printf("sc%d: no video adapter is found.\n", dev->id_unit);
 	return (0);
     }
+    (*biosvidsw.diag)(bootverbose);
+#if defined(VESA) && defined(VM86)
+    if (vesa_load())
+	return FALSE;
+    (*biosvidsw.diag)(bootverbose);
+#endif
 
     sc_port = dev->id_iobase;
     if (sckbdprobe(dev->id_unit, dev->id_flags))
@@ -448,99 +430,24 @@ scprobe(struct isa_device *dev)
 static int
 scvidprobe(int unit, int flags)
 {
-    /* 
-     * XXX don't try to `printf' anything here, the console may not have 
-     * been configured yet. 
-     */
-    u_short volatile *cp;
-    u_short was;
-    u_int pa;
-    u_int segoff;
+    video_adapter_t *adp;
 
     /* do this test only once */
     if (init_done != COLD)
-	return (Crtat != 0);
+	return (crtc_type != -1);
 
-    /*
-     * Finish defaulting crtc variables for a mono screen.  Crtat is a
-     * bogus common variable so that it can be shared with pcvt, so it
-     * can't be statically initialized.  XXX.
-     */
-    Crtat = (u_short *)MONO_BUF;
-    crtc_type = KD_MONO;
-    /* If CGA memory seems to work, switch to color.  */
-    cp = (u_short *)CGA_BUF;
-    was = *cp;
-    *cp = (u_short) 0xA55A;
-    bios_video_mode = *(u_char *)pa_to_va(0x449);
-    if (bootinfo.bi_vesa == 0x102) {
-	bios_video_mode = bootinfo.bi_vesa;
-	Crtat  = (u_short *)pa_to_va(0xA0000);
-	crtc_addr = COLOR_BASE;
-	crtc_type = KD_VGA;
-        bzero(Crtat, 800*600/8);
-    } else if (*cp == 0xA55A) {
-	Crtat = (u_short *)CGA_BUF;
-	crtc_addr = COLOR_BASE;
-	crtc_type = KD_CGA;
-    } else {
-        cp = Crtat;
-	was = *cp;
-	*cp = (u_short) 0xA55A;
-	if (*cp != 0xA55A) {
-	    /* no screen at all, bail out */
-	    Crtat = 0;
-	    return FALSE;
-	}
-    }
-    *cp = was;
+    if ((*biosvidsw.init)() <= 0)
+	return FALSE;
+    if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL)
+	return FALSE;
 
-    if (!VESA_MODE(bios_video_mode)) {
-	/* 
-	 * Check rtc and BIOS date area.
-	 * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy
-	 * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are
-	 * zeros for EGA and VGA. However, the EGA/VGA BIOS will set 
-	 * these bits in BIOSDATA_EQUIPMENT according to the monitor
-	 * type detected.
-	 */
-	switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) {	/* bit 4 and 5 */
-	case 0: /* EGA/VGA, or nothing */
-	    crtc_type = KD_EGA;
-	    /* the color adapter may be in the 40x25 mode... XXX */
-	    break;
-	case 1: /* CGA 40x25 */
-	    /* switch to the 80x25 mode? XXX */
-	    /* FALL THROUGH */
-	case 2: /* CGA 80x25 */
-	    /* `crtc_type' has already been set... */
-	    /* crtc_type = KD_CGA; */
-	    break;
-	case 3: /* MDA */
-	    /* `crtc_type' has already been set... */
-	    /* crtc_type = KD_MONO; */
-	    break;
-	}
-
-	/* is this a VGA or higher ? */
-	outb(crtc_addr, 7);
-	if (inb(crtc_addr) == 7) {
-
-	    crtc_type = KD_VGA;
-	    crtc_vga = TRUE;
-	    read_vgaregs(vgaregs);
-
-	    /* Get the BIOS video mode pointer */
-	    segoff = *(u_int *)pa_to_va(0x4a8);
-	    pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff);
-	    if (ISMAPPED(pa, sizeof(u_int))) {
-		segoff = *(u_int *)pa_to_va(pa);
-		pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff);       
-		if (ISMAPPED(pa, MODE_PARAM_SIZE))
-		    video_mode_ptr = (char *)pa_to_va(pa);
-	    }
-	}
-    }
+    crtc_type = adp->va_type;
+    crtc_vga = (crtc_type == KD_VGA);
+    crtc_addr = adp->va_crtc_addr;
+    Crtat = (u_short *)adp->va_window;
+    adp_flags = adp->va_flags;
+    initial_video_mode = adp->va_initial_mode;
+    bios_video_mode = adp->va_initial_bios_mode;
 
     return TRUE;
 }
@@ -728,48 +635,42 @@ static int
 scattach(struct isa_device *dev)
 {
     scr_stat *scp;
+    video_info_t info;
     dev_t cdev = makedev(CDEV_MAJOR, 0);
-    char *p;
 #ifdef DEVFS
     int vc;
 #endif
 
     scinit();
     flags = dev->id_flags;
-    if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode))
+    if (!ISFONTAVAIL(adp_flags))
 	flags &= ~CHAR_CURSOR;
 
     scp = console[0];
 
-    if (crtc_type == KD_VGA) {
-	cut_buffer_size = scp->xsize * scp->ysize + 1;
-    	cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT);
-	if (cut_buffer != NULL)
-	    cut_buffer[0] = '\0';
-    }
-
-    scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
-				     M_DEVBUF, M_NOWAIT);
-
     /* copy temporary buffer to final buffer */
-    bcopy(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short));
+    scp->scr_buf = NULL;
+    sc_alloc_scr_buffer(scp, FALSE, FALSE);
+    bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short));
 
-    scp->cursor_pos = scp->cursor_oldpos =
-	scp->scr_buf + scp->xpos + scp->ypos * scp->xsize;
-    scp->mouse_pos = scp->mouse_oldpos = 
-	scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize +
-	    		scp->mouse_xpos/8);
+    /* cut buffer is available only when the mouse pointer is used */
+    if (ISMOUSEAVAIL(adp_flags))
+	sc_alloc_cut_buffer(scp, FALSE);
 
     /* initialize history buffer & pointers */
-    scp->history_head = scp->history_pos = 
-	(u_short *)malloc(scp->history_size*sizeof(u_short),
-			  M_DEVBUF, M_NOWAIT);
-    if (scp->history_head != NULL)
-        bzero(scp->history_head, scp->history_size*sizeof(u_short));
-    scp->history = scp->history_head;
+    sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE);
+
+#if defined(VESA) && defined(VM86)
+    if ((flags & VESA800X600) 
+	&& ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) {
+	sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
+	sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
+	initial_video_mode = M_VESA_800x600;
+    }
+#endif /* VESA && VM86 */
 
     /* initialize cursor stuff */
-    if (!(scp->status & UNKNOWN_MODE))
+    if (!ISGRAPHSC(scp))
     	draw_cursor_image(scp);
 
     /* get screen update going */
@@ -777,42 +678,13 @@ scattach(struct isa_device *dev)
 
     update_leds(scp->status);
 
-    if ((crtc_type == KD_VGA) && bootverbose) {
-        printf("sc%d: BIOS video mode:%d\n", dev->id_unit, bios_video_mode);
-        printf("sc%d: VGA registers upon power-up\n", dev->id_unit);
-        dump_vgaregs(vgaregs);
-        printf("sc%d: video mode:%d\n", dev->id_unit, scp->mode);
-        printf("sc%d: VGA registers in BIOS for mode:%d\n", 
-		dev->id_unit, scp->mode);
-        dump_vgaregs(vgaregs2);
-	p = get_mode_param(scp, scp->mode);
-        if (p != NULL) {
-            printf("sc%d: VGA registers to be used for mode:%d\n", 
-		dev->id_unit, scp->mode);
-            dump_vgaregs(p);
-        }
-        printf("sc%d: rows_offset:%d\n", dev->id_unit, rows_offset);
-    }
-    if ((crtc_type == KD_VGA) && !VESA_MODE(bios_video_mode) 
-	&& (video_mode_ptr == NULL))
-        printf("sc%d: WARNING: video mode switching is only partially supported\n",
-	        dev->id_unit); 
-
     printf("sc%d: ", dev->id_unit);
     switch(crtc_type) {
     case KD_VGA:
-	if (VESA_MODE(bios_video_mode))
-	    printf("Graphics display (VESA mode = 0x%x)", bios_video_mode);
-	else if (crtc_addr == MONO_BASE)
-	    printf("VGA mono");
-	else
-	    printf("VGA color");
+	printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
 	break;
     case KD_EGA:
-	if (crtc_addr == MONO_BASE)
-	    printf("EGA mono");
-	else
-	    printf("EGA color");
+	printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono");
 	break;
     case KD_CGA:
 	printf("CGA");
@@ -820,7 +692,7 @@ scattach(struct isa_device *dev)
     case KD_MONO:
     case KD_HERCULES:
     default:
-	printf("MDA/hercules");
+	printf("MDA/Hercules");
 	break;
     }
     printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags);
@@ -896,6 +768,8 @@ scopen(dev_t dev, int flag, int mode, struct proc *p)
 	    return(EBUSY);
     if (minor(dev) < MAXCONS && !console[minor(dev)]) {
 	console[minor(dev)] = alloc_scp();
+	if (ISGRAPHSC(console[minor(dev)]))
+	    sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16);
     }
     if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) {
 	tp->t_winsize.ws_col = console[minor(dev)]->xsize;
@@ -913,7 +787,7 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
     if (!tp)
 	return(ENXIO);
     if (minor(dev) < MAXCONS) {
-	scp = get_scr_stat(tp->t_dev);
+	scp = sc_get_scr_stat(tp->t_dev);
 	if (scp->status & SWITCH_WAIT_ACQ)
 	    wakeup((caddr_t)&scp->smode);
 #if not_yet_done
@@ -927,9 +801,9 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
 	    if (scp->history != NULL) {
 		free(scp->history, M_DEVBUF);
 		if (scp->history_size / scp->xsize
-			> imax(SC_HISTORY_SIZE, scp->ysize))
+			> imax(sc_history_size, scp->ysize))
 		    extra_history_size += scp->history_size / scp->xsize 
-			- imax(SC_HISTORY_SIZE, scp->ysize);
+			- imax(sc_history_size, scp->ysize);
 	    }
 	    free(scp, M_DEVBUF);
 	    console[minor(dev)] = NULL;
@@ -1008,10 +882,17 @@ scintr(int unit)
 	}
     }
 
+#if 0
     if (cur_console->status & MOUSE_ENABLED) {
 	cur_console->status &= ~MOUSE_VISIBLE;
 	remove_mouse_image(cur_console);
     }
+#else
+    if (cur_console->status & MOUSE_VISIBLE) {
+	remove_mouse_image(cur_console);
+	cur_console->status &= ~MOUSE_VISIBLE;
+    }
+#endif
 }
 
 static int
@@ -1030,21 +911,25 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
     u_int i;
     struct tty *tp;
     scr_stat *scp;
-    u_short *usp;
-    char *mp;
+    video_adapter_t *adp;
     int s;
 
     tp = scdevtotty(dev);
     if (!tp)
 	return ENXIO;
-    scp = get_scr_stat(tp->t_dev);
+    scp = sc_get_scr_stat(tp->t_dev);
 
     /* If there is a user_ioctl function call that first */
     if (sc_user_ioctl) {
-	if (error = (*sc_user_ioctl)(dev, cmd, data, flag, p))
+	error = (*sc_user_ioctl)(dev, cmd, data, flag, p);
+	if (error != ENOIOCTL)
 	    return error;
     }
 
+    error = sc_vid_ioctl(tp, cmd, data, flag, p);
+    if (error != ENOIOCTL)
+	return error;
+
     switch (cmd) {  		/* process console hardware related ioctl's */
 
     case GIO_ATTR:      	/* get current attributes */
@@ -1052,18 +937,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case GIO_COLOR:     	/* is this a color console ? */
-	if (crtc_addr == COLOR_BASE)
-	    *(int*)data = 1;
-	else
-	    *(int*)data = 0;
-	return 0;
-
-    case CONS_CURRENT:  	/* get current adapter type */
-	*(int *)data = crtc_type;
-	return 0;
-
-    case CONS_GET:      	/* get current video mode */
-	*(int*)data = scp->mode;
+	*(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0;
 	return 0;
 
     case CONS_BLANKTIME:    	/* set screen saver timeout (0 = no saver) */
@@ -1081,7 +955,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	else
 	    flags &= ~BLINK_CURSOR;
 	if ((*(int*)data) & 0x02) {
-	    if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode))
+	    if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 		return ENXIO;
 	    flags |= CHAR_CURSOR;
 	} else
@@ -1090,7 +964,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * The cursor shape is global property; all virtual consoles
 	 * are affected. Update the cursor in the current console...
 	 */
-	if (!(cur_console->status & UNKNOWN_MODE)) {
+	if (!ISGRAPHSC(cur_console)) {
             remove_cursor_image(cur_console);
 	    if (flags & CHAR_CURSOR)
 	        set_destructive_cursor(cur_console);
@@ -1117,37 +991,22 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    lines = imax(*(int *)data, scp->ysize);
 	    lines0 = (scp->history != NULL) ? 
 		      scp->history_size / scp->xsize : scp->ysize;
+	    if (lines0 > imax(sc_history_size, scp->ysize))
+		i = lines0 - imax(sc_history_size, scp->ysize);
+	    else
+		i = 0;
 	    /*
 	     * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
 	     * lines or scp->ysize lines, whichever is larger. A value 
 	     * greater than that is allowed, subject to extra_history_size.
 	     */
-	    if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size)
-                return EINVAL;
+	    if (lines > imax(sc_history_size, scp->ysize))
+		if (lines - imax(sc_history_size, scp->ysize) >
+		    extra_history_size + i)
+		    return EINVAL;
             if (cur_console->status & BUFFER_SAVED)
                 return EBUSY;
-	    usp = scp->history;
-	    scp->history = NULL;
-	    if (usp != NULL)
-		free(usp, M_DEVBUF);
-	    scp->history_size = lines * scp->xsize;
-	    /*
-	     * extra_history_size += 
-	     *    (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ? 
-	     *     lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
-	     * extra_history_size -= 
-	     *    (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ? 
-	     *	   lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
-	     * lines0 >= ysize && lines >= ysize... Hey, the above can be 
-	     * reduced to the following...
-	     */
-	    extra_history_size += 
-		imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE);
-	    usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
-				    M_DEVBUF, M_WAITOK);
-	    bzero(usp, scp->history_size * sizeof(u_short));
-	    scp->history_head = scp->history_pos = usp;
-	    scp->history = usp;
+	    sc_alloc_history_buffer(scp, lines, i, TRUE);
 	    return 0;
 	}
 	else
@@ -1171,7 +1030,8 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	mouse_info_t *mouse = (mouse_info_t*)data;
 	mouse_info_t buf;
 
-	if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode))
+	/* FIXME: */
+	if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags))
 	    return ENODEV;
 	
 	if (cmd == OLD_CONS_MOUSECTL) {
@@ -1220,7 +1080,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    return 0;
 
 	case MOUSE_SHOW:
-	    if (!(scp->status & MOUSE_ENABLED)) {
+	    if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) {
 		scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE);
 		scp->mouse_oldpos = scp->mouse_pos;
 		mark_all(scp);
@@ -1231,7 +1091,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    break;
 
 	case MOUSE_HIDE:
-	    if (scp->status & MOUSE_ENABLED) {
+	    if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) {
 		scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE);
 		mark_all(scp);
 		return 0;
@@ -1276,7 +1136,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    if (mouse_status.flags == 0)
 		return 0;
 
-	    if (cur_console->status & MOUSE_ENABLED)
+	    if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
 	    	cur_console->status |= MOUSE_VISIBLE;
 
 	    if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
@@ -1321,7 +1181,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) {
 		/* process button presses */
 		if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && 
-		    !(cur_console->status & UNKNOWN_MODE)) {
+		    ISTEXTSC(cur_console)) {
 		    cur_console->mouse_buttons = mouse->u.data.buttons;
 		    if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)
 			mouse_cut_start(cur_console);
@@ -1358,7 +1218,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    if (mouse_status.flags == 0)
 		return 0;
 
-	    if (cur_console->status & MOUSE_ENABLED)
+	    if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED))
 	    	cur_console->status |= MOUSE_VISIBLE;
 
 	    if ((MOUSE_TTY)->t_state & TS_ISOPEN) {
@@ -1387,7 +1247,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 		break;
 	    }
 
-	    if ((cur_console->status & UNKNOWN_MODE) || (cut_buffer == NULL))
+	    if (!ISTEXTSC(cur_console) || (cut_buffer == NULL))
 		break;
 
 	    switch (mouse->u.event.id) {
@@ -1567,18 +1427,41 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case CONS_IDLE:		/* see if the screen has been idle */
-	*(int *)data = (scrn_idle && !(cur_console->status & UNKNOWN_MODE));
+	/*
+	 * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE,
+	 * the user process may have been writing something on the
+	 * screen and syscons is not aware of it. Declare the screen
+	 * is NOT idle if it is in one of these modes. But there is
+	 * an exception to it; if a screen saver is running in the 
+	 * graphics mode in the current screen, we should say that the
+	 * screen has been idle.
+	 */
+	*(int *)data = scrn_idle 
+		       && (!ISGRAPHSC(cur_console)
+			   || (cur_console->status & SAVER_RUNNING));
 	return 0;
 
     case CONS_SAVERMODE:	/* set saver mode */
 	switch(*(int *)data) {
 	case CONS_USR_SAVER:
-	    /* if a LKM screen saver is running, it will eventually stop... */
+	    /* if a LKM screen saver is running, stop it first. */
+	    scsplash_stick(FALSE);
 	    saver_mode = *(int *)data;
+	    s = spltty();
+	    if ((error = wait_scrn_saver_stop())) {
+		splx(s);
+		return error;
+	    }
+	    scp->status |= SAVER_RUNNING;
 	    scsplash_stick(TRUE);
+	    splx(s);
 	    break;
 	case CONS_LKM_SAVER:
+	    s = spltty();
+	    if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING))
+		scp->status &= ~SAVER_RUNNING;
 	    saver_mode = *(int *)data;
+	    splx(s);
 	    break;
 	default:
 	    return EINVAL;
@@ -1597,226 +1480,6 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	splx(s);
 	return 0;
 
-    /* VGA TEXT MODES */
-    case SW_VGA_C40x25:
-    case SW_VGA_C80x25: case SW_VGA_M80x25:
-    case SW_VGA_C80x30: case SW_VGA_M80x30:
-    case SW_VGA_C80x50: case SW_VGA_M80x50:
-    case SW_VGA_C80x60: case SW_VGA_M80x60:
-    case SW_B40x25:     case SW_C40x25:
-    case SW_B80x25:     case SW_C80x25:
-    case SW_ENH_B40x25: case SW_ENH_C40x25:
-    case SW_ENH_B80x25: case SW_ENH_C80x25:
-    case SW_ENH_B80x43: case SW_ENH_C80x43:
-    case SW_EGAMONO80x25:
-
-	if (crtc_type != KD_VGA)
- 	    return ENODEV;
- 	mp = get_mode_param(scp, cmd & 0xff);
- 	if (mp == NULL)
- 	    return ENODEV;
- 
-	s = spltty();
-	if ((error = wait_scrn_saver_stop())) {
-	    splx(s);
-	    return error;
-	}
-
-	scp->status &= ~MOUSE_VISIBLE;
-	remove_cutmarking(scp);
-	if (scp->history != NULL)
-	    i = imax(scp->history_size / scp->xsize 
-		     - imax(SC_HISTORY_SIZE, scp->ysize), 0);
-	else
-	    i = 0;
-	switch (cmd & 0xff) {
-	case M_VGA_C80x60: case M_VGA_M80x60:
-	    if (!(fonts_loaded & FONT_8)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    /*
-	     * This is a kludge to fend off scrn_update() while we
-	     * muck around with scp. XXX
-	     */
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 60;
-	    scp->font_size = 8;
-	    break;
-	case M_VGA_C80x50: case M_VGA_M80x50:
-	    if (!(fonts_loaded & FONT_8)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 50;
-	    scp->font_size = 8;
-	    break;
-	case M_ENH_B80x43: case M_ENH_C80x43:
-	    if (!(fonts_loaded & FONT_8)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 43;
-	    scp->font_size = 8;
-	    break;
-	case M_VGA_C80x30: case M_VGA_M80x30:
-	    scp->status |= UNKNOWN_MODE;
-	    scp->xsize = 80;
-	    scp->ysize = 30;
-	    scp->font_size = mp[2];
-	    break;
-	case M_ENH_C40x25: case M_ENH_B40x25:
-	case M_ENH_C80x25: case M_ENH_B80x25:
-	case M_EGAMONO80x25:
-	    if (!(fonts_loaded & FONT_14)) {
-		splx(s);
-		return EINVAL;
-	    }
-	    /* FALL THROUGH */
-	default:
-	    if ((cmd & 0xff) > M_VGA_CG320) {
-		splx(s);
-		return EINVAL;
-	    }
-	    scp->status |= UNKNOWN_MODE;
-            scp->xsize = mp[0];
-            scp->ysize = mp[1] + rows_offset;
-	    scp->font_size = mp[2];
-	    break;
-	}
-
-	scp->mode = cmd & 0xff;
-	scp->xpixel = scp->xsize * 8;
-	scp->ypixel = scp->ysize * scp->font_size;
-	free(scp->scr_buf, M_DEVBUF);
-	scp->scr_buf = (u_short *)
-	    malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_WAITOK);
-	/* move the text cursor to the home position */
-	move_crsr(scp, 0, 0);
-	/* move the mouse cursor at the center of the screen */
-	scp->mouse_xpos = scp->xpixel / 2;
-	scp->mouse_ypos = scp->ypixel / 2;
-    	scp->mouse_pos = scp->mouse_oldpos = 
-	    scp->scr_buf + (scp->mouse_ypos / scp->font_size) * scp->xsize 
-	    + scp->mouse_xpos / 8;
-	/* allocate a larger cut buffer if necessary */
-	if ((cut_buffer == NULL)
-	    || (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
-	    if (cut_buffer != NULL)
-		free(cut_buffer, M_DEVBUF);
-	    cut_buffer_size = scp->xsize * scp->ysize + 1;
-	    cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT);
-	    if (cut_buffer != NULL)
-		cut_buffer[0] = '\0';
-	}
-	splx(s);
-
-	usp = scp->history;
-	scp->history = NULL;
-	if (usp != NULL) {
-	    free(usp, M_DEVBUF);
-	    extra_history_size += i;
-	}
-	scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
-	usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 
-				M_DEVBUF, M_NOWAIT);
-	if (usp != NULL)
-	    bzero(usp, scp->history_size * sizeof(u_short));
-	scp->history_head = scp->history_pos = usp;
-	scp->history = usp;
-	if (scp == cur_console)
-	    set_mode(scp);
-	clear_screen(scp);
-	scp->status &= ~UNKNOWN_MODE;
-
-	if (tp->t_winsize.ws_col != scp->xsize
-	    || tp->t_winsize.ws_row != scp->ysize) {
-	    tp->t_winsize.ws_col = scp->xsize;
-	    tp->t_winsize.ws_row = scp->ysize;
-	    pgsignal(tp->t_pgrp, SIGWINCH, 1);
-	}
-	return 0;
-
-    /* GRAPHICS MODES */
-    case SW_BG320:     case SW_BG640:
-    case SW_CG320:     case SW_CG320_D:   case SW_CG640_E:
-    case SW_CG640x350: case SW_ENH_CG640:
-    case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:
-
-	if (crtc_type != KD_VGA)
-	    return ENODEV;
-	mp = get_mode_param(scp, cmd & 0xff);
-	if (mp == NULL)
-	    return ENODEV;
-
-	s = spltty();
-	if ((error = wait_scrn_saver_stop())) {
-	    splx(s);
-	    return error;
-	}
-
-	scp->status &= ~MOUSE_VISIBLE;
-	remove_cutmarking(scp);
-	scp->status |= UNKNOWN_MODE;    /* graphics mode */
-	scp->mode = cmd & 0xFF;
-	scp->xpixel = mp[0] * 8;
-	scp->ypixel = (mp[1] + rows_offset) * mp[2];
-	scp->font_size = FONT_NONE;
-	/* move the mouse cursor at the center of the screen */
-	scp->mouse_xpos = scp->xpixel / 2;
-	scp->mouse_ypos = scp->ypixel / 2;
-	splx(s);
-
-	if (scp == cur_console)
-	    set_mode(scp);
-	/* clear_graphics();*/
-
-	if (tp->t_winsize.ws_xpixel != scp->xpixel
-	    || tp->t_winsize.ws_ypixel != scp->ypixel) {
-	    tp->t_winsize.ws_xpixel = scp->xpixel;
-	    tp->t_winsize.ws_ypixel = scp->ypixel;
-	    pgsignal(tp->t_pgrp, SIGWINCH, 1);
-	}
-	return 0;
-
-    case SW_VGA_MODEX:
-	if (crtc_type != KD_VGA)
-	    return ENODEV;
-	mp = get_mode_param(scp, cmd & 0xff);
-	if (mp == NULL)
-	    return ENODEV;
-
-	s = spltty();
-	if ((error = wait_scrn_saver_stop())) {
-	    splx(s);
-	    return error;
-	}
-
-	scp->status &= ~MOUSE_VISIBLE;
-	remove_cutmarking(scp);
-	scp->status |= UNKNOWN_MODE;    /* graphics mode */
-	scp->mode = cmd & 0xFF;
-	scp->xpixel = 320;
-	scp->ypixel = 240;
-	scp->font_size = FONT_NONE;
-	splx(s);
-
-	if (scp == cur_console)
-	    set_mode(scp);
-	/* clear_graphics();*/
-	if (tp->t_winsize.ws_xpixel != scp->xpixel
-	    || tp->t_winsize.ws_ypixel != scp->ypixel) {
-	    tp->t_winsize.ws_xpixel = scp->xpixel;
-	    tp->t_winsize.ws_ypixel = scp->ypixel;
-	    pgsignal(tp->t_pgrp, SIGWINCH, 1);
-	}
-	return 0;
-
     case VT_SETMODE:    	/* set screen switcher mode */
     {
 	struct vt_mode *mode;
@@ -1839,7 +1502,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case VT_RELDISP:    	/* screen switcher ioctl */
-	switch(*data) {
+	switch(*(int *)data) {
 	case VT_FALSE:  	/* user refuses to release screen, abort */
 	    if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
 		old_scp->status &= ~SWITCH_WAIT_REL;
@@ -1879,32 +1542,32 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	for (i = 0; i < MAXCONS; i++) {
 	    tp = VIRTUAL_TTY(i);
 	    if (!(tp->t_state & TS_ISOPEN)) {
-		*data = i + 1;
+		*(int *)data = i + 1;
 		return 0;
 	    }
 	}
 	return EINVAL;
 
     case VT_ACTIVATE:   	/* switch to screen *data */
-	return switch_scr(scp, (*data) - 1);
+	return switch_scr(scp, *(int *)data - 1);
 
     case VT_WAITACTIVE: 	/* wait for switch to occur */
-	if (*data > MAXCONS || *data < 0)
+	if (*(int *)data > MAXCONS || *(int *)data < 0)
 	    return EINVAL;
-	if (minor(dev) == (*data) - 1)
+	if (minor(dev) == *(int *)data - 1)
 	    return 0;
-	if (*data == 0) {
+	if (*(int *)data == 0) {
 	    if (scp == cur_console)
 		return 0;
 	}
 	else
-	    scp = console[(*data) - 1];
+	    scp = console[*(int *)data - 1];
 	while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
 			     "waitvt", 0)) == ERESTART) ;
 	return error;
 
     case VT_GETACTIVE:
-	*data = get_scr_num()+1;
+	*(int *)data = get_scr_num()+1;
 	return 0;
 
     case KDENABIO:      	/* allow io operations */
@@ -1920,102 +1583,28 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	p->p_md.md_regs->tf_eflags &= ~PSL_IOPL;
 	return 0;
 
-    case KDSETMODE:     	/* set current mode of this (virtual) console */
-	switch (*data) {
-	case KD_TEXT:   	/* switch to TEXT (known) mode */
-	    /* restore fonts & palette ! */
-	    if (crtc_type == KD_VGA) {
-		if (!VESA_MODE(scp->mode)) {
-#if 0
-		    /*
-		     * FONT KLUDGE
-		     * Don't load fonts for now... XXX
-		     */
-		    if (fonts_loaded & FONT_8)
-			copy_font(LOAD, FONT_8, font_8);
-		    if (fonts_loaded & FONT_14)
-			copy_font(LOAD, FONT_14, font_14);
-		    if (fonts_loaded & FONT_16)
-			copy_font(LOAD, FONT_16, font_16);
-#endif
-		}
-		load_palette(palette);
-	    }
-
-	    /* move hardware cursor out of the way */
-	    outb(crtc_addr, 14);
-	    outb(crtc_addr + 1, 0xff);
-	    outb(crtc_addr, 15);
-	    outb(crtc_addr + 1, 0xff);
-
-	    /* FALL THROUGH */
-
-	case KD_TEXT1:  	/* switch to TEXT (known) mode */
-	    s = spltty();
-	    if ((error = wait_scrn_saver_stop())) {
-		splx(s);
-		return error;
-	    }
-	    scp->status &= ~MOUSE_VISIBLE;
-	    remove_cutmarking(scp);
-	    scp->status |= UNKNOWN_MODE;
-	    splx(s);
-	    /* no restore fonts & palette */
-	    if (crtc_type == KD_VGA)
-		set_mode(scp);
-	    scp->status &= ~UNKNOWN_MODE;
-	    clear_screen(scp);
-	    return 0;
-
-	case KD_GRAPHICS:	/* switch to GRAPHICS (unknown) mode */
-	    s = spltty();
-	    if ((error = wait_scrn_saver_stop())) {
-		splx(s);
-		return error;
-	    }
-	    scp->status &= ~MOUSE_VISIBLE;
-	    remove_cutmarking(scp);
-	    scp->status |= UNKNOWN_MODE;
-	    splx(s);
-	    return 0;
-	default:
-	    return EINVAL;
-	}
-	/* NOT REACHED */
-
-    case KDGETMODE:     	/* get current mode of this (virtual) console */
-	*data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT;
-	return 0;
-
-    case KDSBORDER:     	/* set border color of this (virtual) console */
-	scp->border = *data;
-	if (scp == cur_console)
-	    set_border(scp->border);
-	return 0;
-
     case KDSKBSTATE:    	/* set keyboard state (locks) */
-	if (*data >= 0 && *data <= LOCK_KEY_MASK) {
-	    scp->status &= ~LOCK_KEY_MASK;
-	    scp->status |= *data;
-	    if (scp == cur_console)
-		update_leds(scp->status);
-	    return 0;
-	}
-	return EINVAL;
+	if (*(int *)data & ~LOCK_KEY_MASK)
+	    return EINVAL;
+	scp->status &= ~LOCK_KEY_MASK;
+	scp->status |= *(int *)data;
+	if (scp == cur_console)
+	    update_leds(scp->status);
+	return 0;
 
     case KDGKBSTATE:    	/* get keyboard state (locks) */
-	*data = scp->status & LOCK_KEY_MASK;
+	*(int *)data = scp->status & LOCK_KEY_MASK;
 	return 0;
 
     case KDSETRAD:      	/* set keyboard repeat & delay rates */
-	if (*data & 0x80)
+	if (*(int *)data & ~0x7f)
 	    return EINVAL;
 	if (sc_kbdc != NULL) 
-	    set_keyboard(KBDC_SET_TYPEMATIC, *data);
+	    set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data);
 	return 0;
 
     case KDSKBMODE:     	/* set keyboard mode */
-	switch (*data) {
+	switch (*(int *)data) {
 	case K_RAW: 		/* switch to RAW scancode mode */
 	    scp->status &= ~KBD_CODE_MODE;
 	    scp->status |= KBD_RAW_MODE;
@@ -2037,7 +1626,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	/* NOT REACHED */
 
     case KDGKBMODE:     	/* get keyboard mode */
-	*data = (scp->status & KBD_RAW_MODE) ? K_RAW : 
+	*(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : 
 		((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE);
 	return 0;
 
@@ -2074,21 +1663,20 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case KDGKBTYPE:     	/* get keyboard type */
-	*data = 0;  		/* type not known (yet) */
+	*(int *)data = 0;  	/* type not known (yet) */
 	return 0;
 
     case KDSETLED:      	/* set keyboard LED status */
-	if (*data >= 0 && *data <= LED_MASK) {
-	    scp->status &= ~LED_MASK;
-	    scp->status |= *data;
-	    if (scp == cur_console)
-		update_leds(scp->status);
-	    return 0;
-	}
-	return EINVAL;
+	if (*(int *)data & ~LED_MASK)
+	    return EINVAL;
+	scp->status &= ~LED_MASK;
+	scp->status |= *(int *)data;
+	if (scp == cur_console)
+	    update_leds(scp->status);
+	return 0;
 
     case KDGETLED:      	/* get keyboard LED status */
-	*data = scp->status & LED_MASK;
+	*(int *)data = scp->status & LED_MASK;
 	return 0;
 
     case GETFKEY:       	/* get functionkey string */
@@ -2143,7 +1731,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	return 0;
 
     case PIO_FONT8x8:   	/* set 8x8 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	bcopy(data, font_8, 8*256);
 	fonts_loaded |= FONT_8;
@@ -2152,17 +1740,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * Always use the font page #0. XXX
 	 * Don't load if the current font size is not 8x8.
 	 */
-	if (!VESA_MODE(cur_console->mode) 
-	    && !(cur_console->status & UNKNOWN_MODE)
-	    && (cur_console->font_size < 14)) {
-	    copy_font(LOAD, FONT_8, font_8);
-	    if (flags & CHAR_CURSOR)
-	        set_destructive_cursor(cur_console);
-	}
+	if (ISTEXTSC(cur_console) && (cur_console->font_size < 14))
+	    copy_font(cur_console, LOAD, 8, font_8);
 	return 0;
 
     case GIO_FONT8x8:   	/* get 8x8 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	if (fonts_loaded & FONT_8) {
 	    bcopy(font_8, data, 8*256);
@@ -2172,7 +1755,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    return ENXIO;
 
     case PIO_FONT8x14:  	/* set 8x14 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	bcopy(data, font_14, 14*256);
 	fonts_loaded |= FONT_14;
@@ -2181,17 +1764,13 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * Always use the font page #0. XXX
 	 * Don't load if the current font size is not 8x14.
 	 */
-	if (!VESA_MODE(cur_console->mode) 
-	    && !(cur_console->status & UNKNOWN_MODE)
-	    && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) {
-	    copy_font(LOAD, FONT_14, font_14);
-	    if (flags & CHAR_CURSOR)
-	        set_destructive_cursor(cur_console);
-	}
+	if (ISTEXTSC(cur_console)
+	    && (cur_console->font_size >= 14) && (cur_console->font_size < 16))
+	    copy_font(cur_console, LOAD, 14, font_14);
 	return 0;
 
     case GIO_FONT8x14:  	/* get 8x14 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	if (fonts_loaded & FONT_14) {
 	    bcopy(font_14, data, 14*256);
@@ -2201,7 +1780,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	    return ENXIO;
 
     case PIO_FONT8x16:  	/* set 8x16 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	bcopy(data, font_16, 16*256);
 	fonts_loaded |= FONT_16;
@@ -2210,17 +1789,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 	 * Always use the font page #0. XXX
 	 * Don't load if the current font size is not 8x16.
 	 */
-	if (!VESA_MODE(cur_console->mode) 
-	    && !(cur_console->status & UNKNOWN_MODE)
-	    && (cur_console->font_size >= 16)) {
-	    copy_font(LOAD, FONT_16, font_16);
-	    if (flags & CHAR_CURSOR)
-	        set_destructive_cursor(cur_console);
-	}
+	if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16))
+	    copy_font(cur_console, LOAD, 16, font_16);
 	return 0;
 
     case GIO_FONT8x16:  	/* get 8x16 dot font */
-	if (crtc_type != KD_VGA)
+	if (!ISFONTAVAIL(get_adapter(scp)->va_flags))
 	    return ENXIO;
 	if (fonts_loaded & FONT_16) {
 	    bcopy(font_16, data, 16*256);
@@ -2247,7 +1821,7 @@ scstart(struct tty *tp)
     struct clist *rbp;
     int s, len;
     u_char buf[PCBURST];
-    scr_stat *scp = get_scr_stat(tp->t_dev);
+    scr_stat *scp = sc_get_scr_stat(tp->t_dev);
 
     if (scp->status & SLKED || blink_in_progress)
 	return; /* XXX who repeats the call when the above flags are cleared? */
@@ -2329,7 +1903,7 @@ sccnputc(dev_t dev, int c)
 
     scp->term = kernel_console;
     current_default = &kernel_default;
-    if (scp == cur_console && !(scp->status & UNKNOWN_MODE))
+    if (scp == cur_console && !ISGRAPHSC(scp))
 	remove_cursor_image(scp);
     buf[0] = c;
     ansi_put(scp, buf, 1);
@@ -2384,25 +1958,28 @@ sccnupdate(scr_stat *scp)
     if (font_loading_in_progress)
 	return;
 
-    if (panicstr) {
+    if (panicstr || shutdown_in_progress) {
 	scsplash_stick(FALSE);
 	run_scrn_saver = FALSE;
+    } else if (scp != cur_console) {
+	return;
     }
+
     if (!run_scrn_saver)
 	scrn_idle = FALSE;
     if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
-	if (scrn_blanked > 0)
+	if (scp->status & SAVER_RUNNING)
             stop_scrn_saver(current_saver);
 
     if (scp != cur_console || blink_in_progress || switch_in_progress)
 	return;
 
-    if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0)
+    if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
 	scrn_update(scp, TRUE);
 }
 
-static scr_stat
-*get_scr_stat(dev_t dev)
+scr_stat
+*sc_get_scr_stat(dev_t dev)
 {
     int unit = minor(dev);
 
@@ -2461,6 +2038,8 @@ scrn_timer(void *arg)
 	    scintr(0);
     }
 
+    scp = cur_console;
+
     /* should we stop the screen saver? */
     getmicrouptime(&tv);
     if (panicstr || shutdown_in_progress) {
@@ -2476,7 +2055,7 @@ scrn_timer(void *arg)
 	    run_scrn_saver = TRUE;
     }
     if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle)
-	if (scrn_blanked > 0)
+	if (scp->status & SAVER_RUNNING)
             stop_scrn_saver(current_saver);
 
     /* should we just return ? */
@@ -2488,14 +2067,13 @@ scrn_timer(void *arg)
     }
 
     /* Update the screen */
-    scp = cur_console;
-    if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0)
+    if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING))
 	scrn_update(scp, TRUE);
 
     /* should we activate the screen saver? */
     if ((saver_mode == CONS_LKM_SAVER) && scrn_idle)
-	if ((scp->status & UNKNOWN_MODE) == 0 || scrn_blanked > 0)
-	    (*current_saver)(TRUE);
+	if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING))
+	    scrn_saver(current_saver, TRUE);
 
     if (arg)
 	timeout(scrn_timer, (void *)TRUE, hz / 25);
@@ -2583,9 +2161,9 @@ add_scrn_saver(void (*this_saver)(int))
 
     if (current_saver != default_saver)
 	return EBUSY;
-    current_saver = this_saver;
+    run_scrn_saver = FALSE;
     saver_mode = CONS_LKM_SAVER;
-    run_scrn_saver = (scrn_blank_time > 0);
+    current_saver = this_saver;
     return 0;
 }
 
@@ -2612,10 +2190,22 @@ remove_scrn_saver(void (*this_saver)(int))
     return 0;
 }
 
+static void
+scrn_saver(void (*saver)(int), int blank)
+{
+    static int busy = FALSE;
+
+    if (busy)
+	return;
+    busy = TRUE;
+    (*saver)(blank);
+    busy = FALSE;
+}
+
 static void
 stop_scrn_saver(void (*saver)(int))
 {
-    (*saver)(FALSE);
+    scrn_saver(saver, FALSE);
     run_scrn_saver = FALSE;
     /* the screen saver may have chosen not to stop after all... */
     if (scrn_blanked > 0)
@@ -2632,8 +2222,8 @@ wait_scrn_saver_stop(void)
 {
     int error = 0;
 
-    run_scrn_saver = FALSE;
     while (scrn_blanked > 0) {
+	run_scrn_saver = FALSE;
 	error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0);
 	run_scrn_saver = FALSE;
 	if (error != ERESTART)
@@ -2642,8 +2232,8 @@ wait_scrn_saver_stop(void)
     return error;
 }
 
-static void
-clear_screen(scr_stat *scp)
+void
+sc_clear_screen(scr_stat *scp)
 {
     move_crsr(scp, 0, 0);
     scp->cursor_oldpos = scp->cursor_pos;
@@ -2668,8 +2258,7 @@ switch_scr(scr_stat *scp, u_int next_scr)
 	switch_in_progress = FALSE;
 
     if (next_scr >= MAXCONS || switch_in_progress ||
-	(cur_console->smode.mode == VT_AUTO
-	 && cur_console->status & UNKNOWN_MODE)) {
+	(cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) {
 	do_bell(scp, BELL_PITCH, BELL_DURATION);
 	return EINVAL;
     }
@@ -2721,25 +2310,26 @@ exchange_scr(void)
 {
     move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
     cur_console = new_scp;
-    if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){
-	if (crtc_type == KD_VGA)
+    if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) {
+	if (adp_flags & V_ADP_MODECHANGE)
 	    set_mode(new_scp);
     }
     move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
-    if (!(new_scp->status & UNKNOWN_MODE) && (flags & CHAR_CURSOR))
+    if (ISTEXTSC(new_scp) && (flags & CHAR_CURSOR))
 	set_destructive_cursor(new_scp);
-    if ((old_scp->status & UNKNOWN_MODE) && crtc_type == KD_VGA)
-	load_palette(palette);
+    if (ISGRAPHSC(old_scp))
+	load_palette(new_scp, palette);
     if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE ||
         old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE)
 	shfts = ctls = alts = agrs = metas = accents = 0;
-    set_border(new_scp->border);
+    set_border(new_scp, new_scp->border);
     update_leds(new_scp->status);
     delayed_next_scr = FALSE;
     mark_all(new_scp);
-    if (new_scp->mode == 0x102) {
-	bzero(Crtat, 800*600/8);
-    }
+
+    /* FIXME: the screen size may be larger than a 64K segment. */
+    if (ISPIXELSC(new_scp))
+	bzero(Crtat, new_scp->xpixel*new_scp->ypixel/8);
 }
 
 static void
@@ -2788,7 +2378,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    return;
 #endif
 	case 'c':   /* Clear screen & home */
-	    clear_screen(scp);
+	    sc_clear_screen(scp);
 	    break;
 
 	case '(':   /* iso-2022: designate 94 character set to G0 */
@@ -2874,7 +2464,7 @@ scan_esc(scr_stat *scp, u_char c)
 		      scp->cursor_pos,
 		      scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos);
     		mark_for_update(scp, scp->cursor_pos - scp->scr_buf);
-    		mark_for_update(scp, scp->xsize * scp->ysize);
+    		mark_for_update(scp, scp->xsize * scp->ysize - 1);
 		remove_cutmarking(scp);
 		break;
 	    case 1: /* clear from beginning of display to cursor */
@@ -2936,7 +2526,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    fillw(scp->term.cur_color | scr_map[0x20], src,
 		  n * scp->xsize);
 	    mark_for_update(scp, scp->ypos * scp->xsize);
-	    mark_for_update(scp, scp->xsize * scp->ysize);
+	    mark_for_update(scp, scp->xsize * scp->ysize - 1);
 	    break;
 
 	case 'M':   /* Delete n lines */
@@ -2951,7 +2541,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    fillw(scp->term.cur_color | scr_map[0x20], src,
 		  n * scp->xsize);
 	    mark_for_update(scp, scp->ypos * scp->xsize);
-	    mark_for_update(scp, scp->xsize * scp->ysize);
+	    mark_for_update(scp, scp->xsize * scp->ysize - 1);
 	    break;
 
 	case 'P':   /* Delete n chars */
@@ -3192,7 +2782,7 @@ scan_esc(scr_stat *scp, u_char c)
 	    if (scp->term.num_param == 1) {
 		scp->border=scp->term.param[0] & 0xff;
 		if (scp == cur_console)
-		    set_border(scp->border);
+		    set_border(cur_console, scp->border);
             }
 	    break;
 
@@ -3209,8 +2799,8 @@ scan_esc(scr_stat *scp, u_char c)
 		    flags |= BLINK_CURSOR;
 		else
 		    flags &= ~BLINK_CURSOR;
-		if ((scp->term.param[0] & 0x02) && 
-		    crtc_type == KD_VGA && !VESA_MODE(bios_video_mode))
+		if ((scp->term.param[0] & 0x02) 
+		    && ISFONTAVAIL(get_adapter(scp)->va_flags)) 
 		    flags |= CHAR_CURSOR;
 		else
 		    flags &= ~CHAR_CURSOR;
@@ -3223,9 +2813,9 @@ scan_esc(scr_stat *scp, u_char c)
 	     * The cursor shape is global property; all virtual consoles
 	     * are affected. Update the cursor in the current console...
 	     */
-	    if (!(cur_console->status & UNKNOWN_MODE)) {
+	    if (!ISGRAPHSC(cur_console)) {
 		remove_cursor_image(cur_console);
-		if (crtc_type == KD_VGA && (flags & CHAR_CURSOR))
+		if (flags & CHAR_CURSOR)
 	            set_destructive_cursor(cur_console);
 		draw_cursor_image(cur_console);
 	    }
@@ -3366,7 +2956,7 @@ outloop:
 	    break;
 
 	case 0x0c:  /* form feed, clears screen */
-	    clear_screen(scp);
+	    sc_clear_screen(scp);
 	    break;
 
 	case 0x0d:  /* return, return to pos 0 */
@@ -3413,42 +3003,17 @@ outloop:
 static void
 scinit(void)
 {
-    u_int hw_cursor;
+    int col;
+    int row;
     u_int i;
 
     if (init_done != COLD)
 	return;
     init_done = WARM;
 
-    /*
-     * Ensure a zero start address.  This is mainly to recover after
-     * switching from pcvt using userconfig().  The registers are w/o
-     * for old hardware so it's too hard to relocate the active screen
-     * memory.
-     */
-    outb(crtc_addr, 12);
-    outb(crtc_addr + 1, 0);
-    outb(crtc_addr, 13);
-    outb(crtc_addr + 1, 0);
-
-    /* extract cursor location */
-    outb(crtc_addr, 14);
-    hw_cursor = inb(crtc_addr + 1) << 8;
-    outb(crtc_addr, 15);
-    hw_cursor |= inb(crtc_addr + 1);
-
-    /*
-     * Validate cursor location.  It may be off the screen.  Then we must
-     * not use it for the initial buffer offset.
-     */
-    if (hw_cursor >= ROW * COL)
-	hw_cursor = (ROW - 1) * COL;
-
-    /* move hardware cursor out of the way */
-    outb(crtc_addr, 14);
-    outb(crtc_addr + 1, 0xff);
-    outb(crtc_addr, 15);
-    outb(crtc_addr + 1, 0xff);
+    /* extract the hardware cursor location and move it out of the way */
+    (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row);
+    (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1);
 
     /* set up the first console */
     current_default = &user_default;
@@ -3456,51 +3021,22 @@ scinit(void)
     init_scp(console[0]);
     cur_console = console[0];
 
-    /* discard the video mode table if we are not familiar with it... */
-    if (video_mode_ptr) {
-        bzero(mode_map, sizeof(mode_map));
-	bcopy(video_mode_ptr + MODE_PARAM_SIZE*console[0]->mode, 
-	      vgaregs2, sizeof(vgaregs2));
-        switch (comp_vgaregs(vgaregs, video_mode_ptr 
-                    + MODE_PARAM_SIZE*console[0]->mode)) {
-        case COMP_IDENTICAL:
-            map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
-            /* 
-             * This is a kludge for Toshiba DynaBook SS433 whose BIOS video
-             * mode table entry has the actual # of rows at the offset 1; 
-	     * BIOSes from other manufacturers store the # of rows - 1 there. 
-	     * XXX
-             */
-	    rows_offset = vgaregs[1] + 1 
-		- video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1];
-            break;
-        case COMP_SIMILAR:
-            map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
-            mode_map[console[0]->mode] = vgaregs;
-	    rows_offset = vgaregs[1] + 1 
-		- video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1];
-            vgaregs[1] -= rows_offset - 1;
-            break;
-        case COMP_DIFFERENT:
-        default:
-            video_mode_ptr = NULL;
-            mode_map[console[0]->mode] = vgaregs;
-	    rows_offset = 1;
-            break;
-        }
-    }
-
     /* copy screen to temporary buffer */
-    if (!VESA_MODE(console[0]->mode))
+    if (ISTEXTSC(console[0]))
 	    generic_bcopy(Crtat, sc_buffer,
 		   console[0]->xsize * console[0]->ysize * sizeof(u_short));
 
     console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos
 	= sc_buffer;
-    console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor;
+    if (col >= console[0]->xsize)
+	col = 0;
+    if (row >= console[0]->ysize)
+	row = console[0]->ysize - 1;
+    console[0]->xpos = col;
+    console[0]->ypos = row;
+    console[0]->cursor_pos = console[0]->cursor_oldpos =
+	sc_buffer + row*console[0]->xsize + col;
     console[0]->cursor_saveunder = *console[0]->cursor_pos;
-    console[0]->xpos = hw_cursor % COL;
-    console[0]->ypos = hw_cursor / COL;
     for (i=1; i<MAXCONS; i++)
 	console[i] = NULL;
     kernel_console.esc = 0;
@@ -3515,28 +3051,26 @@ scinit(void)
 	scr_map[i] = scr_rmap[i] = i;
     }
 
-    /* Save font and palette if VGA */
-    if (crtc_type == KD_VGA) {
-	if (!VESA_MODE(bios_video_mode)) {
-	    if (fonts_loaded & FONT_16) {
-		copy_font(LOAD, FONT_16, font_16);
-	    } else {
-		copy_font(SAVE, FONT_16, font_16);
-		fonts_loaded = FONT_16;
-	    }
-	    set_destructive_cursor(console[0]);
+    /* Save font and palette */
+    if (ISFONTAVAIL(get_adapter(cur_console)->va_flags)) {
+	if (fonts_loaded & FONT_16) {
+	    copy_font(cur_console, LOAD, 16, font_16);
+	} else {
+	    copy_font(cur_console, SAVE, 16, font_16);
+	    fonts_loaded = FONT_16;
+	    set_destructive_cursor(cur_console);
 	}
-	save_palette();
+	/*
+	 * FONT KLUDGE
+	 * Always use the font page #0. XXX
+	 */
+	(*biosvidsw.show_font)(cur_console->adp, 0);
     }
+    save_palette(cur_console, palette);
 
 #ifdef SC_SPLASH_SCREEN
-    /* 
-     * If not booting verbosely, put up the splash.
-     * Note that the splash screen is not currently supported in 
-     * the VESA mode.
-     */
-    if (!(boothowto & RB_VERBOSE) && !VESA_MODE(bios_video_mode))
-	scsplash_init();
+    /* put up the splash. */
+    scsplash_init(cur_console);
 #endif
 }
 
@@ -3551,52 +3085,79 @@ scshutdown(int howto, void *arg)
     shutdown_in_progress = TRUE;
 }
 
-static void
-map_mode_table(char *map[], char *table, int max)
+int
+sc_clean_up(scr_stat *scp)
 {
-    int i;
+    int error;
 
-    for(i = 0; i < max; ++i)
-	map[i] = table + i*MODE_PARAM_SIZE;
-    for(; i < MODE_MAP_SIZE; ++i)
-	map[i] = NULL;
+    if ((error = wait_scrn_saver_stop()))
+	return error;
+    scp->status &= ~MOUSE_VISIBLE;
+    remove_cutmarking(scp);
+    return 0;
 }
 
-static int
-map_mode_num(int mode)
+void
+sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear)
 {
-    static struct {
-        int from;
-        int to;
-    } mode_map[] = {
-        { M_ENH_B80x43, M_ENH_B80x25 },
-        { M_ENH_C80x43, M_ENH_C80x25 },
-        { M_VGA_M80x30, M_VGA_M80x25 },
-        { M_VGA_C80x30, M_VGA_C80x25 },
-        { M_VGA_M80x50, M_VGA_M80x25 },
-        { M_VGA_C80x50, M_VGA_C80x25 },
-        { M_VGA_M80x60, M_VGA_M80x25 },
-        { M_VGA_C80x60, M_VGA_C80x25 },
-        { M_VGA_MODEX,  M_VGA_CG320 },
-    };
-    int i;
+    if (scp->scr_buf)
+	free(scp->scr_buf, M_DEVBUF);
+    scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 
+				     M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
 
-    for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
-        if (mode_map[i].from == mode)
-            return mode_map[i].to;
+    if (clear) {
+        /* clear the screen and move the text cursor to the top-left position */
+	sc_clear_screen(scp);
+    } else {
+	/* retain the current cursor position, but adjust pointers */
+	move_crsr(scp, scp->xpos, scp->ypos);
+	scp->cursor_oldpos = scp->cursor_pos;
     }
-    return mode;
+
+    /* move the mouse cursor at the center of the screen */
+    sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2);
 }
 
-static char 
-*get_mode_param(scr_stat *scp, int mode)
+void
+sc_alloc_cut_buffer(scr_stat *scp, int wait)
 {
-    if (mode >= MODE_MAP_SIZE)
-	mode = map_mode_num(mode);
-    if (mode < MODE_MAP_SIZE)
-	return mode_map[mode];
-    else
-	return NULL;
+    if ((cut_buffer == NULL)
+	|| (cut_buffer_size < scp->xsize * scp->ysize + 1)) {
+	if (cut_buffer != NULL)
+	    free(cut_buffer, M_DEVBUF);
+	cut_buffer_size = scp->xsize * scp->ysize + 1;
+	cut_buffer = (u_char *)malloc(cut_buffer_size, 
+				    M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
+	if (cut_buffer != NULL)
+	    cut_buffer[0] = '\0';
+    }
+}
+
+void
+sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait)
+{
+    u_short *usp;
+
+    if (lines < scp->ysize)
+	lines = scp->ysize;
+
+    usp = scp->history;
+    scp->history = NULL;
+    if (usp != NULL) {
+	free(usp, M_DEVBUF);
+	if (extra > 0)
+	    extra_history_size += extra;
+    }
+
+    scp->history_size = lines * scp->xsize;
+    if (lines > imax(sc_history_size, scp->ysize))
+	extra_history_size -= lines - imax(sc_history_size, scp->ysize);
+    usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 
+			    M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
+    if (usp != NULL)
+	bzero(usp, scp->history_size * sizeof(u_short));
+    scp->history_head = scp->history_pos = usp;
+    scp->history = usp;
 }
 
 static scr_stat
@@ -3606,22 +3167,15 @@ static scr_stat
 
     scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK);
     init_scp(scp);
-    scp->scr_buf = scp->cursor_pos = scp->cursor_oldpos =
-	(u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short),
-			  M_DEVBUF, M_WAITOK);
-    scp->mouse_pos = scp->mouse_oldpos = 
-	scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize +
-			scp->mouse_xpos/8);
-    scp->history_head = scp->history_pos =
-	(u_short *)malloc(scp->history_size*sizeof(u_short),
-			  M_DEVBUF, M_WAITOK);
-    bzero(scp->history_head, scp->history_size*sizeof(u_short));
-    scp->history = scp->history_head;
+    sc_alloc_scr_buffer(scp, TRUE, TRUE);
+    if (ISMOUSEAVAIL(get_adapter(scp)->va_flags))
+	sc_alloc_cut_buffer(scp, TRUE);
+    sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE);
 /* SOS
-    if (crtc_type == KD_VGA && video_mode_ptr)
+    if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE)
 	set_mode(scp);
 */
-    clear_screen(scp);
+    sc_clear_screen(scp);
     scp->cursor_saveunder = *scp->cursor_pos;
     return scp;
 }
@@ -3629,43 +3183,29 @@ static scr_stat
 static void
 init_scp(scr_stat *scp)
 {
-    switch(crtc_type) {
-    case KD_VGA:
-	if (VESA_MODE(bios_video_mode))
-	    scp->mode = bios_video_mode;
-	else if (crtc_addr == MONO_BASE)
-	    scp->mode = M_VGA_M80x25;
-	else
-	    scp->mode = M_VGA_C80x25;
-	scp->font_size = 16;
-	break;
-    case KD_CGA:
-	if (crtc_addr == MONO_BASE)
-	    scp->mode = M_B80x25;
-	else
-	    scp->mode = M_C80x25;
-	scp->font_size = 8;
-	break;
-    case KD_EGA:
-	if (crtc_addr == MONO_BASE)
-	    scp->mode = M_B80x25;
-	else
-	    scp->mode = M_C80x25;
-	scp->font_size = 14;
-	break;
-    case KD_MONO:
-    case KD_HERCULES:
-    default:
-	scp->mode = M_EGAMONO80x25;
-	scp->font_size = 14;
-	break;
-    }
-    scp->initial_mode = scp->mode;
+    video_info_t info;
 
-    scp->xsize = COL;
-    scp->ysize = ROW;
-    scp->xpixel = scp->xsize * 8;
-    scp->ypixel = scp->ysize * scp->font_size;
+    scp->adp = V_ADP_PRIMARY;
+    (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info);
+
+    scp->status = 0;
+    scp->mode = scp->initial_mode = initial_video_mode;
+    scp->scr_buf = NULL;
+    if (info.vi_flags & V_INFO_GRAPHICS) {
+	scp->status |= GRAPHICS_MODE;
+	scp->xpixel = info.vi_width;
+	scp->ypixel = info.vi_height;
+	scp->xsize = info.vi_width/8;
+	scp->ysize = info.vi_height/info.vi_cheight;
+	scp->font_size = FONT_NONE;
+    } else {
+	scp->xsize = info.vi_width;
+	scp->ysize = info.vi_height;
+	scp->xpixel = scp->xsize*8;
+	scp->ypixel = scp->ysize*info.vi_cheight;
+	scp->font_size = info.vi_cheight;
+    }
+    scp->xoff = scp->yoff = 0;
     scp->xpos = scp->ypos = 0;
     scp->saved_xpos = scp->saved_ypos = -1;
     scp->start = scp->xsize * scp->ysize;
@@ -3677,8 +3217,8 @@ init_scp(scr_stat *scp)
 	current_default->std_color;
     scp->term.rev_color = current_default->rev_color;
     scp->border = BG_BLACK;
-    scp->cursor_start = *(char *)pa_to_va(0x461);
-    scp->cursor_end = *(char *)pa_to_va(0x460);
+    scp->cursor_start = *(u_int8_t *)pa_to_va(0x461);
+    scp->cursor_end = *(u_int8_t *)pa_to_va(0x460);
     scp->mouse_xpos = scp->xsize*8/2;
     scp->mouse_ypos = scp->ysize*scp->font_size/2;
     scp->mouse_cut_start = scp->mouse_cut_end = NULL;
@@ -3687,13 +3227,13 @@ init_scp(scr_stat *scp)
     scp->mouse_proc = NULL;
     scp->bell_pitch = BELL_PITCH;
     scp->bell_duration = BELL_DURATION;
-    scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
+    scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0;
     scp->status |= CURSOR_ENABLED;
     scp->pid = 0;
     scp->proc = NULL;
     scp->smode.mode = VT_AUTO;
     scp->history_head = scp->history_pos = scp->history = NULL;
-    scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
+    scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize;
 }
 
 static u_char
@@ -4140,9 +3680,9 @@ next_code:
 			scsplash_stick(FALSE);
 			stop_scrn_saver(current_saver);
 		    } else {
-			if ((cur_console->status & UNKNOWN_MODE) == 0) {
+			if (!ISGRAPHSC(cur_console)) {
 			    scsplash_stick(TRUE);
-			    (*current_saver)(TRUE);
+			    scrn_saver(current_saver, TRUE);
 			}
 		    }
 		}
@@ -4409,475 +3949,100 @@ update_leds(int which)
     set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]);
 }
 
-void
+int
 set_mode(scr_stat *scp)
 {
-    char special_modetable[MODE_PARAM_SIZE];
-    char *mp;
-    int s;
-    int i;
+    video_info_t info;
+    video_adapter_t *adp;
 
+    /* reject unsupported mode */
+    if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
+	return 1;
+
+    /* if this vty is not currently showing, do nothing */
     if (scp != cur_console)
-	return;
-
-    /* 
-     * even if mode switching is disabled, we can change back
-     * to the initial mode or the custom mode based on the initial
-     * mode if we have saved register values upon start-up.
-     */
-    mp = get_mode_param(scp, scp->mode);
-    if (mp == NULL)
-	return;
-    bcopy(mp, &special_modetable, sizeof(special_modetable));
+	return 0;
 
     /* setup video hardware for the given mode */
-    switch (scp->mode) {
-    case M_VGA_C80x60: case M_VGA_M80x60:
-	special_modetable[2]  = 0x08;
-	special_modetable[19] = 0x47;
-	goto special_480l;
+    adp = get_adapter(scp);
+    (*biosvidsw.set_mode)(scp->adp, scp->mode);
+    Crtat = (u_short *)adp->va_window;
 
-    case M_VGA_C80x30: case M_VGA_M80x30:
-	special_modetable[19] = 0x4f;
-special_480l:
-	special_modetable[9] |= 0xc0;
-	special_modetable[16] = 0x08;
-	special_modetable[17] = 0x3e;
-	special_modetable[26] = 0xea;
-	special_modetable[28] = 0xdf;
-	special_modetable[31] = 0xe7;
-	special_modetable[32] = 0x04;
-	goto setup_mode;
-
-    case M_ENH_C80x43: case M_ENH_B80x43:
-	special_modetable[28] = 87;
-	goto special_80x50;
-
-    case M_VGA_C80x50: case M_VGA_M80x50:
-special_80x50:
-	special_modetable[2] = 8;
-	special_modetable[19] = 7;
-	goto setup_mode;
-
-    case M_VGA_C40x25: case M_VGA_C80x25:
-    case M_VGA_M80x25:
-    case M_B40x25:     case M_C40x25:
-    case M_B80x25:     case M_C80x25:
-    case M_ENH_B40x25: case M_ENH_C40x25:
-    case M_ENH_B80x25: case M_ENH_C80x25:
-    case M_EGAMONO80x25:
-
-setup_mode:
-	set_vgaregs(special_modetable);
-	scp->font_size = special_modetable[2];
-
-	/* set font type (size) */
-	if (scp->font_size < 14) {
-	    if (fonts_loaded & FONT_8)
-		copy_font(LOAD, FONT_8, font_8);
-	    i = 0x0a;				/* font 2 */
-	} else if (scp->font_size >= 16) {
-	    if (fonts_loaded & FONT_16)
-		copy_font(LOAD, FONT_16, font_16);
-	    i = 0x00;				/* font 0 */
-	} else {
-	    if (fonts_loaded & FONT_14)
-		copy_font(LOAD, FONT_14, font_14);
-	    i = 0x05;				/* font 1 */
+    if (!(scp->status & GRAPHICS_MODE)) {
+	/* load appropriate font */
+	if (!(scp->status & PIXEL_MODE) 
+	    && ISFONTAVAIL(get_adapter(scp)->va_flags)) {
+	    if (scp->font_size < 14) {
+		if (fonts_loaded & FONT_8)
+		    copy_font(scp, LOAD, 8, font_8);
+	    } else if (scp->font_size >= 16) {
+		if (fonts_loaded & FONT_16)
+		    copy_font(scp, LOAD, 16, font_16);
+	    } else {
+		if (fonts_loaded & FONT_14)
+		    copy_font(scp, LOAD, 14, font_14);
+	    }
+	    /*
+	    * FONT KLUDGE:
+	    * This is an interim kludge to display correct font.
+	    * Always use the font page #0 on the video plane 2.
+	    * Somehow we cannot show the font in other font pages on
+	    * some video cards... XXX
+	    */ 
+	    (*biosvidsw.show_font)(scp->adp, 0);
 	}
-	/*
-	 * FONT KLUDGE:
-	 * This is an interim kludge to display correct font.
-	 * Always use the font page #0 on the video plane 2.
-	 * Somehow we cannot show the font in other font pages on
-	 * some video cards... XXX
-	 */
-	i = 0x00;
-	s = splhigh();
-	outb(TSIDX, 0x00); outb(TSREG, 0x01);
-	outb(TSIDX, 0x03); outb(TSREG, i);
-	outb(TSIDX, 0x00); outb(TSREG, 0x03);
-	splx(s);
+	mark_all(scp);
+    }
+    set_border(scp, scp->border);
+
+    /* move hardware cursor out of the way */
+    (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
+
+    return 0;
+}
+
+void
+copy_font(scr_stat *scp, int operation, int font_size, u_char *buf)
+{
+    /*
+     * FONT KLUDGE:
+     * This is an interim kludge to display correct font.
+     * Always use the font page #0 on the video plane 2.
+     * Somehow we cannot show the font in other font pages on
+     * some video cards... XXX
+     */ 
+    font_loading_in_progress = TRUE;
+    if (operation == LOAD) {
+	(*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256);
 	if (flags & CHAR_CURSOR)
 	    set_destructive_cursor(scp);
-	mark_all(scp);
-	break;
-
-    case M_VGA_MODEX:
-	/* "unchain" the VGA mode */
-	special_modetable[5-1+0x04] &= 0xf7;
-	special_modetable[5-1+0x04] |= 0x04;
-	/* turn off doubleword mode */
-	special_modetable[10+0x14] &= 0xbf;
-	/* turn off word adressing */
-	special_modetable[10+0x17] |= 0x40;
-	/* set logical screen width */
-	special_modetable[10+0x13] = 80;
-	/* set 240 lines */
-	special_modetable[10+0x11] = 0x2c;
-	special_modetable[10+0x06] = 0x0d;
-	special_modetable[10+0x07] = 0x3e;
-	special_modetable[10+0x10] = 0xea;
-	special_modetable[10+0x11] = 0xac;
-	special_modetable[10+0x12] = 0xdf;
-	special_modetable[10+0x15] = 0xe7;
-	special_modetable[10+0x16] = 0x06;
-	/* set vertical sync polarity to reflect aspect ratio */
-	special_modetable[9] = 0xe3;
-	goto setup_grmode;
-
-    case M_BG320:     case M_CG320:     case M_BG640:
-    case M_CG320_D:   case M_CG640_E:
-    case M_CG640x350: case M_ENH_CG640:
-    case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
-
-setup_grmode:
-	set_vgaregs(special_modetable);
-	scp->font_size = FONT_NONE;
-	break;
-
-    default:
-	/* call user defined function XXX */
-	break;
+    } else if (operation == SAVE) {
+	(*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256);
     }
-
-    /* set border color for this (virtual) console */
-    set_border(scp->border);
-    return;
-}
-
-void
-set_border(u_char color)
-{
-    switch (crtc_type) {
-    case KD_EGA:
-    case KD_VGA:
-        inb(crtc_addr + 6);		/* reset flip-flop */
-        outb(ATC, 0x31); outb(ATC, color);
-	break;
-    case KD_CGA:
-	outb(crtc_addr + 5, color & 0x0f); /* color select register */
-	break;
-    case KD_MONO:
-    case KD_HERCULES:
-    default:
-	break;
-    }
-}
-
-static void
-set_vgaregs(char *modetable)
-{
-    int i, s = splhigh();
-
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);   	/* stop sequencer */
-    for (i=0; i<4; i++) {           		/* program sequencer */
-	outb(TSIDX, i+1);
-	outb(TSREG, modetable[i+5]);
-    }
-    outb(MISC, modetable[9]);       		/* set dot-clock */
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);   	/* start sequencer */
-    outb(crtc_addr, 0x11);
-    outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F);
-    for (i=0; i<25; i++) {          		/* program crtc */
-	outb(crtc_addr, i);
-	if (i == 14 || i == 15)     		/* no hardware cursor */
-	    outb(crtc_addr+1, 0xff);
-	else
-	    outb(crtc_addr+1, modetable[i+10]);
-    }
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    for (i=0; i<20; i++) {          		/* program attribute ctrl */
-	outb(ATC, i);
-	outb(ATC, modetable[i+35]);
-    }
-    for (i=0; i<9; i++) {           		/* program graph data ctrl */
-	outb(GDCIDX, i);
-	outb(GDCREG, modetable[i+55]);
-    }
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-    splx(s);
-}
-
-static void
-read_vgaregs(char *buf)
-{
-    int i, j;
-    int s;
-
-    bzero(buf, MODE_PARAM_SIZE);
-
-    s = splhigh();
-
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);   	/* stop sequencer */
-    for (i=0, j=5; i<4; i++) {           
-	outb(TSIDX, i+1);
-	buf[j++] = inb(TSREG);
-    }
-    buf[9] = inb(MISC + 10);      		/* dot-clock */
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);   	/* start sequencer */
-
-    for (i=0, j=10; i<25; i++) {       		/* crtc */
-	outb(crtc_addr, i);
-	buf[j++] = inb(crtc_addr+1);
-    }
-    for (i=0, j=35; i<20; i++) {          	/* attribute ctrl */
-        inb(crtc_addr+6);           		/* reset flip-flop */
-	outb(ATC, i);
-	buf[j++] = inb(ATC + 1);
-    }
-    for (i=0, j=55; i<9; i++) {           	/* graph data ctrl */
-	outb(GDCIDX, i);
-	buf[j++] = inb(GDCREG);
-    }
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-
-    buf[0] = *(char *)pa_to_va(0x44a);		/* COLS */
-    buf[1] = *(char *)pa_to_va(0x484);		/* ROWS */
-    buf[2] = *(char *)pa_to_va(0x485);		/* POINTS */
-    buf[3] = *(char *)pa_to_va(0x44c);
-    buf[4] = *(char *)pa_to_va(0x44d);
-
-    splx(s);
-}
-
-static int 
-comp_vgaregs(u_char *buf1, u_char *buf2)
-{
-    static struct {
-        u_char mask;
-    } params[MODE_PARAM_SIZE] = {
-	0xff, 0x00, 0xff, 		/* COLS, ROWS, POINTS */
-	0xff, 0xff, 			/* page length */
-	0xfe, 0xff, 0xff, 0xff,		/* sequencer registers */
-	0xf3,				/* misc register */
-	0xff, 0xff, 0xff, 0x7f, 0xff,	/* CRTC */
-	0xff, 0xff, 0xff, 0x7f, 0xff,
-	0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0xff, 0x7f, 0xff, 0xff,
-	0x7f, 0xff, 0xff, 0xef, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff,	/* attribute controller registers */
-	0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xf0,
-	0xff, 0xff, 0xff, 0xff, 0xff,	/* GDC register */
-	0xff, 0xff, 0xff, 0xff, 
-    }; 
-    int identical = TRUE;
-    int i;
-
-    for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
-	if (params[i].mask == 0)	/* don't care */
-	    continue;
-	if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
-	    return COMP_DIFFERENT;
-	if (buf1[i] != buf2[i])
-	    identical = FALSE;
-    }
-    return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
-
-#if 0
-    for(i = 0; i < 20; ++i) {
-	if (*buf1++ != *buf2++)
-	    return COMP_DIFFERENT;
-    }
-    buf1 += 2;  /* skip the cursor shape */
-    buf2 += 2;
-    for(i = 22; i < 24; ++i) {
-	if (*buf1++ != *buf2++)
-	    return COMP_DIFFERENT;
-    }
-    buf1 += 2;  /* skip the cursor position */
-    buf2 += 2;
-    for(i = 26; i < MODE_PARAM_SIZE; ++i) {
-	if (*buf1++ != *buf2++)
-	    return COMP_DIFFERENT;
-    }
-    return COMP_IDENTICAL;
-#endif
-}
-
-static void
-dump_vgaregs(u_char *buf)
-{
-    int i;
-
-    for(i = 0; i < MODE_PARAM_SIZE;) {
-	printf("%02x ", buf[i]);
-	if ((++i % 16) == 0)
-	    printf("\n");
-    }
-}
-
-static void
-set_font_mode(u_char *buf)
-{
-    int s = splhigh();
-
-    font_loading_in_progress = TRUE;
-
-    /* save register values */
-    outb(TSIDX, 0x02); buf[0] = inb(TSREG);
-    outb(TSIDX, 0x04); buf[1] = inb(TSREG);
-    outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
-    outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
-    outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
-    inb(crtc_addr + 6);
-    outb(ATC, 0x10); buf[5] = inb(ATC + 1);
-
-    /* setup vga for loading fonts */
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
-    inb(crtc_addr+6);               		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-
-#if SLOW_VGA
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);
-#endif
-    outb(TSIDX, 0x02); outb(TSREG, 0x04);
-    outb(TSIDX, 0x04); outb(TSREG, 0x07);
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);
-#endif
-    outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
-    outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
-    outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
-#else
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0100);
-#endif
-    outw(TSIDX, 0x0402);
-    outw(TSIDX, 0x0704);
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0300);
-#endif
-    outw(GDCIDX, 0x0204);
-    outw(GDCIDX, 0x0005);
-    outw(GDCIDX, 0x0406);               /* addr = a0000, 64kb */
-#endif
-    splx(s);
-}
-
-static void
-set_normal_mode(u_char *buf)
-{
-    char *modetable;
-    int s = splhigh();
-
-    /* setup vga for normal operation mode again */
-    inb(crtc_addr+6);           		/* reset flip-flop */
-    outb(ATC, 0x10); outb(ATC, buf[5]);
-    inb(crtc_addr+6);               		/* reset flip-flop */
-    outb(ATC, 0x20);            		/* enable palette */
-
-#if SLOW_VGA
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x01);
-#endif
-    outb(TSIDX, 0x02); outb(TSREG, buf[0]);
-    outb(TSIDX, 0x04); outb(TSREG, buf[1]);
-#ifndef SC_BAD_FLICKER
-    outb(TSIDX, 0x00); outb(TSREG, 0x03);
-#endif
-    outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
-    outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
-    if (crtc_addr == MONO_BASE) {
-	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
-    } else {
-	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
-    }
-#else
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0100);
-#endif
-    outw(TSIDX, 0x0002 | (buf[0] << 8));
-    outw(TSIDX, 0x0004 | (buf[1] << 8));
-#ifndef SC_BAD_FLICKER
-    outw(TSIDX, 0x0300);
-#endif
-    outw(GDCIDX, 0x0004 | (buf[2] << 8));
-    outw(GDCIDX, 0x0005 | (buf[3] << 8));
-    if (crtc_addr == MONO_BASE)
-        outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
-    else
-        outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
-#endif
-
     font_loading_in_progress = FALSE;
-    splx(s);
-}
-
-void
-copy_font(int operation, int font_type, char* font_image)
-{
-    int ch, line, segment, fontsize;
-    u_char buf[PARAM_BUFSIZE];
-    u_char val;
-
-    switch (font_type) {
-    default:
-    case FONT_8:
-	segment = 0x8000;
-	fontsize = 8;
-	break;
-    case FONT_14:
-	segment = 0x4000;
-	fontsize = 14;
-	break;
-    case FONT_16:
-	segment = 0x0000;
-	fontsize = 16;
-	break;
-    }
-    /*
-     * FONT KLUDGE
-     * Always use the font page #0. XXX
-     */
-    segment = 0x0000;
-    outb(TSIDX, 0x01); val = inb(TSREG);        /* disable screen */
-    outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
-    set_font_mode(buf);
-    for (ch=0; ch < 256; ch++)
-	for (line=0; line < fontsize; line++)
-	if (operation)
-	    *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) =
-		    font_image[(ch*fontsize)+line];
-	else
-	    font_image[(ch*fontsize)+line] =
-	    *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line);
-    set_normal_mode(buf);
-    outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */
 }
 
 static void
 set_destructive_cursor(scr_stat *scp)
 {
-    u_char buf[PARAM_BUFSIZE];
     u_char cursor[32];
-    caddr_t address;
+    u_char *font_buffer;
+    int font_size;
     int i;
-    char *font_buffer;
+
+    if (!ISFONTAVAIL(get_adapter(scp)->va_flags) || !ISTEXTSC(scp))
+	return;
 
     if (scp->font_size < 14) {
 	font_buffer = font_8;
-	address = (caddr_t)VIDEOMEM + 0x8000;
-    }
-    else if (scp->font_size >= 16) {
+	font_size = 8;
+    } else if (scp->font_size >= 16) {
 	font_buffer = font_16;
-	address = (caddr_t)VIDEOMEM;
-    }
-    else {
+	font_size = 16;
+    } else {
 	font_buffer = font_14;
-	address = (caddr_t)VIDEOMEM + 0x4000;
+	font_size = 14;
     }
-    /*
-     * FONT KLUDGE
-     * Always use the font page #0. XXX
-     */
-    address = (caddr_t)VIDEOMEM;
 
     if (scp->status & MOUSE_VISIBLE) {
 	if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR)
@@ -4902,9 +4067,18 @@ set_destructive_cursor(scr_stat *scp)
 #if 1
     while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ;
 #endif
-    set_font_mode(buf);
-    generic_bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32);
-    set_normal_mode(buf);
+    font_loading_in_progress = TRUE;
+    (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1);
+    font_loading_in_progress = FALSE;
+}
+
+void
+sc_move_mouse(scr_stat *scp, int x, int y)
+{
+    scp->mouse_xpos = x;
+    scp->mouse_ypos = y;
+    scp->mouse_pos = scp->mouse_oldpos = 
+	scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8;
 }
 
 static void
@@ -4916,7 +4090,7 @@ set_mouse_pos(scr_stat *scp)
 	scp->mouse_xpos = 0;
     if (scp->mouse_ypos < 0)
 	scp->mouse_ypos = 0;
-    if (scp->status & UNKNOWN_MODE) {
+    if (!ISTEXTSC(scp)) {
         if (scp->mouse_xpos > scp->xpixel-1)
 	    scp->mouse_xpos = scp->xpixel-1;
         if (scp->mouse_ypos > scp->ypixel-1)
@@ -5146,35 +4320,26 @@ mouse_paste(scr_stat *scp)
 static void
 draw_mouse_image(scr_stat *scp)
 {
-    caddr_t address;
-    int i;
-    char *font_buffer;
-    u_char buf[PARAM_BUFSIZE];
     u_short buffer[32];
     u_short xoffset, yoffset;
     u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf);
-    int font_size = scp->font_size;
+    u_char *font_buffer;
+    int font_size;
+    int i;
 
-    if (font_size < 14) {
+    if (scp->font_size < 14) {
 	font_buffer = font_8;
-	address = (caddr_t)VIDEOMEM + 0x8000;
-    }
-    else if (font_size >= 16) {
+	font_size = 8;
+    } else if (scp->font_size >= 16) {
 	font_buffer = font_16;
-	address = (caddr_t)VIDEOMEM;
-    }
-    else {
+	font_size = 16;
+    } else {
 	font_buffer = font_14;
-	address = (caddr_t)VIDEOMEM + 0x4000;
+	font_size = 14;
     }
-    /*
-     * FONT KLUDGE
-     * Always use the font page #0. XXX
-     */
-    address = (caddr_t)VIDEOMEM;
 
     xoffset = scp->mouse_xpos % 8;
-    yoffset = scp->mouse_ypos % font_size;
+    yoffset = scp->mouse_ypos % scp->font_size;
 
     /* prepare mousepointer char's bitmaps */
     bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size),
@@ -5209,9 +4374,11 @@ draw_mouse_image(scr_stat *scp)
     /* wait for vertical retrace to avoid jitter on some videocards */
     while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ;
 #endif
-    set_font_mode(buf);
-    generic_bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + SC_MOUSE_CHAR * 32, 128);
-    set_normal_mode(buf);
+    font_loading_in_progress = TRUE;
+    (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, 
+			   SC_MOUSE_CHAR, 4); 
+    font_loading_in_progress = FALSE;
+
     *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR;
     *(crt_pos+scp->xsize) = 
 	(*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2);
@@ -5229,6 +4396,8 @@ remove_mouse_image(scr_stat *scp)
 {
     u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf);
 
+    if (!ISTEXTSC(scp))
+	return;
     *(crt_pos) = *(scp->mouse_oldpos);
     *(crt_pos+1) = *(scp->mouse_oldpos+1);
     *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize);
@@ -5278,30 +4447,6 @@ remove_cutmarking(scr_stat *scp)
     mark_all(scp);
 }
 
-static void
-save_palette(void)
-{
-    int i;
-
-    outb(PALRADR, 0x00);
-    for (i=0x00; i<0x300; i++)
-	palette[i] = inb(PALDATA);
-    inb(crtc_addr+6);           /* reset flip/flop */
-}
-
-void
-load_palette(char *palette)
-{
-    int i;
-
-    outb(PIXMASK, 0xFF);            /* no pixelmask */
-    outb(PALWADR, 0x00);
-    for (i=0x00; i<0x300; i++)
-	 outb(PALDATA, palette[i]);
-    inb(crtc_addr+6);           /* reset flip/flop */
-    outb(ATC, 0x20);            /* enable palette */
-}
-
 static void
 do_bell(scr_stat *scp, int pitch, int duration)
 {
@@ -5330,7 +4475,7 @@ blink_screen(void *arg)
 {
     scr_stat *scp = arg;
 
-    if ((scp->status & UNKNOWN_MODE) || (blink_in_progress <= 1)) {
+    if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) {
 	blink_in_progress = FALSE;
     	mark_all(scp);
 	if (delayed_next_scr)
@@ -5351,25 +4496,41 @@ blink_screen(void *arg)
 void 
 sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
 {
-    if (!VESA_MODE(scp->mode)) {
-	generic_bcopy(p+from, Crtat+from, (to-from+1)*sizeof (u_short));
-    } else if (scp->mode == 0x102) {
-	u_char *d, *e;
-	int i,j;
+    u_char *font;
+    u_char *d, *e;
+    u_char *f;
+    int font_size;
+    int line_length;
+    int xsize;
+    int i, j;
 
+    if (ISTEXTSC(scp)) {
+	generic_bcopy(p+from, Crtat+from, (to-from+1)*sizeof (u_short));
+    } else /* if ISPIXELSC(scp) */ {
 	if (mark)
-		mark = 255;
-	d = (u_char *)Crtat;
-	d += 10 + 6*16*100 + (from%80) + 16*100*(from/80);
+	    mark = 255;
+	font_size = scp->font_size;
+	if (font_size < 14)
+	    font = font_8;
+	else if (font_size >= 16)
+	    font = font_16;
+	else
+	    font = font_14;
+	line_length = scp->xpixel/8;
+	xsize = scp->xsize;
+	d = (u_char *)Crtat 
+	    + scp->xoff + scp->yoff*font_size*line_length 
+	    + (from%xsize) + font_size*line_length*(from/xsize);
 	for (i = from ; i <= to ; i++) {
 	    e = d;
-	    for (j = 0 ; j < 16; j++) {
-	        *e = mark^font_16[(p[i]&0xff)*16+j];
-		e+=100;
+	    f = &font[(p[i] & 0x00ff)*font_size];
+	    for (j = 0 ; j < font_size; j++, f++) {
+	        *e = mark^*f;
+		e += line_length;
 	    }
 	    d++;
-	    if ((i % 80) == 79)
-		d += 20 + 15*100;
+	    if ((i % xsize) == xsize - 1)
+		d += scp->xoff*2 + (font_size - 1)*line_length;
 	}
     }
 }
@@ -5377,34 +4538,36 @@ sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark)
 #ifdef SC_SPLASH_SCREEN
 
 static void
-scsplash_init(void)
+scsplash_init(scr_stat *scp)
 {
+    video_info_t info;
+
     /* 
      * We currently assume the splash screen always use
      * VGA_CG320 mode and abort installation if this mode is not
      * supported with this video card. XXX
      */
-    if (crtc_type != KD_VGA || get_mode_param(cur_console, M_VGA_CG320) == NULL)
+    if ((*biosvidsw.get_info)(scp->adp, M_VGA_CG320, &info))
 	return;
 
-    if (splash_load() == 0 && add_scrn_saver(scsplash) == 0) {
-	default_saver = scsplash;
+    if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) {
+	default_saver = scsplash_saver;
 	scrn_blank_time = DEFAULT_BLANKTIME;
 	run_scrn_saver = TRUE;
-	if (!(boothowto & RB_CONFIG)) {
+	if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) {
 	    scsplash_stick(TRUE);
-	    scsplash(TRUE);
+	    scsplash_saver(TRUE);
 	}
     }
 }
 
 static void
-scsplash(int show)
+scsplash_saver(int show)
 {
     if (show)
-	splash(TRUE);
+	scsplash(TRUE);
     else if (!sticky_splash)
-	splash(FALSE);
+	scsplash(FALSE);
 }
 
 #endif /* SC_SPLASH_SCREEN */
diff --git a/sys/i386/isa/syscons.h b/sys/i386/isa/syscons.h
index b23a2ae7c5da..315946b57305 100644
--- a/sys/i386/isa/syscons.h
+++ b/sys/i386/isa/syscons.h
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995-1997 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: syscons.h,v 1.38 1998/08/03 09:09:35 yokota Exp $
+ *	$Id$
  */
 
 #ifndef _I386_ISA_SYSCONS_H_
@@ -65,6 +65,9 @@
 #define MOUSE_MOVED	0x01000
 #define MOUSE_CUTTING	0x02000
 #define MOUSE_VISIBLE	0x04000
+#define GRAPHICS_MODE	0x08000
+#define PIXEL_MODE	0x10000
+#define SAVER_RUNNING	0x20000
 
 /* configuration flags */
 #define VISUAL_BELL	0x00001
@@ -74,6 +77,7 @@
 #define XT_KEYBD	0x00010
 #define KBD_NORESET	0x00020
 #define QUIET_BELL	0x00040
+#define VESA800X600	0x00080
 
 /* attribute flags */
 #define NORMAL_ATTR             0x00
@@ -84,9 +88,6 @@
 #define FOREGROUND_CHANGED      0x10
 #define BACKGROUND_CHANGED      0x20
 
-/* video hardware memory addresses */
-#define VIDEOMEM	0x000A0000
-
 /* misc defines */
 #define FALSE		0
 #define TRUE		1
@@ -104,20 +105,6 @@
 #define FONT_14		4
 #define FONT_16		8
 
-/* defines related to hardware addresses */
-#define	MONO_BASE	0x3B4			/* crt controller base mono */
-#define	COLOR_BASE	0x3D4			/* crt controller base color */
-#define MISC		0x3C2			/* misc output register */
-#define ATC		IO_VGA+0x00		/* attribute controller */
-#define TSIDX		IO_VGA+0x04		/* timing sequencer idx */
-#define TSREG		IO_VGA+0x05		/* timing sequencer data */
-#define PIXMASK		IO_VGA+0x06		/* pixel write mask */
-#define PALRADR		IO_VGA+0x07		/* palette read address */
-#define PALWADR		IO_VGA+0x08		/* palette write address */
-#define PALDATA		IO_VGA+0x09		/* palette data register */
-#define GDCIDX		IO_VGA+0x0E		/* graph data controller idx */
-#define GDCREG		IO_VGA+0x0F		/* graph data controller data */
-
 /* special characters */
 #define cntlc		0x03
 #define cntld		0x04
@@ -141,6 +128,7 @@ typedef struct term_stat {
 } term_stat;
 
 typedef struct scr_stat {
+	int		adp;			/* video adapter index */
 	u_short 	*scr_buf;		/* buffer when off screen */
 	int 		xpos;			/* current X position */
 	int 		ypos;			/* current Y position */
@@ -150,6 +138,8 @@ typedef struct scr_stat {
 	int 		ysize;			/* Y text size */
 	int 		xpixel;			/* X graphics size */
 	int 		ypixel;			/* Y graphics size */
+	int		xoff;			/* X offset in pixel mode */
+	int		yoff;			/* Y offset in pixel mode */
 	int		font_size;		/* fontsize in Y direction */
 	int		start;			/* modified area start */
 	int		end;			/* modified area end */
@@ -186,7 +176,8 @@ typedef struct scr_stat {
 	int		history_size;		/* size of history buffer */
 	struct apmhook  r_hook;			/* reconfiguration support */
 #ifdef SC_SPLASH_SCREEN
-	u_char		splash_save_mode;	/* saved mode for splash screen */
+	int		splash_save_mode;	/* saved mode for splash screen */
+	int		splash_save_status;	/* saved status for splash screen */
 #endif
 } scr_stat;
 
@@ -195,18 +186,59 @@ typedef struct default_attr {
 	int             rev_color;              /* reverse hardware color */
 } default_attr;
 
+
+#define ISTEXTSC(scp)	(!((scp)->status 				\
+			  & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE)))
+#define ISGRAPHSC(scp)	(((scp)->status 				\
+			  & (UNKNOWN_MODE | GRAPHICS_MODE)))
+#define ISPIXELSC(scp)	(((scp)->status 				\
+			  & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE))\
+			  == PIXEL_MODE)
+#define ISUNKNOWNSC(scp) ((scp)->status & UNKNOWN_MODE)
+
+#define ISFONTAVAIL(af)	((af) & V_ADP_FONT)
+#define ISMOUSEAVAIL(af) ((af) & V_ADP_FONT)
+#define ISPALAVAIL(af)	((af) & V_ADP_PALETTE)
+
 /* misc prototypes used by different syscons related LKM's */
-void set_border(u_char color);
-void set_mode(scr_stat *scp);
-void copy_font(int operation, int font_type, char* font_image);
-void load_palette(char *palette);
+
+/* syscons.c */
+extern int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, int flag, 
+			    struct proc *p);
+
+int set_mode(scr_stat *scp);
+scr_stat *sc_get_scr_stat(dev_t dev);
+
+void copy_font(scr_stat *scp, int operation, int font_size, u_char *font_image);
+#define save_palette(scp, pal)	(*biosvidsw.save_palette)((scp)->adp, pal)
+#define load_palette(scp, pal)	(*biosvidsw.load_palette)((scp)->adp, pal)
+#define set_border(scp, col)	(*biosvidsw.set_border)((scp)->adp, col)
+#define get_adapter(scp)	(*biosvidsw.adapter)((scp)->adp)
+
 int add_scrn_saver(void (*this)(int));
 int remove_scrn_saver(void (*this)(int));
 
+void sc_clear_screen(scr_stat *scp);
+void sc_move_mouse(scr_stat *scp, int x, int y);
+int sc_clean_up(scr_stat *scp);
+void sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear);
+void sc_alloc_cut_buffer(scr_stat *scp, int wait);
+void sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait);
+
+/* scvidctl.c */
+int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode,
+		     int xsize, int ysize, int fontsize);
+int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode);
+int sc_set_pixel_mode(scr_stat *scp, struct tty *tp,
+		      int xsize, int ysize, int fontsize);
+int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, 
+		 struct proc *p);
+
 #ifdef SC_SPLASH_SCREEN
-void splash(int);
-int splash_load(void);
-int splash_unload(void);
+/* splash.c */
+void scsplash(int);
+int scsplash_load(scr_stat *scp);
+int scsplash_unload(scr_stat *scp);
 #endif
 
 #endif /* !_I386_ISA_SYSCONS_H_ */
diff --git a/sys/i386/isa/vesa.c b/sys/i386/isa/vesa.c
new file mode 100644
index 000000000000..768b647e5cd1
--- /dev/null
+++ b/sys/i386/isa/vesa.c
@@ -0,0 +1,868 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "sc.h"
+#include "opt_vesa.h"
+#include "opt_vm86.h"
+
+#if (NSC > 0 && defined(VESA) && defined(VM86)) || defined(VESA_MODULE)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/console.h>
+#include <machine/md_var.h>
+#include <machine/vm86.h>
+#include <machine/pc/bios.h>
+#include <machine/pc/vesa.h>
+
+#include <i386/isa/videoio.h>
+
+#ifdef VESA_MODULE
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+
+MOD_MISC(vesa);
+#endif
+
+/* VESA video adapter state buffer stub */
+struct adp_state {
+	int		sig;
+#define V_STATE_SIG	0x61736576
+	u_char		regs[1];
+};
+typedef struct adp_state adp_state_t;
+
+/* VESA video adapter */
+static video_adapter_t *vesa_adp = NULL;
+static int vesa_state_buf_size = 0;
+static void *vesa_state_buf = NULL;
+
+/* VESA functions */
+static vi_init_t		vesa_init;
+static vi_adapter_t		vesa_adapter;
+static vi_get_info_t		vesa_get_info;
+static vi_query_mode_t		vesa_query_mode;
+static vi_set_mode_t		vesa_set_mode;
+static vi_save_font_t		vesa_save_font;
+static vi_load_font_t		vesa_load_font;
+static vi_show_font_t		vesa_show_font;
+static vi_save_palette_t	vesa_save_palette;
+static vi_load_palette_t	vesa_load_palette;
+static vi_set_border_t		vesa_set_border;
+static vi_save_state_t		vesa_save_state;
+static vi_load_state_t		vesa_load_state;
+static vi_set_win_org_t		vesa_set_origin;
+static vi_read_hw_cursor_t	vesa_read_hw_cursor;
+static vi_set_hw_cursor_t	vesa_set_hw_cursor;
+static vi_diag_t		vesa_diag;
+
+static struct vidsw vesavidsw = {
+	vesa_init,	vesa_adapter,	vesa_get_info,	vesa_query_mode,
+	vesa_set_mode,	vesa_save_font,	vesa_load_font,	vesa_show_font,
+	vesa_save_palette,vesa_load_palette,vesa_set_border,vesa_save_state,
+	vesa_load_state,vesa_set_origin,vesa_read_hw_cursor,vesa_set_hw_cursor,
+	vesa_diag,
+};
+
+static struct vidsw prevvidsw;
+
+/* VESA BIOS video modes */
+#define VESA_MAXMODES	64
+#define EOT		(-1)
+#define NA		(-2)
+
+static video_info_t vesa_vmode[VESA_MAXMODES + 1] = {
+	{ EOT, },
+};
+
+static int vesa_init_done = FALSE;
+static int has_vesa_bios = FALSE;
+static struct vesa_info *vesa_adp_info = NULL;
+static u_int16_t *vesa_vmodetab = NULL;
+
+/* local macros and functions */
+#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
+
+static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode);
+static int vesa_bios_set_mode(int mode);
+static int vesa_bios_set_dac(int bits);
+static int vesa_bios_save_palette(int start, int colors, u_char *palette);
+static int vesa_bios_load_palette(int start, int colors, u_char *palette);
+#define STATE_SIZE	0
+#define STATE_SAVE	1
+#define STATE_LOAD	2
+#define STATE_HW	(1<<0)
+#define STATE_DATA	(1<<1)
+#define STATE_DAC	(1<<2)
+#define STATE_REG	(1<<3)
+#define STATE_MOST	(STATE_HW | STATE_DATA | STATE_REG)
+#define STATE_ALL	(STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)
+static int vesa_bios_state_buf_size(void);
+static int vesa_bios_save_restore(int code, void *p, size_t size);
+static int translate_flags(u_int16_t vflags);
+static int vesa_bios_init(void);
+static void clear_modes(video_info_t *info, int color);
+
+static void
+dump_buffer(u_char *buf, size_t len)
+{
+    int i;
+
+    for(i = 0; i < len;) {
+	printf("%02x ", buf[i]);
+	if ((++i % 16) == 0)
+	    printf("\n");
+    }
+}
+
+/* VESA BIOS calls */
+static int
+vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
+{
+	struct vm86frame vmf;
+	u_char buf[256];
+	int err;
+
+	bzero(&vmf, sizeof(vmf));
+	bzero(buf, sizeof(buf));  
+	vmf.vmf_eax = 0x4f01; 
+	vmf.vmf_ecx = mode;
+	err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf),
+			  &vmf.vmf_es, &vmf.vmf_di);
+	if ((err != 0) || (vmf.vmf_eax != 0x4f))
+		return 1;
+	bcopy(buf, vmode, sizeof(*vmode));
+	return 0;
+}
+
+static int
+vesa_bios_set_mode(int mode)
+{
+	struct vm86frame vmf;
+	int err;
+
+	bzero(&vmf, sizeof(vmf));
+	vmf.vmf_eax = 0x4f02;
+	vmf.vmf_ebx = mode;
+	err = vm86_intcall(0x10, &vmf);
+	return ((err != 0) || (vmf.vmf_eax != 0x4f));
+}
+
+static int
+vesa_bios_set_dac(int bits)
+{
+	struct vm86frame vmf;
+	int err;
+
+	bzero(&vmf, sizeof(vmf));
+	vmf.vmf_eax = 0x4f08;
+	vmf.vmf_ebx = (bits << 8);
+	err = vm86_intcall(0x10, &vmf);
+	return ((err != 0) || (vmf.vmf_eax != 0x4f));
+}
+
+static int
+vesa_bios_save_palette(int start, int colors, u_char *palette)
+{
+	struct vm86frame vmf;
+	u_char *p;
+	int err;
+	int i;
+
+	p = malloc(colors*4, M_DEVBUF, M_WAITOK);
+
+	bzero(&vmf, sizeof(vmf));
+	vmf.vmf_eax = 0x4f09;
+	vmf.vmf_ebx = 1;	/* get primary palette data */
+	vmf.vmf_ecx = colors;
+	vmf.vmf_edx = start;
+	err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
+	if ((err != 0) || (vmf.vmf_eax != 0x4f)) {
+		free(p, M_DEVBUF);
+		return 1;
+	}
+
+	for (i = 0; i < colors; ++i) {
+		palette[i*3]     = p[i*4 + 1];
+		palette[i*3 + 1] = p[i*4 + 2];
+		palette[i*3 + 2] = p[i*4 + 3];
+	}
+	free(p, M_DEVBUF);
+	return 0;
+}
+
+static int
+vesa_bios_load_palette(int start, int colors, u_char *palette)
+{
+	struct vm86frame vmf;
+	u_char *p;
+	int err;
+	int i;
+
+	p = malloc(colors*4, M_DEVBUF, M_WAITOK);
+	for (i = 0; i < colors; ++i) {
+		p[i*4]     = 0;
+		p[i*4 + 1] = palette[i*3];
+		p[i*4 + 2] = palette[i*3 + 1];
+		p[i*4 + 3] = palette[i*3 + 2];
+	}
+
+	bzero(&vmf, sizeof(vmf));
+	vmf.vmf_eax = 0x4f09;
+	vmf.vmf_ebx = 0;	/* set primary palette data */
+	vmf.vmf_ecx = colors;
+	vmf.vmf_edx = start;
+	err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
+	free(p, M_DEVBUF);
+	return ((err != 0) || (vmf.vmf_eax != 0x4f));
+}
+
+static int
+vesa_bios_state_buf_size(void)
+{
+	struct vm86frame vmf;
+	int err;
+
+	bzero(&vmf, sizeof(vmf));
+	vmf.vmf_eax = 0x4f04; 
+	vmf.vmf_ecx = STATE_MOST;
+	vmf.vmf_edx = STATE_SIZE;
+	err = vm86_intcall(0x10, &vmf);
+	if ((err != 0) || (vmf.vmf_eax != 0x4f))
+		return 0;
+	return vmf.vmf_ebx*64;
+}
+
+static int
+vesa_bios_save_restore(int code, void *p, size_t size)
+{
+	struct vm86frame vmf;
+	int err;
+
+	bzero(&vmf, sizeof(vmf));
+	vmf.vmf_eax = 0x4f04; 
+	vmf.vmf_ecx = STATE_MOST;
+	vmf.vmf_edx = code;	/* STATE_SAVE/STATE_LOAD */
+	err = vm86_datacall(0x10, &vmf, (char *)p, size,
+			  &vmf.vmf_es, &vmf.vmf_bx);
+	return ((err != 0) || (vmf.vmf_eax != 0x4f));
+}
+
+static int
+translate_flags(u_int16_t vflags)
+{
+	static struct {
+		u_int16_t mask;
+		int set;
+		int reset;
+	} ftable[] = {
+		{ V_MODECOLOR, V_INFO_COLOR, 0 },
+		{ V_MODEGRAPHICS, V_INFO_GRAPHICS, 0 },
+		{ V_MODELFB, V_INFO_LENEAR, 0 },
+	};
+	int flags;
+	int i;
+
+	for (flags = 0, i = 0; i < sizeof(ftable)/sizeof(ftable[0]); ++i) {
+		flags |= (vflags & ftable[i].mask) ? 
+			 ftable[i].set : ftable[i].reset;
+	}
+	return flags;
+}
+
+static int
+vesa_bios_init(void)
+{
+	static u_char buf[512];
+	struct vm86frame vmf;
+	struct vesa_mode vmode;
+	u_int32_t p;
+	int modes;
+	int err;
+	int i;
+
+	if (vesa_init_done)
+		return 0;
+
+	has_vesa_bios = FALSE;
+	vesa_adp_info = NULL;
+	vesa_vmode[0].vi_mode = EOT;
+
+	bzero(&vmf, sizeof(vmf));	/* paranoia */
+	bzero(buf, sizeof(buf));
+	bcopy("VBE2", buf, 4);		/* try for VBE2 data */
+	vmf.vmf_eax = 0x4f00;
+	err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf), 
+			  &vmf.vmf_es, &vmf.vmf_di);
+	if ((err != 0) || (vmf.vmf_eax != 0x4f) || bcmp("VESA", buf, 4))
+		return 1;
+	vesa_adp_info = (struct vesa_info *)buf;
+	if (bootverbose)
+		dump_buffer(buf, 64);
+	if (vesa_adp_info->v_flags & V_NONVGA)
+		return 1;
+
+	/* obtain video mode information */
+	p = BIOS_SADDRTOLADDR(vesa_adp_info->v_modetable);
+	vesa_vmodetab = (u_int16_t *)BIOS_PADDRTOVADDR(p);
+	for (i = 0, modes = 0; vesa_vmodetab[i] != 0xffff; ++i) {
+		if (modes >= VESA_MAXMODES)
+			break;
+		if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
+			continue;
+
+		/* reject unsupported modes */
+#if 0
+		if ((vmode.v_modeattr & (V_MODESUPP | V_MODEOPTINFO 
+					| V_MODENONVGA))
+		    != (V_MODESUPP | V_MODEOPTINFO))
+			continue;
+#else
+		if ((vmode.v_modeattr & (V_MODEOPTINFO | V_MODENONVGA))
+		    != (V_MODEOPTINFO))
+			continue;
+#endif
+
+		/* copy some fields */
+		bzero(&vesa_vmode[modes], sizeof(vesa_vmode[modes]));
+		vesa_vmode[modes].vi_mode = vesa_vmodetab[i];
+		vesa_vmode[modes].vi_width = vmode.v_width;
+		vesa_vmode[modes].vi_height = vmode.v_height;
+		vesa_vmode[modes].vi_depth = vmode.v_bpp;
+		vesa_vmode[modes].vi_planes = vmode.v_planes;
+		vesa_vmode[modes].vi_cwidth = vmode.v_cwidth;
+		vesa_vmode[modes].vi_cheight = vmode.v_cheight;
+		vesa_vmode[modes].vi_window = (u_int)vmode.v_waseg << 4;
+		/* XXX window B */
+		vesa_vmode[modes].vi_window_size = vmode.v_wsize;
+		vesa_vmode[modes].vi_window_gran = vmode.v_wgran;
+		vesa_vmode[modes].vi_buffer = vmode.v_lfb;
+		vesa_vmode[modes].vi_buffer_size = vmode.v_offscreen;
+		/* pixel format, memory model... */
+		vesa_vmode[modes].vi_flags = translate_flags(vmode.v_modeattr)
+					     | V_INFO_VESA;
+		++modes;
+	}
+	vesa_vmode[modes].vi_mode = EOT;
+	if (bootverbose)
+		printf("VESA: %d mode(s) found\n", modes);
+
+	has_vesa_bios = TRUE;
+	return 0;
+}
+
+static void
+clear_modes(video_info_t *info, int color)
+{
+	while (info->vi_mode != EOT) {
+		if ((info->vi_flags & V_INFO_COLOR) != color)
+			info->vi_mode = NA;
+		++info;
+	}
+}
+
+/* exported functions */
+
+static int
+vesa_init(void)
+{
+	int adapters;
+	int i;
+
+	adapters = (*prevvidsw.init)();
+	for (i = 0; i < adapters; ++i) {
+		if ((vesa_adp = (*prevvidsw.adapter)(i)) == NULL)
+			continue;
+		if (vesa_adp->va_type == KD_VGA) {
+			vesa_adp->va_flags |= V_ADP_VESA;
+			return adapters;
+		}
+	}
+	vesa_adp = NULL;
+	return adapters;
+}
+
+static video_adapter_t
+*vesa_adapter(int ad)
+{
+	return (*prevvidsw.adapter)(ad);
+}
+
+static int
+vesa_get_info(int ad, int mode, video_info_t *info)
+{
+	int i;
+
+	if ((*prevvidsw.get_info)(ad, mode, info) == 0)
+		return 0;
+
+	if (ad != vesa_adp->va_index)
+		return 1;
+	for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
+		if (vesa_vmode[i].vi_mode == NA)
+			continue;
+		if (vesa_vmode[i].vi_mode == mode) {
+			*info = vesa_vmode[i];
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static int
+vesa_query_mode(int ad, video_info_t *info)
+{
+	int i;
+
+	if ((i = (*prevvidsw.query_mode)(ad, info)) != -1)
+		return i;
+	if (ad != vesa_adp->va_index)
+		return -1;
+
+	for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
+		if ((info->vi_width != 0)
+		    && (info->vi_width != vesa_vmode[i].vi_width))
+			continue;
+		if ((info->vi_height != 0)
+		    && (info->vi_height != vesa_vmode[i].vi_height))
+			continue;
+		if ((info->vi_cwidth != 0)
+		    && (info->vi_cwidth != vesa_vmode[i].vi_cwidth))
+			continue;
+		if ((info->vi_cheight != 0)
+		    && (info->vi_cheight != vesa_vmode[i].vi_cheight))
+			continue;
+		if ((info->vi_depth != 0)
+		    && (info->vi_depth != vesa_vmode[i].vi_depth))
+			continue;
+		if ((info->vi_planes != 0)
+		    && (info->vi_planes != vesa_vmode[i].vi_planes))
+			continue;
+		/* pixel format, memory model */
+		if ((info->vi_flags != 0)
+		    && (info->vi_flags != vesa_vmode[i].vi_flags))
+			continue;
+		return vesa_vmode[i].vi_mode;
+	}
+	return -1;
+}
+
+static int
+vesa_set_mode(int ad, int mode)
+{
+	video_info_t info;
+	size_t len;
+
+	if (ad != vesa_adp->va_index)
+		return (*prevvidsw.set_mode)(ad, mode);
+
+#ifdef SC_VIDEO_DEBUG
+	printf("VESA: set_mode(): %d(%x) -> %d(%x)\n",
+		vesa_adp->va_mode, vesa_adp->va_mode, mode, mode);
+#endif
+	/* 
+	 * If the current mode is a VESA mode and the new mode is not,
+	 * restore the state of the adapter first, so that non-standard, 
+	 * extended SVGA registers are set to the state compatible with
+	 * the standard VGA modes. Otherwise (*prevvidsw.set_mode)() 
+	 * may not be able to set up the new mode correctly.
+	 */
+	if (VESA_MODE(vesa_adp->va_mode)) {
+		if ((*prevvidsw.get_info)(ad, mode, &info) == 0) {
+			/* assert(vesa_state_buf != NULL); */
+		    	if ((vesa_state_buf == NULL)
+			    || vesa_load_state(ad, vesa_state_buf))
+				return 1;
+			free(vesa_state_buf, M_DEVBUF);
+			vesa_state_buf = NULL;
+#ifdef SC_VIDEO_DEBUG
+			printf("VESA: restored\n");
+#endif
+		}
+		/* 
+		 * once (*prevvidsw.get_info)() succeeded, 
+		 * (*prevvidsw.set_mode)() below won't fail...
+		 */
+	}
+
+	/* we may not need to handle this mode after all... */
+	if ((*prevvidsw.set_mode)(ad, mode) == 0)
+		return 0;
+
+	/* is the new mode supported? */
+	if (vesa_get_info(ad, mode, &info))
+		return 1;
+	/* assert(VESA_MODE(mode)); */
+
+#ifdef SC_VIDEO_DEBUG
+	printf("VESA: about to set a VESA mode...\n");
+#endif
+	/* 
+	 * If the current mode is not a VESA mode, save the current state
+	 * so that the adapter state can be restored later when a non-VESA
+	 * mode is to be set up. See above.
+	 */
+	if (!VESA_MODE(vesa_adp->va_mode) && (vesa_state_buf == NULL)) {
+		len = vesa_save_state(ad, NULL, 0);
+		vesa_state_buf = malloc(len, M_DEVBUF, M_WAITOK);
+		if (vesa_save_state(ad, vesa_state_buf, len)) {
+#ifdef SC_VIDEO_DEBUG
+			printf("VESA: state save failed! (len=%d)\n", len);
+#endif
+			free(vesa_state_buf, M_DEVBUF);
+			vesa_state_buf = NULL;
+			return 1;
+		}
+#ifdef SC_VIDEO_DEBUG
+		printf("VESA: saved (len=%d)\n", len);
+		dump_buffer(vesa_state_buf, len);
+#endif
+	}
+
+	if (vesa_bios_set_mode(mode))
+		return 1;
+
+#ifdef SC_VIDEO_DEBUG
+	printf("VESA: mode set!\n");
+#endif
+	vesa_adp->va_mode = mode;
+	vesa_adp->va_flags &= ~V_ADP_COLOR;
+	vesa_adp->va_flags |= 
+		(info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
+	vesa_adp->va_crtc_addr =
+		(vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_BASE : MONO_BASE;
+	vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
+	vesa_adp->va_window_size = info.vi_window_size;
+	vesa_adp->va_window_gran = info.vi_window_gran;
+	if (info.vi_buffer_size == 0) {
+		vesa_adp->va_buffer = 0;
+		vesa_adp->va_buffer_size = 0;
+	} else {
+		vesa_adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
+		vesa_adp->va_buffer_size = info.vi_buffer_size;
+	}
+
+	return 0;
+}
+
+static int
+vesa_save_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
+{
+	return (*prevvidsw.save_font)(ad, page, fontsize, data, ch, count);
+}
+
+static int
+vesa_load_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
+{
+	return (*prevvidsw.load_font)(ad, page, fontsize, data, ch, count);
+}
+
+static int
+vesa_show_font(int ad, int page)
+{
+	return (*prevvidsw.show_font)(ad, page);
+}
+
+static int
+vesa_save_palette(int ad, u_char *palette)
+{
+	if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8) 
+	    || vesa_bios_set_dac(8))
+		return (*prevvidsw.save_palette)(ad, palette);
+
+	return vesa_bios_save_palette(0, 256, palette);
+}
+
+static int
+vesa_load_palette(int ad, u_char *palette)
+{
+	if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8) 
+	    || vesa_bios_set_dac(8))
+		return (*prevvidsw.load_palette)(ad, palette);
+
+	return vesa_bios_load_palette(0, 256, palette);
+}
+
+static int
+vesa_set_border(int ad, int color)
+{
+	return (*prevvidsw.set_border)(ad, color);
+}
+
+static int
+vesa_save_state(int ad, void *p, size_t size)
+{
+	if (ad != vesa_adp->va_index)
+		return (*prevvidsw.save_state)(ad, p, size);
+
+	if (vesa_state_buf_size == 0)
+		vesa_state_buf_size = vesa_bios_state_buf_size();
+	if (size == 0)
+		return (sizeof(int) + vesa_state_buf_size);
+	else if (size < (sizeof(int) + vesa_state_buf_size))
+		return 1;
+
+	((adp_state_t *)p)->sig = V_STATE_SIG;
+	bzero(((adp_state_t *)p)->regs, vesa_state_buf_size);
+	return vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs, 
+				      vesa_state_buf_size);
+}
+
+static int
+vesa_load_state(int ad, void *p)
+{
+	if ((ad != vesa_adp->va_index) 
+	    || (((adp_state_t *)p)->sig != V_STATE_SIG))
+		return (*prevvidsw.load_state)(ad, p);
+
+	return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, 
+				      vesa_state_buf_size);
+}
+
+static int
+vesa_set_origin(int ad, off_t offset)
+{
+	struct vm86frame vmf;
+	int err;
+
+	/*
+	 * This function should return as quickly as possible to 
+	 * maintain good performance of the system. For this reason,
+	 * error checking is kept minimal and let the VESA BIOS to 
+	 * detect error.
+	 */
+	if (ad != vesa_adp->va_index) 
+		return (*prevvidsw.set_win_org)(ad, offset);
+
+	if (vesa_adp->va_window_gran == 0)
+		return 1;
+	bzero(&vmf, sizeof(vmf));
+	vmf.vmf_eax = 0x4f05; 
+	vmf.vmf_ebx = 0;		/* WINDOW_A, XXX */
+	vmf.vmf_edx = offset/vesa_adp->va_window_gran;
+	err = vm86_intcall(0x10, &vmf); 
+	return ((err != 0) || (vmf.vmf_eax != 0x4f));
+}
+
+static int
+vesa_read_hw_cursor(int ad, int *col, int *row)
+{
+	return (*prevvidsw.read_hw_cursor)(ad, col, row);
+}
+
+static int
+vesa_set_hw_cursor(int ad, int col, int row)
+{
+	return (*prevvidsw.set_hw_cursor)(ad, col, row);
+}
+
+static int
+vesa_diag(int level)
+{
+	struct vesa_mode vmode;
+	u_int32_t p;
+	int i;
+
+	/* general adapter information */
+	printf("VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n", 
+	       ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 
+		   + ((vesa_adp_info->v_version & 0x0f00) >> 8),
+	       ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 
+		   + (vesa_adp_info->v_version & 0x000f),
+	       vesa_adp_info->v_memsize * 64, vesa_adp_info->v_flags,
+	       vesa_vmodetab, vesa_adp_info->v_modetable);
+	/* OEM string */
+	p = BIOS_SADDRTOLADDR(vesa_adp_info->v_oemstr);
+	if (p != 0)
+		printf("VESA: %s\n", (char *)BIOS_PADDRTOVADDR(p));
+
+	if (level <= 0)
+		return 0;
+
+	if (vesa_adp_info->v_version >= 0x0200) {
+		/* vendor name */
+		p = BIOS_SADDRTOLADDR(vesa_adp_info->v_venderstr);
+		if (p != 0)
+			printf("VESA: %s, ", (char *)BIOS_PADDRTOVADDR(p));
+		/* product name */
+		p = BIOS_SADDRTOLADDR(vesa_adp_info->v_prodstr);
+		if (p != 0)
+			printf("%s, ", (char *)BIOS_PADDRTOVADDR(p));
+		/* product revision */
+		p = BIOS_SADDRTOLADDR(vesa_adp_info->v_revstr);
+		if (p != 0)
+			printf("%s\n", (char *)BIOS_PADDRTOVADDR(p));
+	}
+
+	/* mode information */
+	for (i = 0; vesa_vmodetab[i] != 0xffff; ++i) {
+		if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
+			continue;
+
+		/* print something for diagnostic purpose */
+		printf("VESA: mode:0x%03x, flags:0x%04x", 
+		       vesa_vmodetab[i], vmode.v_modeattr);
+		if (vmode.v_modeattr & V_MODEOPTINFO) {
+			if (vmode.v_modeattr & V_MODEGRAPHICS) {
+				printf(", G %dx%dx%d %d, ", 
+				       vmode.v_width, vmode.v_height,
+				       vmode.v_bpp, vmode.v_planes);
+			} else {
+				printf(", T %dx%d, ", 
+				       vmode.v_width, vmode.v_height);
+			}
+			printf("font:%dx%d", 
+			       vmode.v_cwidth, vmode.v_cheight);
+		}
+		if (vmode.v_modeattr & V_MODELFB) {
+			printf(", mem:%d, LFB:0x%x, off:0x%x", 
+			       vmode.v_memmodel, vmode.v_lfb, 
+			       vmode.v_offscreen);
+		}
+		printf("\n");
+		printf("VESA: window A:0x%x (%x), window B:0x%x (%x), ",
+		       vmode.v_waseg, vmode.v_waattr,
+		       vmode.v_wbseg, vmode.v_wbattr);
+		printf("size:%dk, gran:%dk\n",
+		       vmode.v_wsize, vmode.v_wgran);
+	}
+
+	return 0;
+}
+
+/* module loading */
+
+#ifdef VESA_MODULE
+static int
+vesa_load(struct lkm_table *lkmtp, int cmd)
+#else
+int
+vesa_load(void)
+#endif
+{
+	int adapters;
+	int error;
+	int s;
+	int i;
+
+	if (vesa_init_done)
+		return 0;
+
+	/*
+	 * If the VESA module is statically linked to the kernel, or
+	 * it has already been loaded, abort loading this module this time.
+	 */
+	vesa_adp = NULL;
+	adapters = (*biosvidsw.init)();
+	for (i = 0; i < adapters; ++i) {
+		if ((vesa_adp = (*biosvidsw.adapter)(i)) == NULL)
+			continue;
+		if (vesa_adp->va_flags & V_ADP_VESA)
+			return ENXIO;
+		if (vesa_adp->va_type == KD_VGA)
+			break;
+	}
+	/* if a VGA adapter is not found, abort */
+	if (i >= adapters)
+		return ENXIO;
+
+	if (vesa_bios_init())
+		return ENXIO;
+	vesa_adp->va_flags |= V_ADP_VESA;
+
+	/* remove conflicting modes if we have more than one adapter */
+	if (adapters > 1) {
+		clear_modes(vesa_vmode,
+			    (vesa_adp->va_flags & V_ADP_COLOR) ? 
+				V_INFO_COLOR : 0);
+	}
+
+#ifdef VESA_MODULE
+	s = spltty();
+#endif
+	if ((error = vesa_load_ioctl()) == 0) {
+		bcopy(&biosvidsw, &prevvidsw, sizeof(prevvidsw));
+		bcopy(&vesavidsw, &biosvidsw, sizeof(vesavidsw));
+		vesa_init_done = TRUE;
+	}
+#ifdef VESA_MODULE
+	splx(s);
+
+	if (error == 0)
+		vesa_diag(bootverbose);
+#endif
+
+	return error;
+}
+
+#ifdef VESA_MODULE
+
+static int
+vesa_unload(struct lkm_table *lkmtp, int cmd)
+{
+	int error;
+	int s;
+
+	/* if the adapter is currently in a VESA mode, don't unload */
+	if ((vesa_adp != NULL) && VESA_MODE(vesa_adp->va_mode))
+		return EBUSY;
+	/* 
+	 * FIXME: if there is at least one vty which is in a VESA mode,
+	 * we shouldn't be unloading! XXX
+	 */
+
+	s = spltty();
+	if ((error = vesa_unload_ioctl()) == 0) {
+		if (vesa_adp)
+			vesa_adp->va_flags &= ~V_ADP_VESA;
+		bcopy(&prevvidsw, &biosvidsw, sizeof(biosvidsw));
+	}
+	splx(s);
+
+	return error;
+}
+
+int
+vesa_mod(struct lkm_table *lkmtp, int cmd, int ver)
+{
+	MOD_DISPATCH(vesa, lkmtp, cmd, ver,
+		vesa_load, vesa_unload, lkm_nullcmd);
+}
+
+#endif /* VESA_MODULE */
+
+#endif /* (NSC > 0 && VESA && VM86) || VESA_MODULE */
diff --git a/sys/i386/isa/videoio.c b/sys/i386/isa/videoio.c
new file mode 100644
index 000000000000..85c8f8d56ba8
--- /dev/null
+++ b/sys/i386/isa/videoio.c
@@ -0,0 +1,1612 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "sc.h"
+#include "opt_syscons.h"
+
+#if NSC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/clock.h>
+#include <machine/console.h>
+#include <machine/md_var.h>
+#include <machine/pc/bios.h>
+
+#include <i386/isa/isa.h>
+#include <i386/isa/videoio.h>
+
+/* this should really be in `rtc.h' */
+#define RTC_EQUIPMENT           0x14
+
+/* video adapter state buffer */
+struct adp_state {
+    int			sig;
+#define V_STATE_SIG	0x736f6962
+    u_char		regs[V_MODE_PARAM_SIZE];
+};
+typedef struct adp_state adp_state_t;
+
+/* video adapter information */
+#define DCC_MONO	0
+#define DCC_CGA40	1
+#define DCC_CGA80	2
+#define DCC_EGAMONO	3
+#define DCC_EGA40	4
+#define DCC_EGA80	5
+
+/* 
+ * NOTE: `va_window' should have a virtual address, but is initialized
+ * with a physical address in the following table, as verify_adapter()
+ * will perform address conversion at run-time.
+ */
+static video_adapter_t adapter_init_value[] = {
+    { 0, KD_MONO, 0, 	      MONO_BASE,  0xb0000, 32, 32, 0, 0, 0, 7, 0 },
+    { 0, KD_CGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 },
+    { 0, KD_CGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 },
+    { 0, KD_EGA, 0,	      MONO_BASE,  0xb0000, 32, 32, 0, 0, 0, 7, 0 },
+    { 0, KD_EGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 },
+    { 0, KD_EGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32, 32, 0, 0, 0, 3, 0 },
+};
+
+static video_adapter_t adapter[V_MAX_ADAPTERS];
+static int adapters = 0;
+
+/* VGA function entries */
+static vi_init_t		vid_init;
+static vi_adapter_t		vid_adapter;
+static vi_get_info_t		vid_get_info;
+static vi_query_mode_t		vid_query_mode;
+static vi_set_mode_t		vid_set_mode;
+static vi_save_font_t		vid_save_font;
+static vi_load_font_t		vid_load_font;
+static vi_show_font_t		vid_show_font;
+static vi_save_palette_t	vid_save_palette;
+static vi_load_palette_t	vid_load_palette;
+static vi_set_border_t		vid_set_border;
+static vi_save_state_t		vid_save_state;
+static vi_load_state_t		vid_load_state;
+static vi_set_win_org_t		vid_set_origin;
+static vi_read_hw_cursor_t	vid_read_hw_cursor;
+static vi_set_hw_cursor_t	vid_set_hw_cursor;
+static vi_diag_t		vid_diag;
+
+struct vidsw biosvidsw = {
+	vid_init,	vid_adapter,	vid_get_info,	vid_query_mode,	
+	vid_set_mode,	vid_save_font,	vid_load_font,	vid_show_font,
+	vid_save_palette,vid_load_palette,vid_set_border,vid_save_state,
+	vid_load_state,	vid_set_origin,	vid_read_hw_cursor, vid_set_hw_cursor,
+	vid_diag,
+};
+
+/* VGA BIOS standard video modes */
+#define EOT		(-1)
+#define NA		(-2)
+
+static video_info_t bios_vmode[] = {
+    /* CGA */
+    { M_B40x25,     V_INFO_COLOR, 40, 25, 8,  8, 2, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_C40x25,     V_INFO_COLOR, 40, 25, 8,  8, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_B80x25,     V_INFO_COLOR, 80, 25, 8,  8, 2, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_C80x25,     V_INFO_COLOR, 80, 25, 8,  8, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    /* EGA */
+    { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    /* VGA */
+    { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_VGA_M80x25, 0,		  80, 25, 8, 16, 2, 1, 0xb0000, 32, 32, 0, 32 },
+    { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    /* MDA */
+    { M_EGAMONO80x25, 0,          80, 25, 8, 14, 2, 1, 0xb0000, 32, 32, 0, 32 },
+    /* EGA */
+    { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8,  8, 2, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8,  8, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    /* VGA */
+    { M_VGA_M80x30, 0,		  80, 30, 8, 16, 2, 1, 0xb0000, 32, 32, 0, 32 },
+    { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_VGA_M80x50, 0,		  80, 50, 8,  8, 2, 1, 0xb0000, 32, 32, 0, 32 },
+    { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8,  8, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_VGA_M80x60, 0,		  80, 60, 8,  8, 2, 1, 0xb0000, 32, 32, 0, 32 },
+    { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8,  8, 4, 1, 0xb8000, 32, 32, 0, 32 },
+    /* CGA */
+    { M_BG320,      V_INFO_COLOR | V_INFO_GRAPHICS,                
+      320, 200, 8,  8, 2, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_CG320,      V_INFO_COLOR | V_INFO_GRAPHICS, 
+      320, 200, 8,  8, 2, 1, 0xb8000, 32, 32, 0, 32 },
+    { M_BG640,      V_INFO_COLOR | V_INFO_GRAPHICS,                
+      640, 200, 8,  8, 1, 1, 0xb8000, 32, 32, 0, 32 },
+    /* EGA */
+    { M_CG320_D,    V_INFO_COLOR | V_INFO_GRAPHICS,
+      320, 200, 8,  8, 4, 4, 0xa0000, 64, 64, 0, 64 },
+    { M_CG640_E,    V_INFO_COLOR | V_INFO_GRAPHICS, 
+      640, 200, 8,  8, 4, 4, 0xa0000, 64, 64, 0, 64 },
+    { M_EGAMONOAPA, V_INFO_GRAPHICS, 		    
+      640, 350, 8, 14, 4, 4, 0xa0000, 64, 64, 0, 64 },
+    { M_ENHMONOAPA2,V_INFO_GRAPHICS, 		    
+      640, 350, 8, 14, 4, 4, 0xa0000, 64, 64, 0, 64 },
+    { M_CG640x350,  V_INFO_COLOR | V_INFO_GRAPHICS, 
+      640, 350, 8, 14, 2, 2, 0xa0000, 64, 64, 0, 64 },
+    { M_ENH_CG640,  V_INFO_COLOR | V_INFO_GRAPHICS, 
+      640, 350, 8, 14, 4, 4, 0xa0000, 64, 64, 0, 64 },
+    /* VGA */
+    { M_BG640x480,  V_INFO_COLOR | V_INFO_GRAPHICS,                
+      640, 480, 8, 16, 4, 4, 0xa0000, 64, 64, 0, 64 },
+    { M_CG640x480,  V_INFO_COLOR | V_INFO_GRAPHICS, 
+      640, 480, 8, 16, 4, 4, 0xa0000, 64, 64, 0, 64 },
+    { M_VGA_CG320,  V_INFO_COLOR | V_INFO_GRAPHICS, 
+      320, 200, 8,  8, 8, 1, 0xa0000, 64, 64, 0, 64 },
+    { M_VGA_MODEX,  V_INFO_COLOR | V_INFO_GRAPHICS, 
+      320, 240, 8,  8, 8, 1, 0xa0000, 64, 64, 0, 64 },
+
+    { EOT },
+};
+
+static int		init_done = FALSE;
+static u_char		*video_mode_ptr = NULL;		/* EGA/VGA */
+static u_char		*video_mode_ptr2 = NULL;	/* CGA/MDA */
+static u_char		*mode_map[V_MODE_MAP_SIZE];
+static adp_state_t	adpstate;
+static adp_state_t	adpstate2;
+static int		rows_offset = 1;
+
+/* local macros and functions */
+#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
+
+static void map_mode_table(u_char *map[], u_char *table, int max);
+static void clear_mode_map(int ad, u_char *map[], int max, int color);
+static int map_mode_num(int mode);
+static int map_bios_mode_num(int type, int color, int bios_mode);
+static u_char *get_mode_param(int mode);
+static void fill_adapter_param(int code, video_adapter_t *adp);
+static int verify_adapter(video_adapter_t *adp);
+#define COMP_IDENTICAL	0
+#define COMP_SIMILAR	1
+#define COMP_DIFFERENT	2
+static int comp_adpregs(u_char *buf1, u_char *buf2);
+
+#define PARAM_BUFSIZE	6
+static void set_font_mode(video_adapter_t *adp, u_char *buf);
+static void set_normal_mode(video_adapter_t *adp, u_char *buf);
+
+static char *adapter_name(int type);
+static void dump_adp_info(int ad, video_adapter_t *adp, int level);
+static void dump_mode_info(int ad, video_info_t *info, int level);
+static void dump_buffer(u_char *buf, size_t len);
+
+extern void generic_bcopy(const void *, void *, size_t);
+
+#define	ISMAPPED(pa, width) \
+	(((pa) <= (u_long)0x1000 - (width)) 		\
+	 || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width)))
+
+#define	prologue(ad, flag, err)	\
+	if (!init_done					\
+	    || ((ad) < 0) || ((ad) >= adapters)		\
+	    || !(adapter[(ad)].va_flags & (flag)))	\
+	    return (err)
+
+/* construct the mode parameter map */
+static void
+map_mode_table(u_char *map[], u_char *table, int max)
+{
+    int i;
+
+    for(i = 0; i < max; ++i)
+	map[i] = table + i*V_MODE_PARAM_SIZE;
+    for(; i < V_MODE_MAP_SIZE; ++i)
+	map[i] = NULL;
+}
+
+static void
+clear_mode_map(int ad, u_char *map[], int max, int color)
+{
+    video_info_t info;
+    int i;
+
+    /*
+     * NOTE: we don't touch `bios_vmode[]' because it is shared
+     * by all adapters.
+     */
+    for(i = 0; i < max; ++i) {
+	if (vid_get_info(ad, i, &info))
+	    continue;
+	if ((info.vi_flags & V_INFO_COLOR) != color)
+	    map[i] = NULL;
+    }
+}
+
+/* the non-standard video mode is based on a standard mode... */
+static int
+map_mode_num(int mode)
+{
+    static struct {
+        int from;
+        int to;
+    } mode_map[] = {
+        { M_ENH_B80x43, M_ENH_B80x25 },
+        { M_ENH_C80x43, M_ENH_C80x25 },
+        { M_VGA_M80x30, M_VGA_M80x25 },
+        { M_VGA_C80x30, M_VGA_C80x25 },
+        { M_VGA_M80x50, M_VGA_M80x25 },
+        { M_VGA_C80x50, M_VGA_C80x25 },
+        { M_VGA_M80x60, M_VGA_M80x25 },
+        { M_VGA_C80x60, M_VGA_C80x25 },
+        { M_VGA_MODEX,  M_VGA_CG320 },
+    };
+    int i;
+
+    for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
+        if (mode_map[i].from == mode)
+            return mode_map[i].to;
+    }
+    return mode;
+}
+
+/* turn the BIOS video number into our video mode number */
+static int
+map_bios_mode_num(int type, int color, int bios_mode)
+{
+    static int cga_modes[7] = {
+	M_B40x25, M_C40x25,		/* 0, 1 */
+	M_B80x25, M_C80x25,		/* 2, 3 */
+	M_BG320, M_CG320,
+	M_BG640,
+    };
+    static int ega_modes[17] = {
+	M_ENH_B40x25, M_ENH_C40x25,	/* 0, 1 */
+	M_ENH_B80x25, M_ENH_C80x25,	/* 2, 3 */
+	M_BG320, M_CG320,
+	M_BG640,
+	M_EGAMONO80x25,			/* 7 */
+	8, 9, 10, 11, 12,
+	M_CG320_D,
+	M_CG640_E,
+	M_ENHMONOAPA2,			/* XXX: video momery > 64K */
+	M_ENH_CG640,			/* XXX: video momery > 64K */
+    };
+    static int vga_modes[20] = {
+	M_VGA_C40x25, M_VGA_C40x25,	/* 0, 1 */
+	M_VGA_C80x25, M_VGA_C80x25,	/* 2, 3 */
+	M_BG320, M_CG320,
+	M_BG640,
+	M_VGA_M80x25,			/* 7 */
+	8, 9, 10, 11, 12,
+	M_CG320_D,
+	M_CG640_E,
+	M_ENHMONOAPA2,
+	M_ENH_CG640,
+	M_BG640x480, M_CG640x480, 
+	M_VGA_CG320,
+    };
+
+    switch (type) {
+
+    case KD_VGA:
+	if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0]))
+	    return vga_modes[bios_mode];
+	else if (color)
+	    return M_VGA_C80x25;
+	else
+	    return M_VGA_M80x25;
+	break;
+
+    case KD_EGA:
+	if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0]))
+	    return ega_modes[bios_mode];
+	else if (color)
+	    return M_ENH_C80x25;
+	else
+	    return M_EGAMONO80x25;
+	break;
+
+    case KD_CGA:
+	if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0]))
+	    return cga_modes[bios_mode];
+	else
+	    return M_C80x25;
+	break;
+
+    case KD_MONO:
+    case KD_HERCULES:
+	return M_EGAMONO80x25;		/* XXX: this name is confusing */
+
+    default:
+	break;
+    }
+    return -1;
+}
+
+/* look up a parameter table entry */
+static u_char 
+*get_mode_param(int mode)
+{
+    if (mode >= V_MODE_MAP_SIZE)
+	mode = map_mode_num(mode);
+    if (mode < V_MODE_MAP_SIZE)
+	return mode_map[mode];
+    else
+	return NULL;
+}
+
+static void
+fill_adapter_param(int code, video_adapter_t *adp)
+{
+    static struct {
+	int primary;
+	int secondary;
+    } dcc[] = {
+	{ DCC_MONO, 			DCC_EGA40 /* CGA monitor */ },
+	{ DCC_MONO, 			DCC_EGA80 /* CGA monitor */ },
+	{ DCC_MONO, 			DCC_EGA80 /* CGA emulation */ },	
+	{ DCC_MONO, 			DCC_EGA80 },
+	{ DCC_CGA40, 			DCC_EGAMONO },
+	{ DCC_CGA80, 			DCC_EGAMONO },
+	{ DCC_EGA40 /* CGA monitor */, 	DCC_MONO},
+	{ DCC_EGA80 /* CGA monitor */, 	DCC_MONO},
+	{ DCC_EGA80 /* CGA emulation */,DCC_MONO },	
+	{ DCC_EGA80, 			DCC_MONO },
+	{ DCC_EGAMONO, 			DCC_CGA40 },
+	{ DCC_EGAMONO, 			DCC_CGA40 },
+    };
+
+    if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) {
+	adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
+	adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
+    } else {
+	adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary];
+	adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary];
+    }
+}
+
+static int
+verify_adapter(video_adapter_t *adp)
+{
+    u_short volatile *buf;
+    u_short v;
+    u_int32_t p;
+
+    buf = (u_short *)BIOS_PADDRTOVADDR(adp->va_window);
+    v = *buf;
+    *buf = (u_short) 0xA55A;
+    if (*buf != 0xA55A)
+	return 1;
+    *buf = v;
+
+    switch (adp->va_type) {
+
+    case KD_EGA:
+	outb(adp->va_crtc_addr, 7);
+	if (inb(adp->va_crtc_addr) == 7) {
+	    adp->va_type = KD_VGA;
+	    adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE;
+	}
+	adp->va_flags |= V_ADP_STATELOAD | V_ADP_FONT | V_ADP_BORDER;
+	/* the color adapter may be in the 40x25 mode... XXX */
+
+	/* get the BIOS video mode pointer */
+	p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8);
+	p = BIOS_SADDRTOLADDR(p);
+	if (ISMAPPED(p, sizeof(u_int32_t))) {
+	    p = *(u_int32_t *)BIOS_PADDRTOVADDR(p);
+	    p = BIOS_SADDRTOLADDR(p);
+	    if (ISMAPPED(p, V_MODE_PARAM_SIZE))
+		video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p);
+	}
+	break;
+
+    case KD_CGA:
+	adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER;
+	/* may be in the 40x25 mode... XXX */
+	break;
+
+    case KD_MONO:
+	break;
+    }
+
+    return 0;
+}
+
+/* compare two parameter table entries */
+static int 
+comp_adpregs(u_char *buf1, u_char *buf2)
+{
+    static struct {
+        u_char mask;
+    } params[V_MODE_PARAM_SIZE] = {
+	0xff, 0x00, 0xff, 		/* COLS, ROWS, POINTS */
+	0x00, 0x00, 			/* page length */
+	0xfe, 0xff, 0xff, 0xff,		/* sequencer registers */
+	0xf3,				/* misc register */
+	0xff, 0xff, 0xff, 0x7f, 0xff,	/* CRTC */
+	0xff, 0xff, 0xff, 0x7f, 0xff,
+	0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0xff, 0x7f, 0xff, 0xff,
+	0x7f, 0xff, 0xff, 0xef, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff,	/* attribute controller registers */
+	0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xf0,
+	0xff, 0xff, 0xff, 0xff, 0xff,	/* GDC register */
+	0xff, 0xff, 0xff, 0xff, 
+    }; 
+    int identical = TRUE;
+    int i;
+
+    if ((buf1 == NULL) || (buf2 == NULL))
+	return COMP_DIFFERENT;
+
+    for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
+	if (params[i].mask == 0)	/* don't care */
+	    continue;
+	if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
+	    return COMP_DIFFERENT;
+	if (buf1[i] != buf2[i])
+	    identical = FALSE;
+    }
+    return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
+}
+
+/* exported functions */
+
+/* all adapters */
+static int
+vid_init(void)
+{
+    video_adapter_t *adp;
+    video_info_t info;
+    u_char *mp;
+    int i;
+
+    /* do this test only once */
+    if (init_done)
+	return adapters;
+    init_done = TRUE;
+
+    /* 
+     * Locate display adapters. 
+     * The AT architecture supports upto two adapters. `syscons' allows
+     * the following combinations of adapters: 
+     *     1) MDA + CGA
+     *     2) MDA + EGA/VGA color 
+     *     3) CGA + EGA/VGA mono
+     * Note that `syscons' doesn't bother with MCGA as it is only
+     * avaiable for low end PS/2 models which has 80286 or earlier CPUs,
+     * thus, they are not running FreeBSD!
+     * When there are two adapaters in the system, one becomes `primary'
+     * and the other `secondary'. The EGA adapter has a set of DIP 
+     * switches on board for this information and the EGA BIOS copies 
+     * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88). 
+     * The VGA BIOS has more sophisticated mechanism and has this 
+     * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains 
+     * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH.
+     */
+
+    /* check rtc and BIOS date area */
+    /* 
+     * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy
+     * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are
+     * zeros for EGA and VGA. However, the EGA/VGA BIOS will set 
+     * these bits in BIOSDATA_EQUIPMENT according to the monitor
+     * type detected.
+     */
+    switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) {	/* bit 4 and 5 */
+    case 0:
+	/* EGA/VGA */
+	fill_adapter_param(*(u_int8_t *)BIOS_PADDRTOVADDR(0x488) & 0x0f, 
+			   adapter);
+	break;
+    case 1:
+	/* CGA 40x25 */
+	/* FIXME: switch to the 80x25 mode? XXX */
+	adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40];
+	adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
+	break;
+    case 2:
+	/* CGA 80x25 */
+	adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80];
+	adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
+	break;
+    case 3:
+	/* MDA */
+	adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
+	adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
+	break;
+    }
+
+    adapters = 0;
+    if (verify_adapter(&adapter[V_ADP_SECONDARY]) == 0) {
+	++adapters;
+	adapter[V_ADP_SECONDARY].va_mode = 
+	    adapter[V_ADP_SECONDARY].va_initial_mode =
+	    map_bios_mode_num(adapter[V_ADP_SECONDARY].va_type, 
+			      adapter[V_ADP_SECONDARY].va_flags & V_ADP_COLOR,
+			      adapter[V_ADP_SECONDARY].va_initial_bios_mode);
+    } else {
+	adapter[V_ADP_SECONDARY].va_type = -1;
+    }
+    if (verify_adapter(&adapter[V_ADP_PRIMARY]) == 0) {
+	++adapters;
+	adapter[V_ADP_PRIMARY].va_initial_bios_mode = 
+	    *(u_int8_t *)BIOS_PADDRTOVADDR(0x449);
+	adapter[V_ADP_PRIMARY].va_mode = 
+	    adapter[V_ADP_PRIMARY].va_initial_mode =
+	    map_bios_mode_num(adapter[V_ADP_PRIMARY].va_type, 
+			      adapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR,
+			      adapter[V_ADP_PRIMARY].va_initial_bios_mode);
+    } else {
+	adapter[V_ADP_PRIMARY] = adapter[V_ADP_SECONDARY];
+	adapter[V_ADP_SECONDARY].va_type = -1;
+    }
+    if (adapters == 0)
+	return adapters;
+    adapter[V_ADP_PRIMARY].va_index = V_ADP_PRIMARY;
+    adapter[V_ADP_SECONDARY].va_index = V_ADP_SECONDARY;
+
+#if 0
+    /*
+     * We cannot have two video adapter of the same type; there must be
+     * only one of color or mono adapter, or one each of them.
+     */
+    if (adapters > 1) {
+	if (!((adapter[0].va_flags ^ adapter[1].va_flags) & V_ADP_COLOR))
+	    /* we have two mono or color adapters!! */
+	    return (adapters = 0);
+    }
+#endif
+
+    /*
+     * Ensure a zero start address.  This is mainly to recover after
+     * switching from pcvt using userconfig().  The registers are w/o
+     * for old hardware so it's too hard to relocate the active screen
+     * memory.
+     * This must be done before vid_save_state() for VGA.
+     */
+    outb(adapter[V_ADP_PRIMARY].va_crtc_addr, 12);
+    outb(adapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
+    outb(adapter[V_ADP_PRIMARY].va_crtc_addr, 13);
+    outb(adapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
+
+    /* the video mode parameter table in EGA/VGA BIOS */
+    /* NOTE: there can be only one EGA/VGA, wheather color or mono,
+     * recognized by the video BIOS.
+     */
+    if ((adapter[V_ADP_PRIMARY].va_type == KD_EGA) ||
+	(adapter[V_ADP_PRIMARY].va_type == KD_VGA)) {
+	adp = &adapter[V_ADP_PRIMARY];
+    } else if ((adapter[V_ADP_SECONDARY].va_type == KD_EGA) ||
+	       (adapter[V_ADP_SECONDARY].va_type == KD_VGA)) {
+	adp = &adapter[V_ADP_SECONDARY];
+    } else {
+	adp = NULL;
+    }
+    bzero(mode_map, sizeof(mode_map));
+    if (adp != NULL) {
+	if (adp->va_type == KD_VGA) {
+	    vid_save_state(adp - adapter, &adpstate, sizeof(adpstate));
+	    if (video_mode_ptr == NULL) {
+		mode_map[map_mode_num(adp->va_initial_mode)] = adpstate.regs;
+		rows_offset = 1;
+	    } else {
+		/* discard the table if we are not familiar with it... */
+		map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
+		mp = get_mode_param(adp->va_initial_mode);
+		if (mp != NULL)
+		    bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs));
+		switch (comp_adpregs(adpstate.regs, mp)) {
+		case COMP_IDENTICAL:
+		    /*
+		     * OK, this parameter table looks reasonably familiar
+		     * to us...
+		     */
+		    /* 
+		     * This is a kludge for Toshiba DynaBook SS433 
+		     * whose BIOS video mode table entry has the actual # 
+		     * of rows at the offset 1; BIOSes from other 
+		     * manufacturers store the # of rows - 1 there. XXX
+		     */
+		    rows_offset = adpstate.regs[1] + 1 - mp[1];
+		    break;
+
+		case COMP_SIMILAR:
+		    /*
+		     * Not exactly the same, but similar enough to be
+		     * trusted. However, use the saved register values
+		     * for the initial mode and other modes which are
+		     * based on the initial mode.
+		     */
+		    mode_map[map_mode_num(adp->va_initial_mode)] = 
+			adpstate.regs;
+		    rows_offset = adpstate.regs[1] + 1 - mp[1];
+		    adpstate.regs[1] -= rows_offset - 1;
+		    break;
+
+		case COMP_DIFFERENT:
+		default:
+		    /*
+		     * Don't use the paramter table in BIOS. It doesn't
+		     * look familiar to us. Video mode switching is allowed
+		     * only if the new mode is the same as or based on
+		     * the initial mode. 
+		     */
+		    video_mode_ptr = NULL;
+		    bzero(mode_map, sizeof(mode_map));
+		    mode_map[map_mode_num(adp->va_initial_mode)] = 
+			adpstate.regs;
+		    rows_offset = 1;
+		    break;
+		}
+	    }
+	    adp->va_flags |= V_ADP_MODECHANGE;
+	} else if (adp->va_type == KD_EGA) {
+	    if (video_mode_ptr == NULL) {
+		adp->va_flags &= ~V_ADP_FONT;
+		rows_offset = 1;
+	    } else {
+		map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1);
+		/* XXX how can one validate the EGA table... */
+		mp = get_mode_param(adp->va_initial_mode);
+		if (mp != NULL) {
+		    adp->va_flags |= V_ADP_MODECHANGE;
+		    rows_offset = 1;
+		} else {
+		    /*
+		     * This is serious. We will not be able to switch video
+		     * modes at all...
+		     */
+		    adp->va_flags &= ~V_ADP_FONT;
+		    video_mode_ptr = NULL;
+		    bzero(mode_map, sizeof(mode_map));
+		    rows_offset = 1;
+                }
+	    }
+	}
+    }
+
+    /* remove conflicting modes if we have more than one adapter */
+    if (adapters > 1) {
+	for (i = 0; i < adapters; ++i) {
+	    if (!(adapter[i].va_flags & V_ADP_MODECHANGE))
+		continue;
+	    clear_mode_map(i, mode_map, M_VGA_CG320 + 1,
+			   (adapter[i].va_flags & V_ADP_COLOR) ? 
+			       V_INFO_COLOR : 0);
+	}
+    }
+
+    /* buffer address */
+    vid_get_info(V_ADP_PRIMARY, 
+		 adapter[V_ADP_PRIMARY].va_initial_mode, &info);
+    adapter[V_ADP_PRIMARY].va_window = BIOS_PADDRTOVADDR(info.vi_window);
+    adapter[V_ADP_PRIMARY].va_window_size = info.vi_window_size;
+    adapter[V_ADP_PRIMARY].va_window_gran = info.vi_window_gran;
+    adapter[V_ADP_PRIMARY].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
+    adapter[V_ADP_PRIMARY].va_buffer_size = info.vi_buffer_size;
+    if (adapters > 1) {
+	vid_get_info(V_ADP_SECONDARY, 
+		     adapter[V_ADP_SECONDARY].va_initial_mode, &info);
+	adapter[V_ADP_SECONDARY].va_window = BIOS_PADDRTOVADDR(info.vi_window);
+	adapter[V_ADP_SECONDARY].va_window_size = info.vi_window_size;
+	adapter[V_ADP_SECONDARY].va_window_gran = info.vi_window_gran;
+	adapter[V_ADP_SECONDARY].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
+	adapter[V_ADP_SECONDARY].va_buffer_size = info.vi_buffer_size;
+    }
+
+    /*
+     * XXX: we should verify the following values for the primary adapter...
+     * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463);
+     * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02) 
+     *                     ? 0 : V_ADP_COLOR;
+     * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);
+     * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);
+     * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);
+     * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c);
+     */
+
+    return adapters;
+}
+
+/* all adapters */
+static video_adapter_t
+*vid_adapter(int ad)
+{
+    if (!init_done)
+	return NULL;
+    if ((ad < 0) || (ad >= adapters))
+	return NULL;
+    return &adapter[ad];
+}
+
+/* all adapters */
+static int
+vid_get_info(int ad, int mode, video_info_t *info)
+{
+    int i;
+
+    if (!init_done)
+	return 1;
+    if ((ad < 0) || (ad >= adapters))
+	return 1;
+
+    if (adapter[ad].va_flags & V_ADP_MODECHANGE) {
+	/*
+	 * If the parameter table entry for this mode is not found, 
+	 * the mode is not supported...
+	 */
+	if (get_mode_param(mode) == NULL)
+	    return 1;
+    } else {
+	/* 
+	 * Even if we don't support video mode switching on this adapter,
+	 * the information on the initial (thus current) video mode 
+	 * should be made available.
+	 */
+	if (mode != adapter[ad].va_initial_mode)
+	    return 1;
+    }
+
+    for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+	if (bios_vmode[i].vi_mode == NA)
+	    continue;
+	if (mode == bios_vmode[i].vi_mode) {
+	    *info = bios_vmode[i];
+	    return 0;
+	}
+    }
+    return 1;
+}
+
+/* all adapters */
+static int
+vid_query_mode(int ad, video_info_t *info)
+{
+    video_info_t buf;
+    int i;
+
+    if (!init_done)
+	return -1;
+    if ((ad < 0) || (ad >= adapters))
+	return -1;
+
+    for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+	if (bios_vmode[i].vi_mode == NA)
+	    continue;
+
+	if ((info->vi_width != 0)
+	    && (info->vi_width != bios_vmode[i].vi_width))
+		continue;
+	if ((info->vi_height != 0)
+	    && (info->vi_height != bios_vmode[i].vi_height))
+		continue;
+	if ((info->vi_cwidth != 0)
+	    && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
+		continue;
+	if ((info->vi_cheight != 0)
+	    && (info->vi_cheight != bios_vmode[i].vi_cheight))
+		continue;
+	if ((info->vi_depth != 0)
+	    && (info->vi_depth != bios_vmode[i].vi_depth))
+		continue;
+	if ((info->vi_planes != 0)
+	    && (info->vi_planes != bios_vmode[i].vi_planes))
+		continue;
+	/* XXX: should check pixel format, memory model */
+	if ((info->vi_flags != 0)
+	    && (info->vi_flags != bios_vmode[i].vi_flags))
+		continue;
+
+	/* verify if this mode is supported on this adapter */
+	if (vid_get_info(ad, bios_vmode[i].vi_mode, &buf))
+		continue;
+	return bios_vmode[i].vi_mode;
+    }
+    return -1;
+}
+
+/* EGA/VGA */
+static int
+vid_set_mode(int ad, int mode)
+{
+    video_info_t info;
+    adp_state_t params;
+
+    prologue(ad, V_ADP_MODECHANGE, 1);
+
+    if (vid_get_info(ad, mode, &info))
+	return 1;
+    params.sig = V_STATE_SIG;
+    bcopy(get_mode_param(mode), params.regs, sizeof(params.regs));
+
+    switch (mode) {
+    case M_VGA_C80x60: case M_VGA_M80x60:
+	params.regs[2]  = 0x08;
+	params.regs[19] = 0x47;
+	goto special_480l;
+
+    case M_VGA_C80x30: case M_VGA_M80x30:
+	params.regs[19] = 0x4f;
+special_480l:
+	params.regs[9] |= 0xc0;
+	params.regs[16] = 0x08;
+	params.regs[17] = 0x3e;
+	params.regs[26] = 0xea;
+	params.regs[28] = 0xdf;
+	params.regs[31] = 0xe7;
+	params.regs[32] = 0x04;
+	goto setup_mode;
+
+    case M_ENH_C80x43: case M_ENH_B80x43:
+	params.regs[28] = 87;
+	goto special_80x50;
+
+    case M_VGA_C80x50: case M_VGA_M80x50:
+special_80x50:
+	params.regs[2] = 8;
+	params.regs[19] = 7;
+	goto setup_mode;
+
+    case M_VGA_C40x25: case M_VGA_C80x25:
+    case M_VGA_M80x25:
+    case M_B40x25:     case M_C40x25:
+    case M_B80x25:     case M_C80x25:
+    case M_ENH_B40x25: case M_ENH_C40x25:
+    case M_ENH_B80x25: case M_ENH_C80x25:
+    case M_EGAMONO80x25:
+
+setup_mode:
+	vid_load_state(ad, &params);
+	break;
+
+    case M_VGA_MODEX:
+	/* "unchain" the VGA mode */
+	params.regs[5-1+0x04] &= 0xf7;
+	params.regs[5-1+0x04] |= 0x04;
+	/* turn off doubleword mode */
+	params.regs[10+0x14] &= 0xbf;
+	/* turn off word adressing */
+	params.regs[10+0x17] |= 0x40;
+	/* set logical screen width */
+	params.regs[10+0x13] = 80;
+	/* set 240 lines */
+	params.regs[10+0x11] = 0x2c;
+	params.regs[10+0x06] = 0x0d;
+	params.regs[10+0x07] = 0x3e;
+	params.regs[10+0x10] = 0xea;
+	params.regs[10+0x11] = 0xac;
+	params.regs[10+0x12] = 0xdf;
+	params.regs[10+0x15] = 0xe7;
+	params.regs[10+0x16] = 0x06;
+	/* set vertical sync polarity to reflect aspect ratio */
+	params.regs[9] = 0xe3;
+	goto setup_grmode;
+
+    case M_BG320:     case M_CG320:     case M_BG640:
+    case M_CG320_D:   case M_CG640_E:
+    case M_CG640x350: case M_ENH_CG640:
+    case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
+
+setup_grmode:
+	vid_load_state(ad, &params);
+	break;
+
+    default:
+	return 1;
+    }
+
+    adapter[ad].va_mode = mode;
+    adapter[ad].va_flags &= ~V_ADP_COLOR;
+    adapter[ad].va_flags |= 
+	(info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
+    adapter[ad].va_crtc_addr =
+	(adapter[ad].va_flags & V_ADP_COLOR) ? COLOR_BASE : MONO_BASE;
+    adapter[ad].va_window = BIOS_PADDRTOVADDR(info.vi_window);
+    adapter[ad].va_window_size = info.vi_window_size;
+    adapter[ad].va_window_gran = info.vi_window_gran;
+    if (info.vi_buffer_size == 0) {
+    	adapter[ad].va_buffer = 0;
+    	adapter[ad].va_buffer_size = 0;
+    } else {
+    	adapter[ad].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
+    	adapter[ad].va_buffer_size = info.vi_buffer_size;
+    }
+
+    return 0;
+}
+
+static void
+set_font_mode(video_adapter_t *adp, u_char *buf)
+{
+    u_char *mp;
+    int s;
+
+    s = splhigh();
+
+    /* save register values */
+    if (adp->va_type == KD_VGA) {
+	outb(TSIDX, 0x02); buf[0] = inb(TSREG);
+	outb(TSIDX, 0x04); buf[1] = inb(TSREG);
+	outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
+	outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
+	outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
+	inb(adp->va_crtc_addr + 6);
+	outb(ATC, 0x10); buf[5] = inb(ATC + 1);
+    } else /* if (adp->va_type == KD_EGA) */ {
+	/* 
+	 * EGA cannot be read; copy parameters from the mode parameter 
+	 * table. 
+	 */
+	mp = get_mode_param(adp->va_mode);
+	buf[0] = mp[5 + 0x02 - 1];
+	buf[1] = mp[5 + 0x04 - 1];
+	buf[2] = mp[55 + 0x04];
+	buf[3] = mp[55 + 0x05];
+	buf[4] = mp[55 + 0x06];
+	buf[5] = mp[35 + 0x10];
+    }
+
+    /* setup vga for loading fonts */
+    inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
+    outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
+    inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
+    outb(ATC, 0x20);				/* enable palette */
+
+#if SLOW_VGA
+#ifndef SC_BAD_FLICKER
+    outb(TSIDX, 0x00); outb(TSREG, 0x01);
+#endif
+    outb(TSIDX, 0x02); outb(TSREG, 0x04);
+    outb(TSIDX, 0x04); outb(TSREG, 0x07);
+#ifndef SC_BAD_FLICKER
+    outb(TSIDX, 0x00); outb(TSREG, 0x03);
+#endif
+    outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
+    outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
+    outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
+#else
+#ifndef SC_BAD_FLICKER
+    outw(TSIDX, 0x0100);
+#endif
+    outw(TSIDX, 0x0402);
+    outw(TSIDX, 0x0704);
+#ifndef SC_BAD_FLICKER
+    outw(TSIDX, 0x0300);
+#endif
+    outw(GDCIDX, 0x0204);
+    outw(GDCIDX, 0x0005);
+    outw(GDCIDX, 0x0406);               /* addr = a0000, 64kb */
+#endif
+
+    splx(s);
+}
+
+static void
+set_normal_mode(video_adapter_t *adp, u_char *buf)
+{
+    int s;
+
+    s = splhigh();
+
+    /* setup vga for normal operation mode again */
+    inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
+    outb(ATC, 0x10); outb(ATC, buf[5]);
+    inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
+    outb(ATC, 0x20);				/* enable palette */
+
+#if SLOW_VGA
+#ifndef SC_BAD_FLICKER
+    outb(TSIDX, 0x00); outb(TSREG, 0x01);
+#endif
+    outb(TSIDX, 0x02); outb(TSREG, buf[0]);
+    outb(TSIDX, 0x04); outb(TSREG, buf[1]);
+#ifndef SC_BAD_FLICKER
+    outb(TSIDX, 0x00); outb(TSREG, 0x03);
+#endif
+    outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
+    outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
+    if (adp->va_crtc_addr == MONO_BASE) {
+	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
+    } else {
+	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
+    }
+#else
+#ifndef SC_BAD_FLICKER
+    outw(TSIDX, 0x0100);
+#endif
+    outw(TSIDX, 0x0002 | (buf[0] << 8));
+    outw(TSIDX, 0x0004 | (buf[1] << 8));
+#ifndef SC_BAD_FLICKER
+    outw(TSIDX, 0x0300);
+#endif
+    outw(GDCIDX, 0x0004 | (buf[2] << 8));
+    outw(GDCIDX, 0x0005 | (buf[3] << 8));
+    if (adp->va_crtc_addr == MONO_BASE)
+        outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
+    else
+        outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
+#endif
+
+    splx(s);
+}
+
+/* EGA/VGA */
+static int
+vid_save_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
+{
+    u_char buf[PARAM_BUFSIZE];
+    u_char val = 0;
+    u_int32_t segment;
+    int c;
+    int s;
+
+    prologue(ad, V_ADP_FONT, 1);
+
+    if (fontsize < 14) {
+	/* FONT_8 */
+	fontsize = 8;
+    } else if (fontsize >= 32) {
+	fontsize = 32;
+    } else if (fontsize >= 16) {
+	/* FONT_16 */
+	fontsize = 16;
+    } else {
+	/* FONT_14 */
+	fontsize = 14;
+    }
+
+    if (page < 0 || page >= 8)
+	return 1;
+    segment = VIDEOMEM + 0x4000*page;
+    if (page > 3)
+	segment -= 0xe000;
+
+    if (adapter[ad].va_type == KD_VGA) {	/* what about EGA? XXX */
+	s = splhigh();
+	outb(TSIDX, 0x00); outb(TSREG, 0x01);
+	outb(TSIDX, 0x01); val = inb(TSREG);	/* disable screen */
+	outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
+	outb(TSIDX, 0x00); outb(TSREG, 0x03);
+	splx(s);
+    }
+
+    set_font_mode(&adapter[ad], buf);
+    if (fontsize == 32) {
+	generic_bcopy((void *)BIOS_PADDRTOVADDR(segment + ch*32), data, 
+		      fontsize*count);
+    } else {
+	for (c = ch; count > 0; ++c, --count) {
+	    generic_bcopy((void *)BIOS_PADDRTOVADDR(segment + c*32), data, 
+			  fontsize);
+	    data += fontsize;
+	}
+    }
+    set_normal_mode(&adapter[ad], buf);
+
+    if (adapter[ad].va_type == KD_VGA) {
+	s = splhigh();
+	outb(TSIDX, 0x00); outb(TSREG, 0x01);
+	outb(TSIDX, 0x01); outb(TSREG, val & 0xdf);	/* enable screen */
+	outb(TSIDX, 0x00); outb(TSREG, 0x03);
+	splx(s);
+    }
+
+    return 0;
+}
+
+/* EGA/VGA */
+static int
+vid_load_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
+{
+    u_char buf[PARAM_BUFSIZE];
+    u_char val = 0;
+    u_int32_t segment;
+    int c;
+    int s;
+
+    prologue(ad, V_ADP_FONT, 1);
+
+    if (fontsize < 14) {
+	/* FONT_8 */
+	fontsize = 8;
+    } else if (fontsize >= 32) {
+	fontsize = 32;
+    } else if (fontsize >= 16) {
+	/* FONT_16 */
+	fontsize = 16;
+    } else {
+	/* FONT_14 */
+	fontsize = 14;
+    }
+
+    if (page < 0 || page >= 8)
+	return 1;
+    segment = VIDEOMEM + 0x4000*page;
+    if (page > 3)
+	segment -= 0xe000;
+
+    if (adapter[ad].va_type == KD_VGA) {	/* what about EGA? XXX */
+	s = splhigh();
+	outb(TSIDX, 0x00); outb(TSREG, 0x01);
+	outb(TSIDX, 0x01); val = inb(TSREG);	/* disable screen */
+	outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
+	outb(TSIDX, 0x00); outb(TSREG, 0x03);
+	splx(s);
+    }
+
+    set_font_mode(&adapter[ad], buf);
+    if (fontsize == 32) {
+	generic_bcopy(data, (void *)BIOS_PADDRTOVADDR(segment + ch*32),
+		      fontsize*count);
+    } else {
+	for (c = ch; count > 0; ++c, --count) {
+	    generic_bcopy(data, (void *)BIOS_PADDRTOVADDR(segment + c*32), 
+			  fontsize);
+	    data += fontsize;
+	}
+    }
+    set_normal_mode(&adapter[ad], buf);
+
+    if (adapter[ad].va_type == KD_VGA) {
+	s = splhigh();
+	outb(TSIDX, 0x00); outb(TSREG, 0x01);
+	outb(TSIDX, 0x01); outb(TSREG, val & 0xdf);	/* enable screen */
+	outb(TSIDX, 0x00); outb(TSREG, 0x03);
+	splx(s);
+    }
+
+    return 0;
+}
+
+/* EGA/VGA */
+static int
+vid_show_font(int ad, int page)
+{
+    static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f };
+    int s;
+
+    prologue(ad, V_ADP_FONT, 1);
+    if (page < 0 || page >= 8)
+	return 1;
+
+    s = splhigh();
+    outb(TSIDX, 0x03); outb(TSREG, cg[page]);
+    splx(s);
+
+    return 0;
+}
+
+/* VGA */
+static int
+vid_save_palette(int ad, u_char *palette)
+{
+    int i;
+
+    prologue(ad, V_ADP_PALETTE, 1);
+
+    /* 
+     * We store 8 bit values in the palette buffer, while the standard
+     * VGA has 6 bit DAC .
+     */
+    outb(PALRADR, 0x00);
+    for (i = 0; i < 256*3; ++i)
+	palette[i] = inb(PALDATA) << 2; 
+    inb(adapter[ad].va_crtc_addr + 6);	/* reset flip/flop */
+    return 0;
+}
+
+/* VGA */
+static int
+vid_load_palette(int ad, u_char *palette)
+{
+    int i;
+
+    prologue(ad, V_ADP_PALETTE, 1);
+
+    outb(PIXMASK, 0xff);		/* no pixelmask */
+    outb(PALWADR, 0x00);
+    for (i = 0; i < 256*3; ++i)
+	outb(PALDATA, palette[i] >> 2);
+    inb(adapter[ad].va_crtc_addr + 6);	/* reset flip/flop */
+    outb(ATC, 0x20);			/* enable palette */
+    return 0;
+}
+
+/* CGA/EGA/VGA */
+static int
+vid_set_border(int ad, int color)
+{
+    prologue(ad, V_ADP_BORDER, 1);
+
+    switch (adapter[ad].va_type) {
+    case KD_EGA:
+    case KD_VGA:    
+	inb(adapter[ad].va_crtc_addr + 6);	/* reset flip-flop */
+	outb(ATC, 0x31); outb(ATC, color & 0xff); 
+	break;  
+    case KD_CGA:    
+	outb(adapter[ad].va_crtc_addr + 5, color & 0x0f); /* color select register */
+	break;  
+    case KD_MONO:   
+    case KD_HERCULES:
+    default:
+	break;  
+    }
+    return 0;
+}
+
+/* VGA */
+static int
+vid_save_state(int ad, void *p, size_t size)
+{
+    video_info_t info;
+    u_char *buf;
+    int crtc_addr;
+    int i, j;
+    int s;
+
+    if (size == 0) {
+	/* return the required buffer size */
+	prologue(ad, V_ADP_STATESAVE, 0);
+	return sizeof(adp_state_t);
+    } else {
+	prologue(ad, V_ADP_STATESAVE, 1);
+	if (size < sizeof(adp_state_t))
+	    return 1;
+    }
+
+    ((adp_state_t *)p)->sig = V_STATE_SIG;
+    buf = ((adp_state_t *)p)->regs;
+    bzero(buf, V_MODE_PARAM_SIZE);
+    crtc_addr = adapter[ad].va_crtc_addr;
+
+    s = splhigh();
+
+    outb(TSIDX, 0x00); outb(TSREG, 0x01);	/* stop sequencer */
+    for (i = 0, j = 5; i < 4; i++) {           
+	outb(TSIDX, i + 1);
+	buf[j++]  =  inb(TSREG);
+    }
+    buf[9]  =  inb(MISC + 10);			/* dot-clock */
+    outb(TSIDX, 0x00); outb(TSREG, 0x03);	/* start sequencer */
+
+    for (i = 0, j = 10; i < 25; i++) {		/* crtc */
+	outb(crtc_addr, i);
+	buf[j++]  =  inb(crtc_addr + 1);
+    }
+    for (i = 0, j = 35; i < 20; i++) {		/* attribute ctrl */
+        inb(crtc_addr + 6);			/* reset flip-flop */
+	outb(ATC, i);
+	buf[j++]  =  inb(ATC + 1);
+    }
+    for (i = 0, j = 55; i < 9; i++) {		/* graph data ctrl */
+	outb(GDCIDX, i);
+	buf[j++]  =  inb(GDCREG);
+    }
+    inb(crtc_addr + 6);				/* reset flip-flop */
+    outb(ATC, 0x20);				/* enable palette */
+
+    splx(s);
+
+#if 1
+    if (vid_get_info(ad, adapter[ad].va_mode, &info) == 0) {
+	if (info.vi_flags & V_INFO_GRAPHICS) {
+	    buf[0] = info.vi_width/info.vi_cwidth; /* COLS */
+	    buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */
+	} else {
+	    buf[0] = info.vi_width;		/* COLS */
+	    buf[1] = info.vi_height - 1;	/* ROWS */
+	}
+	buf[2] = info.vi_cheight;		/* POINTS */
+    } else {
+	/* XXX: shouldn't be happening... */
+	printf("video#%d: failed to obtain mode info. (vid_save_state())\n",
+	       ad);
+    }
+#else
+    buf[0] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);	/* COLS */
+    buf[1] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);	/* ROWS */
+    buf[2] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);	/* POINTS */
+    buf[3] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44c);
+    buf[4] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44d);
+#endif
+
+    return 0;
+}
+
+/* EGA/VGA */
+static int
+vid_load_state(int ad, void *p)
+{
+    u_char *buf;
+    int crtc_addr;
+    int s;
+    int i;
+
+    prologue(ad, V_ADP_STATELOAD, 1);
+    if (((adp_state_t *)p)->sig != V_STATE_SIG)
+	return 1;
+
+    buf = ((adp_state_t *)p)->regs;
+    crtc_addr = adapter[ad].va_crtc_addr;
+
+    s = splhigh();
+
+    outb(TSIDX, 0x00); outb(TSREG, 0x01);	/* stop sequencer */
+    for (i = 0; i < 4; ++i) {			/* program sequencer */
+	outb(TSIDX, i + 1);
+	outb(TSREG, buf[i + 5]);
+    }
+    outb(MISC, buf[9]);				/* set dot-clock */
+    outb(TSIDX, 0x00); outb(TSREG, 0x03);	/* start sequencer */
+    outb(crtc_addr, 0x11);
+    outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
+    for (i = 0; i < 25; ++i) {			/* program crtc */
+	outb(crtc_addr, i);
+	outb(crtc_addr + 1, buf[i + 10]);
+    }
+    inb(crtc_addr+6);				/* reset flip-flop */
+    for (i = 0; i < 20; ++i) {			/* program attribute ctrl */
+	outb(ATC, i);
+	outb(ATC, buf[i + 35]);
+    }
+    for (i = 0; i < 9; ++i) {			/* program graph data ctrl */
+	outb(GDCIDX, i);
+	outb(GDCREG, buf[i + 55]);
+    }
+    inb(crtc_addr + 6);				/* reset flip-flop */
+    outb(ATC, 0x20);				/* enable palette */
+
+    if (ad == V_ADP_PRIMARY) {
+	*(u_int8_t *)BIOS_PADDRTOVADDR(0x44a) = buf[0];	/* COLS */
+	*(u_int8_t *)BIOS_PADDRTOVADDR(0x484) = buf[1] + rows_offset - 1; /* ROWS */
+	*(u_int8_t *)BIOS_PADDRTOVADDR(0x485) = buf[2];	/* POINTS */
+#if 0
+	*(u_int8_t *)BIOS_PADDRTOVADDR(0x44c) = buf[3];
+	*(u_int8_t *)BIOS_PADDRTOVADDR(0x44d) = buf[4];
+#endif
+    }
+
+    splx(s);
+    return 0;
+}
+
+/* all */
+static int
+vid_set_origin(int ad, off_t offset)
+{
+    /* 
+     * The standard video modes do not require window mapping; 
+     * always return error.
+     */
+    return 1;
+}
+
+/* all */
+static int
+vid_read_hw_cursor(int ad, int *col, int *row)
+{
+    video_info_t info;
+    u_int16_t off;
+
+    if (!init_done)
+	return 1;
+    if ((ad < 0) || (ad >= adapters))
+	return 1;
+
+    (*biosvidsw.get_info)(ad, adapter[ad].va_mode, &info);
+    if (info.vi_flags & V_INFO_GRAPHICS)
+	return 1;
+
+    outb(adapter[ad].va_crtc_addr, 14);
+    off = inb(adapter[ad].va_crtc_addr + 1);
+    outb(adapter[ad].va_crtc_addr, 15);
+    off = (off << 8) | inb(adapter[ad].va_crtc_addr + 1);
+
+    *row = off / info.vi_width;
+    *col = off % info.vi_width;
+
+    return 0;
+}
+
+/* all */
+static int
+vid_set_hw_cursor(int ad, int col, int row)
+{
+    video_info_t info;
+    u_int16_t off;
+
+    if (!init_done)
+	return 1;
+    if ((ad < 0) || (ad >= adapters))
+	return 1;
+
+    (*biosvidsw.get_info)(ad, adapter[ad].va_mode, &info);
+    if (info.vi_flags & V_INFO_GRAPHICS)
+	return 1;
+
+    if ((col == -1) || (row == -1))
+	off = 0xffff;
+    else
+	off = row*info.vi_width + col;
+    outb(adapter[ad].va_crtc_addr, 14);
+    outb(adapter[ad].va_crtc_addr + 1, off >> 8);
+    outb(adapter[ad].va_crtc_addr, 15);
+    outb(adapter[ad].va_crtc_addr + 1, off & 0x00ff);
+
+    return 0;
+}
+
+static char
+*adapter_name(int type)
+{
+    static struct {
+	int type;
+	char *name;
+    } names[] = {
+	{ KD_MONO,	"MDA" },
+	{ KD_HERCULES,	"Hercules" },
+	{ KD_CGA,	"CGA" },
+	{ KD_EGA,	"EGA" },
+	{ KD_VGA,	"VGA" },
+	{ KD_PC98,	"PC-98xx" },
+	{ -1,		"Unknown" },
+    };
+    int i;
+
+    for (i = 0; names[i].type != -1; ++i)
+	if (names[i].type == type)
+	    break;
+    return names[i].name;
+}
+
+static void
+dump_adp_info(int ad, video_adapter_t *adp, int level)
+{
+    if (level <= 0)
+	return;
+
+    printf("video#%d: adapter type:%s (%d), flags:0x%x, CRTC:0x%x\n", 
+	   ad, adapter_name(adp->va_type), adp->va_type, 
+	   adp->va_flags, adp->va_crtc_addr);
+    printf("video#%d: init mode:%d, bios mode:%d, current mode:%d\n",
+	   ad, adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
+    printf("video#%d: window:0x%x size:%dk gran:%dk, buf:0x%x size:%dk\n",
+	   ad, 
+	   adp->va_window, adp->va_window_size, adp->va_window_gran,
+	   adp->va_buffer, adp->va_buffer_size);
+}
+
+static void
+dump_mode_info(int ad, video_info_t *info, int level)
+{
+    if (level <= 0)
+	return;
+
+    printf("video#%d: mode:%d, flags:0x%x ", 
+	   ad, info->vi_mode, info->vi_flags);
+    if (info->vi_flags & V_INFO_GRAPHICS)
+	printf("G %dx%dx%d, %d plane(s), font:%dx%d, ",
+	       info->vi_width, info->vi_height, 
+	       info->vi_depth, info->vi_planes, 
+	       info->vi_cwidth, info->vi_cheight); 
+    else
+	printf("T %dx%d, font:%dx%d, ",
+	       info->vi_width, info->vi_height, 
+	       info->vi_cwidth, info->vi_cheight); 
+    printf("win:0x%x\n", info->vi_window);
+}
+
+static void
+dump_buffer(u_char *buf, size_t len)
+{
+    int i;
+
+    for(i = 0; i < len;) {
+	printf("%02x ", buf[i]);
+	if ((++i % 16) == 0)
+	    printf("\n");
+    }
+}
+
+static int
+vid_diag(int level)
+{
+    video_info_t info;
+    u_char *mp;
+    int ad;
+    int i;
+
+    if (!init_done)
+	return 1;
+
+    if (level > 0) {
+	printf("video: RTC equip. code:0x%02x, DCC code:0x%02x\n",
+	       rtcin(RTC_EQUIPMENT), *(u_int8_t *)BIOS_PADDRTOVADDR(0x488));
+	printf("video: CRTC:0x%x, video option:0x%02x, ",
+	       *(u_int16_t *)BIOS_PADDRTOVADDR(0x463),
+	       *(u_int8_t *)BIOS_PADDRTOVADDR(0x487));
+	printf("rows:%d, cols:%d, font height:%d\n",
+	       *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a),
+	       *(u_int8_t *)BIOS_PADDRTOVADDR(0x484) + 1,
+	       *(u_int8_t *)BIOS_PADDRTOVADDR(0x485));
+	printf("video: param table EGA/VGA:%p, CGA/MDA:%p\n", 
+	       video_mode_ptr, video_mode_ptr2);
+	printf("video: rows_offset:%d\n", rows_offset);
+    }
+
+    for (ad = 0; ad < adapters; ++ad) {
+	dump_adp_info(ad, &adapter[ad], level);
+
+	if (!(adapter[ad].va_flags & V_ADP_MODECHANGE)) {
+	    vid_get_info(ad, adapter[ad].va_initial_mode, &info);
+	    dump_mode_info(ad, &info, level);
+	} else {
+	    for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+		if (bios_vmode[i].vi_mode == NA)
+		    continue;
+		if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
+		    continue;
+		dump_mode_info(ad, &bios_vmode[i], level);
+	    }
+	}
+	if ((adapter[ad].va_type != KD_EGA) && (adapter[ad].va_type != KD_VGA))
+	    continue;
+
+	if (video_mode_ptr == NULL)
+	    printf("video#%d: WARNING: video mode switching is not fully supported on this adapter\n", ad);
+
+	if (level <= 0)
+	    continue;
+
+	if (adapter[ad].va_type == KD_VGA) {
+	    printf("VGA parameters upon power-up\n");
+	    dump_buffer(adpstate.regs, sizeof(adpstate.regs));
+	    printf("VGA parameters in BIOS for mode %d\n", 
+		adapter[ad].va_initial_mode);
+	    dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
+	}
+
+	mp = get_mode_param(adapter[ad].va_initial_mode);
+	if (mp == NULL)	/* this shouldn't be happening */
+	    continue;
+	printf("EGA/VGA parameters to be used for mode %d\n", 
+	    adapter[ad].va_initial_mode);
+	dump_buffer(mp, V_MODE_PARAM_SIZE);
+    }
+
+    return 0;
+}
+
+#endif /* NSC > 0 */
diff --git a/sys/i386/isa/videoio.h b/sys/i386/isa/videoio.h
new file mode 100644
index 000000000000..74d17d0bf0ec
--- /dev/null
+++ b/sys/i386/isa/videoio.h
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ *    products derived from this software without specific prior written 
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#ifndef _I386_ISA_VIDEOIO_H_
+#define _I386_ISA_VIDEOIO_H_
+
+#ifdef KERNEL
+
+#define V_MAX_ADAPTERS		2
+
+#define V_MODE_MAP_SIZE		(M_VGA_CG320 + 1)
+#define V_MODE_PARAM_SIZE	64
+
+/* physical addresses */
+#define MONO_BUF		BIOS_PADDRTOVADDR(0xb0000)
+#define CGA_BUF			BIOS_PADDRTOVADDR(0xb8000)
+#define GRAPHICS_BUF		BIOS_PADDRTOVADDR(0xa0000)
+#define VIDEOMEM		0x000A0000
+
+/* I/O port addresses */
+#define MONO_BASE	0x3B4			/* crt controller base mono */
+#define COLOR_BASE	0x3D4			/* crt controller base color */
+#define MISC		0x3C2			/* misc output register */
+#define ATC		IO_VGA+0x00		/* attribute controller */
+#define TSIDX		IO_VGA+0x04		/* timing sequencer idx */
+#define TSREG		IO_VGA+0x05		/* timing sequencer data */
+#define PIXMASK		IO_VGA+0x06		/* pixel write mask */
+#define PALRADR		IO_VGA+0x07		/* palette read address */
+#define PALWADR		IO_VGA+0x08		/* palette write address */
+#define PALDATA		IO_VGA+0x09		/* palette data register */
+#define GDCIDX		IO_VGA+0x0E		/* graph data controller idx */
+#define GDCREG		IO_VGA+0x0F		/* graph data controller data */
+
+/* video function table */
+typedef int vi_init_t(void);
+typedef video_adapter_t *vi_adapter_t(int ad);
+typedef int vi_get_info_t(int ad, int mode, video_info_t *info);
+typedef int vi_query_mode_t(int ad, video_info_t *info);
+typedef int vi_set_mode_t(int ad, int mode);
+typedef int vi_save_font_t(int ad, int page, int size, u_char *data, 
+			   int c, int count);
+typedef int vi_load_font_t(int ad, int page, int size, u_char *data, 
+			   int c, int count);
+typedef int vi_show_font_t(int ad, int page);
+typedef int vi_save_palette_t(int ad, u_char *palette);
+typedef int vi_load_palette_t(int ad, u_char *palette);
+typedef int vi_set_border_t(int ad, int border);
+typedef int vi_save_state_t(int ad, void *p, size_t size);
+typedef int vi_load_state_t(int ad, void *p);
+typedef int vi_set_win_org_t(int ad, off_t offset);
+typedef int vi_read_hw_cursor_t(int ad, int *col, int *row);
+typedef int vi_set_hw_cursor_t(int ad, int col, int row);
+typedef int vi_diag_t(int level);
+
+struct vidsw {
+    vi_init_t		*init;			/* all */
+    vi_adapter_t	*adapter;		/* all */
+    vi_get_info_t	*get_info;		/* all */
+    vi_query_mode_t	*query_mode;		/* all */
+    vi_set_mode_t	*set_mode;		/* EGA/VGA */
+    vi_save_font_t	*save_font;		/* EGA/VGA */
+    vi_load_font_t	*load_font;		/* EGA/VGA */
+    vi_show_font_t	*show_font;		/* EGA/VGA */
+    vi_save_palette_t	*save_palette;		/* VGA */
+    vi_load_palette_t	*load_palette;		/* VGA */
+    vi_set_border_t	*set_border;		/* CGA/EGA/VGA */
+    vi_save_state_t	*save_state;		/* VGA */
+    vi_load_state_t	*load_state;		/* EGA/VGA */
+    vi_set_win_org_t	*set_win_org;		/* all */
+    vi_read_hw_cursor_t	*read_hw_cursor;	/* all */
+    vi_set_hw_cursor_t	*set_hw_cursor;		/* all */
+    vi_diag_t		*diag;			/* all */
+};
+
+extern struct vidsw biosvidsw;
+
+#endif /* KERNEL */
+
+#endif /* !_I386_ISA_VIDEOIO_H_ */
diff --git a/sys/i386/isa/wst.c b/sys/i386/isa/wst.c
index 390eb2c35efb..ff5f5435f31e 100644
--- a/sys/i386/isa/wst.c
+++ b/sys/i386/isa/wst.c
@@ -6,13 +6,13 @@
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer 
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: wst.c,v 1.10 1998/08/24 02:28:16 bde Exp $
+ *	$Id$
  */
 
 #include "wdc.h"
diff --git a/sys/modules/syscons/blank/blank_saver.c b/sys/modules/syscons/blank/blank_saver.c
index 451dc9a4b241..d5f4cf0bf560 100644
--- a/sys/modules/syscons/blank/blank_saver.c
+++ b/sys/modules/syscons/blank/blank_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: blank_saver.c,v 1.10 1997/07/15 14:49:09 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
diff --git a/sys/modules/syscons/daemon/daemon_saver.c b/sys/modules/syscons/daemon/daemon_saver.c
index f3cf3dce7736..688df41f274a 100644
--- a/sys/modules/syscons/daemon/daemon_saver.c
+++ b/sys/modules/syscons/daemon/daemon_saver.c
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: daemon_saver.c,v 1.8 1998/01/16 17:58:43 bde Exp $
+ *	$Id: daemon_saver.c,v 1.9 1998/08/06 09:14:20 yokota Exp $
  */
 
 #include <sys/param.h>
@@ -205,7 +205,7 @@ daemon_saver(int blank)
 			/* clear the screen and set the border color */
 			fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
 			      Crtat, scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			xlen = ylen = tlen = 0;
 		}
 		if (scrn_blanked++ < 2)
@@ -322,7 +322,7 @@ daemon_saver(int blank)
 		draw_string(txpos, typos, toff, (char *)message, tlen);
 	} else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/sys/modules/syscons/fade/fade_saver.c b/sys/modules/syscons/fade/fade_saver.c
index 341f7e8d240c..41176e76e092 100644
--- a/sys/modules/syscons/fade/fade_saver.c
+++ b/sys/modules/syscons/fade/fade_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995-1997 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: fade_saver.c,v 1.11 1997/07/15 14:49:25 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -84,7 +84,7 @@ fade_saver(int blank)
 	else {
 		switch (crtc_type) {
 		case KD_VGA:
-			load_palette(palette);
+			load_palette(cur_console, palette);
 			count = 0;
 			break;
 		case KD_EGA:
diff --git a/sys/modules/syscons/green/green_saver.c b/sys/modules/syscons/green/green_saver.c
index b8c82958ac34..667866284681 100644
--- a/sys/modules/syscons/green/green_saver.c
+++ b/sys/modules/syscons/green/green_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: green_saver.c,v 1.10 1997/07/15 14:49:29 yokota Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
diff --git a/sys/modules/syscons/saver.h b/sys/modules/syscons/saver.h
index 7118e4588e22..96cc010e9b81 100644
--- a/sys/modules/syscons/saver.h
+++ b/sys/modules/syscons/saver.h
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995-1997 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,12 +25,12 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *  $Id: saver.h,v 1.9 1997/07/15 14:48:11 yokota Exp $
+ *	$Id$
  */
-
 #include <machine/apm_bios.h>
 #include <machine/console.h>
 
+#include <i386/isa/videoio.h>
 #include <i386/isa/syscons.h>
 
 extern scr_stat	*cur_console;
diff --git a/sys/modules/syscons/snake/snake_saver.c b/sys/modules/syscons/snake/snake_saver.c
index c3fa1fe7ce38..c5011d04bac2 100644
--- a/sys/modules/syscons/snake/snake_saver.c
+++ b/sys/modules/syscons/snake/snake_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: snake_saver.c,v 1.16 1998/01/16 17:58:50 bde Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -63,7 +63,7 @@ snake_saver(int blank)
 		if (scrn_blanked <= 0) {
 			fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20],
 			      Crtat, scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			dirx = (scp->xpos ? 1 : -1);
 			diry = (scp->ypos ?
 				scp->xsize : -scp->xsize);
@@ -99,7 +99,7 @@ snake_saver(int blank)
 	}
 	else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/sys/modules/syscons/star/star_saver.c b/sys/modules/syscons/star/star_saver.c
index 517a5579968f..8ac65bdba71c 100644
--- a/sys/modules/syscons/star/star_saver.c
+++ b/sys/modules/syscons/star/star_saver.c
@@ -1,18 +1,18 @@
 /*-
- * Copyright (c) 1995 S�ren Schmidt
+ * Copyright (c) 1995-1998 S�ren Schmidt
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software withough specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: star_saver.c,v 1.13 1998/01/16 17:58:55 bde Exp $
+ *	$Id$
  */
 
 #include <sys/param.h>
@@ -62,7 +62,7 @@ star_saver(int blank)
 			scrn_blanked = 1;
 			fillw((FG_LIGHTGREY|BG_BLACK)<<8|scr_map[0x20], Crtat,
 			      scp->xsize * scp->ysize);
-			set_border(0);
+			set_border(scp, 0);
 			for(i=0; i<NUM_STARS; i++) {
 				stars[i][0] =
 					random() % (scp->xsize*scp->ysize);
@@ -80,7 +80,7 @@ star_saver(int blank)
 	}
 	else {
 		if (scrn_blanked > 0) {
-			set_border(scp->border);
+			set_border(scp, scp->border);
 			scrn_blanked = 0;
 		}
 	}
diff --git a/sys/pc98/pc98/wst.c b/sys/pc98/pc98/wst.c
index 390eb2c35efb..ff5f5435f31e 100644
--- a/sys/pc98/pc98/wst.c
+++ b/sys/pc98/pc98/wst.c
@@ -6,13 +6,13 @@
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer 
- *    in this position and unchanged.
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: wst.c,v 1.10 1998/08/24 02:28:16 bde Exp $
+ *	$Id$
  */
 
 #include "wdc.h"
diff --git a/usr.sbin/vidcontrol/vidcontrol.1 b/usr.sbin/vidcontrol/vidcontrol.1
index aea546717aec..f4c9d211a55c 100644
--- a/usr.sbin/vidcontrol/vidcontrol.1
+++ b/usr.sbin/vidcontrol/vidcontrol.1
@@ -11,7 +11,7 @@
 .\"    documentation and/or other materials provided with the distribution.
 .\"
 .\"     @(#)vidcontrol.1
-.\"	$Id: vidcontrol.1,v 1.11 1997/07/24 23:46:35 wosch Exp $
+.\"	$Id: vidcontrol.1,v 1.12 1997/10/27 07:52:08 charnier Exp $
 .\"
 .Dd May 22, 1994
 .Dt VIDCONTROL 1
@@ -25,6 +25,7 @@
 .Op Fl b Ar color
 .Op Fl c Ar appearance
 .Op Fl d
+.Op Fl i Ar adapter|mode
 .Op Fl l Ar scrmap
 .Op Fl L
 .Op Fl m Ar on|off
@@ -84,6 +85,10 @@ Install screen output map file from
 .Ar scrmap
 .It Fl L
 Install default screen output map.
+.It Fl i Ar adapter
+Shows info about the current videoadapter.
+.It Fl i Ar mode
+Shows the possible videomodes with the current video hardware.
 .It Fl m Ar on|off
 Switch the mousepointer
 .Ar on
diff --git a/usr.sbin/vidcontrol/vidcontrol.c b/usr.sbin/vidcontrol/vidcontrol.c
index 81f13da223e9..4c97cabf2166 100644
--- a/usr.sbin/vidcontrol/vidcontrol.c
+++ b/usr.sbin/vidcontrol/vidcontrol.c
@@ -28,7 +28,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-	"$Id: vidcontrol.c,v 1.18 1997/10/27 07:52:10 charnier Exp $";
+	"$Id: vidcontrol.c,v 1.19 1998/07/14 10:32:27 bde Exp $";
 #endif /* not lint */
 
 #include <ctype.h>
@@ -259,6 +259,7 @@ void
 video_mode(int argc, char **argv, int *index)
 {
 	unsigned long mode;
+	int size[3];
 
 	if (*index < argc) {
 		if (!strcmp(argv[*index], "VGA_40x25"))
@@ -277,10 +278,27 @@ video_mode(int argc, char **argv, int *index)
 			mode = SW_ENH_C80x25;
 		else if (!strcmp(argv[*index], "EGA_80x43"))
 			mode = SW_ENH_C80x43;
+		else if (!strcmp(argv[*index], "VESA_132x25"))
+			mode = SW_VESA_C132x25;
+		else if (!strcmp(argv[*index], "VESA_132x43"))
+			mode = SW_VESA_C132x43;
+		else if (!strcmp(argv[*index], "VESA_132x50"))
+			mode = SW_VESA_C132x50;
+		else if (!strcmp(argv[*index], "VESA_132x60"))
+			mode = SW_VESA_C132x60;
+		else if (!strcmp(argv[*index], "VESA_800x600"))
+			mode = SW_VESA_800x600;
 		else
 			return;
 		if (ioctl(0, mode, NULL) < 0)
 			warn("cannot set videomode");
+		if (mode == SW_VESA_800x600) {
+			size[0] = 80;	/* columns */
+			size[1] = 25;	/* rows */
+			size[2] = 16;	/* font size */
+			if (ioctl(0, KDRASTER, size))
+				warn("cannot activate raster display");
+		}
 		(*index)++;
 	}
 	return;
@@ -375,6 +393,103 @@ set_mouse(char *arg)
 	ioctl(0, CONS_MOUSECTL, &mouse);
 }
 
+static char
+*adapter_name(int type)
+{
+    static struct {
+	int type;
+	char *name;
+    } names[] = {
+	{ KD_MONO,	"MDA" },
+	{ KD_HERCULES,	"Hercules" },
+	{ KD_CGA,	"CGA" },
+	{ KD_EGA,	"EGA" },
+	{ KD_VGA,	"VGA" },
+	{ KD_PC98,	"PC-98xx" },
+	{ -1,		"Unknown" },
+    };
+    int i;
+
+    for (i = 0; names[i].type != -1; ++i)
+	if (names[i].type == type)
+	    break;
+    return names[i].name;
+}
+
+void
+show_adapter_info(void)
+{
+	struct video_adapter ad;
+
+	ad.va_index = 0;
+	if (ioctl(0, CONS_ADPINFO, &ad)) {
+		warn("failed to obtain adapter information");
+		return;
+	}
+
+	printf("adapter %d:\n", ad.va_index);
+	printf("    type:%s%s (%d), flags:0x%08x, CRTC:0x%x\n", 
+	       (ad.va_flags & V_ADP_VESA) ? "VESA " : "",
+	       adapter_name(ad.va_type), ad.va_type, 
+	       ad.va_flags, ad.va_crtc_addr);
+	printf("    initial mode:%d, current mode:%d, BIOS mode:%d\n",
+	       ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode);
+}
+
+void
+show_mode_info(void)
+{
+	struct video_info info;
+	char buf[80];
+	int mode;
+	int c;
+
+	printf("    mode#     flags   type    size       "
+	       "font      window      linear buffer\n");
+	printf("---------------------------------------"
+	       "---------------------------------------\n");
+	for (mode = 0; mode < M_VESA_MODE_MAX; ++mode) {
+		info.vi_mode = mode;
+		if (ioctl(0, CONS_MODEINFO, &info))
+			continue;
+
+		printf("%3d (0x%03x)", mode, mode);
+    		printf(" 0x%08x", info.vi_flags);
+		if (info.vi_flags & V_INFO_GRAPHICS) {
+			c = 'G';
+			snprintf(buf, sizeof(buf), "%dx%dx%d %d",
+				 info.vi_width, info.vi_height, 
+				 info.vi_depth, info.vi_planes);
+		} else {
+			c = 'T';
+			snprintf(buf, sizeof(buf), "%dx%d",
+				 info.vi_width, info.vi_height);
+		}
+		printf(" %c %-15s", c, buf);
+		snprintf(buf, sizeof(buf), "%dx%d", 
+			 info.vi_cwidth, info.vi_cheight); 
+		printf(" %-5s", buf);
+    		printf(" 0x%05x %2dk %2dk", 
+		       info.vi_window, info.vi_window_size, 
+		       info.vi_window_gran);
+    		printf(" 0x%08x %2dk\n",
+		       info.vi_buffer, info.vi_buffer_size);
+	}
+}
+
+void
+show_info(char *arg)
+{
+	if (!strcmp(arg, "adapter"))
+		show_adapter_info();
+	else if (!strcmp(arg, "mode"))
+		show_mode_info();
+	else {
+		warnx("argument to -i must either adapter or mode");
+		return;
+	}
+}
+
 void
 test_frame()
 {
@@ -402,7 +517,7 @@ main(int argc, char **argv)
 	info.size = sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) < 0)
 		err(1, "must be on a virtual console");
-	while((opt = getopt(argc, argv, "b:c:df:l:Lm:r:s:t:x")) != -1)
+	while((opt = getopt(argc, argv, "b:c:df:i:l:Lm:r:s:t:x")) != -1)
 		switch(opt) {
 			case 'b':
 				set_border_color(optarg);
@@ -417,6 +532,9 @@ main(int argc, char **argv)
 				load_font(optarg,
 					nextarg(argc, argv, &optind, 'f'));
 				break;
+			case 'i':
+				show_info(optarg);
+				break;
 			case 'l':
 				load_scrnmap(optarg);
 				break;