1
mirror of https://github.com/mpv-player/mpv synced 2024-12-24 07:33:46 +01:00

use libvbe from vesautils

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@16257 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
alex 2005-08-18 11:26:04 +00:00
parent 23bc87ab98
commit 6c5df75cce
8 changed files with 9 additions and 2035 deletions

View File

@ -78,6 +78,7 @@ VO_LIBS = $(AA_LIB) \
$(SVGA_LIB) \
$(DIRECTFB_LIB) \
$(CACA_LIB) \
$(VESA_LIB) \
AO_LIBS = $(ARTS_LIB) \
$(ESD_LIB) \

14
configure vendored
View File

@ -4290,23 +4290,22 @@ esac
echocheck "VESA support"
if test "$_vesa" = auto ; then
if x86 && linux ; then
_vesa=no
cat > $TMPC << EOF
#include <sys/io.h>
int main(void) { return 0; }
#include <vbe.h>
int main(void) { vbeVersion(); return 0; }
EOF
cc_check && _vesa=yes
fi
_vesa=no
cc_check -lvbe -llrmi && _vesa=yes
fi
if test "$_vesa" = yes ; then
_def_vesa='#define HAVE_VESA 1'
_ld_vesa="-lvbe -llrmi"
_vosrc="$_vosrc vo_vesa.c vesa_lvo.c"
_vomodules="vesa $_vomodules"
echores "yes"
else
_def_vesa='#undef HAVE_VESA'
echores "no (not supported on this OS/architecture)"
echores "no"
_novomodules="vesa $_novomodules"
fi
@ -7025,6 +7024,7 @@ JPEG_LIB = $_ld_jpg
GIF_LIB = $_ld_gif
SDL_LIB = $_ld_sdl
SVGA_LIB = $_ld_svga
VESA_LIB = $_ld_vesa
AA_LIB = $_ld_aa
CACA_INC = $_inc_caca
CACA_LIB = $_ld_caca

View File

@ -30,13 +30,13 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <vbe.h>
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
#include "sub.h"
#include "osdep/vbelib.h"
#include "bswap.h"
#include "aspect.h"
#include "vesa_lvo.h"

View File

@ -7,12 +7,6 @@ SRCS= shmem.c strsep.c strl.c vsscanf.c scandir.c gettimeofday.c fseeko.c \
swab.c
# timer.c
ifeq ($(TARGET_ARCH_X86),yes)
ifeq ($(TARGET_OS),Linux)
SRCS += lrmi.c vbelib.c
endif
endif
getch = getch2.c
timer = timer-lx.c
ifeq ($(MACOSX_FINDER_SUPPORT),yes)

View File

