From: Bernd Schmidt (crux@Pool.Informatik.RWTH-Aachen.DE)
Date: Mon 20 Jul 1998 - 13:58:19 IDT
With the following patch, the VESA driver included in svgalib-1.3.0 works
with my Millenium II. The problem was that the BIOS did an interrupt call
and the driver wasn't prepared for that.
Programs that work: koules, lincity, xaos, zgv. Unfortunately, the function
vga_draw_scanline doesn't seem to work with the VESA driver.
The patch contains a bit of noise at the top that makes the file compile
with glibc-2.0.94 together with linux-2.1.109 headers and egcs-1.0.3.
Bernd
diff -dru svgalib-1.3.0/src/lrmi.c svgalib-1.3.0.hacked/src/lrmi.c
--- svgalib-1.3.0/src/lrmi.c Thu Jun 11 16:36:27 1998
+++ svgalib-1.3.0.hacked/src/lrmi.c Mon Jul 20 00:12:41 1998
@@ -22,17 +22,24 @@
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
+#include <errno.h>
-#include <syscall.h>
+#include <sys/syscall.h>
-#ifndef SYS_vm86old
-#define SYS___svgalib_vm86old SYS_vm86
-#else
-#define SYS___svgalib_vm86old SYS_vm86old
-#endif
+#define __NR___svgalib_vm86old SYS_vm86old
-_syscall1(int, __svgalib_vm86old, struct vm86_struct *, vs)
+int __svgalib_vm86old (struct vm86_struct *arg1)
+{
+ long __res;
+
+ __asm__ volatile ("pushl %%ebx\n\tmovl %%ecx,%%ebx\n\tint $0x80\n\tpopl %%ebx"
+ : "=a" (__res)
+ : "0" (__NR_vm86old), "c" ((long)(arg1)));
+
+ __syscall_return (int,__res);
+}
+
#define vm86 __svgalib_vm86old
@@ -603,6 +610,14 @@
"d" (context.vm.regs.edx));
}
+static unsigned char *get_insn_ptr (struct vm86_struct *ctx)
+{
+ unsigned char *insn;
+ insn = (unsigned char *)((unsigned int)ctx->regs.cs << 4);
+ insn += ctx->regs.eip;
+ return insn;
+}
+
static int
emulate(void)
{
@@ -614,8 +629,7 @@
} prefix = { 0, 0 };
int i = 0;
- insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4);
- insn += context.vm.regs.eip;
+ insn = get_insn_ptr (&context.vm);
while (1)
{
@@ -736,25 +750,50 @@
static int
run_vm86(void)
- {
- unsigned int vret;
-
- while (1)
- {
- vret = vm86(&context.vm);
+{
+ while (1) {
+ unsigned int vret = vm86(&context.vm);
if (VM86_TYPE(vret) == VM86_INTx
- && VM86_ARG(vret) == RETURN_TO_32_INT)
+ && VM86_ARG(vret) == RETURN_TO_32_INT)
return 1;
+ if (VM86_TYPE(vret) == VM86_INTx) {
+ unsigned int oldcs, oldeip;
+ unsigned int vret1;
+ unsigned int seg, off;
+ unsigned char *insn = get_insn_ptr (&context.vm);
+
+ seg = get_int_seg(VM86_ARG(vret));
+ off = get_int_off(VM86_ARG(vret));
+
+ if (seg < 0xa000) {
+ return 0;
+ }
+ oldcs = context.vm.regs.cs;
+ oldeip = context.vm.regs.eip;
+ context.vm.regs.cs = seg;
+ context.vm.regs.eip = off;
+
+ pushw(DEFAULT_VM86_FLAGS);
+ pushw(context.ret_seg);
+ pushw(context.ret_off);
+
+ vret1 = run_vm86();
+ if (vret1 == 0)
+ return 0;
+ context.vm.regs.cs = oldcs;
+ context.vm.regs.eip = oldeip;
+ continue;
+ }
+
if (VM86_TYPE(vret) != VM86_UNKNOWN)
return 0;
if (!emulate())
return 0;
- }
}
-
+}
int
__svgalib_LRMI_call(struct LRMI_regs *r)
@@ -765,8 +804,8 @@
set_regs(r);
- context.vm.regs.cs = r->cs;
- context.vm.regs.eip = r->ip;
+ context.vm.regs.cs = r->cs;
+ context.vm.regs.eip = r->ip;
if (r->ss == 0 && r->sp == 0)
{
This archive was generated by hypermail 2.1.4 : Wed 21 Jan 2004 - 22:10:22 IST