aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/fb/vesa.c
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2010-08-25 22:09:02 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2010-08-25 22:09:02 +0000
commita73f383ee91d6e75879bc16d7dd2a91a0630b369 (patch)
tree19563808acf680cdd390790a0ed75c27f962905f /sys/dev/fb/vesa.c
parent81f6480d42b7f4ee008398fcc839c489bc1a140f (diff)
Notes
Diffstat (limited to 'sys/dev/fb/vesa.c')
-rw-r--r--sys/dev/fb/vesa.c67
1 files changed, 57 insertions, 10 deletions
diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c
index d369175bb92b..96a8aaa8c928 100644
--- a/sys/dev/fb/vesa.c
+++ b/sys/dev/fb/vesa.c
@@ -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)