@ -1,928 +0,0 @@
/*
Linux Real Mode Interface - A library of DPMI-like functions for Linux.
Copyright (C) 1998 by Josh Vanderhoof
You are free to distribute and modify this file, as long as you
do not remove this copyright notice and clearly label modified
versions as being modified.
This software has NO WARRANTY. Use it at your own risk.
Original location: http://cvs.debian.org/lrmi/
Modified for use with MPlayer, see the CVS log for details.
*/
#include "../config.h"
#ifdef HAVE_VESA
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/io.h>
#include <asm/vm86.h>
#ifdef USE_LIBC_VM86
#include <sys/vm86.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include "lrmi.h"
#define REAL_MEM_BASE ((void *)0x10000)
#define REAL_MEM_SIZE 0x10000
#define REAL_MEM_BLOCKS 0x100
struct mem_block
{
unsigned int size : 20;
unsigned int free : 1;
};
static struct
{
int ready;
int count;
struct mem_block blocks[REAL_MEM_BLOCKS];
} mem_info = { .ready = 0, };
static int
real_mem_init(void)
{
void *m;
int fd_zero;
if (mem_info.ready)
return 1;
fd_zero = open("/dev/zero", O_RDONLY);
if (fd_zero == -1)
{
perror("open /dev/zero");
return 0;
}
m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, fd_zero, 0);
if (m == (void *)-1)
{
perror("mmap /dev/zero");
close(fd_zero);
return 0;
}
mem_info.ready = 1;
mem_info.count = 1;
mem_info.blocks[0].size = REAL_MEM_SIZE;
mem_info.blocks[0].free = 1;
return 1;
}
static void
insert_block(int i)
{
memmove(
mem_info.blocks + i + 1,
mem_info.blocks + i,
(mem_info.count - i) * sizeof(struct mem_block));
mem_info.count++;
}
static void
delete_block(int i)
{
mem_info.count--;
memmove(
mem_info.blocks + i,
mem_info.blocks + i + 1,
(mem_info.count - i) * sizeof(struct mem_block));
}
void *
LRMI_alloc_real(int size)
{
int i;
char *r = (char *)REAL_MEM_BASE;
if (!mem_info.ready)
return NULL;
if (mem_info.count == REAL_MEM_BLOCKS)
return NULL;
size = (size + 15) & ~15;
for (i = 0; i < mem_info.count; i++)
{
if (mem_info.blocks[i].free && size < mem_info.blocks[i].size)
{
insert_block(i);
mem_info.blocks[i].size = size;
mem_info.blocks[i].free = 0;
mem_info.blocks[i + 1].size -= size;
return (void *)r;
}
r += mem_info.blocks[i].size;
}
return NULL;
}
void
LRMI_free_real(void *m)
{
int i;
char *r = (char *)REAL_MEM_BASE;
if (!mem_info.ready)
return;
i = 0;
while (m != (void *)r)
{
r += mem_info.blocks[i].size;
i++;
if (i == mem_info.count)
return;
}
mem_info.blocks[i].free = 1;
if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free)
{
mem_info.blocks[i].size += mem_info.blocks[i + 1].size;
delete_block(i + 1);
}
if (i - 1 >= 0 && mem_info.blocks[i - 1].free)
{
mem_info.blocks[i - 1].size += mem_info.blocks[i].size;
delete_block(i);
}
}
#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)
#define DEFAULT_STACK_SIZE 0x1000
#define RETURN_TO_32_INT 255
static struct
{
int ready;
unsigned short ret_seg, ret_off;
unsigned short stack_seg, stack_off;
struct vm86_struct vm;
} context = { .ready = 0, };
static inline void
set_bit(unsigned int bit, void *array)
{
unsigned char *a = array;
a[bit / 8] |= (1 << (bit % 8));
}
static inline unsigned int
get_int_seg(int i)
{
return *(unsigned short *)(i * 4 + 2);
}
static inline unsigned int
get_int_off(int i)
{
return *(unsigned short *)(i * 4);
}
static inline void
pushw(unsigned short i)
{
struct vm86_regs *r = &context.vm.regs;
r->esp -= 2;
*(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i;
}
int
LRMI_init(void)
{
void *m;
int fd_mem;
if (context.ready)
return 1;
if (!real_mem_init())
return 0;
/*
Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502)
and the ROM (0xa0000 - 0x100000)
*/
fd_mem = open("/dev/mem", O_RDWR);
if (fd_mem == -1)
{
perror("open /dev/mem");
return 0;
}
m = mmap((void *)0, 0x502,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, fd_mem, 0);
if (m == (void *)-1)
{
perror("mmap /dev/mem");
return 0;
}
m = mmap((void *)0xa0000, 0x100000 - 0xa0000,
PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000);
if (m == (void *)-1)
{
perror("mmap /dev/mem");
return 0;
}
/*
Allocate a stack
*/
m = LRMI_alloc_real(DEFAULT_STACK_SIZE);
context.stack_seg = (unsigned int)m >> 4;
context.stack_off = DEFAULT_STACK_SIZE;
/*
Allocate the return to 32 bit routine
*/
m = LRMI_alloc_real(2);
context.ret_seg = (unsigned int)m >> 4;
context.ret_off = (unsigned int)m & 0xf;
((unsigned char *)m)[0] = 0xcd; /* int opcode */
((unsigned char *)m)[1] = RETURN_TO_32_INT;
memset(&context.vm, 0, sizeof(context.vm));
/*
Enable kernel emulation of all ints except RETURN_TO_32_INT
*/
memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored));
set_bit(RETURN_TO_32_INT, &context.vm.int_revectored);
context.ready = 1;
return 1;
}
static void
set_regs(struct LRMI_regs *r)
{
context.vm.regs.edi = r->edi;
context.vm.regs.esi = r->esi;
context.vm.regs.ebp = r->ebp;
context.vm.regs.ebx = r->ebx;
context.vm.regs.edx = r->edx;
context.vm.regs.ecx = r->ecx;
context.vm.regs.eax = r->eax;
context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
context.vm.regs.es = r->es;
context.vm.regs.ds = r->ds;
context.vm.regs.fs = r->fs;
context.vm.regs.gs = r->gs;
}
static void
get_regs(struct LRMI_regs *r)
{
r->edi = context.vm.regs.edi;
r->esi = context.vm.regs.esi;
r->ebp = context.vm.regs.ebp;
r->ebx = context.vm.regs.ebx;
r->edx = context.vm.regs.edx;
r->ecx = context.vm.regs.ecx;
r->eax = context.vm.regs.eax;
r->flags = context.vm.regs.eflags;
r->es = context.vm.regs.es;
r->ds = context.vm.regs.ds;
r->fs = context.vm.regs.fs;
r->gs = context.vm.regs.gs;
}
#define DIRECTION_FLAG (1 << 10)
static void
em_ins(int size)
{
unsigned int edx, edi;
edx = context.vm.regs.edx & 0xffff;
edi = context.vm.regs.edi & 0xffff;
edi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.eflags & DIRECTION_FLAG)
{
if (size == 4)
asm volatile ("std; insl; cld"
: "=D" (edi) : "d" (edx), "0" (edi));
else if (size == 2)
asm volatile ("std; insw; cld"
: "=D" (edi) : "d" (edx), "0" (edi));
else
asm volatile ("std; insb; cld"
: "=D" (edi) : "d" (edx), "0" (edi));
}
else
{
if (size == 4)
asm volatile ("cld; insl"
: "=D" (edi) : "d" (edx), "0" (edi));
else if (size == 2)
asm volatile ("cld; insw"
: "=D" (edi) : "d" (edx), "0" (edi));
else
asm volatile ("cld; insb"
: "=D" (edi) : "d" (edx), "0" (edi));
}
edi -= (unsigned int)context.vm.regs.ds << 4;
context.vm.regs.edi &= 0xffff0000;
context.vm.regs.edi |= edi & 0xffff;
}
static void
em_rep_ins(int size)
{
unsigned int ecx, edx, edi;
ecx = context.vm.regs.ecx & 0xffff;
edx = context.vm.regs.edx & 0xffff;
edi = context.vm.regs.edi & 0xffff;
edi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.eflags & DIRECTION_FLAG)
{
if (size == 4)
asm volatile ("std; rep; insl; cld"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else if (size == 2)
asm volatile ("std; rep; insw; cld"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else
asm volatile ("std; rep; insb; cld"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
}
else
{
if (size == 4)
asm volatile ("cld; rep; insl"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else if (size == 2)
asm volatile ("cld; rep; insw"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else
asm volatile ("cld; rep; insb"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
}
edi -= (unsigned int)context.vm.regs.ds << 4;
context.vm.regs.edi &= 0xffff0000;
context.vm.regs.edi |= edi & 0xffff;
context.vm.regs.ecx &= 0xffff0000;
context.vm.regs.ecx |= ecx & 0xffff;
}
static void
em_outs(int size)
{
unsigned int edx, esi;
edx = context.vm.regs.edx & 0xffff;
esi = context.vm.regs.esi & 0xffff;
esi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.eflags & DIRECTION_FLAG)
{
if (size == 4)
asm volatile ("std; outsl; cld"
: "=S" (esi) : "d" (edx), "0" (esi));
else if (size == 2)
asm volatile ("std; outsw; cld"
: "=S" (esi) : "d" (edx), "0" (esi));
else
asm volatile ("std; outsb; cld"
: "=S" (esi) : "d" (edx), "0" (esi));
}
else
{
if (size == 4)
asm volatile ("cld; outsl"
: "=S" (esi) : "d" (edx), "0" (esi));
else if (size == 2)
asm volatile ("cld; outsw"
: "=S" (esi) : "d" (edx), "0" (esi));
else
asm volatile ("cld; outsb"
: "=S" (esi) : "d" (edx), "0" (esi));
}
esi -= (unsigned int)context.vm.regs.ds << 4;
context.vm.regs.esi &= 0xffff0000;
context.vm.regs.esi |= esi & 0xffff;
}
static void
em_rep_outs(int size)
{
unsigned int ecx, edx, esi;
ecx = context.vm.regs.ecx & 0xffff;
edx = context.vm.regs.edx & 0xffff;
esi = context.vm.regs.esi & 0xffff;
esi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.eflags & DIRECTION_FLAG)
{
if (size == 4)
asm volatile ("std; rep; outsl; cld"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else if (size == 2)
asm volatile ("std; rep; outsw; cld"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else
asm volatile ("std; rep; outsb; cld"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
}
else
{
if (size == 4)
asm volatile ("cld; rep; outsl"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else if (size == 2)
asm volatile ("cld; rep; outsw"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else
asm volatile ("cld; rep; outsb"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
}
esi -= (unsigned int)context.vm.regs.ds << 4;
context.vm.regs.esi &= 0xffff0000;
context.vm.regs.esi |= esi & 0xffff;
context.vm.regs.ecx &= 0xffff0000;
context.vm.regs.ecx |= ecx & 0xffff;
}
static void
em_inbl(unsigned char literal)
{
context.vm.regs.eax = inb(literal) & 0xff;
}
static void
em_inb(void)
{
asm volatile ("inb (%w1), %b0"
: "=a" (context.vm.regs.eax)
: "d" (context.vm.regs.edx), "0" (context.vm.regs.eax));
}
static void
em_inw(void)
{
asm volatile ("inw (%w1), %w0"
: "=a" (context.vm.regs.eax)
: "d" (context.vm.regs.edx), "0" (context.vm.regs.eax));
}
static void
em_inl(void)
{
asm volatile ("inl (%w1), %0"
: "=a" (context.vm.regs.eax)
: "d" (context.vm.regs.edx));
}
static void
em_outbl(unsigned char literal)
{
outb(context.vm.regs.eax & 0xff, literal);
}
static void
em_outb(void)
{
asm volatile ("outb %b0, (%w1)"
: : "a" (context.vm.regs.eax),
"d" (context.vm.regs.edx));
}
static void
em_outw(void)
{
asm volatile ("outw %w0, (%w1)"
: : "a" (context.vm.regs.eax),
"d" (context.vm.regs.edx));
}
static void
em_outl(void)
{
asm volatile ("outl %0, (%w1)"
: : "a" (context.vm.regs.eax),
"d" (context.vm.regs.edx));
}
static int
emulate(void)
{
unsigned char *insn;
struct
{
unsigned int size : 1;
unsigned int rep : 1;
} prefix = { 0, 0 };
int i = 0;
insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4);
insn += context.vm.regs.eip;
while (1)
{
if (insn[i] == 0x66)
{
prefix.size = 1 - prefix.size;
i++;
}
else if (insn[i] == 0xf3)
{
prefix.rep = 1;
i++;
}
else if (insn[i] == 0xf0 || insn[i] == 0xf2
|| insn[i] == 0x26 || insn[i] == 0x2e
|| insn[i] == 0x36 || insn[i] == 0x3e
|| insn[i] == 0x64 || insn[i] == 0x65
|| insn[i] == 0x67)
{
/* these prefixes are just ignored */
i++;
}
else if (insn[i] == 0x6c)
{
if (prefix.rep)
em_rep_ins(1);
else
em_ins(1);
i++;
break;
}
else if (insn[i] == 0x6d)
{
if (prefix.rep)
{
if (prefix.size)
em_rep_ins(4);
else
em_rep_ins(2);
}
else
{
if (prefix.size)
em_ins(4);
else
em_ins(2);
}
i++;
break;
}
else if (insn[i] == 0x6e)
{
if (prefix.rep)
em_rep_outs(1);
else
em_outs(1);
i++;
break;
}
else if (insn[i] == 0x6f)
{
if (prefix.rep)
{
if (prefix.size)
em_rep_outs(4);
else
em_rep_outs(2);
}
else
{
if (prefix.size)
em_outs(4);
else
em_outs(2);
}
i++;
break;
}
else if (insn[i] == 0xe4)
{
em_inbl(insn[i + 1]);
i += 2;
break;
}
else if (insn[i] == 0xe6)
{
em_outbl(insn[i + 1]);
i += 2;
break;
}
else if (insn[i] == 0xec)
{
em_inb();
i++;
break;
}
else if (insn[i] == 0xed)
{
if (prefix.size)
em_inl();
else
em_inw();
i++;
break;
}
else if (insn[i] == 0xee)
{
em_outb();
i++;
break;
}
else if (insn[i] == 0xef)
{
if (prefix.size)
em_outl();
else
em_outw();
i++;
break;
}
else
return 0;
}
context.vm.regs.eip += i;
return 1;
}
/*
I don't know how to make sure I get the right vm86() from libc.
The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc)
which should be declared as "int vm86(struct vm86_struct *);" in
<sys/vm86.h>.
This just does syscall 113 with inline asm, which should work
for both libc's (I hope).
*/
#if !defined(USE_LIBC_VM86)
static int
lrmi_vm86(struct vm86_struct *vm)
{
int r;
#ifdef __PIC__
asm volatile (
"pushl %%ebx\n\t"
"movl %2, %%ebx\n\t"
"int $0x80\n\t"
"popl %%ebx"
: "=a" (r)
: "0" (113), "r" (vm));
#else
asm volatile (
"int $0x80"
: "=a" (r)
: "0" (113), "b" (vm));
#endif
return r;
}
#else
#define lrmi_vm86 vm86
#endif
static void
debug_info(int vret)
{
int i;
unsigned char *p;
fputs("vm86() failed\n", stderr);
fprintf(stderr, "return = 0x%x\n", vret);
fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax);
fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx);
fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx);
fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx);
fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi);
fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi);
fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp);
fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip);
fprintf(stderr, "cs = 0x%04x\n", context.vm.regs.cs);
fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp);
fprintf(stderr, "ss = 0x%04x\n", context.vm.regs.ss);
fprintf(stderr, "ds = 0x%04x\n", context.vm.regs.ds);
fprintf(stderr, "es = 0x%04x\n", context.vm.regs.es);
fprintf(stderr, "fs = 0x%04x\n", context.vm.regs.fs);
fprintf(stderr, "gs = 0x%04x\n", context.vm.regs.gs);
fprintf(stderr, "eflags = 0x%08lx\n", context.vm.regs.eflags);
fputs("cs:ip = [ ", stderr);
p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff));
for (i = 0; i < 16; ++i)
fprintf(stderr, "%02x ", (unsigned int)p[i]);
fputs("]\n", stderr);
}
static int
run_vm86(void)
{
unsigned int vret;
sigset_t allsigs, cursigs;
unsigned long oldgs, oldfs;
while (1)
{
sigfillset(&allsigs);
sigprocmask(SIG_SETMASK, &allsigs, &cursigs);
asm volatile ("movl %%gs, %0" : "=g" (oldgs));
asm volatile ("movl %%fs, %0" : "=g" (oldfs));
vret = lrmi_vm86(&context.vm);
asm volatile ("movl %0, %%fs" :: "g" (oldfs));
asm volatile ("movl %0, %%gs" :: "g" (oldgs));
sigprocmask(SIG_SETMASK, &cursigs, NULL);
if (VM86_TYPE(vret) == VM86_INTx)
{
unsigned int v = VM86_ARG(vret);
if (v == RETURN_TO_32_INT)
return 1;
pushw(context.vm.regs.eflags);
pushw(context.vm.regs.cs);
pushw(context.vm.regs.eip);
context.vm.regs.cs = get_int_seg(v);
context.vm.regs.eip = get_int_off(v);
context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK);
continue;
}
if (VM86_TYPE(vret) != VM86_UNKNOWN)
break;
if (!emulate())
break;
}
#ifdef ORIGINAL_LRMI_CODE_THAT_GOT_IFDEFED_OUT
debug_info(vret);
#endif
return 0;
}
int
LRMI_call(struct LRMI_regs *r)
{
unsigned int vret;
memset(&context.vm.regs, 0, sizeof(context.vm.regs));
set_regs(r);
context.vm.regs.cs = r->cs;
context.vm.regs.eip = r->ip;
if (r->ss == 0 && r->sp == 0)
{
context.vm.regs.ss = context.stack_seg;
context.vm.regs.esp = context.stack_off;
}
else
{
context.vm.regs.ss = r->ss;
context.vm.regs.esp = r->sp;
}
pushw(context.ret_seg);
pushw(context.ret_off);
vret = run_vm86();
get_regs(r);
return vret;
}
int
LRMI_int(int i, struct LRMI_regs *r)
{
unsigned int vret;
unsigned int seg, off;
seg = get_int_seg(i);
off = get_int_off(i);
/*
If the interrupt is in regular memory, it's probably
still pointing at a dos TSR (which is now gone).
*/
if (seg < 0xa000 || (seg << 4) + off >= 0x100000)
{
#ifdef ORIGINAL_LRMI_CODE_THAT_GOT_IFDEFED_OUT
fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off);
#endif
return 0;
}
memset(&context.vm.regs, 0, sizeof(context.vm.regs));
set_regs(r);
context.vm.regs.cs = seg;
context.vm.regs.eip = off;
if (r->ss == 0 && r->sp == 0)
{
context.vm.regs.ss = context.stack_seg;
context.vm.regs.esp = context.stack_off;
}
else
{
context.vm.regs.ss = r->ss;
context.vm.regs.esp = r->sp;
}
pushw(DEFAULT_VM86_FLAGS);
pushw(context.ret_seg);
pushw(context.ret_off);
vret = run_vm86();
get_regs(r);
return vret;
}
#endif

