Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Oct 2009 18:41:00 +0000 (UTC)
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r198419 - head/sys/dev/fb
Message-ID:  <200910231841.n9NIf0L5069062@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jkim
Date: Fri Oct 23 18:41:00 2009
New Revision: 198419
URL: http://svn.freebsd.org/changeset/base/198419

Log:
  - When we restore VESA state, try BIOS POST earlier.  VESA restore state
  function may not work properly if we don't.  Turn off hardware cursor as
  vesa_set_mode() does.
  - Add VBE 3.0 specific fields in VESA mode structure and pack it.  Note
  the padding is 190 bytes although VBE 3.0 says 189 bytes.  It must be wrong
  because the size of structure becomes 255 bytes and the specification says
  it must be 256 bytes in total.  In fact, an example code in the spec. does
  it right, though.  While we are at it, fix some i386-isms.
  - Remove state buffer size limitation.  It is no longer necessary since
  sys/compat/x86bios/x86bios.c r198251.
  - Move int 0x10 vector test into vesa_bios_post() as we always do it anyway.

Modified:
  head/sys/dev/fb/vesa.c
  head/sys/dev/fb/vesa.h

Modified: head/sys/dev/fb/vesa.c
==============================================================================
--- head/sys/dev/fb/vesa.c	Fri Oct 23 18:27:34 2009	(r198418)
+++ head/sys/dev/fb/vesa.c	Fri Oct 23 18:41:00 2009	(r198419)
@@ -74,8 +74,7 @@ typedef struct adp_state adp_state_t;
 
 /* VESA video adapter */
 static video_adapter_t *vesa_adp = NULL;
-static int vesa_state_buf_size = 0;
-#define VESA_BIOS_BUFSIZE	(3 * PAGE_SIZE)
+static ssize_t vesa_state_buf_size = -1;
 
 /* VESA functions */
 #if 0
@@ -188,7 +187,7 @@ static int vesa_bios_load_palette2(int s
 #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 ssize_t vesa_bios_state_buf_size(void);
 static int vesa_bios_save_restore(int code, void *p, size_t size);
 static int vesa_bios_get_line_length(void);
 static int vesa_bios_set_line_length(int pixel, int *bytes, int *lines);
@@ -282,6 +281,10 @@ vesa_bios_post(void)
 	}
 	regs.R_DL = 0x80;
 	x86bios_call(&regs, 0xc000, 0x0003);
+
+	if (x86bios_get_intr(0x10) == 0)
+		return (1);
+
 	return (0);
 }
 
@@ -532,7 +535,7 @@ vesa_bios_load_palette2(int start, int c
 }
 #endif
 
