From owner-svn-src-all@FreeBSD.ORG Wed Aug 25 22:09:03 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4FC0E1065675; Wed, 25 Aug 2010 22:09:03 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3E91D8FC19; Wed, 25 Aug 2010 22:09:03 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o7PM92oJ024007; Wed, 25 Aug 2010 22:09:02 GMT (envelope-from jkim@svn.freebsd.org) Received: (from jkim@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o7PM92hY024005; Wed, 25 Aug 2010 22:09:02 GMT (envelope-from jkim@svn.freebsd.org) Message-Id: <201008252209.o7PM92hY024005@svn.freebsd.org> From: Jung-uk Kim Date: Wed, 25 Aug 2010 22:09:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r211827 - head/sys/dev/fb X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 25 Aug 2010 22:09:03 -0000 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 #include #include +#include #include #include @@ -61,6 +62,8 @@ __FBSDID("$FreeBSD$"); #include +#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(®s, 0xc000, 0x0003); + x86bios_call(®s, 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(®s); 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)