View File

@ -1,86 +0,0 @@
/*
Linux Real Mode Interface - A library of DPMI-like functions for Linux.
Copyright (C) 1998 by Josh Vanderhoof
You are free to distribute and modify this file, as long as you
do not remove this copyright notice and clearly label modified
versions as being modified.
This software has NO WARRANTY. Use it at your own risk.
Original location: http://cvs.debian.org/lrmi/
*/
#ifndef LRMI_H
#define LRMI_H
struct LRMI_regs
{
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int reserved;
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
unsigned int eax;
unsigned short int flags;
unsigned short int es;
unsigned short int ds;
unsigned short int fs;
unsigned short int gs;
unsigned short int ip;
unsigned short int cs;
unsigned short int sp;
unsigned short int ss;
};
#ifndef LRMI_PREFIX
#define LRMI_PREFIX LRMI_
#endif
#define LRMI_CONCAT2(a, b) a ## b
#define LRMI_CONCAT(a, b) LRMI_CONCAT2(a, b)
#define LRMI_MAKENAME(a) LRMI_CONCAT(LRMI_PREFIX, a)
/*
Initialize
returns 1 if sucessful, 0 for failure
*/
#define LRMI_init LRMI_MAKENAME(init)
int
LRMI_init(void);
/*
Simulate a 16 bit far call
returns 1 if sucessful, 0 for failure
*/
#define LRMI_call LRMI_MAKENAME(call)
int
LRMI_call(struct LRMI_regs *r);
/*
Simulate a 16 bit interrupt
returns 1 if sucessful, 0 for failure
*/
#define LRMI_int LRMI_MAKENAME(int)
int
LRMI_int(int interrupt, struct LRMI_regs *r);
/*
Allocate real mode memory
The returned block is paragraph (16 byte) aligned
*/
#define LRMI_alloc_real LRMI_MAKENAME(alloc_real)
void *
LRMI_alloc_real(int size);
/*
Free real mode memory
*/
#define LRMI_free_real LRMI_MAKENAME(free_real)
void
LRMI_free_real(void *m);
#endif

