From 1fb323a09785c214177edfae0d57d2462ddc1353 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sun, 22 Nov 2009 11:04:39 +0100
Subject: [PATCH] vga(4): Relax and simplify conditions for mode rejection a bit.

When mapping the video parameter table to our mode_map, only reject
modes which are neither 40x25, 80x25 nor 80x30, instead of rejecting or
accepting the whole table based on comparing the initial mode's BIOS and
power-up register settings.

Add a VGA_KEEP_POWERON_MODE option which preserves the register settings
which were found for the initial mode upon power-on for switching back
to it from another mode. This is kinda similar to what's proposed in
FreeBSD's kern/64114.
---
 share/man/man4/vga.4           |   41 ++++++++-------
 sys/config/LINT                |    5 ++-
 sys/dev/video/fb/vga.c         |  116 +++++-----------------------------------
 sys/platform/pc32/conf/options |    2 +-
 sys/platform/pc64/conf/options |    5 +--
 5 files changed, 41 insertions(+), 128 deletions(-)

diff --git a/share/man/man4/vga.4 b/share/man/man4/vga.4
index 7732448..d50f3c8 100644
--- a/share/man/man4/vga.4
+++ b/share/man/man4/vga.4
@@ -25,19 +25,19 @@
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\" $FreeBSD: src/share/man/man4/vga.4,v 1.7.2.10 2002/12/20 18:03:05 trhodes Exp $
-.\" $DragonFly: src/share/man/man4/vga.4,v 1.6 2008/01/09 22:08:29 swildner Exp $
 .\"
-.Dd January 9, 2008
+.Dd November 22, 2009
 .Dt VGA 4
 .Os
 .Sh NAME
-.Nm vesa ,
-.Nm vga
+.Nm vga ,
+.Nm vesa
 .Nd generic video card interface
 .Sh SYNOPSIS
 .Cd "options VESA"
 .Cd "options VESA_DEBUG=N"
 .Cd "options VGA_ALT_SEQACCESS"
+.Cd "options VGA_KEEP_POWERON_MODE"
 .Cd "options VGA_NO_FONT_LOADING"
 .Cd "options VGA_NO_MODE_CHANGE"
 .Cd "options VGA_SLOW_IOACCESS"
@@ -80,7 +80,7 @@ can be used to control the
 .Nm
 driver.
 These options provide compatibility with certain VGA cards.
-.Bl -tag -width ".Dv VGA_NO_FONT_LOADING"
+.Bl -tag -width ".Dv VGA_KEEP_POWERON_MODE"
 .It Dv VGA_ALT_SEQACCESS
 You may want to try this option if the mouse pointer is not drawn correctly
 or the font does not seem to be loaded properly on the VGA card.
@@ -90,6 +90,9 @@ Set the VGA support debug level to
 .Fa N .
 The default value is 0, which suppresses all debugging output.
 A value of 2 gives maximum verbosity.
+.It Dv VGA_KEEP_POWERON_MODE
+This option keeps the initial mode's register settings for switching back
+to it from another mode.
 .It Dv VGA_SLOW_IOACCESS
 Older VGA cards may require this option for proper operation.
 It makes the driver perform byte-wide I/O to VGA registers and
@@ -100,23 +103,10 @@ These modes are not always supported by the video card and the display.
 It is highly likely that LCD display cannot work with these modes.
 .El
 .Pp
-The following options add optional features to the driver.
-.Bl -tag -width ".Dv VGA_NO_FONT_LOADING"
-.It Dv VESA
-Add VESA BIOS Extension support to the driver.
-If the VGA card has the VESA BIOS Extension 1.2 or later,
-this option will utilize it to switch to high resolution modes.
-.It Dv VESA_DEBUG=N
-Set the VESA support debug level to
-.Fa N .
-The default value is 0, which suppresses all debugging output.
-A value of 2 gives maximum verbosity.
-.El
-.Pp
 The following options will remove some features from the
 .Nm
 driver and save kernel memory.
