Collapase interrupt supporting functions to a new module, and switch from
x86emu to this new module. This changeset also brings a fix for bugs introduced with the initial x86emu commit, which prevents the user from using some display mode or cause instant reboots during mode switch. Submitted by: paradox <ddkprog yahoo com>
This commit is contained in:
parent
91d345423d
commit
205d67b00d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=197383
@ -2758,4 +2758,4 @@ options BROOKTREE_ALLOC_PAGES=(217*4+1)
|
||||
options MAXFILES=999
|
||||
|
||||
# x86 real mode emulator
|
||||
options X86EMU
|
||||
options X86BIOS
|
||||
|
@ -2828,6 +2828,8 @@ dev/xen/netfront/netfront.c optional xen | xenhvm
|
||||
dev/xen/xenpci/xenpci.c optional xenpci
|
||||
dev/xen/xenpci/evtchn.c optional xenpci
|
||||
dev/xen/xenpci/machine_reboot.c optional xenpci
|
||||
contrib/x86emu/x86emu.c optional x86emu | dpms | vesa
|
||||
contrib/x86emu/x86emu_util.c optional x86emu | dpms | vesa
|
||||
dev/x86bios/x86bios.c optional x86bios | dpms | vesa
|
||||
dev/x86bios/x86bios_alloc.c optional x86bios | dpms | vesa
|
||||
contrib/x86emu/x86emu.c optional x86bios | dpms | vesa
|
||||
contrib/x86emu/x86emu_util.c optional x86bios | dpms | vesa
|
||||
|
||||
|
@ -838,4 +838,4 @@ SND_FEEDER_RATE_HP opt_snd.h
|
||||
SND_PCM_64 opt_snd.h
|
||||
SND_OLDSTEREO opt_snd.h
|
||||
|
||||
X86EMU
|
||||
X86BIOS
|
||||
|
@ -33,10 +33,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <contrib/x86emu/x86emu.h>
|
||||
#include <contrib/x86emu/x86emu_regs.h>
|
||||
|
||||
@ -8335,32 +8331,3 @@ pop_long(struct x86emu *emu)
|
||||
emu->x86.R_SP += 4;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
x86emu_modevent(module_t mod __unused, int type, void *data __unused)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ENOTSUP;
|
||||
break;
|
||||
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
static moduledata_t x86emu_mod = {
|
||||
"x86emu",
|
||||
x86emu_modevent,
|
||||
NULL,
|
||||
};
|
||||
|
||||
DECLARE_MODULE(x86emu, x86emu_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
|
||||
MODULE_VERSION(x86emu, 1);
|
||||
|
@ -67,11 +67,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <contrib/x86emu/x86emu.h>
|
||||
#include <contrib/x86emu/x86emu_regs.h>
|
||||
#include <dev/x86bios/x86bios.h>
|
||||
|
||||
/*
|
||||
* VESA DPMS States
|
||||
@ -94,9 +90,6 @@ struct dpms_softc {
|
||||
int dpms_initial_state;
|
||||
};
|
||||
|
||||
static struct x86emu vesa_emu;
|
||||
static unsigned char *emumem = NULL;
|
||||
|
||||
static int dpms_attach(device_t);
|
||||
static int dpms_detach(device_t);
|
||||
static int dpms_get_supported_states(int *);
|
||||
@ -126,59 +119,7 @@ static driver_t dpms_driver = {
|
||||
static devclass_t dpms_devclass;
|
||||
|
||||
DRIVER_MODULE(dpms, vgapci, dpms_driver, dpms_devclass, NULL, NULL);
|
||||
MODULE_DEPEND(dpms, x86emu, 1, 1, 1);
|
||||
|
||||
static uint8_t
|
||||
vm86_emu_inb(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port == 0xb2) /* APM scratch register */
|
||||
return 0;
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inb(port);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
vm86_emu_inw(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inw(port);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
vm86_emu_inl(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inl(port);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val)
|
||||
{
|
||||
if (port == 0xb2) /* APM scratch register */
|
||||
return;
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outb(port, val);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outw(port, val);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outl(port, val);
|
||||
}
|
||||
MODULE_DEPEND(dpms, x86bios, 1, 1, 1);
|
||||
|
||||
static void
|
||||
dpms_identify(driver_t *driver, device_t parent)
|
||||
@ -192,7 +133,6 @@ dpms_identify(driver_t *driver, device_t parent)
|
||||
*/
|
||||
if (devclass_get_device(dpms_devclass, 0) == NULL)
|
||||
device_add_child(parent, "dpms", 0);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
@ -200,21 +140,6 @@ dpms_probe(device_t dev)
|
||||
{
|
||||
int error, states;
|
||||
|
||||
emumem = pmap_mapbios(0x0, 0xc00000);
|
||||
|
||||
memset(&vesa_emu, 0, sizeof(vesa_emu));
|
||||
x86emu_init_default(&vesa_emu);
|
||||
|
||||
vesa_emu.emu_inb = vm86_emu_inb;
|
||||
vesa_emu.emu_inw = vm86_emu_inw;
|
||||
vesa_emu.emu_inl = vm86_emu_inl;
|
||||
vesa_emu.emu_outb = vm86_emu_outb;
|
||||
vesa_emu.emu_outw = vm86_emu_outw;
|
||||
vesa_emu.emu_outl = vm86_emu_outl;
|
||||
|
||||
vesa_emu.mem_base = (char *)emumem;
|
||||
vesa_emu.mem_size = 1024 * 1024;
|
||||
|
||||
error = dpms_get_supported_states(&states);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -240,8 +165,6 @@ dpms_attach(device_t dev)
|
||||
static int
|
||||
dpms_detach(device_t dev)
|
||||
{
|
||||
if (emumem)
|
||||
pmap_unmapdev((vm_offset_t)emumem, 0xc00000);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -267,17 +190,19 @@ dpms_resume(device_t dev)
|
||||
static int
|
||||
dpms_call_bios(int subfunction, int *bh)
|
||||
{
|
||||
vesa_emu.x86.R_AX = VBE_DPMS_FUNCTION;
|
||||
vesa_emu.x86.R_BL = subfunction;
|
||||
vesa_emu.x86.R_BH = *bh;
|
||||
vesa_emu.x86.R_ES = 0;
|
||||
vesa_emu.x86.R_DI = 0;
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86regs_t regs;
|
||||
|
||||
if ((vesa_emu.x86.R_EAX & 0xffff) != 0x004f)
|
||||
regs.R_AX = VBE_DPMS_FUNCTION;
|
||||
regs.R_BL = subfunction;
|
||||
regs.R_BH = *bh;
|
||||
regs.R_ES = 0;
|
||||
regs.R_DI = 0;
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_EAX & 0xffff) != 0x004f)
|
||||
return (ENXIO);
|
||||
|
||||
*bh = vesa_emu.x86.R_BH;
|
||||
*bh = regs.R_BH;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -45,16 +45,15 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/pc/bios.h>
|
||||
#include <dev/fb/vesa.h>
|
||||
|
||||
#include <dev/fb/fbreg.h>
|
||||
#include <dev/fb/vgareg.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <machine/cpufunc.h>
|
||||
|
||||
#include <contrib/x86emu/x86emu.h>
|
||||
#include <contrib/x86emu/x86emu_regs.h>
|
||||
#include <dev/x86bios/x86bios.h>
|
||||
|
||||
#define VESA_VIA_CLE266 "VIA CLE266\r\n"
|
||||
|
||||
@ -73,7 +72,7 @@ typedef struct adp_state adp_state_t;
|
||||
/* VESA video adapter */
|
||||
static video_adapter_t *vesa_adp = NULL;
|
||||
static int vesa_state_buf_size = 0;
|
||||
#define VESA_X86EMU_BUFSIZE (3 * PAGE_SIZE)
|
||||
#define VESA_BIOS_BUFSIZE (3 * PAGE_SIZE)
|
||||
|
||||
/* VESA functions */
|
||||
#if 0
|
||||
@ -106,8 +105,6 @@ static vi_bitblt_t vesa_bitblt;
|
||||
static vi_diag_t vesa_diag;
|
||||
static int vesa_bios_info(int level);
|
||||
|
||||
static struct x86emu vesa_emu;
|
||||
|
||||
static video_switch_t vesavidsw = {
|
||||
vesa_probe,
|
||||
vesa_init,
|
||||
@ -206,77 +203,6 @@ static void vesa_unmap_buffer(vm_offset_t vaddr, size_t size);
|
||||
static int vesa_get_origin(video_adapter_t *adp, off_t *offset);
|
||||
#endif
|
||||
|
||||
#define SEG_ADDR(x) (((x) >> 4) & 0x00F000)
|
||||
#define SEG_OFF(x) ((x) & 0x0FFFF)
|
||||
|
||||
#if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
#define B_O16(x) (x)
|
||||
#define B_O32(x) (x)
|
||||
#else
|
||||
#define B_O16(x) ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8))
|
||||
#define B_O32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \
|
||||
| (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
|
||||
#endif
|
||||
|
||||
#define L_ADD(x) (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00)
|
||||
#define FARP(p) (((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff))
|
||||
|
||||
#define REALOFF(x) (x*4096)
|
||||
|
||||
static unsigned char *emumem = NULL;
|
||||
|
||||
static uint8_t
|
||||
vm86_emu_inb(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port == 0xb2) /* APM scratch register */
|
||||
return 0;
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inb(port);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
vm86_emu_inw(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inw(port);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
vm86_emu_inl(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inl(port);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val)
|
||||
{
|
||||
if (port == 0xb2) /* APM scratch register */
|
||||
return;
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outb(port, val);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outw(port, val);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outl(port, val);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_buffer(u_char *buf, size_t len)
|
||||
{
|
||||
@ -293,8 +219,11 @@ dump_buffer(u_char *buf, size_t len)
|
||||
static int
|
||||
int10_set_mode(int mode)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x0000 | mode;
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86regs_t regs;
|
||||
|
||||
regs.R_EAX = 0x0000 | mode;
|
||||
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -303,21 +232,28 @@ int10_set_mode(int mode)
|
||||
static int
|
||||
vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
|
||||
{
|
||||
x86regs_t regs;
|
||||
int offs;
|
||||
u_char *buf;
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f01;
|
||||
vesa_emu.x86.R_ECX = mode;
|
||||
regs.R_EAX = 0x4f01;
|
||||
regs.R_ECX = mode;
|
||||
|
||||
buf = (emumem + REALOFF(3));
|
||||
vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(3));
|
||||
vesa_emu.x86.R_DI = SEG_OFF(REALOFF(3));
|
||||
buf = (u_char *)x86biosAlloc(1, &offs);
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_ES = SEG_ADDR(offs);
|
||||
regs.R_DI = SEG_OFF(offs);
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
{
|
||||
x86biosFree(buf, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bcopy(buf, vmode, sizeof(*vmode));
|
||||
x86biosFree(buf, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -325,62 +261,73 @@ vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
|
||||
static int
|
||||
vesa_bios_set_mode(int mode)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f02;
|
||||
vesa_emu.x86.R_EBX = mode;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f02;
|
||||
regs.R_EBX = mode;
|
||||
|
||||
return ((vesa_emu.x86.R_AX & 0xff) != 0x4f);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
return ((regs.R_AX & 0xff) != 0x4f);
|
||||
}
|
||||
|
||||
static int
|
||||
vesa_bios_get_dac(void)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f08;
|
||||
vesa_emu.x86.R_EBX = 1;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f08;
|
||||
regs.R_EBX = 1;
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return 6;
|
||||
|
||||
return ((vesa_emu.x86.R_EBX >> 8) & 0x00ff);
|
||||
return ((regs.R_EBX >> 8) & 0x00ff);
|
||||
}
|
||||
|
||||
static int
|
||||
vesa_bios_set_dac(int bits)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f08;
|
||||
vesa_emu.x86.R_EBX = (bits << 8);
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f08;
|
||||
regs.R_EBX = (bits << 8);
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return 6;
|
||||
|
||||
return ((vesa_emu.x86.R_EBX >> 8) & 0x00ff);
|
||||
return ((regs.R_EBX >> 8) & 0x00ff);
|
||||
}
|
||||
|
||||
static int
|
||||
vesa_bios_save_palette(int start, int colors, u_char *palette, int bits)
|
||||
{
|
||||
x86regs_t regs;
|
||||
int offs;
|
||||
u_char *p;
|
||||
int i;
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f09;
|
||||
vesa_emu.x86.R_EBX = 1;
|
||||
vesa_emu.x86.R_ECX = colors;
|
||||
vesa_emu.x86.R_EDX = start;
|
||||
regs.R_EAX = 0x4f09;
|
||||
regs.R_EBX = 1;
|
||||
regs.R_ECX = colors;
|
||||
regs.R_EDX = start;
|
||||
|
||||
vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2));
|
||||
vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2));
|
||||
p = (u_char *)x86biosAlloc(1, &offs);
|
||||
|
||||
p = emumem + REALOFF(2);
|
||||
regs.R_ES = SEG_ADDR(offs);
|
||||
regs.R_DI = SEG_OFF(offs);
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
{
|
||||
x86biosFree(p, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bits = 8 - bits;
|
||||
for (i = 0; i < colors; ++i) {
|
||||
@ -388,6 +335,8 @@ vesa_bios_save_palette(int start, int colors, u_char *palette, int bits)
|
||||
palette[i*3 + 1] = p[i*4 + 1] << bits;
|
||||
palette[i*3 + 2] = p[i*4] << bits;
|
||||
}
|
||||
|
||||
x86biosFree(p, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -395,23 +344,28 @@ static int
|
||||
vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b,
|
||||
int bits)
|
||||
{
|
||||
x86regs_t regs;
|
||||
int offs;
|
||||
u_char *p;
|
||||
int i;
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f09;
|
||||
vesa_emu.x86.R_EBX = 1;
|
||||
vesa_emu.x86.R_ECX = colors;
|
||||
vesa_emu.x86.R_EDX = start;
|
||||
regs.R_EAX = 0x4f09;
|
||||
regs.R_EBX = 1;
|
||||
regs.R_ECX = colors;
|
||||
regs.R_EDX = start;
|
||||
|
||||
vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2));
|
||||
vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2));
|
||||
p = (u_char *)x86biosAlloc(1, &offs);
|
||||
|
||||
p = emumem + REALOFF(2);
|
||||
regs.R_ES = SEG_ADDR(offs);
|
||||
regs.R_DI = SEG_OFF(offs);
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
{
|
||||
x86biosFree(p, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bits = 8 - bits;
|
||||
for (i = 0; i < colors; ++i) {
|
||||
@ -419,16 +373,20 @@ vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b,
|
||||
g[i] = p[i*4 + 1] << bits;
|
||||
b[i] = p[i*4] << bits;
|
||||
}
|
||||
|
||||
x86biosFree(p, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
vesa_bios_load_palette(int start, int colors, u_char *palette, int bits)
|
||||
{
|
||||
x86regs_t regs;
|
||||
int offs;
|
||||
u_char *p;
|
||||
int i;
|
||||
|
||||
p = (emumem + REALOFF(2));
|
||||
p = (u_char *)x86biosAlloc(1, &offs);
|
||||
|
||||
bits = 8 - bits;
|
||||
for (i = 0; i < colors; ++i) {
|
||||
@ -438,17 +396,19 @@ vesa_bios_load_palette(int start, int colors, u_char *palette, int bits)
|
||||
p[i*4 + 3] = 0;
|
||||
}
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f09;
|
||||
vesa_emu.x86.R_EBX = 0;
|
||||
vesa_emu.x86.R_ECX = colors;
|
||||
vesa_emu.x86.R_EDX = start;
|
||||
regs.R_EAX = 0x4f09;
|
||||
regs.R_EBX = 0;
|
||||
regs.R_ECX = colors;
|
||||
regs.R_EDX = start;
|
||||
|
||||
vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2));
|
||||
vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2));
|
||||
regs.R_ES = SEG_ADDR(offs);
|
||||
regs.R_DI = SEG_OFF(offs);
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
return ((vesa_emu.x86.R_AX & 0xff) != 0x4f);
|
||||
x86biosFree(p, 1);
|
||||
|
||||
return ((regs.R_AX & 0xff) != 0x4f);
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
@ -456,10 +416,12 @@ static int
|
||||
vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b,
|
||||
int bits)
|
||||
{
|
||||
x86regs_t regs;
|
||||
int offs;
|
||||
u_char *p;
|
||||
int i;
|
||||
|
||||
p = (emumem + REALOFF(2));
|
||||
p = (u_char *)x86biosAlloc(1, &offs);
|
||||
|
||||
bits = 8 - bits;
|
||||
for (i = 0; i < colors; ++i) {
|
||||
@ -469,93 +431,106 @@ vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b,
|
||||
p[i*4 + 3] = 0;
|
||||
}
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f09;
|
||||
vesa_emu.x86.R_EBX = 0;
|
||||
vesa_emu.x86.R_ECX = colors;
|
||||
vesa_emu.x86.R_EDX = start;
|
||||
regs.R_EAX = 0x4f09;
|
||||
regs.R_EBX = 0;
|
||||
regs.R_ECX = colors;
|
||||
regs.R_EDX = start;
|
||||
|
||||
vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2));
|
||||
vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2));
|
||||
regs.R_ES = SEG_ADDR(offs);
|
||||
regs.R_DI = SEG_OFF(offs);
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
return ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosFree(p, 1);
|
||||
|
||||
return ((regs.R_AX & 0xff) != 0x4f);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
vesa_bios_state_buf_size(void)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f04;
|
||||
vesa_emu.x86.R_ECX = STATE_ALL;
|
||||
vesa_emu.x86.R_EDX = STATE_SIZE;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f04;
|
||||
regs.R_ECX = STATE_ALL;
|
||||
regs.R_EDX = STATE_SIZE;
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return 0;
|
||||
|
||||
return vesa_emu.x86.R_BX*64;
|
||||
return regs.R_BX*64;
|
||||
}
|
||||
|
||||
static int
|
||||
vesa_bios_save_restore(int code, void *p, size_t size)
|
||||
{
|
||||
x86regs_t regs;
|
||||
int offs;
|
||||
u_char *buf;
|
||||
|
||||
if (size > VESA_X86EMU_BUFSIZE)
|
||||
if (size > VESA_BIOS_BUFSIZE)
|
||||
return (1);
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f04;
|
||||
vesa_emu.x86.R_ECX = STATE_ALL;
|
||||
vesa_emu.x86.R_EDX = code;
|
||||
regs.R_EAX = 0x4f04;
|
||||
regs.R_ECX = STATE_ALL;
|
||||
regs.R_EDX = code;
|
||||
|
||||
buf = emumem + REALOFF(2);
|
||||
buf = (u_char *)x86biosAlloc(1, &offs);
|
||||
|
||||
vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2));
|
||||
vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2));
|
||||
regs.R_ES = SEG_ADDR(offs);
|
||||
regs.R_DI = SEG_OFF(offs);
|
||||
|
||||
bcopy(p, buf, size);
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
bcopy(buf, p, size);
|
||||
|
||||
return ((vesa_emu.x86.R_AX & 0xff) != 0x4f);
|
||||
x86biosFree(p, 1);
|
||||
|
||||
return ((regs.R_AX & 0xff) != 0x4f);
|
||||
}
|
||||
|
||||
static int
|
||||
vesa_bios_get_line_length(void)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f06;
|
||||
vesa_emu.x86.R_EBX = 1;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f06;
|
||||
regs.R_EBX = 1;
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return -1;
|
||||
return vesa_emu.x86.R_BX;
|
||||
|
||||
return regs.R_BX;
|
||||
}
|
||||
|
||||
static int
|
||||
vesa_bios_set_line_length(int pixel, int *bytes, int *lines)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f06;
|
||||
vesa_emu.x86.R_EBX = 0;
|
||||
vesa_emu.x86.R_ECX = pixel;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f06;
|
||||
regs.R_EBX = 0;
|
||||
regs.R_ECX = pixel;
|
||||
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
#if VESA_DEBUG > 1
|
||||
printf("bx:%d, cx:%d, dx:%d\n", vesa_emu.x86.R_BX, vesa_emu.x86.R_CX, vesa_emu.x86.R_DX);
|
||||
printf("bx:%d, cx:%d, dx:%d\n", regs.R_BX, regs.R_CX, regs.R_DX);
|
||||
#endif
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return -1;
|
||||
|
||||
if (bytes)
|
||||
*bytes = vesa_emu.x86.R_BX;
|
||||
*bytes = regs.R_BX;
|
||||
if (lines)
|
||||
*lines = vesa_emu.x86.R_DX;
|
||||
*lines = regs.R_DX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -564,16 +539,18 @@ vesa_bios_set_line_length(int pixel, int *bytes, int *lines)
|
||||
static int
|
||||
vesa_bios_get_start(int *x, int *y)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f07;
|
||||
vesa_emu.x86.R_EBX = 1;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f07;
|
||||
regs.R_EBX = 1;
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return -1;
|
||||
|
||||
*x = vesa_emu.x86.R_CX;
|
||||
*y = vesa_emu.x86.R_DX;
|
||||
*x = regs.R_CX;
|
||||
*y = regs.R_DX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -582,14 +559,16 @@ vesa_bios_get_start(int *x, int *y)
|
||||
static int
|
||||
vesa_bios_set_start(int x, int y)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f07;
|
||||
vesa_emu.x86.R_EBX = 0x80;
|
||||
vesa_emu.x86.R_EDX = y;
|
||||
vesa_emu.x86.R_ECX = x;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f07;
|
||||
regs.R_EBX = 0x80;
|
||||
regs.R_EDX = y;
|
||||
regs.R_ECX = x;
|
||||
|
||||
return ((vesa_emu.x86.R_AX & 0xff) != 0x4f);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
return ((regs.R_AX & 0xff) != 0x4f);
|
||||
}
|
||||
|
||||
/* map a generic video mode to a known mode */
|
||||
@ -665,6 +644,8 @@ vesa_bios_init(void)
|
||||
static struct vesa_info buf;
|
||||
struct vesa_mode vmode;
|
||||
video_info_t *p;
|
||||
x86regs_t regs;
|
||||
int offs;
|
||||
u_char *vmbuf;
|
||||
int is_via_cle266;
|
||||
int modes;
|
||||
@ -678,16 +659,16 @@ vesa_bios_init(void)
|
||||
vesa_vmode_max = 0;
|
||||
vesa_vmode[0].vi_mode = EOT;
|
||||
|
||||
vmbuf = (emumem + REALOFF(2));
|
||||
vmbuf = (u_char *)x86biosAlloc(1, &offs);
|
||||
bcopy("VBE2", vmbuf, 4); /* try for VBE2 data */
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f00;
|
||||
vesa_emu.x86.R_ES = SEG_ADDR(REALOFF(2));
|
||||
vesa_emu.x86.R_DI = SEG_OFF(REALOFF(2));
|
||||
regs.R_EAX = 0x4f00;
|
||||
regs.R_ES = SEG_ADDR(offs);
|
||||
regs.R_DI = SEG_OFF(offs);
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if (((vesa_emu.x86.R_AX & 0xff) != 0x4f) || bcmp("VESA", vmbuf, 4))
|
||||
if (((regs.R_AX & 0xff) != 0x4f) || bcmp("VESA", vmbuf, 4))
|
||||
return 1;
|
||||
|
||||
bcopy(vmbuf, &buf, sizeof(buf));
|
||||
@ -707,17 +688,17 @@ vesa_bios_init(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
vesa_oemstr = (char *)(emumem + L_ADD(vesa_adp_info->v_oemstr));
|
||||
vesa_oemstr = (char *)x86biosOffs(FARP(vesa_adp_info->v_oemstr));
|
||||
|
||||
is_via_cle266 = strcmp(vesa_oemstr, VESA_VIA_CLE266) == 0;
|
||||
|
||||
if (vesa_adp_info->v_version >= 0x0200) {
|
||||
vesa_venderstr = (char *)(emumem+L_ADD(vesa_adp_info->v_venderstr));
|
||||
vesa_prodstr = (char *)(emumem+L_ADD(vesa_adp_info->v_prodstr));
|
||||
vesa_revstr = (char *)(emumem+L_ADD(vesa_adp_info->v_revstr));
|
||||
vesa_venderstr = (char *)x86biosOffs(FARP(vesa_adp_info->v_venderstr));
|
||||
vesa_prodstr = (char *)x86biosOffs(FARP(vesa_adp_info->v_prodstr));
|
||||
vesa_revstr = (char *)x86biosOffs(FARP(vesa_adp_info->v_revstr));
|
||||
}
|
||||
|
||||
vesa_vmodetab = (u_int16_t *)(emumem+L_ADD(vesa_adp_info->v_modetable));
|
||||
vesa_vmodetab = (u_int16_t *)x86biosOffs(FARP(vesa_adp_info->v_modetable));
|
||||
|
||||
if (vesa_vmodetab == NULL)
|
||||
return 1;
|
||||
@ -802,7 +783,7 @@ vesa_bios_init(void)
|
||||
- vmode.v_lfb;
|
||||
else
|
||||
vesa_vmode[modes].vi_buffer_size
|
||||
= vmode.v_offscreen + vmode.v_offscreensize*1024
|
||||
= vmode.v_offscreen + vmode.v_offscreensize*1024;
|
||||
#endif
|
||||
vesa_vmode[modes].vi_mem_model
|
||||
= vesa_translate_mmodel(vmode.v_memmodel);
|
||||
@ -843,6 +824,9 @@ vesa_bios_init(void)
|
||||
++modes;
|
||||
}
|
||||
vesa_vmode[modes].vi_mode = EOT;
|
||||
|
||||
x86biosFree(vmbuf, 1);
|
||||
|
||||
if (bootverbose)
|
||||
printf("VESA: %d mode(s) found\n", modes);
|
||||
|
||||
@ -1127,7 +1111,7 @@ vesa_set_mode(video_adapter_t *adp, int mode)
|
||||
} else {
|
||||
vesa_adp->va_buffer = 0;
|
||||
vesa_adp->va_buffer_size = info.vi_buffer_size;
|
||||
vesa_adp->va_window = (vm_offset_t)(emumem+L_ADD(info.vi_window));
|
||||
vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
|
||||
vesa_adp->va_window_size = info.vi_window_size;
|
||||
vesa_adp->va_window_gran = info.vi_window_gran;
|
||||
}
|
||||
@ -1276,14 +1260,16 @@ vesa_load_state(video_adapter_t *adp, void *p)
|
||||
static int
|
||||
vesa_get_origin(video_adapter_t *adp, off_t *offset)
|
||||
{
|
||||
vesa_emu.x86.R_EAX = 0x4f05;
|
||||
vesa_emu.x86.R_EBX = 0x10;
|
||||
x86regs_t regs;
|
||||
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f05;
|
||||
regs.R_EBX = 0x10;
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return 1;
|
||||
*offset = vesa_emu.x86.DX*adp->va_window_gran;
|
||||
*offset = regs.DX*adp->va_window_gran;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1292,6 +1278,8 @@ vesa_get_origin(video_adapter_t *adp, off_t *offset)
|
||||
static int
|
||||
vesa_set_origin(video_adapter_t *adp, off_t offset)
|
||||
{
|
||||
x86regs_t regs;
|
||||
|
||||
/*
|
||||
* This function should return as quickly as possible to
|
||||
* maintain good performance of the system. For this reason,
|
||||
@ -1308,18 +1296,18 @@ vesa_set_origin(video_adapter_t *adp, off_t offset)
|
||||
if (adp->va_window_gran == 0)
|
||||
return 1;
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f05;
|
||||
vesa_emu.x86.R_EBX = 0;
|
||||
vesa_emu.x86.R_EDX = offset/adp->va_window_gran;
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f05;
|
||||
regs.R_EBX = 0;
|
||||
regs.R_EDX = offset/adp->va_window_gran;
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
if ((vesa_emu.x86.R_AX & 0xff) != 0x4f)
|
||||
if ((regs.R_AX & 0xff) != 0x4f)
|
||||
return 1;
|
||||
|
||||
vesa_emu.x86.R_EAX = 0x4f05;
|
||||
vesa_emu.x86.R_EBX = 1;
|
||||
vesa_emu.x86.R_EDX = offset/adp->va_window_gran;
|
||||
x86emu_exec_intr(&vesa_emu, 0x10);
|
||||
regs.R_EAX = 0x4f05;
|
||||
regs.R_EBX = 1;
|
||||
regs.R_EDX = offset/adp->va_window_gran;
|
||||
x86biosCall(®s, 0x10);
|
||||
|
||||
adp->va_window_orig = (offset/adp->va_window_gran)*adp->va_window_gran;
|
||||
return 0; /* XXX */
|
||||
@ -1654,22 +1642,6 @@ vesa_load(void)
|
||||
if (vesa_init_done)
|
||||
return 0;
|
||||
|
||||
/* Can `emumem' be NULL here? */
|
||||
emumem = pmap_mapbios(0x0, 0xc00000);
|
||||
|
||||
memset(&vesa_emu, 0, sizeof(vesa_emu));
|
||||
x86emu_init_default(&vesa_emu);
|
||||
|
||||
vesa_emu.emu_inb = vm86_emu_inb;
|
||||
vesa_emu.emu_inw = vm86_emu_inw;
|
||||
vesa_emu.emu_inl = vm86_emu_inl;
|
||||
vesa_emu.emu_outb = vm86_emu_outb;
|
||||
vesa_emu.emu_outw = vm86_emu_outw;
|
||||
vesa_emu.emu_outl = vm86_emu_outl;
|
||||
|
||||
vesa_emu.mem_base = (char *)emumem;
|
||||
vesa_emu.mem_size = 1024 * 1024;
|
||||
|
||||
/* locate a VGA adapter */
|
||||
s = spltty();
|
||||
vesa_adp = NULL;
|
||||
@ -1717,9 +1689,6 @@ vesa_unload(void)
|
||||
}
|
||||
splx(s);
|
||||
|
||||
if (emumem)
|
||||
pmap_unmapdev((vm_offset_t)emumem, 0xc00000);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1744,6 +1713,6 @@ static moduledata_t vesa_mod = {
|
||||
};
|
||||
|
||||
DECLARE_MODULE(vesa, vesa_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
|
||||
MODULE_DEPEND(vesa, x86emu, 1, 1, 1);
|
||||
MODULE_DEPEND(vesa, x86bios, 1, 1, 1);
|
||||
|
||||
#endif /* VGA_NO_MODE_CHANGE */
|
||||
|
218
sys/dev/x86bios/x86bios.c
Normal file
218
sys/dev/x86bios/x86bios.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*-
|
||||
* Written by paradox <ddkprog@yahoo.com>
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_x86bios.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
|
||||
#include <contrib/x86emu/x86emu.h>
|
||||
#include <contrib/x86emu/x86emu_regs.h>
|
||||
#include <dev/x86bios/x86bios.h>
|
||||
|
||||
unsigned char *pbiosMem = NULL;
|
||||
static unsigned char *pbiosStack = NULL;
|
||||
|
||||
int busySegMap[5];
|
||||
|
||||
static struct x86emu xbios86emu;
|
||||
|
||||
static struct mtx x86bios_lock;
|
||||
|
||||
static uint8_t
|
||||
vm86_emu_inb(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port == 0xb2) /* APM scratch register */
|
||||
return 0;
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inb(port);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
vm86_emu_inw(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inw(port);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
vm86_emu_inl(struct x86emu *emu, uint16_t port)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return 0;
|
||||
return inl(port);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val)
|
||||
{
|
||||
if (port == 0xb2) /* APM scratch register */
|
||||
return;
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outb(port, val);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outw(port, val);
|
||||
}
|
||||
|
||||
static void
|
||||
vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val)
|
||||
{
|
||||
if (port >= 0x80 && port < 0x88) /* POST status register */
|
||||
return;
|
||||
outl(port, val);
|
||||
}
|
||||
|
||||
void
|
||||
x86biosCall(struct x86regs *regs, int intno)
|
||||
{
|
||||
if (intno < 0 || intno > 255)
|
||||
return;
|
||||
|
||||
mtx_lock(&x86bios_lock);
|
||||
critical_enter();
|
||||
|
||||
xbios86emu.x86.R_EAX = regs->R_EAX;
|
||||
xbios86emu.x86.R_EBX = regs->R_EBX;
|
||||
xbios86emu.x86.R_ECX = regs->R_ECX;
|
||||
xbios86emu.x86.R_EDX = regs->R_EDX;
|
||||
|
||||
xbios86emu.x86.R_ESP = regs->R_ESP;
|
||||
xbios86emu.x86.R_EBP = regs->R_EBP;
|
||||
xbios86emu.x86.R_ESI = regs->R_ESI;
|
||||
xbios86emu.x86.R_EDI = regs->R_EDI;
|
||||
xbios86emu.x86.R_EIP = regs->R_EIP;
|
||||
xbios86emu.x86.R_EFLG = regs->R_EFLG;
|
||||
|
||||
xbios86emu.x86.R_CS = regs->R_CS;
|
||||
xbios86emu.x86.R_DS = regs->R_DS;
|
||||
xbios86emu.x86.R_SS = regs->R_SS;
|
||||
xbios86emu.x86.R_ES = regs->R_ES;
|
||||
xbios86emu.x86.R_FS = regs->R_FS;
|
||||
xbios86emu.x86.R_GS = regs->R_GS;
|
||||
|
||||
x86emu_exec_intr(&xbios86emu, intno);
|
||||
|
||||
regs->R_EAX = xbios86emu.x86.R_EAX;
|
||||
regs->R_EBX = xbios86emu.x86.R_EBX;
|
||||
regs->R_ECX = xbios86emu.x86.R_ECX;
|
||||
regs->R_EDX = xbios86emu.x86.R_EDX;
|
||||
|
||||
regs->R_ESP = xbios86emu.x86.R_ESP;
|
||||
regs->R_EBP = xbios86emu.x86.R_EBP;
|
||||
regs->R_ESI = xbios86emu.x86.R_ESI;
|
||||
regs->R_EDI = xbios86emu.x86.R_EDI;
|
||||
regs->R_EIP = xbios86emu.x86.R_EIP;
|
||||
regs->R_EFLG = xbios86emu.x86.R_EFLG;
|
||||
|
||||
regs->R_CS = xbios86emu.x86.R_CS;
|
||||
regs->R_DS = xbios86emu.x86.R_DS;
|
||||
regs->R_SS = xbios86emu.x86.R_SS;
|
||||
regs->R_ES = xbios86emu.x86.R_ES;
|
||||
regs->R_FS = xbios86emu.x86.R_FS;
|
||||
regs->R_GS = xbios86emu.x86.R_GS;
|
||||
|
||||
critical_exit();
|
||||
mtx_unlock(&x86bios_lock);
|
||||
}
|
||||
|
||||
void *
|
||||
x86biosOffs(uint32_t offs)
|
||||
{
|
||||
return (pbiosMem + offs);
|
||||
}
|
||||
|
||||
static void
|
||||
x86bios_init(void *arg __unused)
|
||||
{
|
||||
int offs;
|
||||
|
||||
mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_DEF);
|
||||
|
||||
/* Can pbiosMem be NULL here? */
|
||||
pbiosMem = pmap_mapbios(0x0, MAPPED_MEMORY_SIZE);
|
||||
|
||||
memset(&xbios86emu, 0, sizeof(xbios86emu));
|
||||
x86emu_init_default(&xbios86emu);
|
||||
|
||||
xbios86emu.emu_inb = vm86_emu_inb;
|
||||
xbios86emu.emu_inw = vm86_emu_inw;
|
||||
xbios86emu.emu_inl = vm86_emu_inl;
|
||||
xbios86emu.emu_outb = vm86_emu_outb;
|
||||
xbios86emu.emu_outw = vm86_emu_outw;
|
||||
xbios86emu.emu_outl = vm86_emu_outl;
|
||||
|
||||
xbios86emu.mem_base = (char *)pbiosMem;
|
||||
xbios86emu.mem_size = 1024 * 1024;
|
||||
|
||||
memset(busySegMap, 0, sizeof(busySegMap));
|
||||
|
||||
pbiosStack = x86biosAlloc(1, &offs);
|
||||
}
|
||||
|
||||
static void
|
||||
x86bios_uninit(void *arg __unused)
|
||||
{
|
||||
x86biosFree(pbiosStack, 1);
|
||||
|
||||
if (pbiosMem)
|
||||
pmap_unmapdev((vm_offset_t)pbiosMem,
|
||||
MAPPED_MEMORY_SIZE);
|
||||
|
||||
mtx_destroy(&x86bios_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
x86bios_modevent(module_t mod __unused, int type, void *data __unused)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
x86bios_init(NULL);
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
x86bios_uninit(NULL);
|
||||
break;
|
||||
default:
|
||||
err = ENOTSUP;
|
||||
break;
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static moduledata_t x86bios_mod = {
|
||||
"x86bios",
|
||||
x86bios_modevent,
|
||||
NULL,
|
||||
};
|
||||
|
||||
DECLARE_MODULE(x86bios, x86bios_mod, SI_SUB_KLD, SI_ORDER_ANY);
|
||||
MODULE_VERSION(x86bios, 1);
|
||||
|
138
sys/dev/x86bios/x86bios.h
Normal file
138
sys/dev/x86bios/x86bios.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*-
|
||||
* Written by paradox <ddkprog@yahoo.com>
|
||||
* Public domain.
|
||||
*
|
||||
* x86 registers were borrowed from x86emu.h x86emu_regs.h
|
||||
* for compatability.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _X86BIOS_H_
|
||||
#define _X86BIOS_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
struct x86_register32 {
|
||||
uint32_t e_reg;
|
||||
};
|
||||
|
||||
struct x86_register16 {
|
||||
uint16_t filler0;
|
||||
uint16_t x_reg;
|
||||
};
|
||||
|
||||
struct x86_register8 {
|
||||
uint8_t filler0, filler1;
|
||||
uint8_t h_reg, l_reg;
|
||||
};
|
||||
|
||||
#else /* !__BIG_ENDIAN__ */
|
||||
|
||||
struct x86_register32 {
|
||||
uint32_t e_reg;
|
||||
};
|
||||
|
||||
struct x86_register16 {
|
||||
uint16_t x_reg;
|
||||
};
|
||||
|
||||
struct x86_register8 {
|
||||
uint8_t l_reg, h_reg;
|
||||
};
|
||||
|
||||
#endif /* __BIG_ENDIAN__ */
|
||||
|
||||
union x86_register {
|
||||
struct x86_register32 I32_reg;
|
||||
struct x86_register16 I16_reg;
|
||||
struct x86_register8 I8_reg;
|
||||
};
|
||||
|
||||
struct x86regs {
|
||||
uint16_t register_cs;
|
||||
uint16_t register_ds;
|
||||
uint16_t register_es;
|
||||
uint16_t register_fs;
|
||||
uint16_t register_gs;
|
||||
uint16_t register_ss;
|
||||
uint32_t register_flags;
|
||||
union x86_register register_a;
|
||||
union x86_register register_b;
|
||||
union x86_register register_c;
|
||||
union x86_register register_d;
|
||||
|
||||
union x86_register register_sp;
|
||||
union x86_register register_bp;
|
||||
union x86_register register_si;
|
||||
union x86_register register_di;
|
||||
union x86_register register_ip;
|
||||
};
|
||||
|
||||
typedef struct x86regs x86regs_t;
|
||||
|
||||
/* 8 bit registers */
|
||||
#define R_AH register_a.I8_reg.h_reg
|
||||
#define R_AL register_a.I8_reg.l_reg
|
||||
#define R_BH register_b.I8_reg.h_reg
|
||||
#define R_BL register_b.I8_reg.l_reg
|
||||
#define R_CH register_c.I8_reg.h_reg
|
||||
#define R_CL register_c.I8_reg.l_reg
|
||||
#define R_DH register_d.I8_reg.h_reg
|
||||
#define R_DL register_d.I8_reg.l_reg
|
||||
|
||||
/* 16 bit registers */
|
||||
#define R_AX register_a.I16_reg.x_reg
|
||||
#define R_BX register_b.I16_reg.x_reg
|
||||
#define R_CX register_c.I16_reg.x_reg
|
||||
#define R_DX register_d.I16_reg.x_reg
|
||||
|
||||
/* 32 bit extended registers */
|
||||
#define R_EAX register_a.I32_reg.e_reg
|
||||
#define R_EBX register_b.I32_reg.e_reg
|
||||
#define R_ECX register_c.I32_reg.e_reg
|
||||
#define R_EDX register_d.I32_reg.e_reg
|
||||
|
||||
/* special registers */
|
||||
#define R_SP register_sp.I16_reg.x_reg
|
||||
#define R_BP register_bp.I16_reg.x_reg
|
||||
#define R_SI register_si.I16_reg.x_reg
|
||||
#define R_DI register_di.I16_reg.x_reg
|
||||
#define R_IP register_ip.I16_reg.x_reg
|
||||
#define R_FLG register_flags
|
||||
|
||||
/* special registers */
|
||||
#define R_ESP register_sp.I32_reg.e_reg
|
||||
#define R_EBP register_bp.I32_reg.e_reg
|
||||
#define R_ESI register_si.I32_reg.e_reg
|
||||
#define R_EDI register_di.I32_reg.e_reg
|
||||
#define R_EIP register_ip.I32_reg.e_reg
|
||||
#define R_EFLG register_flags
|
||||
|
||||
/* segment registers */
|
||||
#define R_CS register_cs
|
||||
#define R_DS register_ds
|
||||
#define R_SS register_ss
|
||||
#define R_ES register_es
|
||||
#define R_FS register_fs
|
||||
#define R_GS register_gs
|
||||
|
||||
#define SEG_ADDR(x) (((x) >> 4) & 0x00F000)
|
||||
#define SEG_OFF(x) ((x) & 0x0FFFF)
|
||||
#define FARP(x) ((le32toh(x) & 0xffff) + ((le32toh(x) >> 12) & 0xffff00))
|
||||
|
||||
#define MAPPED_MEMORY_SIZE 0xc00000
|
||||
#define PAGE_RESERV (4096*5)
|
||||
|
||||
__BEGIN_DECLS
|
||||
void x86biosCall(struct x86regs *regs, int intno);
|
||||
void *x86biosAlloc(int count, int *segs);
|
||||
void x86biosFree(void *pbuf, int count);
|
||||
void *x86biosOffs(uint32_t offs);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_X86BIOS_H_ */
|
81
sys/dev/x86bios/x86bios_alloc.c
Normal file
81
sys/dev/x86bios/x86bios_alloc.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*-
|
||||
* Copyright (C) 1999 Egbert Eich
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and that
|
||||
* both that copyright notice and this permission notice appear in
|
||||
* supporting documentation, and that the name of the authors not be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The authors makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* xserver/hw/xfree86/int10/generic.c
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <dev/x86bios/x86bios.h>
|
||||
|
||||
extern unsigned char *pbiosMem;
|
||||
extern int busySegMap[5];
|
||||
|
||||
void *
|
||||
x86biosAlloc(int count, int *segs)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
/* find the free segblock of page */
|
||||
for (i = 0; i < (PAGE_RESERV - count); i++)
|
||||
{
|
||||
if (busySegMap[i] == 0)
|
||||
{
|
||||
/* find the capacity of segblock */
|
||||
for (j = i; j < (i + count); j++)
|
||||
{
|
||||
if (busySegMap[j] == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == (i + count))
|
||||
break;
|
||||
i += count;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == (PAGE_RESERV - count))
|
||||
return NULL;
|
||||
|
||||
/* make the segblock is used */
|
||||
for (j = i; j < (i + count); j++)
|
||||
busySegMap[i] = 1;
|
||||
|
||||
*segs = i * 4096;
|
||||
|
||||
return (pbiosMem + *segs);
|
||||
}
|
||||
|
||||
void
|
||||
x86biosFree(void *pbuf, int count)
|
||||
{
|
||||
int i;
|
||||
int busySeg;
|
||||
|
||||
busySeg = ((unsigned char *)pbuf - (unsigned char *)pbiosMem)/4096;
|
||||
|
||||
for (i = busySeg; i < (busySeg + count); i++)
|
||||
busySegMap[i] = 0;
|
||||
}
|
@ -298,7 +298,7 @@ SUBDIR= ${_3dfx} \
|
||||
wlan_xauth \
|
||||
${_wpi} \
|
||||
${_wpifw} \
|
||||
x86emu \
|
||||
x86bios \
|
||||
${_xe} \
|
||||
xfs \
|
||||
xl \
|
||||
|
10
sys/modules/x86bios/Makefile
Normal file
10
sys/modules/x86bios/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
KMOD= x86bios
|
||||
SRCS= opt_x86bios.h
|
||||
|
||||
.PATH: ${.CURDIR}/../../contrib/x86emu
|
||||
.PATH: ${.CURDIR}/../../dev/x86bios
|
||||
SRCS+= x86bios.c x86bios_alloc.c x86emu.c x86emu_util.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../contrib/x86emu
|
||||
|
||||
KMOD= x86emu
|
||||
SRCS= x86emu.c x86emu_util.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user