View File

@ -1,777 +0,0 @@
/*
This file contains implementation of VESA library which is based on
LRMI (Linux real-mode interface).
So it's not an emulator - it calls real int 10h handler under Linux.
Note: VESA is available only on x86 systems.
You can redistribute this file under terms and conditions
of GNU General Public licence v2.
Written by Nick Kurshev <nickols_k@mail.ru>
Neomagic TV out support by Rudolf Marek <r.marek et sh.cvut.cz>
*/
#include <../config.h>
#ifdef HAVE_VESA
#include "vbelib.h"
#include "lrmi.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
static struct VesaProtModeInterface vbe_pm_info;
static struct VesaModeInfoBlock curr_mode_info;
static inline int VERR(const void *p)
{
register int retval;
__asm __volatile(
"xorl %0, %0\n\t"
"verr %1\n\t"
"setnz %b0"
:"=q"(retval)
:"m"(*(unsigned char *)p)
:"memory","cc");
return retval;
}
#if 0
static inline int VERW(const void *p)
{
register int retval;
__asm __volatile(
"xorl %0, %0\n\t"
"verw %1\n\t"
"setnz %b0"
:"=q"(retval)
:"m"(*(unsigned char *)p)
:"memory","cc");
return retval;
}
#endif
#define HAVE_VERBOSE_VAR 1
#ifdef HAVE_VERBOSE_VAR
extern int verbose;
static void __dump_regs(struct LRMI_regs *r)
{
printf("vbelib: eax=%08lXh ebx=%08lXh ecx=%08lXh edx=%08lXh\n"
"vbelib: edi=%08lXh esi=%08lXh ebp=%08lXh esp=%08lXh\n"
"vbelib: ds=%04Xh es=%04Xh ss=%04Xh cs:ip=%04X:%04X\n"
"vbelib: fs=%04Xh gs=%04Xh ss:sp=%04X:%04X flags=%04X\n"
,(unsigned long)r->eax,(unsigned long)r->ebx,(unsigned long)r->ecx,(unsigned long)r->edx
,(unsigned long)r->edi,(unsigned long)r->esi,(unsigned long)r->ebp,(unsigned long)r->reserved
,r->ds,r->es,r->ss,r->cs,r->ip
,r->fs,r->gs,r->ss,r->sp,r->flags);
}
static inline int VBE_LRMI_int(int int_no, struct LRMI_regs *r)
{
int retval;
if(verbose > 1)
{
printf("vbelib: registers before int %02X\n",int_no);
__dump_regs(r);
}
retval = LRMI_int(int_no,r);
if(verbose > 1)
{
printf("vbelib: Interrupt handler returns: %X\n",retval);
printf("vbelib: registers after int %02X\n",int_no);
__dump_regs(r);
}
return retval;
}
#else
#define VBE_LRMI_int(int_no,regs) (VBE_LRMI_int(int_no,regs))
#endif
/**
* Set console to graphics or text mode.
* This is a clean way to enable/disable console text output
* and cursor blinking.
*
* @param mode The new wanted mode. Can be either KD_GRAPHICS to switch
* to graphics mode or anything else to switch back to the
* original mode.
*/
static void kd_set_mode(int mode)
{
static int old_mode = KD_TEXT;
int fd;
if ((fd = open("/dev/tty0", O_RDWR)) < 0)
return;
if(mode == KD_GRAPHICS)
old_mode = ioctl(fd, KDGETMODE);
else
mode = old_mode;
ioctl(fd, KDSETMODE, mode);
close(fd);
}
static unsigned hh_int_10_seg;
static int fd_mem;
/*
the list of supported video modes is stored in the reserved portion of
the SuperVGA information record by some implementations, and it may
thus be necessary to either copy the mode list or use a different
buffer for all subsequent VESA calls
*/
static void *controller_info;
int vbeInit( void )
{
unsigned short iopl_port;
size_t i;
if(!LRMI_init()) return VBE_VM86_FAIL;
if(!(controller_info = LRMI_alloc_real(sizeof(struct VbeInfoBlock)))) return VBE_OUT_OF_DOS_MEM;
/*
Allow read/write to ALL io ports
*/
hh_int_10_seg = *(unsigned short *)PhysToVirtSO(0x0000,0x0042);
/* Video BIOS should be at C000:0000 and above */
hh_int_10_seg >>= 12;
if(hh_int_10_seg < 0xC) return VBE_BROKEN_BIOS;
ioperm(0, 1024, 1);
iopl(3);
memset(&vbe_pm_info,0,sizeof(struct VesaProtModeInterface));
vbeGetProtModeInfo(&vbe_pm_info);
i = 0;
if(vbe_pm_info.iopl_ports) /* Can be NULL !!!*/
while((iopl_port=vbe_pm_info.iopl_ports[i]) != 0xFFFF
&& vbe_pm_info.iopl_ports[i++] > 1023) ioperm(iopl_port,1,1);
iopl(3);
fd_mem = open("/dev/mem",O_RDWR);
kd_set_mode(KD_GRAPHICS);
return VBE_OK;
}
int vbeDestroy( void )
{
kd_set_mode(KD_TEXT);
close(fd_mem);
LRMI_free_real(controller_info);
return VBE_OK;
}
/* Fixme!!! This code is compatible only with mplayer's version of lrmi*/
static inline int is_addr_valid(const void *p)
{
return (p < (const void *)0x502) ||
(p >= (const void *)0x10000 && p < (const void *)0x20000) ||
(p >= (const void *)0xa0000 && p < (const void *)0x100000);
}
static int check_str(const unsigned char *str)
{
size_t i;
int null_found = 0;
for(i = 0;i < 256;i++)
{
if(is_addr_valid(&str[i]))
{
if(VERR(&str[i]))
{
if(!str[i]) { null_found = 1; break; }
}
else break;
}
else break;
}
return null_found;
}
static int check_wrd(const unsigned short *str)
{
size_t i;
int ffff_found = 0;
for(i = 0;i < 1024;i++)
{
if(is_addr_valid(&str[i]))
{
if(VERR(&str[i]))
{
if(str[i] == 0xffff) { ffff_found = 1; break; }
}
else break;
}
else break;
}
return ffff_found;
}
static void print_str(unsigned char *str)
{
size_t i;
fflush(stdout);
printf("vbelib: ");
for(i = 0;i < 256;i++) { printf("%02X(%c) ",str[i],isprint(str[i])?str[i]:'.'); if(!str[i]) break; }
printf("\n");
fflush(stdout);
}
static void print_wrd(unsigned short *str)
{
size_t i;
fflush(stdout);
printf("vbelib: ");
for(i = 0;i < 256;i++) { printf("%04X ",str[i]); if(str[i] == 0xffff) break; }
printf("\n");
fflush(stdout);
}
int vbeGetControllerInfo(struct VbeInfoBlock *data)
{
struct LRMI_regs r;
int retval;
memcpy(controller_info,data,sizeof(struct VbeInfoBlock));
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f00;
r.es = VirtToPhysSeg(controller_info);
r.edi = VirtToPhysOff(controller_info);
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
FarPtr fpdata;
retval = VBE_OK;
memcpy(data,controller_info,sizeof(struct VbeInfoBlock));
fpdata.seg = (unsigned long)(data->OemStringPtr) >> 16;
fpdata.off = (unsigned long)(data->OemStringPtr) & 0xffff;
data->OemStringPtr = PhysToVirt(fpdata);
if(!check_str(data->OemStringPtr)) data->OemStringPtr = NULL;
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1)
{
printf("vbelib: OemStringPtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemStringPtr);
if(data->OemStringPtr) print_str(data->OemStringPtr);
fflush(stdout);
}
#endif
fpdata.seg = (unsigned long)(data->VideoModePtr) >> 16;
fpdata.off = (unsigned long)(data->VideoModePtr) & 0xffff;
data->VideoModePtr = PhysToVirt(fpdata);
if(!check_wrd(data->VideoModePtr))
{
data->VideoModePtr = NULL;
retval = VBE_BROKEN_BIOS;
}
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1)
{
printf("vbelib: VideoModePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->VideoModePtr);
if(data->VideoModePtr) print_wrd(data->VideoModePtr);
fflush(stdout);
}
#endif
fpdata.seg = (unsigned long)(data->OemVendorNamePtr) >> 16;
fpdata.off = (unsigned long)(data->OemVendorNamePtr) & 0xffff;
data->OemVendorNamePtr = PhysToVirt(fpdata);
if(!check_str(data->OemVendorNamePtr)) data->OemVendorNamePtr = NULL;
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1)
{
printf("vbelib: OemVendorNamePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemVendorNamePtr);
if(data->OemVendorNamePtr) print_str(data->OemVendorNamePtr);
fflush(stdout);
}
#endif
fpdata.seg = (unsigned long)(data->OemProductNamePtr) >> 16;
fpdata.off = (unsigned long)(data->OemProductNamePtr) & 0xffff;
data->OemProductNamePtr = PhysToVirt(fpdata);
if(!check_str(data->OemProductNamePtr)) data->OemProductNamePtr = NULL;
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1)
{
printf("vbelib: OemProductNamePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemProductNamePtr);
if(data->OemVendorNamePtr) print_str(data->OemProductNamePtr);
fflush(stdout);
}
#endif
fpdata.seg = (unsigned long)(data->OemProductRevPtr) >> 16;
fpdata.off = (unsigned long)(data->OemProductRevPtr) & 0xffff;
data->OemProductRevPtr = PhysToVirt(fpdata);
if(!check_str(data->OemProductRevPtr)) data->OemProductRevPtr = NULL;
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1)
{
printf("vbelib: OemProductRevPtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemProductRevPtr);
if(data->OemProductRevPtr) print_str(data->OemProductRevPtr);
fflush(stdout);
}
#endif
}
return retval;
}
int vbeGetModeInfo(unsigned mode,struct VesaModeInfoBlock *data)
{
struct LRMI_regs r;
void *rm_space;
int retval;
if(!(rm_space = LRMI_alloc_real(sizeof(struct VesaModeInfoBlock)))) return VBE_OUT_OF_DOS_MEM;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f01;
r.ecx = mode;
r.es = VirtToPhysSeg(rm_space);
r.edi = VirtToPhysOff(rm_space);
if(!VBE_LRMI_int(0x10,&r))
{
LRMI_free_real(rm_space);
return VBE_VM86_FAIL;
}
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
retval = VBE_OK;
memcpy(data,rm_space,sizeof(struct VesaModeInfoBlock));
}
LRMI_free_real(rm_space);
return retval;
}
int vbeSetTV(unsigned int vesa_mode,unsigned int TV_mode) {
#define NR_MODES 8
unsigned int mode_table[NR_MODES] =
{0x101,0x103,0x111,0x114,0x120,0x121,0x122,0x123};
unsigned int tv_table[][NR_MODES] = {
{0x201,0x202,0x211,0x212,0x221,0x231,0x222,0x232},
{0x200,0x203,0x210,0x213,0x220,0x230,0xFFFF,0xFFFF}};
/*
Alternate mode map. If modes like 320x240 and 400x300 does not work, but
640x480 and 800x600 work, then try to replace above two lines with this
lines and write email to me if it works.
r.marek et sh.cvut.cz
{0x201,0x202,0x211,0x212,0x222,0x223,0x224,0x225},
{0x200,0x203,0x210,0x213,0x220,0x221,0xFFFF,0xFFFF}};
*/
int i,retval;
struct LRMI_regs r;
memset(&r,0,sizeof(struct LRMI_regs));
for (i=0;((mode_table[i]!=(vesa_mode&0x3FF))&&(i<NR_MODES));i++) ;
if (i==NR_MODES) return 0;
if(verbose > 1) printf("vbelib: Trying to set TV mode %x\n",tv_table[TV_mode][i]);
r.eax = 0x4f14;
r.ebx = 0x20;
r.edx = 0;
r.edi = 0;
r.ecx = tv_table[TV_mode][i];
retval = VBE_LRMI_int(0x10,&r);
if(!retval) return VBE_VM86_FAIL;
return r.eax & 0xffff;
}
int vbeSetMode(unsigned mode,struct VesaCRTCInfoBlock *data)
{
struct LRMI_regs r;
void *rm_space = NULL;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
if(data)
{
if(!(rm_space = LRMI_alloc_real(sizeof(struct VesaCRTCInfoBlock)))) return VBE_OUT_OF_DOS_MEM;
r.es = VirtToPhysSeg(rm_space);
r.edi = VirtToPhysOff(rm_space);
memcpy(rm_space,data,sizeof(struct VesaCRTCInfoBlock));
}
r.eax = 0x4f02;
r.ebx = mode;
retval = VBE_LRMI_int(0x10,&r);
LRMI_free_real(rm_space);
if(!retval) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
/* Just info for internal use (currently in SetDiplayStart func). */
vbeGetModeInfo(mode,&curr_mode_info);
retval = VBE_OK;
}
return retval;
}
int vbeGetMode(unsigned *mode)
{
struct LRMI_regs r;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f03;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
*mode = r.ebx;
retval = VBE_OK;
}
return retval;
}
int vbeGetPixelClock(unsigned *mode,unsigned *pixel_clock) // in Hz
{
struct LRMI_regs r;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f0b;
r.ebx = 0;
r.edx = *mode;
r.ecx = *pixel_clock;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
*pixel_clock = r.ecx;
retval = VBE_OK;
}
return retval;
}
int vbeSaveState(void **data)
{
struct LRMI_regs r;
int retval;
void *rm_space;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f04;
r.edx = 0x00;
r.ecx = 0x0f;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval != 0x4f) return retval;
if(!(rm_space = LRMI_alloc_real((r.ebx & 0xffff)*64))) return VBE_OUT_OF_DOS_MEM;
r.eax = 0x4f04;
r.edx = 0x01;
r.ecx = 0x0f;
r.es = VirtToPhysSeg(rm_space);
r.ebx = VirtToPhysOff(rm_space);
if(!VBE_LRMI_int(0x10,&r))
{
LRMI_free_real(rm_space);
return VBE_VM86_FAIL;
}
retval = r.eax & 0xffff;
if(retval != 0x4f)
{
LRMI_free_real(rm_space);
return retval;
}
*data = rm_space;
return VBE_OK;
}
int vbeRestoreState(void *data)
{
struct LRMI_regs r;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f04;
r.edx = 0x02;
r.ecx = 0x0f;
r.es = VirtToPhysSeg(data);
r.ebx = VirtToPhysOff(data);
retval = VBE_LRMI_int(0x10,&r);
LRMI_free_real(data);
if(!retval) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f) retval = VBE_OK;
return retval;
}
int vbeGetWindow(unsigned *win_num)
{
struct LRMI_regs r;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f05;
r.ebx = (*win_num & 0x0f) | 0x0100;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
*win_num = r.edx & 0xffff;
retval = VBE_OK;
}
return retval;
}
int vbeSetWindow(unsigned win_num,unsigned win_gran)
{
int retval;
if(vbe_pm_info.SetWindowCall)
{
/* Don't verbose this stuff from performance reasons */
/* 32-bit function call is much better of int 10h */
__asm __volatile(
"pushl %%ebx\n"
"movl %1, %%ebx\n"
::"a"(0x4f05),"S"(win_num & 0x0f),"d"(win_gran):"memory");
(*vbe_pm_info.SetWindowCall)();
__asm __volatile("popl %%ebx":::"memory");
retval = VBE_OK;
}
else
{
struct LRMI_regs r;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f05;
r.ebx = win_num & 0x0f;
r.edx = win_gran;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f) retval = VBE_OK;
}
return retval;
}
int vbeGetScanLineLength(unsigned *num_pixels,unsigned *num_bytes)
{
struct LRMI_regs r;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f06;
r.ebx = 1;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
if(num_bytes) *num_bytes = r.ebx & 0xffff;
if(num_pixels) *num_pixels= r.ecx & 0xffff;
retval = VBE_OK;
}
return retval;
}
int vbeGetMaxScanLines(unsigned *num_pixels,unsigned *num_bytes, unsigned *num_lines)
{
struct LRMI_regs r;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f06;
r.ebx = 3;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
if(num_bytes) *num_bytes = r.ebx & 0xffff;
if(num_pixels) *num_pixels= r.ecx & 0xffff;
if(num_lines) *num_lines = r.edx & 0xffff;
retval = VBE_OK;
}
return retval;
}
int vbeSetScanLineLength(unsigned num_pixels)
{
int retval;
struct LRMI_regs r;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f06;
r.ebx = 0;
r.ecx = num_pixels;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f) retval = VBE_OK;
return retval;
}
int vbeSetScanLineLengthB(unsigned num_bytes)
{
int retval;
struct LRMI_regs r;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f06;
r.ebx = 2;
r.ecx = num_bytes;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f) retval = VBE_OK;
return retval;
}
int vbeGetDisplayStart(unsigned *pixel_num,unsigned *scan_line)
{
struct LRMI_regs r;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f07;
r.ebx = 1;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
if(pixel_num) *pixel_num = r.ecx & 0xffff;
if(scan_line) *scan_line = r.edx & 0xffff;
retval = VBE_OK;
}
return retval;
}
int vbeSetDisplayStart(unsigned long offset, int vsync)
{
int retval;
if(vbe_pm_info.SetDisplayStart)
{
/* Don't verbose this stuff from performance reasons */
/* 32-bit function call is much better of int 10h */
__asm __volatile(
"pushl %%ebx\n"
"movl %1, %%ebx\n"
::"a"(0x4f07),"S"(vsync ? 0x80 : 0),
"c"((offset>>2) & 0xffff),"d"((offset>>18)&0xffff):"memory");
(*vbe_pm_info.SetDisplayStart)();
__asm __volatile("popl %%ebx":::"memory");
retval = VBE_OK;
}
else
{
struct LRMI_regs r;
unsigned long pixel_num;
memset(&r,0,sizeof(struct LRMI_regs));
pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine;
if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++;
r.eax = 0x4f07;
r.ebx = vsync ? 0x82 : 2;
r.ecx = pixel_num;
r.edx = offset/(unsigned long)curr_mode_info.BytesPerScanLine;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f) retval = VBE_OK;
else retval = VBE_BROKEN_BIOS;
}
return retval;
}
int vbeSetScheduledDisplayStart(unsigned long offset, int vsync)
{
int retval;
struct LRMI_regs r;
unsigned long pixel_num;
memset(&r,0,sizeof(struct LRMI_regs));
pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine;
if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++;
r.eax = 0x4f07;
r.ebx = vsync ? 0x82 : 2;
r.ecx = offset;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f) retval = VBE_OK;
return retval;
}
struct realVesaProtModeInterface
{
unsigned short SetWindowCall;
unsigned short SetDisplayStart;
unsigned short SetPaletteData;
unsigned short iopl_ports;
}__attribute__((packed));
int vbeGetProtModeInfo(struct VesaProtModeInterface *pm_info)
{
struct LRMI_regs r;
int retval;
unsigned info_offset;
struct realVesaProtModeInterface *rm_info;
memset(&r,0,sizeof(struct LRMI_regs));
r.eax = 0x4f0a;
r.ebx = 0;
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f)
{
retval = VBE_OK;
info_offset = r.edi&0xffff;
if((r.es >> 12) != hh_int_10_seg) retval = VBE_BROKEN_BIOS;
rm_info = PhysToVirtSO(r.es,info_offset);
pm_info->SetWindowCall = PhysToVirtSO(r.es,info_offset+rm_info->SetWindowCall);
if(!is_addr_valid(pm_info->SetWindowCall)) retval = VBE_BROKEN_BIOS;
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1) printf("vbelib: SetWindowCall=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetWindowCall,pm_info->SetWindowCall);
#endif
pm_info->SetDisplayStart = PhysToVirtSO(r.es,info_offset+rm_info->SetDisplayStart);
if(!is_addr_valid(pm_info->SetDisplayStart)) retval = VBE_BROKEN_BIOS;
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1) printf("vbelib: SetDisplayStart=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetDisplayStart,pm_info->SetDisplayStart);
#endif
pm_info->SetPaletteData = PhysToVirtSO(r.es,info_offset+rm_info->SetPaletteData);
if(!is_addr_valid(pm_info->SetPaletteData)) retval = VBE_BROKEN_BIOS;
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1) printf("vbelib: SetPaletteData=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetPaletteData,pm_info->SetPaletteData);
#endif
pm_info->iopl_ports = PhysToVirtSO(r.es,info_offset+rm_info->iopl_ports);
if(!rm_info->iopl_ports) pm_info->iopl_ports = NULL;
else
if(!check_wrd(pm_info->iopl_ports))
{
pm_info->iopl_ports = NULL;
/* retval = VBE_BROKEN_BIOS; <- It's for broken BIOSes only */
}
#ifdef HAVE_VERBOSE_VAR
if(verbose > 1)
{
printf("vbelib: iopl_ports=%04X:%04X => %p\n",r.es,info_offset+rm_info->iopl_ports,pm_info->iopl_ports);
if(pm_info->iopl_ports) print_wrd(pm_info->iopl_ports);
fflush(stdout);
}
#endif
}
return retval;
}
/* --------- Standard VGA stuff -------------- */
int vbeWriteString(int x, int y, int attr, char *str)
{
struct LRMI_regs r;
void *rm_space = NULL;
int retval;
memset(&r,0,sizeof(struct LRMI_regs));
r.ecx = strlen(str);
r.edx = ((y<<8)&0xff00)|(x&0xff);
r.ebx = attr;
if(!(rm_space = LRMI_alloc_real(r.ecx))) return VBE_OUT_OF_DOS_MEM;
r.es = VirtToPhysSeg(rm_space);
r.ebp = VirtToPhysOff(rm_space);
memcpy(rm_space,str,r.ecx);
r.eax = 0x1300;
retval = VBE_LRMI_int(0x10,&r);
LRMI_free_real(rm_space);
if(!retval) return VBE_VM86_FAIL;
retval = r.eax & 0xffff;
if(retval == 0x4f) retval = VBE_OK;
return retval;
}
void * vbeMapVideoBuffer(unsigned long phys_addr,unsigned long size)
{
void *lfb;
if(fd_mem == -1) return NULL;
if(verbose > 1) printf("vbelib: vbeMapVideoBuffer(%08lX,%08lX)\n",phys_addr,size);
/* Here we don't need with MAP_FIXED and prefered address (first argument) */
lfb = mmap((void *)0,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd_mem,phys_addr);
return lfb == (void *)-1 ? 0 : lfb;
}
void vbeUnmapVideoBuffer(unsigned long linear_addr,unsigned long size)
{
if(verbose > 1) printf("vbelib: vbeUnmapVideoBuffer(%08lX,%08lX)\n",linear_addr,size);
munmap((void *)linear_addr,size);
}
#endif

