Add VGA BIOS modes to Tiny-X Xvesa server
This commit is contained in:
parent
f16d5d6817
commit
8f634a6516
|
@ -1,5 +1,5 @@
|
|||
XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
|
||||
XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/trident/Imakefile,v 1.4 2000/09/15 07:25:12 keithp Exp $
|
||||
XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/trident/Imakefile,v 1.5 2000/09/19 23:49:55 keithp Exp $
|
||||
KDRIVE=..
|
||||
#include "../Kdrive.tmpl"
|
||||
|
||||
|
@ -7,7 +7,7 @@ SRCS = trident.c tridentdraw.c tridentcurs.c tridentstub.c
|
|||
|
||||
OBJS = trident.o tridentdraw.o tridentcurs.o tridentstub.o
|
||||
|
||||
DEFINES = -DVESA
|
||||
DEFINES = -DVESA /* -DUSE_PCI*/
|
||||
|
||||
INCLUDES = -I. $(KDINCS) -I$(KDRIVE)/fbdev -I$(KDRIVE)/vesa
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.c,v 1.12 2000/09/27 20:46:36 keithp Exp $ */
|
||||
/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.c,v 1.13 2000/10/11 06:04:40 keithp Exp $ */
|
||||
|
||||
#include "trident.h"
|
||||
#define extern
|
||||
|
@ -33,14 +33,32 @@
|
|||
Bool
|
||||
tridentCardInit (KdCardInfo *card)
|
||||
{
|
||||
int k;
|
||||
char *pixels;
|
||||
int k;
|
||||
char *pixels;
|
||||
TridentCardInfo *tridentc;
|
||||
CARD8 r39;
|
||||
|
||||
tridentc = (TridentCardInfo *) xalloc (sizeof (TridentCardInfo));
|
||||
if (!tridentc)
|
||||
return FALSE;
|
||||
|
||||
iopl (3);
|
||||
tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE(card),
|
||||
TRIDENT_COP_SIZE(card));
|
||||
tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF(card));
|
||||
tridentc->mmio = FALSE;
|
||||
r39 = tridentReadIndex (tridentc, 0x3d4, 0x39);
|
||||
if (r39 & 1)
|
||||
{
|
||||
tridentc->mmio = TRUE;
|
||||
r39 = tridentReadIndex (tridentc, 0x3d4, 0x39);
|
||||
if ((r39 & 1) == 0)
|
||||
{
|
||||
ErrorF ("Trident: inconsisent IO mapping values\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VESA
|
||||
if (!vesaInitialize (card, &tridentc->vesa))
|
||||
#else
|
||||
|
@ -51,11 +69,6 @@ tridentCardInit (KdCardInfo *card)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
iopl (3);
|
||||
tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE(card),
|
||||
TRIDENT_COP_SIZE(card));
|
||||
tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF(card));
|
||||
tridentc->mmio = FALSE;
|
||||
#ifdef USE_PCI
|
||||
tridentc->window = (CARD32 *) (tridentc->cop_base + 0x10000);
|
||||
#else
|
||||
|
@ -92,15 +105,32 @@ tridentScreenInit (KdScreenInfo *screen)
|
|||
if (tridents->vesa.mapping != VESA_LINEAR)
|
||||
screen->dumb = TRUE;
|
||||
tridents->screen = tridents->vesa.fb;
|
||||
memory = tridents->vesa.fb_size;
|
||||
#else
|
||||
tridents->screen = tridentc->fb.fb;
|
||||
memory = (2048 + 512) * 1024;
|
||||
#endif
|
||||
screen_size = screen->fb[0].byteStride * screen->height;
|
||||
memory = (2048 + 512) * 1024;
|
||||
if (tridents->screen && memory >= screen_size + 2048)
|
||||
{
|
||||
memory -= 2048;
|
||||
tridents->cursor_base = tridents->screen + memory - 2048;
|
||||
}
|
||||
else
|
||||
tridents->cursor_base = 0;
|
||||
memory -= screen_size;
|
||||
#if 0
|
||||
if (memory > screen->fb[0].byteStride)
|
||||
{
|
||||
screen->off_screen = tridents->screen + screen_size;
|
||||
screen->off_screen_size = memory - screen_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
screen->off_screen = 0;
|
||||
screen->off_screen_size = 0;
|
||||
}
|
||||
#endif
|
||||
screen->driver = tridents;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.h,v 1.6 2000/09/15 07:25:12 keithp Exp $ */
|
||||
/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.h,v 1.7 2000/10/11 06:04:40 keithp Exp $ */
|
||||
|
||||
#ifndef _TRIDENT_H_
|
||||
#define _TRIDENT_H_
|
||||
|
@ -34,7 +34,6 @@
|
|||
/*
|
||||
* offset from ioport beginning
|
||||
*/
|
||||
#define USE_PCI
|
||||
|
||||
#ifdef USE_PCI
|
||||
#define TRIDENT_COP_BASE(c) (c->attr.address[1])
|
||||
|
@ -219,6 +218,8 @@ typedef struct _tridentScreenInfo {
|
|||
#endif
|
||||
CARD8 *cursor_base;
|
||||
CARD8 *screen;
|
||||
CARD8 *off_screen;
|
||||
int off_screen_size;
|
||||
TridentCursor cursor;
|
||||
} TridentScreenInfo;
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
XCOMM $XFree86$
|
||||
XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/vesa/Imakefile,v 1.2 2000/09/03 05:11:22 keithp Exp $
|
||||
KDRIVE=..
|
||||
#include "../Kdrive.tmpl"
|
||||
|
||||
SRCS = vesa.c vesainit.c vbe.c
|
||||
SRCS = vesa.c vesainit.c vbe.c vga.c vm86.c
|
||||
|
||||
OBJS = vesa.o vesainit.o vbe.o
|
||||
OBJS = vesa.o vesainit.o vbe.o vga.o vm86.o
|
||||
|
||||
INCLUDES = -I. $(KDINCS)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $XFree86$
|
||||
.\" $XFree86: xc/programs/Xserver/hw/kdrive/vesa/Xvesa.man,v 1.2 2000/09/03 05:11:22 keithp Exp $
|
||||
.TH Xvesa 1
|
||||
.SH NAME
|
||||
Xvesa \- VESA VBE tiny X server
|
||||
|
@ -11,10 +11,13 @@ Xvesa \- VESA VBE tiny X server
|
|||
is a generic X server for Linux on the x86 platform.
|
||||
.B Xvesa
|
||||
doesn't know about any particular hardware, and sets the video mode by
|
||||
running the video BIOS in VM86 mode.
|
||||
running the video BIOS in VM86 mode.
|
||||
.B Xvesa
|
||||
therefore runs untrusted code with full priviledges, and is one of the
|
||||
most insecure X servers available.
|
||||
.B Xvesa
|
||||
uses both standard VGA BIOS modes and any modes advertised by a VESA 2.0
|
||||
BIOS if available.
|
||||
.B Run at your own risk.
|
||||
.SH OPTIONS
|
||||
In addition to the normal tiny-X server's options (to be described in
|
||||
|
@ -28,9 +31,9 @@ specifies the VESA video mode to use. If mode
|
|||
is not supported by your BIOS and hardware,
|
||||
.B Xvesa
|
||||
will fail, hang your system, or make your monitor explode; you are on
|
||||
your own. This option is ignored if the
|
||||
your own. This option overrides any
|
||||
.B -screen
|
||||
option was used.
|
||||
options.
|
||||
.TP 8
|
||||
.B -listmodes
|
||||
tells the server to list all supported video modes. If
|
||||
|
@ -55,8 +58,11 @@ don't use a linear framebuffer even if one is available. You don't
|
|||
want to use this option.
|
||||
.TP 8
|
||||
.B -swaprgb
|
||||
pass RGB values in the order that works on my machine. Use this if
|
||||
pass RGB values in the order that works on broken BIOSes. Use this if
|
||||
the colours are wrong in PseudoColor modes.
|
||||
.TP 8
|
||||
.B -verbose
|
||||
emit diagnostic messages during BIOS initialization and teardown.
|
||||
.SH KEYBOARD
|
||||
Xvesa handles the keyboard in the same manner as the
|
||||
.B Xfbdev
|
||||
|
@ -69,10 +75,17 @@ assumed to be buggy. Allowing your users to run
|
|||
is a major security hole. Allowing yourself to run
|
||||
.B Xvesa
|
||||
is probably a mistake.
|
||||
.B Xvesa
|
||||
records the current BIOS mode when it starts and restores that mode on
|
||||
termination; if the video card has been reprogrammed by another application,
|
||||
the display will almost certainly be trashed. The alternative of saving and
|
||||
restoring the complete video card state has proven unreliable on most video
|
||||
cards.
|
||||
.SH SEE ALSO
|
||||
X(1), Xserver(1), xdm(1), xinit(1), Xfbdev(1).
|
||||
.SH AUTHORS
|
||||
The tiny-X server was written by Keith Packard, and the VESA driver
|
||||
was added by Juliusz Chroboczek who didn't realise what he was doing
|
||||
until it was too late. Tiny-X uses code from XFree86, which in turn
|
||||
is based on the Sample Implementation.
|
||||
is based on the Sample Implementation. Keith Packard then added support for
|
||||
standard VGA BIOS modes and is especially proud of 320x200 16 color mode.
|
||||
|
|
1366
hw/kdrive/vesa/vbe.c
1366
hw/kdrive/vesa/vbe.c
File diff suppressed because it is too large
Load Diff
|
@ -28,56 +28,6 @@ THE SOFTWARE.
|
|||
#define VBE_WINDOW_READ 2
|
||||
#define VBE_WINDOW_WRITE 4
|
||||
|
||||
#ifndef U8
|
||||
#define U8 unsigned char
|
||||
#define U16 unsigned short
|
||||
#define U32 unsigned int
|
||||
#endif
|
||||
|
||||
/* The whole addressable memory */
|
||||
#define SYSMEM_BASE 0x00000
|
||||
#define SYSMEM_SIZE 0x100000
|
||||
|
||||
/* Interrupt vectors and BIOS data area */
|
||||
/* This is allocated privately from /dev/mem */
|
||||
#define MAGICMEM_BASE 0x00000
|
||||
#define MAGICMEM_SIZE 0x01000
|
||||
|
||||
/* The low memory, allocated privately from /dev/zero */
|
||||
/* 64KB should be enough for anyone, as they used to say */
|
||||
#define LOMEM_BASE 0x10000
|
||||
#define LOMEM_SIZE 0x10000
|
||||
|
||||
/* The video memory and BIOS ROM, allocated shared from /dev/mem */
|
||||
#define HIMEM_BASE 0xA0000
|
||||
#define HIMEM_SIZE (SYSMEM_BASE + SYSMEM_SIZE - HIMEM_BASE)
|
||||
|
||||
/* The BIOS ROM */
|
||||
#define ROM_BASE 0xC0000
|
||||
#define ROM_SIZE 0x30000
|
||||
|
||||
#define STACK_SIZE 0x1000
|
||||
|
||||
#define POINTER_SEGMENT(ptr) (((unsigned int)ptr)>>4)
|
||||
#define POINTER_OFFSET(ptr) (((unsigned int)ptr)&0x000F)
|
||||
#define MAKE_POINTER(seg, off) (((((unsigned int)(seg))<<4) + (unsigned int)(off)))
|
||||
#define MAKE_POINTER_1(lw) MAKE_POINTER(((lw)&0xFFFF0000)/0x10000, (lw)&0xFFFF)
|
||||
#define ALLOC_FAIL ((U32)-1)
|
||||
|
||||
typedef struct _VbeInfoRec {
|
||||
int devmem, devzero;
|
||||
void *magicMem, *loMem, *hiMem;
|
||||
U32 brk;
|
||||
struct vm86_struct vms;
|
||||
U32 ret_code, stack_base, vib_base, vmib_base, statebuffer_base, palette_scratch_base;
|
||||
U8 palette_format;
|
||||
int palette_wait;
|
||||
int windowA_offset;
|
||||
int windowB_offset;
|
||||
int last_window;
|
||||
int vga_palette;
|
||||
} VbeInfoRec, *VbeInfoPtr;
|
||||
|
||||
typedef struct _VbeInfoBlock {
|
||||
U8 VbeSignature[4]; /* VBE Signature */
|
||||
U16 VbeVersion; /* VBE Version */
|
||||
|
@ -134,6 +84,15 @@ typedef struct _VbeModeInfoBlock {
|
|||
U8 Reserved2[206]; /* remainder of ModeInfoBlock */
|
||||
} __attribute__((packed)) VbeModeInfoBlock;
|
||||
|
||||
typedef struct _VbeInfoRec {
|
||||
U8 palette_format;
|
||||
int palette_wait;
|
||||
int windowA_offset;
|
||||
int windowB_offset;
|
||||
int window_size;
|
||||
int last_window;
|
||||
VbeModeInfoBlock vmib;
|
||||
} VbeInfoRec, *VbeInfoPtr;
|
||||
|
||||
typedef struct _SupVbeInfoBlock {
|
||||
U8 SupVbeSignature[7]; /* Supplemental VBE Signature */
|
||||
|
@ -147,32 +106,58 @@ typedef struct _SupVbeInfoBlock {
|
|||
U8 Reserved[221]; /* Reserved */
|
||||
} __attribute__((packed)) SupVbeInfoBlock;
|
||||
|
||||
VbeInfoPtr VbeSetup(void);
|
||||
void VbeCleanup(VbeInfoPtr vi);
|
||||
VbeInfoBlock *VbeGetInfo(VbeInfoPtr vi);
|
||||
VbeModeInfoBlock *VbeGetModeInfo(VbeInfoPtr vi, int mode);
|
||||
int VbeSetMode(VbeInfoPtr vi, int mode, int linear);
|
||||
int VbeGetMode(VbeInfoPtr vi, int *mode);
|
||||
int VbeSetupStateBuffer(VbeInfoPtr vi);
|
||||
int VbeSaveState(VbeInfoPtr vi);
|
||||
int VbeRestoreState(VbeInfoPtr vi);
|
||||
void *VbeMapFramebuffer(VbeInfoPtr vi, VbeModeInfoBlock *vmib);
|
||||
int VbeUnmapFrambuffer(VbeInfoPtr vi, VbeModeInfoBlock *vmib, void *fb);
|
||||
int VbeSetPalette(VbeInfoPtr vi, int first, int number, U8 *entries);
|
||||
int VbeSetPaletteOptions(VbeInfoPtr vi, U8 bits, int wait);
|
||||
void *VbeSetWindow(VbeInfoPtr vi, int offset, int purpose, int *size_return);
|
||||
int VbeReportInfo(VbeInfoPtr, VbeInfoBlock *);
|
||||
int VbeReportModeInfo(VbeInfoPtr, U16 mode, VbeModeInfoBlock *);
|
||||
int
|
||||
VbeGetVib (Vm86InfoPtr vi, VbeInfoBlock *vib);
|
||||
|
||||
int VbeDoInterrupt(VbeInfoPtr, int num);
|
||||
int VbeDoInterrupt10(VbeInfoPtr vi);
|
||||
int VbeIsMemory(VbeInfoPtr vi, U32 i);
|
||||
U8 VbeMemory(VbeInfoPtr, U32);
|
||||
U16 VbeMemoryW(VbeInfoPtr, U32);
|
||||
U32 VbeMemoryL(VbeInfoPtr, U32);
|
||||
void VbeWriteMemory(VbeInfoPtr, U32, U8);
|
||||
void VbeWriteMemoryW(VbeInfoPtr, U32, U16);
|
||||
void VbeWriteMemoryL(VbeInfoPtr, U32, U32);
|
||||
int VbeAllocateMemory(VbeInfoPtr, int);
|
||||
void VbeDebug(VbeInfoPtr vi);
|
||||
int
|
||||
VbeGetVmib (Vm86InfoPtr vi, int mode, VbeModeInfoBlock *vmib);
|
||||
|
||||
void
|
||||
VbeReportInfo (Vm86InfoPtr vi);
|
||||
|
||||
int
|
||||
VbeGetNmode (Vm86InfoPtr vi);
|
||||
|
||||
int
|
||||
VbeGetModes (Vm86InfoPtr vi, VesaModePtr modes, int nmode);
|
||||
|
||||
int
|
||||
VbeGetModeInfo(Vm86InfoPtr vi, int m, VesaModePtr mode);
|
||||
|
||||
VbeInfoPtr
|
||||
VbeInit (Vm86InfoPtr vi);
|
||||
|
||||
int
|
||||
VbeSetMode (Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, int linear);
|
||||
|
||||
int
|
||||
VbeGetMode(Vm86InfoPtr vi, int *mode);
|
||||
|
||||
void *
|
||||
VbeMapFramebuffer(Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, int *size);
|
||||
|
||||
void
|
||||
VbeUnmapFramebuffer(Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, void *fb);
|
||||
|
||||
int
|
||||
VbeSetPalette(Vm86InfoPtr vi, VbeInfoPtr vbe, int first, int number, U8 *entries);
|
||||
|
||||
int
|
||||
VbeGetPalette(Vm86InfoPtr vi, VbeInfoPtr vbe, int first, int number, U8 *entries);
|
||||
|
||||
int
|
||||
VbeSetPaletteOptions(Vm86InfoPtr vi, VbeInfoPtr vbe, U8 bits, int wait);
|
||||
|
||||
void *
|
||||
VbeSetWindow(Vm86InfoPtr vi, VbeInfoPtr vbe, int offset, int purpose, int *size_return);
|
||||
|
||||
int
|
||||
VbeReportVib(Vm86InfoPtr vi, VbeInfoBlock *vib);
|
||||
|
||||
int
|
||||
VbeReportModeInfo(Vm86InfoPtr vi, U16 mode, VbeModeInfoBlock *vmib);
|
||||
|
||||
int
|
||||
VbeDoInterrupt10(Vm86InfoPtr vi);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,54 +25,127 @@ THE SOFTWARE.
|
|||
#define _VESA_H_
|
||||
|
||||
#include "kdrive.h"
|
||||
#include <sys/vm86.h>
|
||||
#include "vbe.h"
|
||||
#include "vm86.h"
|
||||
|
||||
#define VESA_TEXT_SAVE (64*1024)
|
||||
|
||||
#define MODE_SUPPORTED 0x01
|
||||
#define MODE_COLOUR 0x08
|
||||
#define MODE_GRAPHICS 0x10
|
||||
#define MODE_VGA 0x20
|
||||
#define MODE_LINEAR 0x80
|
||||
|
||||
#define MODE_DIRECT 0x1
|
||||
|
||||
#define MEMORY_TEXT 0
|
||||
#define MEMORY_CGA 1
|
||||
#define MEMORY_HERCULES 2
|
||||
#define MEMORY_PLANAR 3
|
||||
#define MEMORY_PSEUDO 4
|
||||
#define MEMORY_NONCHAIN 5
|
||||
#define MEMORY_DIRECT 6
|
||||
#define MEMORY_YUV 7
|
||||
|
||||
typedef struct _VesaMode {
|
||||
int mode;
|
||||
VbeModeInfoBlock vmib;
|
||||
int mode; /* mode number */
|
||||
int vbe; /* a VBE mode */
|
||||
int ModeAttributes; /* mode attributes */
|
||||
int NumberOfPlanes; /* number of memory planes */
|
||||
int BitsPerPixel; /* bits per pixel */
|
||||
int MemoryModel; /* memory model type */
|
||||
int RedMaskSize; /* size of direct color red mask in bits */
|
||||
int RedFieldPosition; /* bit position of lsb of red mask */
|
||||
int GreenMaskSize; /* size of direct color green mask in bits */
|
||||
int GreenFieldPosition; /* bit position of lsb of green mask */
|
||||
int BlueMaskSize; /* size of direct color blue mask in bits */
|
||||
int BlueFieldPosition; /* bit position of lsb of blue mask */
|
||||
int RsvdMaskSize; /* size of direct color reserved mask bits*/
|
||||
int RsvdFieldPosition; /* bit position of lsb of reserved mask */
|
||||
int DirectColorModeInfo; /* direct color mode attributes */
|
||||
int XResolution; /* horizontal resolution */
|
||||
int YResolution; /* vertical resolution */
|
||||
int BytesPerScanLine; /* bytes per scan line */
|
||||
} VesaModeRec, *VesaModePtr;
|
||||
|
||||
#include "vbe.h"
|
||||
#include "vga.h"
|
||||
|
||||
typedef struct _VesaCardPriv {
|
||||
VbeInfoPtr vi;
|
||||
VbeInfoBlock *vib;
|
||||
int vbe;
|
||||
Vm86InfoPtr vi;
|
||||
VesaModePtr modes;
|
||||
int nmode;
|
||||
char text[VESA_TEXT_SAVE];
|
||||
int nmode;
|
||||
int vga_palette;
|
||||
int old_vbe_mode;
|
||||
int old_vga_mode;
|
||||
VbeInfoPtr vbeInfo;
|
||||
char text[VESA_TEXT_SAVE];
|
||||
} VesaCardPrivRec, *VesaCardPrivPtr;
|
||||
|
||||
#define VESA_LINEAR 0
|
||||
#define VESA_WINDOWED 1
|
||||
#define VESA_PLANAR 2
|
||||
#define VESA_MONO 3
|
||||
|
||||
typedef struct _VesaScreenPriv {
|
||||
VesaModePtr mode;
|
||||
Bool shadow;
|
||||
Bool rotate;
|
||||
int mapping;
|
||||
int origDepth;
|
||||
void *fb;
|
||||
void *fb;
|
||||
int fb_size;
|
||||
} VesaScreenPrivRec, *VesaScreenPrivPtr;
|
||||
|
||||
extern int vesa_video_mode;
|
||||
extern Bool vesa_force_mode;
|
||||
|
||||
Bool vesaListModes(void);
|
||||
Bool vesaInitialize(KdCardInfo *card, VesaCardPrivPtr priv);
|
||||
Bool vesaCardInit(KdCardInfo *card);
|
||||
Bool vesaInitialize (KdCardInfo *card, VesaCardPrivPtr priv);
|
||||
Bool vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr);
|
||||
Bool vesaScreenInit(KdScreenInfo *screen);
|
||||
Bool vesaInitScreen(ScreenPtr pScreen);
|
||||
Bool vesaEnable(ScreenPtr pScreen);
|
||||
void vesaDisable(ScreenPtr pScreen);
|
||||
void vesaPreserve(KdCardInfo *card);
|
||||
void vesaRestore(KdCardInfo *card);
|
||||
void vesaCardFini(KdCardInfo *card);
|
||||
void vesaScreenFini(KdScreenInfo *screen);
|
||||
void vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs);
|
||||
void vesaGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs);
|
||||
int vesaProcessArgument (int argc, char **argv, int i);
|
||||
void
|
||||
vesaListModes(void);
|
||||
|
||||
Bool
|
||||
vesaInitialize(KdCardInfo *card, VesaCardPrivPtr priv);
|
||||
|
||||
Bool
|
||||
vesaCardInit(KdCardInfo *card);
|
||||
|
||||
Bool
|
||||
vesaInitialize (KdCardInfo *card, VesaCardPrivPtr priv);
|
||||
|
||||
Bool
|
||||
vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr);
|
||||
|
||||
Bool
|
||||
vesaScreenInit(KdScreenInfo *screen);
|
||||
|
||||
Bool
|
||||
vesaInitScreen(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
vesaEnable(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
vesaDisable(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
vesaPreserve(KdCardInfo *card);
|
||||
|
||||
void
|
||||
vesaRestore(KdCardInfo *card);
|
||||
|
||||
void
|
||||
vesaCardFini(KdCardInfo *card);
|
||||
|
||||
void
|
||||
vesaScreenFini(KdScreenInfo *screen);
|
||||
|
||||
void
|
||||
vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs);
|
||||
|
||||
void
|
||||
vesaGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs);
|
||||
|
||||
int
|
||||
vesaProcessArgument (int argc, char **argv, int i);
|
||||
|
||||
#endif _VESA_H_
|
||||
|
|
|
@ -23,7 +23,7 @@ THE SOFTWARE.
|
|||
|
||||
#include "vesa.h"
|
||||
|
||||
KdCardFuncs vesaFuncs = {
|
||||
const KdCardFuncs vesaFuncs = {
|
||||
vesaCardInit, /* cardinit */
|
||||
vesaScreenInit, /* scrinit */
|
||||
vesaInitScreen, /* initScreen */
|
||||
|
|
240
hw/kdrive/vesa/vga.c
Normal file
240
hw/kdrive/vesa/vga.c
Normal file
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* $XFree86$
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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.
|
||||
*/
|
||||
|
||||
#include "vesa.h"
|
||||
|
||||
static const VesaModeRec vgaModes[] = {
|
||||
{
|
||||
6, 0,
|
||||
MODE_SUPPORTED | MODE_GRAPHICS | MODE_VGA | MODE_LINEAR,
|
||||
1, 1, MEMORY_PLANAR,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
640, 200, 80,
|
||||
},
|
||||
{
|
||||
0xd, 0,
|
||||
MODE_SUPPORTED | MODE_GRAPHICS | MODE_VGA | MODE_COLOUR,
|
||||
4, 4, MEMORY_PLANAR,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
320, 200, 40,
|
||||
},
|
||||
{
|
||||
0xe, 0,
|
||||
MODE_SUPPORTED | MODE_GRAPHICS | MODE_VGA | MODE_COLOUR,
|
||||
4, 4, MEMORY_PLANAR,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
640, 200, 80,
|
||||
},
|
||||
{
|
||||
0x10, 0,
|
||||
MODE_SUPPORTED | MODE_GRAPHICS | MODE_VGA | MODE_COLOUR,
|
||||
4, 4, MEMORY_PLANAR,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
640, 350, 80,
|
||||
},
|
||||
{
|
||||
0x11, 0,
|
||||
MODE_SUPPORTED | MODE_GRAPHICS | MODE_VGA | MODE_LINEAR,
|
||||
1, 1, MEMORY_PLANAR,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
640, 480, 80,
|
||||
},
|
||||
{
|
||||
0x12, 0,
|
||||
MODE_SUPPORTED | MODE_GRAPHICS | MODE_VGA | MODE_COLOUR,
|
||||
4, 4, MEMORY_PLANAR,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
640, 480, 80,
|
||||
},
|
||||
{
|
||||
0x13, 0,
|
||||
MODE_SUPPORTED | MODE_GRAPHICS | MODE_VGA | MODE_COLOUR | MODE_LINEAR,
|
||||
8, 8, MEMORY_PSEUDO,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
320, 200, 320,
|
||||
},
|
||||
};
|
||||
|
||||
#define NUM_VGA_MODE (sizeof vgaModes / sizeof vgaModes[0])
|
||||
|
||||
int
|
||||
VgaGetNmode (Vm86InfoPtr vi)
|
||||
{
|
||||
return NUM_VGA_MODE;
|
||||
}
|
||||
|
||||
int
|
||||
VgaGetModes (Vm86InfoPtr vi, VesaModePtr mode, int nmode)
|
||||
{
|
||||
if (nmode > NUM_VGA_MODE)
|
||||
nmode = NUM_VGA_MODE;
|
||||
memcpy (mode, vgaModes, nmode * sizeof (VesaModeRec));
|
||||
return nmode;
|
||||
}
|
||||
|
||||
int
|
||||
VgaSetMode(Vm86InfoPtr vi, int mode)
|
||||
{
|
||||
int code;
|
||||
|
||||
vi->vms.regs.eax = mode & 0x7f;
|
||||
code = Vm86DoInterrupt (vi, 0x10);
|
||||
if(code < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
VgaGetMode (Vm86InfoPtr vi, int *mode)
|
||||
{
|
||||
*mode = Vm86Memory (vi, 0x449);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
VgaSetWritePlaneMask(Vm86InfoPtr vi, int mask)
|
||||
{
|
||||
asm volatile ("outb %b0,%w1" : : "a" (2), "d" (0x3c4));
|
||||
asm volatile ("outb %b0,%w1" : : "a" (mask), "d" (0x3c5));
|
||||
}
|
||||
|
||||
int
|
||||
VgaSetReadPlaneMap(Vm86InfoPtr vi, int map)
|
||||
{
|
||||
asm volatile ("outb %b0,%w1" : : "a" (4), "d" (0x3ce));
|
||||
asm volatile ("outb %b0,%w1" : : "a" (map), "d" (0x3cf));
|
||||
}
|
||||
|
||||
int
|
||||
VgaSetPalette(Vm86InfoPtr vi, int first, int number, U8 *entries)
|
||||
{
|
||||
U8 *palette_scratch;
|
||||
int mark;
|
||||
int palette_base;
|
||||
int i, j, code;
|
||||
|
||||
if(number == 0)
|
||||
return 0;
|
||||
|
||||
if(first < 0 || number < 0 || first + number > 256) {
|
||||
ErrorF("Cannot set %d, %d palette entries\n", first, number);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mark = Vm86MarkMemory (vi);
|
||||
palette_base = Vm86AllocateMemory (vi, 3 * 256);
|
||||
|
||||
palette_scratch = &LM(vi, palette_base);
|
||||
|
||||
vi->vms.regs.eax = 0x1012;
|
||||
vi->vms.regs.ebx = first;
|
||||
vi->vms.regs.ecx = number;
|
||||
vi->vms.regs.es = POINTER_SEGMENT(palette_base);
|
||||
vi->vms.regs.edx = POINTER_OFFSET(palette_base);
|
||||
j = 0;
|
||||
i = 0;
|
||||
while (number--)
|
||||
{
|
||||
palette_scratch[j++] = entries[i++] >> 2;
|
||||
palette_scratch[j++] = entries[i++] >> 2;
|
||||
palette_scratch[j++] = entries[i++] >> 2;
|
||||
i++;
|
||||
}
|
||||
code = Vm86DoInterrupt(vi, 0x10);
|
||||
Vm86ReleaseMemory (vi, mark);
|
||||
|
||||
if(code < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
VgaGetPalette(Vm86InfoPtr vi, int first, int number, U8 *entries)
|
||||
{
|
||||
U8 *palette_scratch;
|
||||
int mark;
|
||||
int palette_base;
|
||||
int i, j, code;
|
||||
|
||||
if(number == 0)
|
||||
return 0;
|
||||
|
||||
if(first < 0 || number < 0 || first + number > 256) {
|
||||
ErrorF("Cannot get %d, %d palette entries\n", first, number);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mark = Vm86MarkMemory (vi);
|
||||
palette_base = Vm86AllocateMemory (vi, 3 * 256);
|
||||
|
||||
palette_scratch = &LM(vi, palette_base);
|
||||
|
||||
vi->vms.regs.eax = 0x1017;
|
||||
vi->vms.regs.ebx = first;
|
||||
vi->vms.regs.ecx = number;
|
||||
vi->vms.regs.es = POINTER_SEGMENT(palette_base);
|
||||
vi->vms.regs.edx = POINTER_OFFSET(palette_base);
|
||||
|
||||
code = VbeDoInterrupt10(vi);
|
||||
if(code < 0)
|
||||
return -1;
|
||||
|
||||
j = 0;
|
||||
i = 0;
|
||||
while (number--)
|
||||
{
|
||||
entries[i++] = palette_scratch[j++] << 2;
|
||||
entries[i++] = palette_scratch[j++] << 2;
|
||||
entries[i++] = palette_scratch[j++] << 2;
|
||||
entries[i++] = 0;
|
||||
}
|
||||
|
||||
Vm86ReleaseMemory (vi, mark);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define VGA_FB(vm) ((vm) < 8 ? 0xb8000 : 0xa0000)
|
||||
|
||||
void *
|
||||
VgaSetWindow (Vm86InfoPtr vi, int vmode, int bytes, int mode, int *size)
|
||||
{
|
||||
*size = 0x10000 - bytes;
|
||||
return &LM(vi,VGA_FB(vmode) + bytes);
|
||||
}
|
||||
|
||||
void *
|
||||
VgaMapFramebuffer (Vm86InfoPtr vi, int vmode, int *size)
|
||||
{
|
||||
if (VGA_FB(vmode) == 0xa0000)
|
||||
*size = 0x10000;
|
||||
else
|
||||
*size = 0x4000;
|
||||
return &LM(vi,VGA_FB(vmode));
|
||||
}
|
||||
|
||||
void
|
||||
VgaUnmapFramebuffer (Vm86InfoPtr vi)
|
||||
{
|
||||
}
|
61
hw/kdrive/vesa/vga.h
Normal file
61
hw/kdrive/vesa/vga.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* $XFree86$
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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.
|
||||
*/
|
||||
|
||||
#ifndef _VGA_H_
|
||||
#define _VGA_H_
|
||||
|
||||
int
|
||||
VgaGetNmode (Vm86InfoPtr vi);
|
||||
|
||||
int
|
||||
VgaGetModes (Vm86InfoPtr vi, VesaModePtr mode, int nmode);
|
||||
|
||||
int
|
||||
VgaSetMode(Vm86InfoPtr vi, int mode);
|
||||
|
||||
int
|
||||
VgaGetMode (Vm86InfoPtr vi, int *mode);
|
||||
|
||||
int
|
||||
VgaSetWritePlaneMask(Vm86InfoPtr vi, int mask);
|
||||
|
||||
int
|
||||
VgaSetReadPlaneMap(Vm86InfoPtr vi, int map);
|
||||
|
||||
int
|
||||
VgaSetPalette(Vm86InfoPtr vi, int first, int number, U8 *entries);
|
||||
|
||||
int
|
||||
VgaGetPalette(Vm86InfoPtr vi, int first, int number, U8 *entries);
|
||||
|
||||
void *
|
||||
VgaSetWindow (Vm86InfoPtr vi, int vmode, int bytes, int mode, int *size);
|
||||
|
||||
void *
|
||||
VgaMapFramebuffer (Vm86InfoPtr vi, int vmode, int *size);
|
||||
|
||||
void
|
||||
VgaUnmapFramebuffer (Vm86InfoPtr vi);
|
||||
|
||||
#endif /* _VGA_H_ */
|
697
hw/kdrive/vesa/vm86.c
Normal file
697
hw/kdrive/vesa/vm86.c
Normal file
|
@ -0,0 +1,697 @@
|
|||
/*
|
||||
* $XFree86$
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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.
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2000 by Juliusz Chroboczek
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "vm86.h"
|
||||
|
||||
#define PUSHW(vi, i) \
|
||||
{ vi->vms.regs.esp -= 2;\
|
||||
LMW(vi,MAKE_POINTER(vi->vms.regs.ss, vi->vms.regs.esp)) = i;}
|
||||
|
||||
static int vm86old(struct vm86_struct *vms);
|
||||
static int vm86_loop(Vm86InfoPtr vi);
|
||||
|
||||
static const U8 rev_ints[32] =
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x80,
|
||||
};
|
||||
|
||||
static const U8 retcode_data[2] =
|
||||
{ 0xCD, 0xFF };
|
||||
|
||||
Vm86InfoPtr
|
||||
Vm86Setup(void)
|
||||
{
|
||||
int devmem = -1, devzero = -1;
|
||||
void *magicMem, *loMem, *hiMem;
|
||||
U32 stack_base, ret_code;
|
||||
Vm86InfoPtr vi = NULL;
|
||||
|
||||
devmem = open("/dev/mem", O_RDWR);
|
||||
if(devmem < 0) {
|
||||
perror("open /dev/mem");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
devzero = open("/dev/zero", O_RDWR);
|
||||
if(devmem < 0) {
|
||||
perror("open /dev/zero");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
magicMem = mmap((void*)MAGICMEM_BASE, MAGICMEM_SIZE,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_FIXED, devmem, MAGICMEM_BASE);
|
||||
|
||||
if(magicMem == MAP_FAILED) {
|
||||
ErrorF("Couldn't map magic memory\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
loMem = mmap((void*)LOMEM_BASE, LOMEM_SIZE,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_FIXED, devzero, LOMEM_BASE);
|
||||
if(loMem == MAP_FAILED) {
|
||||
ErrorF("Couldn't map low memory\n");
|
||||
munmap(magicMem, MAGICMEM_SIZE);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hiMem = mmap((void*)HIMEM_BASE, HIMEM_SIZE,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_SHARED | MAP_FIXED,
|
||||
devmem, HIMEM_BASE);
|
||||
if(hiMem == MAP_FAILED) {
|
||||
ErrorF("Couldn't map high memory\n");
|
||||
munmap(magicMem, MAGICMEM_SIZE);
|
||||
munmap(loMem, LOMEM_SIZE);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vi = xalloc(sizeof(Vm86InfoRec));
|
||||
if (!vi)
|
||||
goto unmapfail;
|
||||
|
||||
vi->magicMem = magicMem;
|
||||
vi->loMem = loMem;
|
||||
vi->hiMem = hiMem;
|
||||
vi->brk = LOMEM_BASE;
|
||||
|
||||
stack_base = Vm86AllocateMemory(vi, STACK_SIZE);
|
||||
if(stack_base == ALLOC_FAIL)
|
||||
goto unmapfail;
|
||||
ret_code = Vm86AllocateMemory(vi, sizeof(retcode_data));
|
||||
if(ret_code == ALLOC_FAIL)
|
||||
goto unmapfail;
|
||||
|
||||
vi->stack_base = stack_base;
|
||||
vi->ret_code = ret_code;
|
||||
|
||||
memset(&vi->vms, 0, sizeof(struct vm86_struct));
|
||||
vi->vms.flags = 0;
|
||||
vi->vms.screen_bitmap = 0;
|
||||
vi->vms.cpu_type = CPU_586;
|
||||
memcpy(&vi->vms.int_revectored, rev_ints, sizeof(rev_ints));
|
||||
|
||||
iopl(3);
|
||||
|
||||
if(devmem >= 0)
|
||||
close(devmem);
|
||||
if(devzero >= 0)
|
||||
close(devzero);
|
||||
|
||||
return vi;
|
||||
|
||||
unmapfail:
|
||||
munmap(magicMem, MAGICMEM_SIZE);
|
||||
munmap(loMem, LOMEM_SIZE);
|
||||
munmap(hiMem, HIMEM_SIZE);
|
||||
fail:
|
||||
if(devmem >= 0)
|
||||
close(devmem);
|
||||
if(devzero >= 0)
|
||||
close(devzero);
|
||||
if(vi)
|
||||
xfree(vi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Vm86Cleanup(Vm86InfoPtr vi)
|
||||
{
|
||||
munmap(vi->magicMem, MAGICMEM_SIZE);
|
||||
munmap(vi->loMem, LOMEM_SIZE);
|
||||
munmap(vi->hiMem, HIMEM_SIZE);
|
||||
xfree(vi);
|
||||
}
|
||||
|
||||
int
|
||||
Vm86DoInterrupt(Vm86InfoPtr vi, int num)
|
||||
{
|
||||
U16 seg, off;
|
||||
int code;
|
||||
|
||||
if(num < 0 || num>256) {
|
||||
ErrorF("Interrupt %d doesn't exist\n");
|
||||
return -1;
|
||||
}
|
||||
seg = MMW(vi,num * 4 + 2);
|
||||
off = MMW(vi,num * 4);
|
||||
if(MAKE_POINTER(seg, off) < ROM_BASE ||
|
||||
MAKE_POINTER(seg, off) >= ROM_BASE + ROM_SIZE) {
|
||||
ErrorF("Interrupt pointer doesn't point at ROM\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(&(LM(vi,vi->ret_code)), retcode_data, sizeof(retcode_data));
|
||||
vi->vms.regs.eflags = IF_MASK | IOPL_MASK;
|
||||
vi->vms.regs.ss = POINTER_SEGMENT(vi->stack_base);
|
||||
vi->vms.regs.esp = STACK_SIZE;
|
||||
PUSHW(vi, IF_MASK | IOPL_MASK);
|
||||
PUSHW(vi, POINTER_SEGMENT(vi->ret_code));
|
||||
PUSHW(vi, POINTER_OFFSET(vi->ret_code));
|
||||
vi->vms.regs.cs = seg;
|
||||
vi->vms.regs.eip = off;
|
||||
OsBlockSignals ();
|
||||
code = vm86_loop(vi);
|
||||
OsReleaseSignals ();
|
||||
if(code < 0) {
|
||||
perror("vm86 failed");
|
||||
return -1;
|
||||
} else if(code != 0) {
|
||||
ErrorF("vm86 returned 0x%04X\n", code);
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DEBUG_VBE 0
|
||||
#if DEBUG_VBE
|
||||
#define DBG(x) ErrorF x; usleep(10*1000)
|
||||
#else
|
||||
#define DBG(x)
|
||||
#endif
|
||||
|
||||
static inline U8
|
||||
vm86_inb(U16 port)
|
||||
{
|
||||
U8 value;
|
||||
|
||||
if (port != 0x3da)
|
||||
{
|
||||
DBG(("inb 0x%04x", port));
|
||||
}
|
||||
asm volatile ("inb %w1,%b0" : "=a" (value) : "d" (port));
|
||||
if (port != 0x3da)
|
||||
{
|
||||
DBG((" = 0x%02x\n", value));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline U16
|
||||
vm86_inw(U16 port)
|
||||
{
|
||||
U16 value;
|
||||
DBG(("inw 0x%04x", port));
|
||||
asm volatile ("inw %w1,%w0" : "=a" (value) : "d" (port));
|
||||
DBG((" = 0x%04x\n", value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline U32
|
||||
vm86_inl(U16 port)
|
||||
{
|
||||
U32 value;
|
||||
DBG(("inl 0x%04x", port));
|
||||
asm volatile ("inl %w1,%0" : "=a" (value) : "d" (port));
|
||||
DBG((" = 0x%08x\n", value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void
|
||||
vm86_outb(U16 port, U8 value)
|
||||
{
|
||||
#if 0
|
||||
static U8 CR;
|
||||
|
||||
if (port == 0x3d4)
|
||||
CR = value;
|
||||
if (port == 0x3d5 && CR == 0xa4)
|
||||
{
|
||||
DBG(("outb 0x%04x = 0x%02x (skipped)\n", port, value));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG(("outb 0x%04x = 0x%02x\n", port, value));
|
||||
asm volatile ("outb %b0,%w1" : : "a" (value), "d" (port));
|
||||
}
|
||||
|
||||
static inline void
|
||||
vm86_outw(U16 port, U16 value)
|
||||
{
|
||||
DBG(("outw 0x%04x = 0x%04x\n", port, value));
|
||||
asm volatile ("outw %w0,%w1" : : "a" (value), "d" (port));
|
||||
}
|
||||
|
||||
static inline void
|
||||
vm86_outl(U16 port, U32 value)
|
||||
{
|
||||
DBG(("outl 0x%04x = 0x%08x\n", port, value));
|
||||
asm volatile ("outl %0,%w1" : : "a" (value), "d" (port));
|
||||
}
|
||||
|
||||
#define SEG_CS 1
|
||||
#define SEG_DS 2
|
||||
#define SEG_ES 3
|
||||
#define SEG_SS 4
|
||||
#define SEG_GS 5
|
||||
#define SEG_FS 6
|
||||
#define REP 1
|
||||
#define REPNZ 2
|
||||
#define SET_8(_x, _y) (_x) = (_x & ~0xFF) | (_y & 0xFF);
|
||||
#define SET_16(_x, _y) (_x) = (_x & ~0xFFFF) | (_y & 0xFFFF);
|
||||
#define INC_IP(_i) SET_16(regs->eip, (regs->eip + _i))
|
||||
#define AGAIN INC_IP(1); goto again;
|
||||
|
||||
static int
|
||||
vm86_emulate(Vm86InfoPtr vi)
|
||||
{
|
||||
struct vm86_regs *regs = &vi->vms.regs;
|
||||
U8 opcode;
|
||||
int size;
|
||||
int pref_seg = 0, pref_rep = 0, pref_66 = 0, pref_67 = 0;
|
||||
U32 count;
|
||||
int code;
|
||||
|
||||
again:
|
||||
if(!Vm86IsMemory(vi, MAKE_POINTER(regs->cs, regs->eip))) {
|
||||
ErrorF("Trying to execute unmapped memory\n");
|
||||
return -1;
|
||||
}
|
||||
opcode = Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip));
|
||||
switch(opcode) {
|
||||
case 0x2E: pref_seg = SEG_CS; AGAIN;
|
||||
case 0x3E: pref_seg = SEG_DS; AGAIN;
|
||||
case 0x26: pref_seg = SEG_ES; AGAIN;
|
||||
case 0x36: pref_seg = SEG_SS; AGAIN;
|
||||
case 0x65: pref_seg = SEG_GS; AGAIN;
|
||||
case 0x64: pref_seg = SEG_FS; AGAIN;
|
||||
case 0x66: pref_66 = 1; AGAIN;
|
||||
case 0x67: pref_67 = 1; AGAIN;
|
||||
case 0xF2: pref_rep = REPNZ; AGAIN;
|
||||
case 0xF3: pref_rep = REP; AGAIN;
|
||||
|
||||
case 0xEC: /* IN AL, DX */
|
||||
SET_8(regs->eax, vm86_inb(regs->edx & 0xFFFF));
|
||||
INC_IP(1);
|
||||
break;
|
||||
case 0xED: /* IN AX, DX */
|
||||
if(pref_66)
|
||||
regs->eax = vm86_inl(regs->edx & 0xFFFF);
|
||||
else
|
||||
SET_16(regs->eax, vm86_inw(regs->edx & 0xFFFF));
|
||||
INC_IP(1);
|
||||
break;
|
||||
case 0xE4: /* IN AL, imm8 */
|
||||
SET_8(regs->eax,
|
||||
vm86_inb(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1))));
|
||||
INC_IP(2);
|
||||
break;
|
||||
case 0xE5: /* IN AX, imm8 */
|
||||
if(pref_66)
|
||||
regs->eax =
|
||||
vm86_inl(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)));
|
||||
else
|
||||
SET_16(regs->eax,
|
||||
vm86_inw(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1))));
|
||||
INC_IP(2);
|
||||
break;
|
||||
case 0x6C: /* INSB */
|
||||
case 0x6D: /* INSW */
|
||||
if(opcode == 0x6C) {
|
||||
Vm86WriteMemory(vi, MAKE_POINTER(regs->es, regs->edi),
|
||||
vm86_inb(regs->edx & 0xFFFF));
|
||||
size = 1;
|
||||
} else if(pref_66) {
|
||||
Vm86WriteMemoryL(vi, MAKE_POINTER(regs->es, regs->edi),
|
||||
vm86_inl(regs->edx & 0xFFFF));
|
||||
size = 4;
|
||||
} else {
|
||||
Vm86WriteMemoryW(vi, MAKE_POINTER(regs->es, regs->edi),
|
||||
vm86_inw(regs->edx & 0xFFFF));
|
||||
size = 2;
|
||||
}
|
||||
if(regs->eflags & (1<<10))
|
||||
regs->edi -= size;
|
||||
else
|
||||
regs->edi += size;
|
||||
if(pref_rep) {
|
||||
if(pref_66) {
|
||||
regs->ecx--;
|
||||
if(regs->ecx != 0) {
|
||||
goto again;
|
||||
} else {
|
||||
SET_16(regs->ecx, regs->ecx - 1);
|
||||
if(regs->ecx & 0xFFFF != 0)
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
INC_IP(1);
|
||||
break;
|
||||
|
||||
case 0xEE: /* OUT DX, AL */
|
||||
vm86_outb(regs->edx & 0xFFFF, regs->eax & 0xFF);
|
||||
INC_IP(1);
|
||||
break;
|
||||
case 0xEF: /* OUT DX, AX */
|
||||
if(pref_66)
|
||||
vm86_outl(regs->edx & 0xFFFF, regs->eax);
|
||||
else
|
||||
vm86_outw(regs->edx & 0xFFFF, regs->eax & 0xFFFF);
|
||||
INC_IP(1);
|
||||
break;
|
||||
case 0xE6: /* OUT imm8, AL */
|
||||
vm86_outb(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)),
|
||||
regs->eax & 0xFF);
|
||||
INC_IP(2);
|
||||
break;
|
||||
case 0xE7: /* OUT imm8, AX */
|
||||
if(pref_66)
|
||||
vm86_outl(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)),
|
||||
regs->eax);
|
||||
else
|
||||
vm86_outw(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip+1)),
|
||||
regs->eax & 0xFFFF);
|
||||
INC_IP(2);
|
||||
break;
|
||||
case 0x6E: /* OUTSB */
|
||||
case 0x6F: /* OUTSW */
|
||||
if(opcode == 0x6E) {
|
||||
vm86_outb(regs->edx & 0xFFFF,
|
||||
Vm86Memory(vi, MAKE_POINTER(regs->es, regs->edi)));
|
||||
size = 1;
|
||||
} else if(pref_66) {
|
||||
vm86_outl(regs->edx & 0xFFFF,
|
||||
Vm86Memory(vi, MAKE_POINTER(regs->es, regs->edi)));
|
||||
size = 4;
|
||||
} else {
|
||||
vm86_outw(regs->edx & 0xFFFF,
|
||||
Vm86Memory(vi, MAKE_POINTER(regs->es, regs->edi)));
|
||||
size = 2;
|
||||
}
|
||||
if(regs->eflags & (1<<10))
|
||||
regs->edi -= size;
|
||||
else
|
||||
regs->edi += size;
|
||||
if(pref_rep) {
|
||||
if(pref_66) {
|
||||
regs->ecx--;
|
||||
if(regs->ecx != 0) {
|
||||
goto again;
|
||||
} else {
|
||||
SET_16(regs->ecx, regs->ecx - 1);
|
||||
if(regs->ecx & 0xFFFF != 0)
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
INC_IP(1);
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
ErrorF("Hit 0F trap in VM86 code\n");
|
||||
return -1;
|
||||
case 0xF0:
|
||||
ErrorF("Hit lock prefix in VM86 code\n");
|
||||
return -1;
|
||||
case 0xF4:
|
||||
ErrorF("Hit HLT in VM86 code\n");
|
||||
return -1;
|
||||
|
||||
default:
|
||||
ErrorF("Unhandled GP fault in VM86 code (opcode = 0x%02X)\n",
|
||||
opcode);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#undef SEG_CS
|
||||
#undef SEG_DS
|
||||
#undef SEG_ES
|
||||
#undef SEG_SS
|
||||
#undef SEG_GS
|
||||
#undef SEG_FS
|
||||
#undef REP
|
||||
#undef REPNZ
|
||||
#undef SET_8
|
||||
#undef SET_16
|
||||
#undef INC_IP
|
||||
#undef AGAIN
|
||||
|
||||
static int
|
||||
vm86_loop(Vm86InfoPtr vi)
|
||||
{
|
||||
int code;
|
||||
|
||||
while(1) {
|
||||
code = vm86old(&vi->vms);
|
||||
switch(VM86_TYPE(code)) {
|
||||
case VM86_SIGNAL:
|
||||
continue;
|
||||
case VM86_UNKNOWN:
|
||||
code = vm86_emulate(vi);
|
||||
if(code < 0) {
|
||||
Vm86Debug(vi);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case VM86_INTx:
|
||||
if(VM86_ARG(code) == 0xFF)
|
||||
return 0;
|
||||
else {
|
||||
PUSHW(vi, vi->vms.regs.eflags)
|
||||
PUSHW(vi, vi->vms.regs.cs);
|
||||
PUSHW(vi, vi->vms.regs.eip);
|
||||
vi->vms.regs.cs = MMW(vi,VM86_ARG(code) * 4 + 2);
|
||||
vi->vms.regs.eip = MMW(vi,VM86_ARG(code) * 4);
|
||||
}
|
||||
break;
|
||||
case VM86_STI:
|
||||
ErrorF("VM86 code enabled interrupts\n");
|
||||
Vm86Debug(vi);
|
||||
return -1;
|
||||
default:
|
||||
ErrorF("Unexpected result code 0x%X from vm86\n", code);
|
||||
Vm86Debug(vi);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Vm86IsMemory(Vm86InfoPtr vi, U32 i)
|
||||
{
|
||||
if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
|
||||
return 1;
|
||||
else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
|
||||
return 1;
|
||||
else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
U8
|
||||
Vm86Memory(Vm86InfoPtr vi, U32 i)
|
||||
{
|
||||
if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
|
||||
return MM(vi, i);
|
||||
else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
|
||||
return LM(vi, i);
|
||||
else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
|
||||
return HM(vi, i);
|
||||
else {
|
||||
ErrorF("Reading unmapped memory at 0x%08X\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
U16
|
||||
Vm86MemoryW(Vm86InfoPtr vi, U32 i)
|
||||
{
|
||||
if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
|
||||
return MMW(vi, i);
|
||||
else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
|
||||
return LMW(vi, i);
|
||||
else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
|
||||
return HMW(vi, i);
|
||||
else {
|
||||
ErrorF("Reading unmapped memory at 0x%08X\n", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
U32
|
||||
Vm86MemoryL(Vm86InfoPtr vi, U32 i)
|
||||
{
|
||||
if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
|
||||
return MML(vi, i);
|
||||
else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
|
||||
return LML(vi, i);
|
||||
else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
|
||||
return HML(vi, i);
|
||||
else {
|
||||
ErrorF("Reading unmapped memory at 0x%08X\n", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vm86WriteMemory(Vm86InfoPtr vi, U32 i, U8 val)
|
||||
{
|
||||
if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
|
||||
MM(vi, i) = val;
|
||||
else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
|
||||
LM(vi, i) = val;
|
||||
else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
|
||||
HM(vi, i) = val;
|
||||
else {
|
||||
ErrorF("Writing unmapped memory at 0x%08X\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vm86WriteMemoryW(Vm86InfoPtr vi, U32 i, U16 val)
|
||||
{
|
||||
if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
|
||||
MMW(vi, i) = val;
|
||||
else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
|
||||
LMW(vi, i) = val;
|
||||
else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
|
||||
HMW(vi, i) = val;
|
||||
else {
|
||||
ErrorF("Writing unmapped memory at 0x%08X\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vm86WriteMemoryL(Vm86InfoPtr vi, U32 i, U32 val)
|
||||
{
|
||||
if(i >= MAGICMEM_BASE && i< MAGICMEM_BASE + MAGICMEM_SIZE)
|
||||
MML(vi, i) = val;
|
||||
else if(i >= LOMEM_BASE && i< LOMEM_BASE + LOMEM_SIZE)
|
||||
LML(vi, i) = val;
|
||||
else if(i >= HIMEM_BASE && i< HIMEM_BASE + HIMEM_SIZE)
|
||||
HML(vi, i) = val;
|
||||
else {
|
||||
ErrorF("Writing unmapped memory at 0x%08X\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Vm86AllocateMemory(Vm86InfoPtr vi, int n)
|
||||
{
|
||||
int ret;
|
||||
if(n<0) {
|
||||
ErrorF("Asked to allocate negative amount of memory\n");
|
||||
return vi->brk;
|
||||
}
|
||||
|
||||
n = (n + 15) & ~15;
|
||||
if(vi->brk + n > LOMEM_BASE + LOMEM_SIZE) {
|
||||
ErrorF("Out of low memory\n");
|
||||
exit(2);
|
||||
}
|
||||
ret = vi->brk;
|
||||
vi->brk += n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
Vm86MarkMemory (Vm86InfoPtr vi)
|
||||
{
|
||||
return vi->brk;
|
||||
}
|
||||
|
||||
void
|
||||
Vm86ReleaseMemory (Vm86InfoPtr vi, int mark)
|
||||
{
|
||||
vi->brk = mark;
|
||||
}
|
||||
|
||||
static int
|
||||
vm86old(struct vm86_struct *vm)
|
||||
{
|
||||
int res;
|
||||
|
||||
asm volatile (
|
||||
"pushl %%ebx\n\t"
|
||||
"movl %2, %%ebx\n\t"
|
||||
"movl %1,%%eax\n\t"
|
||||
"int $0x80\n\t"
|
||||
"popl %%ebx"
|
||||
: "=a" (res) : "n" (113), "r" (vm));
|
||||
if(res < 0) {
|
||||
errno = -res;
|
||||
res = -1;
|
||||
} else
|
||||
errno = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
Vm86Debug(Vm86InfoPtr vi)
|
||||
{
|
||||
struct vm86_regs *regs = &vi->vms.regs;
|
||||
int i;
|
||||
|
||||
ErrorF("eax=0x%08lX ebx=0x%08lX ecx=0x%08lX edx=0x%08lX\n",
|
||||
regs->eax, regs->ebx, regs->ecx, regs->edx);
|
||||
ErrorF("esi=0x%08lX edi=0x%08lX ebp=0x%08lX\n",
|
||||
regs->esi, regs->edi, regs->ebp);
|
||||
ErrorF("eip=0x%08lX esp=0x%08lX eflags=0x%08lX\n",
|
||||
regs->eip, regs->esp, regs->eflags);
|
||||
ErrorF("cs=0x%04lX ds=0x%04lX es=0x%04lX fs=0x%04lX gs=0x%04lX\n",
|
||||
regs->cs, regs->ds, regs->es, regs->fs, regs->gs);
|
||||
for(i=-7; i<8; i++) {
|
||||
ErrorF(" %s%02X",
|
||||
i==0?"->":"",
|
||||
Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip + i)));
|
||||
}
|
||||
ErrorF("\n");
|
||||
}
|
||||
|
||||
#ifdef NOT_IN_X_SERVER
|
||||
static void
|
||||
ErrorF(char *f, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, f);
|
||||
vfprintf(stderr, f, args);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
165
hw/kdrive/vesa/vm86.h
Normal file
165
hw/kdrive/vesa/vm86.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* $XFree86$
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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.
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2000 by Juliusz Chroboczek
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _VM86_H_
|
||||
#define _VM86_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/vm86.h>
|
||||
#include <sys/io.h>
|
||||
|
||||
#ifdef NOT_IN_X_SERVER
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <malloc.h>
|
||||
static void ErrorF(char*, ...);
|
||||
#define xalloc(a) malloc(a)
|
||||
#define xcalloc(a,b) calloc(a,b)
|
||||
#define xfree(a) free(a)
|
||||
#else
|
||||
#include "X.h"
|
||||
#include "Xproto.h"
|
||||
#include "Xos.h"
|
||||
#include "os.h"
|
||||
#endif
|
||||
|
||||
typedef unsigned char U8;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
|
||||
/* The whole addressable memory */
|
||||
#define SYSMEM_BASE 0x00000
|
||||
#define SYSMEM_SIZE 0x100000
|
||||
|
||||
/* Interrupt vectors and BIOS data area */
|
||||
/* This is allocated privately from /dev/mem */
|
||||
#define MAGICMEM_BASE 0x00000
|
||||
#define MAGICMEM_SIZE 0x01000
|
||||
|
||||
/* The low memory, allocated privately from /dev/zero */
|
||||
/* 64KB should be enough for anyone, as they used to say */
|
||||
#define LOMEM_BASE 0x10000
|
||||
#define LOMEM_SIZE 0x10000
|
||||
|
||||
/* The video memory and BIOS ROM, allocated shared from /dev/mem */
|
||||
#define HIMEM_BASE 0xA0000
|
||||
#define HIMEM_SIZE (SYSMEM_BASE + SYSMEM_SIZE - HIMEM_BASE)
|
||||
|
||||
/* The BIOS ROM */
|
||||
#define ROM_BASE 0xC0000
|
||||
#define ROM_SIZE 0x30000
|
||||
|
||||
#define STACK_SIZE 0x1000
|
||||
|
||||
#define POINTER_SEGMENT(ptr) (((unsigned int)ptr)>>4)
|
||||
#define POINTER_OFFSET(ptr) (((unsigned int)ptr)&0x000F)
|
||||
#define MAKE_POINTER(seg, off) (((((unsigned int)(seg))<<4) + (unsigned int)(off)))
|
||||
#define MAKE_POINTER_1(lw) MAKE_POINTER(((lw)&0xFFFF0000)/0x10000, (lw)&0xFFFF)
|
||||
#define ALLOC_FAIL ((U32)-1)
|
||||
|
||||
typedef struct _Vm86InfoRec {
|
||||
void *magicMem, *loMem, *hiMem;
|
||||
U32 brk;
|
||||
struct vm86_struct vms;
|
||||
U32 ret_code, stack_base;
|
||||
} Vm86InfoRec, *Vm86InfoPtr;
|
||||
|
||||
#define LM(vi,i) (((char*)vi->loMem)[i-LOMEM_BASE])
|
||||
#define LMW(vi,i) (*(U16*)(&LM(vi,i)))
|
||||
#define LML(vi,i) (*(U32*)(&LM(vi,i)))
|
||||
#define MM(vi,i) (((char*)vi->magicMem)[i-MAGICMEM_BASE])
|
||||
#define MMW(vi,i) (*(U16*)(&MM(vi,i)))
|
||||
#define MML(vi,i) (*(U32*)(&MM(vi,i)))
|
||||
#define HM(vi,i) (((char*)vi->hiMem)[i-HIMEM_BASE])
|
||||
#define HMW(vi,i) (*(U16*)(&MM(vi,i)))
|
||||
#define HML(vi,i) (*(U32*)(&MM(vi,i)))
|
||||
|
||||
Vm86InfoPtr
|
||||
Vm86Setup(void);
|
||||
|
||||
void
|
||||
Vm86Cleanup(Vm86InfoPtr vi);
|
||||
|
||||
int
|
||||
Vm86DoInterrupt(Vm86InfoPtr vi, int num);
|
||||
|
||||
int
|
||||
Vm86IsMemory(Vm86InfoPtr vi, U32 i);
|
||||
|
||||
U8
|
||||
Vm86Memory(Vm86InfoPtr, U32);
|
||||
|
||||
U16
|
||||
Vm86MemoryW(Vm86InfoPtr, U32);
|
||||
|
||||
U32
|
||||
Vm86MemoryL(Vm86InfoPtr, U32);
|
||||
|
||||
void
|
||||
Vm86WriteMemory(Vm86InfoPtr, U32, U8);
|
||||
|
||||
void
|
||||
Vm86WriteMemoryW(Vm86InfoPtr, U32, U16);
|
||||
|
||||
void
|
||||
Vm86WriteMemoryL(Vm86InfoPtr, U32, U32);
|
||||
|
||||
int
|
||||
Vm86AllocateMemory(Vm86InfoPtr, int);
|
||||
|
||||
int
|
||||
Vm86MarkMemory (Vm86InfoPtr vi);
|
||||
|
||||
void
|
||||
Vm86ReleaseMemory (Vm86InfoPtr vi, int mark);
|
||||
|
||||
void
|
||||
Vm86Debug(Vm86InfoPtr vi);
|
||||
|
||||
#endif /* _VM86_H_ */
|
Loading…
Reference in New Issue
Block a user