-.Bl -tag -width ".Dv VGA_NO_FONT_LOADING"
+.Bl -tag -width ".Dv VGA_KEEP_POWERON_MODE"
 .It Dv VGA_NO_FONT_LOADING
 This option removes font loading from the driver.
 Note that if you use this option and
@@ -128,6 +118,19 @@ See
 .It Dv VGA_NO_MODE_CHANGE
 This option prevents the driver from changing video modes.
 .El
+.Pp
+The following options add optional features to the driver.
+.Bl -tag -width ".Dv VGA_KEEP_POWERON_MODE"
+.It Dv VESA
+Add VESA BIOS Extension support to the driver.
+If the VGA card has the VESA BIOS Extension 1.2 or later,
+this option will utilize it to switch to high resolution modes.
+.It Dv VESA_DEBUG=N
+Set the VESA support debug level to
+.Fa N .
+The default value is 0, which suppresses all debugging output.
+A value of 2 gives maximum verbosity.
+.El
 .Sh EXAMPLES
 Your kernel configuration should normally have:
 .Pp
diff --git a/sys/config/LINT b/sys/config/LINT
index 21f06ae..2ed3021 100644
--- a/sys/config/LINT
+++ b/sys/config/LINT
@@ -3,7 +3,6 @@
 #	as much of the source tree as it can.
 #
 # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $
-# $DragonFly: src/sys/config/LINT,v 1.177 2008/11/17 11:55:20 swildner Exp $
 #
 # See the kernconf(5) manual page for more information on the format of
 # this file.
@@ -1124,6 +1123,10 @@ options 	VGA_ALT_SEQACCESS
 
 options		VGA_DEBUG=2		# enable VGA debug output
 
+# If you experience problems switching back to 80x25, the following
+# option might help.
+#options	VGA_KEEP_POWERON_MODE	# use power-on settings for 80x25
+
 # If you can dispense with some vga driver features, you may want to
 # use the following options to save some memory.
 #options 	VGA_NO_FONT_LOADING	# don't save/load font
diff --git a/sys/dev/video/fb/vga.c b/sys/dev/video/fb/vga.c
index 3cf293b..945efc1 100644
--- a/sys/dev/video/fb/vga.c
+++ b/sys/dev/video/fb/vga.c
@@ -27,7 +27,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/fb/vga.c,v 1.9.2.1 2001/08/11 02:58:44 yokota Exp $
- * $DragonFly: src/sys/dev/video/fb/vga.c,v 1.25 2008/01/19 08:50:12 swildner Exp $
  */
 
 #include "opt_vga.h"
@@ -373,28 +372,19 @@ static u_char		*video_mode_ptr = NULL;
 #endif
 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))
 
 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
-static void map_mode_table(u_char **, u_char *, int);
-#endif
-#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+static void map_mode_table(u_char **, u_char *);
 static int map_mode_num(int);
 #endif
 static int map_bios_mode_num(int);
 static u_char *get_mode_param(int);
 static int verify_adapter(video_adapter_t *);
 static void update_adapter_info(video_adapter_t *, video_info_t *);
-#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
-#define COMP_IDENTICAL	0
-#define COMP_SIMILAR	1
-#define COMP_DIFFERENT	2
-static int comp_adpregs(u_char *, u_char *);
-#endif
 static int probe_adapters(void);
 static int set_line_length(video_adapter_t *, int);
 static int set_display_start(video_adapter_t *, int, int);
@@ -454,16 +444,18 @@ vga_configure(int flags)
 /* local subroutines */
 
 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
-/* construct the mode parameter map */
+/* construct the mode parameter map (accept 40x25, 80x25 and 80x30 modes) */
 static void