-static int
+static ssize_t
 vesa_bios_state_buf_size(void)
 {
 	x86regs_t regs;
@@ -557,9 +560,6 @@ vesa_bios_save_restore(int code, void *p
 	uint32_t offs;
 	void *buf;
 
-	if (size > VESA_BIOS_BUFSIZE)
-		return (1);
-
 	if (code != STATE_SAVE && code != STATE_LOAD)
 		return (1);
 
@@ -808,12 +808,11 @@ vesa_bios_init(void)
 	if (x86bios_get_intr(0x10) == 0) {
 		if (vesa_bios_post() != 0)
 			return (1);
-		offs = x86bios_get_intr(0x10);
-		if (offs == 0)
-			return (1);
-		if (bootverbose)
+		if (bootverbose) {
+			offs = x86bios_get_intr(0x10);
 			printf("VESA: interrupt vector installed (0x%x)\n",
 			    BIOS_SADDRTOLADDR(offs));
+		}
 	}
 
 	x86bios_init_regs(&regs);
@@ -879,6 +878,22 @@ vesa_bios_init(void)
 		if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
 			continue;
 
+		vmode.v_modeattr = le16toh(vmode.v_modeattr);
+		vmode.v_wgran = le16toh(vmode.v_wgran);
+		vmode.v_wsize = le16toh(vmode.v_wsize);
+		vmode.v_waseg = le16toh(vmode.v_waseg);
+		vmode.v_wbseg = le16toh(vmode.v_wbseg);
+		vmode.v_posfunc = le32toh(vmode.v_posfunc);
+		vmode.v_bpscanline = le16toh(vmode.v_bpscanline);
+		vmode.v_width = le16toh(vmode.v_width);
+		vmode.v_height = le16toh(vmode.v_height);
+		vmode.v_lfb = le32toh(vmode.v_lfb);
+		vmode.v_offscreen = le32toh(vmode.v_offscreen);
+		vmode.v_offscreensize = le16toh(vmode.v_offscreensize);
+		vmode.v_maxpixelclock = le32toh(vmode.v_maxpixelclock);
+		vmode.v_linbpscanline = le16toh(vmode.v_linbpscanline);
+		vmode.v_maxpixelclock = le32toh(vmode.v_maxpixelclock);
+
 		/* reject unsupported modes */
 #if 0
 		if ((vmode.v_modeattr & (V_MODESUPP | V_MODEOPTINFO 
@@ -1417,11 +1432,14 @@ vesa_save_state(video_adapter_t *adp, vo
 	if (adp != vesa_adp)
 		return ((*prevvidsw->save_state)(adp, p, size));
 
-	if (vesa_state_buf_size == 0)
+	if (vesa_state_buf_size == -1) {
 		vesa_state_buf_size = vesa_bios_state_buf_size();
+		if (vesa_state_buf_size == 0)
+			return (1);
+	}
 	if (size == 0)
-		return (sizeof(int) + vesa_state_buf_size);
-	else if (size < (sizeof(int) + vesa_state_buf_size))
+		return (offsetof(adp_state_t, regs) + vesa_state_buf_size);
+	else if (size < (offsetof(adp_state_t, regs) + vesa_state_buf_size))
 		return (1);
 
 	((adp_state_t *)p)->sig = V_STATE_SIG;
@@ -1438,22 +1456,36 @@ vesa_load_state(video_adapter_t *adp, vo
 	if ((adp != vesa_adp) || (((adp_state_t *)p)->sig != V_STATE_SIG))
 		return ((*prevvidsw->load_state)(adp, p));
 
+	if (vesa_state_buf_size <= 0)
+		return (1);
+
+	/*
+	 * If the current mode is not the same, probably it was powered down.
+	 * Try BIOS POST to restore a sane state.
+	 */
+	mode = vesa_bios_get_current_mode();
+	if (mode >= 0 && (mode & 0x1ff) != adp->va_mode &&
+	    VESA_MODE(adp->va_mode))
+		(void)vesa_bios_post();
+
 	ret = vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs,
 	    vesa_state_buf_size);
 
 	/*
-	 * If the current mode is not restored properly, try BIOS POST and
-	 * force setting the mode.
+	 * If the desired mode is not restored, force setting the mode.
 	 */
-	flags = adp->va_info.vi_flags;
-	if (!(flags & V_INFO_GRAPHICS))
-		flags &= ~V_INFO_LINEAR;
-	mode = adp->va_mode | ((flags & V_INFO_LINEAR) ? 0x4000 : 0);
-	if (vesa_bios_get_current_mode() != mode && vesa_bios_post() == 0 &&
-	    x86bios_get_intr(0x10) != 0) {
-		int10_set_mode(adp->va_initial_bios_mode);
-		vesa_bios_set_mode(mode);
+	mode = vesa_bios_get_current_mode();
+	if (mode >= 0 && (mode & 0x1ff) != adp->va_mode &&
+	    VESA_MODE(adp->va_mode)) {
+		mode = adp->va_mode;
+		flags = adp->va_info.vi_flags;
+		if ((flags & V_INFO_GRAPHICS) != 0 &&
+		    (flags & V_INFO_LINEAR) != 0)
+			mode |= 0x4000;
+		(void)vesa_bios_set_mode(mode);
+		(void)(*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
 	}
+
 	return (ret);
 }
 

Modified: head/sys/dev/fb/vesa.h
==============================================================================
--- head/sys/dev/fb/vesa.h	Fri Oct 23 18:27:34 2009	(r198418)
+++ head/sys/dev/fb/vesa.h	Fri Oct 23 18:41:00 2009	(r198419)
@@ -108,7 +108,21 @@ struct vesa_mode 
     u_int32_t		v_lfb;
     u_int32_t		v_offscreen;
     u_int16_t		v_offscreensize;
-};
+    /* 3.0 implementations */
+    u_int16_t		v_linbpscanline;
+    u_int8_t		v_bankipages;
+    u_int8_t		v_linipages;
+    u_int8_t		v_linredmasksize;
+    u_int8_t		v_linredfieldpos;
+    u_int8_t		v_lingreenmasksize;
+    u_int8_t		v_lingreenfieldpos;
+    u_int8_t		v_linbluemasksize;
+    u_int8_t		v_linbluefieldpos;
+    u_int8_t		v_linresmasksize;
+    u_int8_t		v_linresfieldpos;
+    u_int32_t		v_maxpixelclock;
+    u_int8_t		v_reserved1[190];
+} __packed;
 
 #ifdef _KERNEL
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910231841.n9NIf0L5069062>