View File

@ -1,230 +0,0 @@
/*
VESA VBE 2.0 compatible structures and definitions.
You can redistribute this file under terms and conditions
of GNU General Public licence v2.
Written by Nick Kurshev <nickols_k@mail.ru>
*/
#ifndef __VESA_VBELIB_INCLUDED__
#define __VESA_VBELIB_INCLUDED__ 1
/* Note: every pointer within structures is 32-bit protected mode pointer.
So you don't need to convert it from real mode. */
typedef struct tagFarPtr
{
unsigned short off;
unsigned short seg;
}FarPtr;
#define VBE_DAC_8BIT (1 << 0)
#define VBE_NONVGA_CRTC (1 << 1)
#define VBE_SNOWED_RAMDAC (1 << 2)
#define VBE_STEREOSCOPIC (1 << 3)
#define VBE_STEREO_EVC (1 << 4)
struct VbeInfoBlock {
char VESASignature[4]; /* 'VESA' 4 byte signature */
short VESAVersion; /* VBE version number */
char * OemStringPtr; /* Pointer to OEM string */
long Capabilities; /* Capabilities of video card */
unsigned short* VideoModePtr; /* Pointer to supported modes */
short TotalMemory; /* Number of 64kb memory blocks */
/* VBE 2.0 and above */
short OemSoftwareRev;
char * OemVendorNamePtr;
char * OemProductNamePtr;
char * OemProductRevPtr;
char reserved[222];
char OemData[256]; /* Pad to 512 byte block size */
}__attribute__ ((packed));
static inline FarPtr VirtToPhys(void *ptr)
{
FarPtr retval;
retval.seg = ((unsigned long)ptr) >> 4;
retval.off = ((unsigned long)ptr) & 0x0f;
return retval;
}
static inline unsigned short VirtToPhysSeg(void *ptr)
{
return ((unsigned long)ptr) >> 4;
}
static inline unsigned short VirtToPhysOff(void *ptr)
{
return ((unsigned long)ptr) & 0x0f;
}
static inline void * PhysToVirt(FarPtr ptr)
{
return (void *)((ptr.seg << 4) | ptr.off);
}
static inline void * PhysToVirtSO(unsigned short seg,unsigned short off)
{
return (void *)((seg << 4) | off);
}
#define MODE_ATTR_MODE_SUPPORTED (1 << 0)
#define MODE_ATTR_TTY (1 << 2)
#define MODE_ATTR_COLOR (1 << 3)
#define MODE_ATTR_GRAPHICS (1 << 4)
#define MODE_ATTR_NOT_VGA (1 << 5)
#define MODE_ATTR_NOT_WINDOWED (1 << 6)
#define MODE_ATTR_LINEAR (1 << 7)
#define MODE_ATTR_DOUBLESCAN (1 << 8)
#define MODE_ATTR_INTERLACE (1 << 9)
#define MODE_ATTR_TRIPLEBUFFER (1 << 10)
#define MODE_ATTR_STEREOSCOPIC (1 << 11)
#define MODE_ATTR_DUALDISPLAY (1 << 12)
#define MODE_WIN_RELOCATABLE (1 << 0)
#define MODE_WIN_READABLE (1 << 1)
#define MODE_WIN_WRITEABLE (1 << 2)
#define NEO_PAL 0
#define NEO_NTSC 1
/* SuperVGA mode information block */
struct VesaModeInfoBlock {
unsigned short ModeAttributes; /* 00: Mode attributes */
unsigned char WinAAttributes; /* 02: Window A attributes */
unsigned char WinBAttributes; /* 03: Window B attributes */
unsigned short WinGranularity; /* 04: Window granularity in k */
unsigned short WinSize; /* 06: Window size in k */
unsigned short WinASegment; /* 08: Window A segment */
unsigned short WinBSegment; /* 0A: Window B segment */
FarPtr WinFuncPtr; /* 0C: 16-bit far pointer to window function */
unsigned short BytesPerScanLine; /* 10: Bytes per scanline */
/* VBE 1.2 and above */
unsigned short XResolution; /* 12: Horizontal resolution */
unsigned short YResolution; /* 14: Vertical resolution */
unsigned char XCharSize; /* 16: Character cell width */
unsigned char YCharSize; /* 17: Character cell height */
unsigned char NumberOfPlanes; /* 18: Number of memory planes */
unsigned char BitsPerPixel; /* 19: Bits per pixel */
unsigned char NumberOfBanks; /* 1A: Number of CGA style banks */
unsigned char MemoryModel; /* 1B: Memory model type */
unsigned char BankSize; /* 1C: Size of CGA style banks */
unsigned char NumberOfImagePages; /* 1D: Number of images pages */
unsigned char res1; /* 1E: Reserved */
/* Direct Color fields (required for direct/6 and YUV/7 memory models) */
unsigned char RedMaskSize; /* 1F: Size of direct color red mask */
unsigned char RedFieldPosition; /* 20: Bit posn of lsb of red mask */
unsigned char GreenMaskSize; /* 21: Size of direct color green mask */
unsigned char GreenFieldPosition; /* 22: Bit posn of lsb of green mask */
unsigned char BlueMaskSize; /* 23: Size of direct color blue mask */
unsigned char BlueFieldPosition; /* 24: Bit posn of lsb of blue mask */
unsigned char RsvdMaskSize; /* 25: Size of direct color res mask */
unsigned char RsvdFieldPosition; /* 26: Bit posn of lsb of res mask */
unsigned char DirectColorModeInfo; /* 27: Direct color mode attributes */
/* VBE 2.0 and above */
unsigned long PhysBasePtr; /* 28: physical address for flat memory frame buffer. (Should be converted to linear before using) */
unsigned short res3[3]; /* 2C: Reserved - always set to 0 */
/* VBE 3.0 and above */
unsigned short LinBytesPerScanLine; /* 32: bytes per scan line for linear modes */
unsigned char BnkNumberOfImagePages;/* 34: number of images for banked modes */
unsigned char LinNumberOfImagePages;/* 35: number of images for linear modes */
unsigned char LinRedMaskSize; /* 36: size of direct color red mask (linear modes) */
unsigned char LinRedFieldPosition; /* 37: bit position of lsb of red mask (linear modes) */
unsigned char LinGreenMaskSize; /* 38: size of direct color green mask (linear modes) */
unsigned char LinGreenFieldPosition;/* 39: bit position of lsb of green mask (linear modes) */
unsigned char LinBlueMaskSize; /* 40: size of direct color blue mask (linear modes) */
unsigned char LinBlueFieldPosition; /* 41: bit position of lsb of blue mask (linear modes) */
unsigned char LinRsvdMaskSize; /* 42: size of direct color reserved mask (linear modes) */
unsigned char LinRsvdFieldPosition; /* 43: bit position of lsb of reserved mask (linear modes) */
unsigned long MaxPixelClock; /* 44: maximum pixel clock (in Hz) for graphics mode */
char res4[189]; /* 48: remainder of ModeInfoBlock */
}__attribute__ ((packed));
typedef enum {
memText= 0,
memCGA = 1,
memHercules = 2,
memPL = 3, /* Planar memory model */
memPK = 4, /* Packed pixel memory model */
mem256 = 5,
memRGB = 6, /* Direct color RGB memory model */
memYUV = 7, /* Direct color YUV memory model */
} memModels;
struct VesaCRTCInfoBlock {
unsigned short hTotal; /* Horizontal total in pixels */
unsigned short hSyncStart; /* Horizontal sync start in pixels */
unsigned short hSyncEnd; /* Horizontal sync end in pixels */
unsigned short vTotal; /* Vertical total in lines */
unsigned short vSyncStart; /* Vertical sync start in lines */
unsigned short vSyncEnd; /* Vertical sync end in lines */
unsigned char Flags; /* Flags (Interlaced, Double Scan etc) */
unsigned long PixelClock; /* Pixel clock in units of Hz */
unsigned short RefreshRate;/* Refresh rate in units of 0.01 Hz*/
unsigned char Reserved[40];/* remainder of CRTCInfoBlock*/
}__attribute__ ((packed));
#define VESA_CRTC_DOUBLESCAN 0x01
#define VESA_CRTC_INTERLACED 0x02
#define VESA_CRTC_HSYNC_NEG 0x04
#define VESA_CRTC_VSYNC_NEG 0x08
#define VESA_MODE_CRTC_REFRESH (1 << 11)
#define VESA_MODE_USE_LINEAR (1 << 14)
#define VESA_MODE_NOT_CLEAR (1 << 15)
/* This will contain accesible 32-bit protmode pointers */
struct VesaProtModeInterface
{
void (*SetWindowCall)(void);
void (*SetDisplayStart)(void);
void (*SetPaletteData)(void);
unsigned short * iopl_ports;
};
/*
All functions below return:
0 if succesful
0xffff if vm86 syscall error occurs
0x4fxx if VESA error occurs
*/
#define VBE_OK 0
#define VBE_VM86_FAIL -1
#define VBE_OUT_OF_DOS_MEM -2
#define VBE_OUT_OF_MEM -3
#define VBE_BROKEN_BIOS -4
#define VBE_VESA_ERROR_MASK 0x004f
#define VBE_VESA_ERRCODE_MASK 0xff00
extern int vbeInit( void );
extern int vbeDestroy( void );
extern int vbeGetControllerInfo(struct VbeInfoBlock *);
extern int vbeGetModeInfo(unsigned mode,struct VesaModeInfoBlock *);
extern int vbeSetMode(unsigned mode,struct VesaCRTCInfoBlock *);
extern int vbeGetMode(unsigned *mode);
extern int vbeGetPixelClock(unsigned *mode,unsigned *pixel_clock);
extern int vbeSaveState(void **data); /* note never copy this data */
extern int vbeRestoreState(void *data);
extern int vbeGetWindow(unsigned *win_num); /* win_A=0 or win_B=1 */
extern int vbeSetWindow(unsigned win_num,unsigned win_gran);
extern int vbeGetScanLineLength(unsigned *num_pixels,unsigned *num_bytes);
extern int vbeGetMaxScanLines(unsigned *num_pixels,unsigned *num_bytes, unsigned *num_lines);
extern int vbeSetScanLineLength(unsigned num_pixels);
extern int vbeSetScanLineLengthB(unsigned num_bytes);
extern int vbeGetDisplayStart(unsigned *pixel_num,unsigned *scan_line);
extern int vbeSetDisplayStart(unsigned long offset, int vsync);
extern int vbeSetScheduledDisplayStart(unsigned long offset, int vsync);
extern int vbeSetTV(unsigned int vesa_mode,unsigned int TV_mode);
/*
Func 0x08-0x09:
Support of palette currently is not implemented.
*/
extern int vbeGetProtModeInfo(struct VesaProtModeInterface *);
/* Standard VGA stuff */
int vbeWriteString(int x, int y, int attr, char *str);
/* Misc stuff (For portability only) */
void * vbeMapVideoBuffer(unsigned long phys_addr,unsigned long size);
void vbeUnmapVideoBuffer(unsigned long linear_addr,unsigned long size);
#endif