Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Aug 2010 22:09:02 +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: r211827 - head/sys/dev/fb
Message-ID:  <201008252209.o7PM92hY024005@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jkim
Date: Wed Aug 25 22:09:02 2010
New Revision: 211827
URL: http://svn.freebsd.org/changeset/base/211827

Log:
  Add an experimental feature to shadow video BIOS.  Long ago, this trick was
  supported by many BIOSes to improve performance of VESA BIOS calls for real
  mode OSes but it is not our intention here.  However, this may help some
  platforms where the video ROMs are inaccessible after suspend, for example.
  Note it may consume up to 64K bytes of contiguous memory depending on video
  controller model when it is enabled.  This feature can be disabled by
  setting zero to 'debug.vesa.shadow_rom' loader tunable via loader(8) or
  loader.conf(5).  The default is 1 (enabled), for now.

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

Modified: head/sys/dev/fb/vesa.c
==============================================================================
--- head/sys/dev/fb/vesa.c	Wed Aug 25 21:32:08 2010	(r211826)
+++ head/sys/dev/fb/vesa.c	Wed Aug 25 22:09:02 2010	(r211827)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/fbio.h>
+#include <sys/sysctl.h>
 
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
@@ -61,6 +62,8 @@ __FBSDID("$FreeBSD$");
 
 #include <compat/x86bios/x86bios.h>
 
+#define	VESA_BIOS_OFFSET	0xc0000
+#define	VESA_PALETTE_SIZE	(256 * 4)
 #define	VESA_VIA_CLE266		"VIA CLE266\r\n"
 
 #ifndef VESA_DEBUG
@@ -83,11 +86,21 @@ static ssize_t vesa_state_buf_size = 0;
 
 static u_char *vesa_palette = NULL;
 static uint32_t vesa_palette_offs = 0;
-#define	VESA_PALETTE_SIZE	(256 * 4)
+
+static void *vesa_bios = NULL;
+static uint32_t vesa_bios_offs = VESA_BIOS_OFFSET;
+static uint32_t vesa_bios_int10 = 0;
+static size_t vesa_bios_size = 0;
 
 /* VESA video adapter */
 static video_adapter_t *vesa_adp = NULL;
 
+SYSCTL_NODE(_debug, OID_AUTO, vesa, CTLFLAG_RD, NULL, "VESA debugging");
+static int vesa_shadow_rom = 1;
+TUNABLE_INT("debug.vesa.shadow_rom", &vesa_shadow_rom);
+SYSCTL_INT(_debug_vesa, OID_AUTO, shadow_rom, CTLFLAG_RDTUN, &vesa_shadow_rom,
+    1, "Enable video BIOS shadow");
+
 /* VESA functions */
 #if 0
 static int			vesa_nop(void);
@@ -242,7 +255,7 @@ vesa_bios_post(void)
 	device_t dev;
 	int count, i, is_pci;
 
-	if (x86bios_get_orm(0xc0000) == NULL)
+	if (x86bios_get_orm(vesa_bios_offs) == NULL)
 		return (1);
 
 	dev = NULL;
@@ -253,7 +266,7 @@ vesa_bios_post(void)
 	if (dc != NULL && devclass_get_devices(dc, &devs, &count) == 0) {
 		for (i = 0; i < count; i++)
 			if (device_get_flags(devs[i]) != 0 &&
-			    x86bios_match_device(0xc0000, devs[i])) {
+			    x86bios_match_device(vesa_bios_offs, devs[i])) {
 				dev = devs[i];
 				is_pci = 1;
 				break;
@@ -279,7 +292,8 @@ vesa_bios_post(void)
 		    (pci_get_function(dev) & 0x07);
 	}
 	regs.R_DL = 0x80;
-	x86bios_call(&regs, 0xc000, 0x0003);
+	x86bios_call(&regs, X86BIOS_PHYSTOSEG(vesa_bios_offs + 3),
+	    X86BIOS_PHYSTOOFF(vesa_bios_offs + 3));
 
 	if (x86bios_get_intr(0x10) == 0)
 		return (1);
@@ -754,6 +768,7 @@ vesa_bios_init(void)
 	size_t bsize;
 	size_t msize;
 	void *vmbuf;
+	uint8_t *vbios;
 	uint32_t offs;
 	uint16_t vers;
 	int is_via_cle266;
@@ -765,22 +780,44 @@ vesa_bios_init(void)
 
 	has_vesa_bios = FALSE;
 	vesa_adp_info = NULL;
+	vesa_bios_offs = VESA_BIOS_OFFSET;
 	vesa_vmode_max = 0;
 	vesa_vmode[0].vi_mode = EOT;
 
 	/*
 	 * If the VBE real mode interrupt vector is not found, try BIOS POST.
 	 */
-	if (x86bios_get_intr(0x10) == 0) {
+	vesa_bios_int10 = x86bios_get_intr(0x10);
+	if (vesa_bios_int10 == 0) {
 		if (vesa_bios_post() != 0)
 			return (1);
-		if (bootverbose) {
-			offs = x86bios_get_intr(0x10);
-			printf("VESA: interrupt vector installed (0x%x)\n",
-			    BIOS_SADDRTOLADDR(offs));
-		}
+		vesa_bios_int10 = x86bios_get_intr(0x10);
+		if (vesa_bios_int10 == 0)
+			return (1);
 	}
 
+	/*
+	 * Shadow video ROM.
+	 */
+	offs = BIOS_SADDRTOLADDR(vesa_bios_int10);
+	if (vesa_shadow_rom) {
+		vbios = x86bios_get_orm(vesa_bios_offs);
+		if (vbios != NULL) {
+			vesa_bios_size = vbios[2] * 512;
+			vesa_bios = x86bios_alloc(&vesa_bios_offs,
+			    vesa_bios_size, M_WAITOK);
+			memcpy(vesa_bios, vbios, vesa_bios_size);
+			offs = offs - VESA_BIOS_OFFSET + vesa_bios_offs;
+			offs = (X86BIOS_PHYSTOSEG(offs) << 16) +
+			    X86BIOS_PHYSTOOFF(offs);
+			x86bios_set_intr(0x10, offs);
+		} else
+			printf("VESA: failed to shadow video ROM\n");
+	}
+	if (bootverbose)
+		printf("VESA: INT 0x10 vector 0x%04x:0x%04x\n",
+		    X86BIOS_PHYSTOSEG(offs), X86BIOS_PHYSTOOFF(offs));
+
 	x86bios_init_regs(&regs);
 	regs.R_AX = 0x4f00;
 
@@ -1011,6 +1048,12 @@ vesa_bios_init(void)
 	return (0);
 
 fail:
+	if (vesa_bios != NULL) {
+		x86bios_set_intr(0x10, vesa_bios_int10);
+		vesa_bios_offs = VESA_BIOS_OFFSET;
+		x86bios_free(vesa_bios, vesa_bios_size);
+		vesa_bios = NULL;
+	}
 	if (vmbuf != NULL)
 		x86bios_free(vmbuf, sizeof(buf));
 	if (vesa_adp_info != NULL) {
@@ -1862,6 +1905,10 @@ vesa_unload(void)
 		}
 	}
 
+	if (vesa_bios != NULL) {
+		x86bios_set_intr(0x10, vesa_bios_int10);
+		x86bios_free(vesa_bios, vesa_bios_size);
+	}
 	if (vesa_adp_info != NULL)
 		free(vesa_adp_info, M_DEVBUF);
 	if (vesa_oemstr != NULL)



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