summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2005-02-28 20:40:44 +0000
committeriedowse <iedowse@FreeBSD.org>2005-02-28 20:40:44 +0000
commite1e12e9266e2bfb4f1ec24985b6db8bda8c3924c (patch)
tree485aca6c4ab549b93cf1adbada22353292d1537b /sys
parent2a1aef8db38147a03dd3a8c47b7461e61442ebaa (diff)
downloadFreeBSD-src-e1e12e9266e2bfb4f1ec24985b6db8bda8c3924c.zip
FreeBSD-src-e1e12e9266e2bfb4f1ec24985b6db8bda8c3924c.tar.gz
Add a missing bcopy() to make saving the VESA state actually work.
Also save the DAC state, increase the maximum save state size from 4k to 8k, and refuse to save the VESA state if the BIOS reports it is larger than the maximum size we can handle. It doesn't appear that anything currently uses this code, but it turns out to be capable of restoring some notebook displays to a working state after a suspend-resume cycle.
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/vesa.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/sys/i386/isa/vesa.c b/sys/i386/isa/vesa.c
index d51f68f..b1e8196 100644
--- a/sys/i386/isa/vesa.c
+++ b/sys/i386/isa/vesa.c
@@ -187,6 +187,7 @@ static int vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g,
#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)
+#define STATE_MAXSIZE (2 * PAGE_SIZE)
static int 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);
@@ -423,7 +424,7 @@ vesa_bios_state_buf_size(void)
bzero(&vmf, sizeof(vmf));
vmf.vmf_eax = 0x4f04;
- vmf.vmf_ecx = STATE_MOST;
+ vmf.vmf_ecx = STATE_ALL;
vmf.vmf_edx = STATE_SIZE;
err = vm86_intcall(0x10, &vmf);
if ((err != 0) || (vmf.vmf_ax != 0x4f))
@@ -438,15 +439,19 @@ vesa_bios_save_restore(int code, void *p, size_t size)
u_char *buf;
int err;
+ if (size > STATE_MAXSIZE)
+ return (1);
+
bzero(&vmf, sizeof(vmf));
vmf.vmf_eax = 0x4f04;
- vmf.vmf_ecx = STATE_MOST;
+ vmf.vmf_ecx = STATE_ALL;
vmf.vmf_edx = code; /* STATE_SAVE/STATE_LOAD */
buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_bx);
bcopy(p, buf, size);
err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
+ bcopy(buf, p, size);
return ((err != 0) || (vmf.vmf_ax != 0x4f));
}
@@ -797,7 +802,12 @@ vesa_bios_init(void)
printf("VESA: %d mode(s) found\n", modes);
has_vesa_bios = (modes > 0);
- return (has_vesa_bios ? 0 : 1);
+ if (!has_vesa_bios)
+ return (1);
+
+ /* Get a second page to support STATE_MAXSIZE. */
+ (void)vm86_addpage(&vesa_vmcontext, 2, 0);
+ return (0);
}
static void
OpenPOWER on IntegriCloud