-map_mode_table(u_char *map[], u_char *table, int max)
+map_mode_table(u_char *map[], u_char *table)
 {
     int i;
 
-    for(i = 0; i < max; ++i)
+    for(i = 0; i < V_MODE_MAP_SIZE; ++i) {
 	map[i] = table + i*V_MODE_PARAM_SIZE;
-    for(; i < V_MODE_MAP_SIZE; ++i)
-	map[i] = NULL;
+	if (!(((map[i][0] == 80) && (map[i][1] == 24 || map[i][1] == 29)) ||
+	      ((map[i][0] == 40) && (map[i][1] == 24))))
+	    map[i] = NULL;
+	}
 }
 #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
 
@@ -622,48 +614,6 @@ update_adapter_info(video_adapter_t *adp, video_info_t *info)
     bcopy(info, &adp->va_info, sizeof(adp->va_info));
 }
 
-#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
-/* 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 regs */
-	{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;
-}
-#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
-
 /* probe video adapters and return the number of detected adapters */
 static int
 probe_adapters(void)
@@ -736,51 +686,16 @@ probe_adapters(void)
 	mode_map[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);
+	map_mode_table(mode_map, video_mode_ptr);
 	mp = get_mode_param(adp->va_initial_mode);
+#if !defined(VGA_KEEP_POWERON_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[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));
+	else
+#endif
+	{
 	    mode_map[adp->va_initial_mode] = adpstate.regs;
 	    rows_offset = 1;
-	    break;
 	}
     }
 #endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
@@ -2483,11 +2398,6 @@ vga_diag(video_adapter_t *adp, int level)
     if (level <= 0)
 	return 0;
 
-    kprintf("VGA parameters upon power-up\n");
-    dump_buffer(adpstate.regs, sizeof(adpstate.regs));
-    kprintf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode);
-    dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
-
     mp = get_mode_param(adp->va_initial_mode);
     if (mp == NULL)	/* this shouldn't be happening */
 	return 0;
diff --git a/sys/platform/pc32/conf/options b/sys/platform/pc32/conf/options
index 2dd1537..5a6f3fd 100644
--- a/sys/platform/pc32/conf/options
+++ b/sys/platform/pc32/conf/options
@@ -1,5 +1,4 @@
 # $FreeBSD: src/sys/conf/options.i386,v 1.132.2.18 2003/03/14 21:22:35 jhb Exp $
-# $DragonFly: src/sys/platform/pc32/conf/options,v 1.2 2007/11/07 17:42:50 dillon Exp $
 #
 
 DISABLE_PSE
@@ -91,6 +90,7 @@ SC_TWOBUTTON_MOUSE	opt_syscons.h
 
 VGA_ALT_SEQACCESS	opt_vga.h
 VGA_DEBUG		opt_vga.h
+VGA_KEEP_POWERON_MODE	opt_vga.h
 VGA_NO_FONT_LOADING	opt_vga.h
 VGA_NO_MODE_CHANGE	opt_vga.h
 VGA_SLOW_IOACCESS	opt_vga.h
diff --git a/sys/platform/pc64/conf/options b/sys/platform/pc64/conf/options
index 6b2147d..17cc12d 100644
--- a/sys/platform/pc64/conf/options
+++ b/sys/platform/pc64/conf/options
@@ -1,7 +1,3 @@
-#
-# $DragonFly: src/sys/platform/pc64/conf/options,v 1.4 2008/08/29 17:07:15 dillon Exp $
-#
-
 DISABLE_PSE
 PMAP_SHPGPERPROC	opt_pmap.h
 PPC_PROBE_CHIPSET	opt_ppc.h
@@ -44,6 +40,7 @@ SC_TWOBUTTON_MOUSE	opt_syscons.h
 
 VGA_ALT_SEQACCESS	opt_vga.h
 VGA_DEBUG		opt_vga.h
+VGA_KEEP_POWERON_MODE	opt_vga.h
 VGA_NO_FONT_LOADING	opt_vga.h
 VGA_NO_MODE_CHANGE	opt_vga.h
 VGA_SLOW_IOACCESS	opt_vga.h
-- 
1.6.2.5

