summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2000-10-20 00:19:51 +0000
committerKeith Packard <keithp@keithp.com>2000-10-20 00:19:51 +0000
commit8f634a6516caca0e4be875e696820a820e480cff (patch)
tree05a2cbcde355e23de13fa64e64ea8ec6e340e8fd
parentf16d5d6817f15be35293ee995d073eb57fafe283 (diff)
Add VGA BIOS modes to Tiny-X Xvesa serverxf-4_0_1fxf-4_0_1exf-4_0_1d
-rw-r--r--hw/kdrive/trident/Imakefile4
-rw-r--r--hw/kdrive/trident/trident.c48
-rw-r--r--hw/kdrive/trident/trident.h5
-rw-r--r--hw/kdrive/vesa/Imakefile6
-rw-r--r--hw/kdrive/vesa/Xvesa.man25
-rw-r--r--hw/kdrive/vesa/vbe.c1344
-rw-r--r--hw/kdrive/vesa/vbe.h141
-rw-r--r--hw/kdrive/vesa/vesa.c880
-rw-r--r--hw/kdrive/vesa/vesa.h123
-rw-r--r--hw/kdrive/vesa/vesainit.c2
-rw-r--r--hw/kdrive/vesa/vga.c240
-rw-r--r--hw/kdrive/vesa/vga.h61
-rw-r--r--hw/kdrive/vesa/vm86.c697
-rw-r--r--hw/kdrive/vesa/vm86.h165
14 files changed, 2339 insertions, 1402 deletions
diff --git a/hw/kdrive/trident/Imakefile b/hw/kdrive/trident/Imakefile
index 838cca4d1..1f881a49d 100644
--- a/hw/kdrive/trident/Imakefile
+++ b/hw/kdrive/trident/Imakefile
@@ -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
diff --git a/hw/kdrive/trident/trident.c b/hw/kdrive/trident/trident.c
index df4e6cde9..7c8c9cc69 100644
--- a/hw/kdrive/trident/trident.c
+++ b/hw/kdrive/trident/trident.c
@@ -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;
}
diff --git a/hw/kdrive/trident/trident.h b/hw/kdrive/trident/trident.h
index 15b64a01f..46ba6c0f6 100644
--- a/hw/kdrive/trident/trident.h
+++ b/hw/kdrive/trident/trident.h
@@ -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;
diff --git a/hw/kdrive/vesa/Imakefile b/hw/kdrive/vesa/Imakefile
index b891e70b3..4a30f94a0 100644
--- a/hw/kdrive/vesa/Imakefile
+++ b/hw/kdrive/vesa/Imakefile
@@ -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)
diff --git a/hw/kdrive/vesa/Xvesa.man b/hw/kdrive/vesa/Xvesa.man
index 958934aa9..766ac8145 100644
--- a/hw/kdrive/vesa/Xvesa.man
+++ b/hw/kdrive/vesa/Xvesa.man
@@ -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.
diff --git a/hw/kdrive/vesa/vbe.c b/hw/kdrive/vesa/vbe.c
index fa2fbeaa3..d4a2817c8 100644
--- a/hw/kdrive/vesa/vbe.c
+++ b/hw/kdrive/vesa/vbe.c
@@ -19,539 +19,409 @@ 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.
*/
-/* $XFree86$ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/vesa/vbe.c,v 1.5 2000/09/27 20:46:37 keithp Exp $ */
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/vm86.h>
-#include <sys/io.h>
-#include "vbe.h"
+#include "vesa.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
-
-static int vm86old(struct vm86_struct *vms);
-static int vm86_loop(VbeInfoPtr vi);
-
-static 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 U8 retcode_data[2] =
-{ 0xCD, 0xFF };
-
-#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)))
-
-#define PUSHW(vi, i) \
-{ vi->vms.regs.esp -= 2;\
- LMW(vi,MAKE_POINTER(vi->vms.regs.ss, vi->vms.regs.esp)) = i;}
-
-VbeInfoPtr
-VbeSetup()
+int
+VbeGetVib (Vm86InfoPtr vi, VbeInfoBlock *vib)
{
- int devmem = -1, devzero = -1;
- void *magicMem, *loMem, *hiMem;
- U32 stack_base, vib_base, vmib_base, ret_code;
- VbeInfoPtr 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;
+ int code;
+ int mark;
+ int vib_base;
+ VbeInfoBlock *vib_low;
+
+ mark = Vm86MarkMemory (vi);
+ vib_base = Vm86AllocateMemory (vi, sizeof (VbeInfoBlock));
+ vib_low = (VbeInfoBlock*)&(LM(vi, vib_base));
+ vi->vms.regs.eax = 0x4F00;
+ vi->vms.regs.es = POINTER_SEGMENT(vib_base);
+ vi->vms.regs.edi = POINTER_OFFSET(vib_base);
+ memcpy(vib_low->VbeSignature, "VBE2", 4);
+ code = VbeDoInterrupt10(vi);
+ if(code >= 0)
+ {
+ if(memcmp(vib_low->VbeSignature, "VESA", 4) == 0)
+ *vib = *vib_low;
+ else
+ code = -1;
}
+ Vm86ReleaseMemory (vi, mark);
+ return code;
+}
- vi = xalloc(sizeof(VbeInfoRec));
- if (!vi)
- goto unmapfail;
-
- vi->devmem = devmem;
- vi->devzero = devzero;
- vi->magicMem = magicMem;
- vi->loMem = loMem;
- vi->hiMem = hiMem;
- vi->brk = LOMEM_BASE;
-
- stack_base = VbeAllocateMemory(vi, STACK_SIZE);
- if(stack_base == ALLOC_FAIL)
- goto unmapfail;
- ret_code = VbeAllocateMemory(vi, sizeof(retcode_data));
- if(ret_code == ALLOC_FAIL)
- goto unmapfail;
- vib_base = VbeAllocateMemory(vi, sizeof(VbeInfoBlock));
- if(vib_base == ALLOC_FAIL)
- goto unmapfail;
- vmib_base = VbeAllocateMemory(vi, sizeof(VbeModeInfoBlock));
- if(vmib_base == ALLOC_FAIL)
- goto unmapfail;
-
- vi->stack_base = stack_base;
- vi->ret_code = ret_code;
- vi->vib_base = vib_base;
- vi->vmib_base = vmib_base;
- vi->statebuffer_base = ~0;
- vi->palette_scratch_base = ~0;
- vi->palette_format = 6;
- vi->palette_wait = 0;
- vi->windowA_offset = vi->windowB_offset = -1;
- vi->last_window = 1;
- vi->vga_palette = 1;
+int
+VbeGetVmib (Vm86InfoPtr vi, int mode, VbeModeInfoBlock *vmib)
+{
+ int code;
+ int mark;
+ int vib_base;
+ int vmib_base;
+ VbeModeInfoBlock *vmib_low;
- 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));
-
- ioperm(0, 0x400, 1);
- iopl(3);
-
- 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;
+ mark = Vm86MarkMemory (vi);
+
+ vmib_base = Vm86AllocateMemory (vi, sizeof (VbeModeInfoBlock));
+ vmib_low = (VbeModeInfoBlock*)&(LM(vi, vmib_base));
+
+ vi->vms.regs.eax = 0x4F01;
+ vi->vms.regs.ecx = mode&0xFFFF;
+ vi->vms.regs.es = POINTER_SEGMENT(vmib_base);
+ vi->vms.regs.edi = POINTER_OFFSET(vmib_base);
+ code = VbeDoInterrupt10(vi);
+
+ if(code >= 0)
+ *vmib = *vmib_low;
+ Vm86ReleaseMemory (vi, mark);
+ return code;
}
void
-VbeCleanup(VbeInfoPtr vi)
+VbeReportInfo (Vm86InfoPtr vi)
{
- munmap(vi->magicMem, MAGICMEM_SIZE);
- munmap(vi->loMem, LOMEM_SIZE);
- munmap(vi->hiMem, HIMEM_SIZE);
- close (vi->devmem);
- close (vi->devzero);
- xfree(vi);
-}
+ VbeInfoBlock vib;
+ int code;
-VbeInfoBlock *
-VbeGetInfo(VbeInfoPtr vi)
-{
- int code;
- VbeInfoBlock *vib = (VbeInfoBlock*)&(LM(vi, vi->vib_base));
- vi->vms.regs.eax = 0x4F00;
- vi->vms.regs.es = POINTER_SEGMENT(vi->vib_base);
- vi->vms.regs.edi = POINTER_OFFSET(vi->vib_base);
- memcpy(vib->VbeSignature, "VBE2", 4);
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return NULL;
- if(memcmp(vib->VbeSignature, "VESA", 4) != 0) {
- ErrorF("Int 10 didn't return VESA signature in info block");
- return NULL;
- }
- return vib;
+ code = VbeGetVib (vi, &vib);
+ if (code >= 0)
+ VbeReportVib(vi, &vib);
}
-VbeModeInfoBlock *
-VbeGetModeInfo(VbeInfoPtr vi, int mode)
+int
+VbeGetNmode (Vm86InfoPtr vi)
{
- int code;
- U32 p;
- VbeInfoBlock *vib = (VbeInfoBlock*)&(LM(vi, vi->vib_base));
- VbeModeInfoBlock *vmib = (VbeModeInfoBlock*)&(LM(vi, vi->vmib_base));
- p = MAKE_POINTER_1(vib->VideoModePtr);
- if(!VbeIsMemory(vi, p)) {
- ErrorF("VideoModePtr 0x%08X doesn't point at low memory\n",
- vib->VideoModePtr);
- return NULL;
+ VbeInfoBlock vib;
+ int code;
+ int ret = 0;
+ unsigned int p;
+ int n;
+ int mode;
+
+ code = VbeGetVib (vi, &vib);
+ if (code >= 0)
+ {
+ p = MAKE_POINTER_1(vib.VideoModePtr);
+ for (n = 0; ; n++)
+ {
+ mode = Vm86MemoryW(vi, p);
+ if (mode == 0xffff)
+ break;
+ p += 2;
+ }
+ code = n;
}
- vi->vms.regs.eax = 0x4F01;
- vi->vms.regs.ecx = mode&0xFFFF;
- vi->vms.regs.es = POINTER_SEGMENT(vi->vmib_base);
- vi->vms.regs.edi = POINTER_OFFSET(vi->vmib_base);
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return NULL;
- else
- return vmib;
+ return code;
}
int
-VbeSetMode(VbeInfoPtr vi, int mode, int linear)
+VbeGetModes (Vm86InfoPtr vi, VesaModePtr modes, int nmode)
{
- int code;
+ VbeInfoBlock vib;
+ int code;
+ int ret = 0;
+ unsigned int p;
+ int n;
+ int mode;
+ VbeModeInfoBlock vmib;
- vi->windowA_offset = vi->windowB_offset = -1;
- vi->last_window = 1;
+ code = VbeGetVib (vi, &vib);
+ if (code < 0)
+ return code;
+
+ memset (modes, '\0', n * sizeof (VesaModeRec));
- vi->vms.regs.eax = 0x4F02;
- vi->vms.regs.ebx = (mode & 0xFFFF) | 0x8000;
- if(linear)
- vi->vms.regs.ebx |= 0x4000;
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return -1;
- return 0;
+ p = MAKE_POINTER_1(vib.VideoModePtr);
+ for (n = 0; n < nmode; n++)
+ {
+ mode = Vm86MemoryW(vi, p);
+ if (mode == 0xffff)
+ break;
+ modes[n].mode = mode;
+ modes[n].vbe = 1;
+ p += 2;
+ }
+
+ nmode = n;
+
+ for (n = 0; n < nmode; n++)
+ {
+ code = VbeGetVmib (vi, modes[n].mode, &vmib);
+ if (code >= 0)
+ {
+ modes[n].ModeAttributes = vmib.ModeAttributes;
+ modes[n].NumberOfPlanes = vmib.NumberOfPlanes;
+ modes[n].BitsPerPixel = vmib.BitsPerPixel;
+ modes[n].MemoryModel = vmib.MemoryModel;
+ modes[n].RedMaskSize = vmib.RedMaskSize;
+ modes[n].RedFieldPosition = vmib.RedFieldPosition;
+ modes[n].GreenMaskSize = vmib.GreenMaskSize;
+ modes[n].GreenFieldPosition = vmib.GreenFieldPosition;
+ modes[n].BlueMaskSize = vmib.BlueMaskSize;
+ modes[n].BlueFieldPosition = vmib.BlueFieldPosition;
+ modes[n].RsvdMaskSize = vmib.RsvdMaskSize;
+ modes[n].RsvdFieldPosition = vmib.RsvdFieldPosition;
+ modes[n].DirectColorModeInfo = vmib.DirectColorModeInfo;
+ modes[n].XResolution = vmib.XResolution;
+ modes[n].YResolution = vmib.YResolution;
+ modes[n].BytesPerScanLine = vmib.BytesPerScanLine;
+ }
+ }
+
+ return nmode;
}
-int
-VbeGetMode(VbeInfoPtr vi, int *mode)
+VbeInfoPtr
+VbeInit (Vm86InfoPtr vi)
{
- int code;
- vi->vms.regs.eax = 0x4F03;
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return - 1;
- *mode = vi->vms.regs.ebx & 0xFFFF;
- return 0;
-}
+ VbeInfoPtr vbe;
+ int code;
+ VbeInfoBlock vib;
-int
-VbeSetupStateBuffer(VbeInfoPtr vi)
-{
- int code;
- if(vi->statebuffer_base != ~0)
- return 0;
- vi->vms.regs.eax = 0x4F04;
- vi->vms.regs.edx = 0x0000;
- vi->vms.regs.ecx = 0x000F;
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return -1;
- vi->statebuffer_base = VbeAllocateMemory(vi, vi->vms.regs.ebx & 0xFFFF);
- return 0;
+ code = VbeGetVib (vi, &vib);
+ if (code < 0)
+ return 0;
+
+ vbe = xalloc (sizeof (VbeInfoRec));
+ if (!vbe)
+ return 0;
+ vbe->palette_format = 6;
+ vbe->palette_wait = TRUE;
+ return vbe;
}
-int
-VbeSaveState(VbeInfoPtr vi)
+void
+VbeCleanup (Vm86InfoPtr vi, VbeInfoPtr vbe)
{
- int code;
- code = VbeSetupStateBuffer(vi);
- if(code < 0)
- return -1;
- vi->vms.regs.eax = 0x4F04;
- vi->vms.regs.edx = 0x0001;
- vi->vms.regs.ecx = 0x000F;
- vi->vms.regs.es = POINTER_SEGMENT(vi->statebuffer_base);
- vi->vms.regs.ebx = POINTER_OFFSET(vi->statebuffer_base);
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return -1;
- return 0;
+ xfree (vbe);
}
int
-VbeRestoreState(VbeInfoPtr vi)
+VbeSetMode (Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, int linear)
{
- int code;
- vi->vms.regs.eax = 0x4F04;
- vi->vms.regs.edx = 0x0002;
- vi->vms.regs.ecx = 0x000F;
- vi->vms.regs.es = POINTER_SEGMENT(vi->statebuffer_base);
- vi->vms.regs.ebx = POINTER_OFFSET(vi->statebuffer_base);
+ int code;
+ VbeInfoBlock vib;
+ int palette_wait = 0, palette_hi = 0;
+
+ code = VbeGetVib (vi, &vib);
+ if (code < 0)
+ return -1;
+
+ code = VbeGetVmib (vi, mode, &vbe->vmib);
+ if (code < 0)
+ return -1;
+
+ mode = (mode & 0xffff) | 0x8000;
+ if (linear)
+ mode |= 0x4000;
+
+ vi->vms.regs.eax = 0x4F02;
+ vi->vms.regs.ebx = mode;
code = VbeDoInterrupt10(vi);
if(code < 0)
return -1;
+
+ vbe->windowA_offset = vbe->windowB_offset = -1;
+ vbe->last_window = 1;
+
+ if(vib.Capabilities[0] & 1)
+ palette_hi = 1;
+ if(vib.Capabilities[0] & 4)
+ palette_wait = 1;
+
+ if(palette_hi || palette_wait)
+ VbeSetPaletteOptions(vi, vbe, palette_hi?8:6, palette_wait);
+
return 0;
}
-int
-VbeSetTextMode(VbeInfoPtr vi, int mode)
+int
+VbeGetMode(Vm86InfoPtr vi, int *mode)
{
int code;
- vi->vms.regs.eax = mode & 0x7f;
+ vi->vms.regs.eax = 0x4F03;
code = VbeDoInterrupt10(vi);
if(code < 0)
- return -1;
+ return - 1;
+ *mode = vi->vms.regs.ebx & 0xFFFF;
return 0;
}
void *
-VbeMapFramebuffer(VbeInfoPtr vi,
- VbeModeInfoBlock *vmib)
-{
- U8 *fb;
- VbeInfoBlock *vib = (VbeInfoBlock*)&(LM(vi, vi->vib_base));
- int size;
- int pagesize = getpagesize(), before, after;
-
- size = 1024 * 64L * vib->TotalMemory;
+VbeMapFramebuffer(Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, int *ret_size)
+{
+ U8 *fb;
+ VbeInfoBlock vib;
+ VbeModeInfoBlock vmib;
+ int size;
+ int pagesize = getpagesize();
+ int before, after;
+ int devmem;
+
+ if (VbeGetVib (vi, &vib) < 0)
+ return 0;
+
+ if (VbeGetVmib (vi, mode, &vmib) < 0)
+ return 0;
+
+ size = 1024 * 64L * vib.TotalMemory;
+
+ *ret_size = size;
- before = vmib->PhysBasePtr % pagesize;
- after = pagesize - ((vmib->PhysBasePtr + size) % pagesize);
+ before = vmib.PhysBasePtr % pagesize;
+ after = pagesize - ((vmib.PhysBasePtr + size) % pagesize);
if(after == pagesize)
after = 0;
- fb = mmap(0, before + size + after,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- vi->devmem, vmib->PhysBasePtr - before);
- if(fb == MAP_FAILED) {
- ErrorF("Failed to map framebuffer: %d\n", errno);
+ fb = KdMapDevice (vmib.PhysBasePtr - before, before + size + after);
+
+ if(fb == 0)
+ {
+ ErrorF("Failed to map framebuffer\n");
return NULL;
}
return fb + before;
}
-int
-VbeUnmapFramebuffer(VbeInfoPtr vi,
- VbeModeInfoBlock *vmib,
- void *fb)
+void
+VbeUnmapFramebuffer(Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, void *fb)
{
- int code;
- VbeInfoBlock *vib = (VbeInfoBlock*)&(LM(vi, vi->vib_base));
- int size;
- int pagesize = getpagesize(), before, after;
+ VbeInfoBlock vib;
+ VbeModeInfoBlock vmib;
+ int size;
+ int pagesize = getpagesize();
+ int before, after;
- size = 1024 * 64L * vib->TotalMemory;
+ if (VbeGetVib (vi, &vib) < 0)
+ return;
+
+ if (VbeGetVmib (vi, mode, &vmib) < 0)
+ return;
+
+ size = 1024 * 64L * vib.TotalMemory;
- before = vmib->PhysBasePtr % pagesize;
- after = pagesize - ((vmib->PhysBasePtr + size) % pagesize);
+ before = vmib.PhysBasePtr % pagesize;
+ after = pagesize - ((vmib.PhysBasePtr + size) % pagesize);
if(after == pagesize)
after = 0;
fb = (void *) ((char *) fb - before);
- code = munmap(fb, before + size + after);
- if(code) {
- ErrorF("Couldn't unmap framebuffer: %d\n", errno);
- return -1;
- }
- return 0;
-}
-
-static int
-PreparePalette(VbeInfoPtr vi)
-{
- int code;
- if(vi->palette_scratch_base == ~0) {
- vi->palette_scratch_base = VbeAllocateMemory(vi, 4*256);
- if(vi->palette_scratch_base == ALLOC_FAIL) {
- ErrorF("Couldn't allocate scratch area for palette transfer\n");
- return -1;
- }
- }
- if(!vi->palette_format) {
- /* This isn't used currently */
- vi->vms.regs.eax = 0x4F08;
- vi->vms.regs.ebx = 0x01;
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return -1;
- vi->palette_format = vi->vms.regs.ebx & 0xFF;
- }
- return 0;
+ KdUnmapDevice (fb, before + size + after);
}
int
-VbeSetPalette(VbeInfoPtr vi, int first, int number, U8 *entries)
+VbeSetPalette(Vm86InfoPtr vi, VbeInfoPtr vbe, int first, int number, U8 *entries)
{
- U8 *palette_scratch;
- int i, j, code;
+ U8 *palette_scratch;
+ int mark;
+ int palette_base;
+ int i, j, code;
if(number == 0)
return 0;
- code = PreparePalette(vi);
- if(code < 0)
- return -1;
-
if(first < 0 || number < 0 || first + number > 256) {
ErrorF("Cannot set %d, %d palette entries\n", first, number);
return -1;
}
- palette_scratch = &LM(vi, vi->palette_scratch_base);
-
- if(vi->palette_format < 6 || vi->palette_format > 8) {
- ErrorF("Impossible palette format %d\n", vi->palette_format);
+ if(vbe->palette_format < 6 || vbe->palette_format > 8) {
+ ErrorF("Impossible palette format %d\n", vbe->palette_format);
return -1;
}
- if (vi->vga_palette)
- {
- vi->vms.regs.eax = 0x1012;
- vi->vms.regs.ebx = first;
- vi->vms.regs.ecx = number;
- vi->vms.regs.es = POINTER_SEGMENT(vi->palette_scratch_base);
- vi->vms.regs.edx = POINTER_OFFSET(vi->palette_scratch_base);
- j = 0;
- i = 0;
- while (number--)
- {
- palette_scratch[j++] = entries[i++] >> (8-vi->palette_format);
- palette_scratch[j++] = entries[i++] >> (8-vi->palette_format);
- palette_scratch[j++] = entries[i++] >> (8-vi->palette_format);
- i++;
- }
- }
+ mark = Vm86MarkMemory (vi);
+ palette_base = Vm86AllocateMemory (vi, 4 * 256);
+
+ palette_scratch = &LM(vi, palette_base);
+
+ for(i=0; i<number*4; i++)
+ palette_scratch[i] = entries[i] >> (8 - vbe->palette_format);
+
+ vi->vms.regs.eax = 0x4F09;
+ if(vbe->palette_wait)
+ vi->vms.regs.ebx = 0x80;
else
- {
- for(i=0; i<number*4; i++)
- palette_scratch[i] = entries[i] >> (8 - vi->palette_format);
-
- vi->vms.regs.eax = 0x4F09;
- if(vi->palette_wait)
- vi->vms.regs.ebx = 0x80;
- else
- vi->vms.regs.ebx = 0x00;
- vi->vms.regs.ecx = number;
- vi->vms.regs.edx = first;
- vi->vms.regs.es = POINTER_SEGMENT(vi->palette_scratch_base);
- vi->vms.regs.edi = POINTER_OFFSET(vi->palette_scratch_base);
- }
+ vi->vms.regs.ebx = 0x00;
+ vi->vms.regs.ecx = number;
+ vi->vms.regs.edx = first;
+ vi->vms.regs.es = POINTER_SEGMENT(palette_base);
+ vi->vms.regs.edi = POINTER_OFFSET(palette_base);
code = VbeDoInterrupt10(vi);
+ Vm86ReleaseMemory (vi, mark);
+
if(code < 0)
return -1;
return 0;
-}
+}
int
-VbeGetPalette(VbeInfoPtr vi, int first, int number, U8 *entries)
+VbeGetPalette(Vm86InfoPtr vi, VbeInfoPtr vbe, int first, int number, U8 *entries)
{
- U8 *palette_scratch;
- int i, j, code;
+ U8 *palette_scratch;
+ int mark;
+ int palette_base;
+ int i, j, code;
- code = PreparePalette(vi);
- if(code < 0)
- return -1;
+ if(number == 0)
+ return 0;
- if(first< 0 || number < 0 || first + number > 256) {
+ if(first < 0 || number < 0 || first + number > 256) {
ErrorF("Cannot get %d, %d palette entries\n", first, number);
return -1;
}
- palette_scratch = &LM(vi, vi->palette_scratch_base);
-
- if(vi->palette_format < 6 || vi->palette_format > 8) {
- ErrorF("Impossible palette format %d\n", vi->palette_format);
+ if(vbe->palette_format < 6 || vbe->palette_format > 8) {
+ ErrorF("Impossible palette format %d\n", vbe->palette_format);
return -1;
}
-retry:
- if (vi->vga_palette)
- {
- vi->vms.regs.eax = 0x1017;
- vi->vms.regs.ebx = first;
- vi->vms.regs.ecx = number;
- vi->vms.regs.es = POINTER_SEGMENT(vi->palette_scratch_base);
- vi->vms.regs.edx = POINTER_OFFSET(vi->palette_scratch_base);
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- return -1;
- j = 0;
- i = 0;
- while (number--)
- {
- entries[i++] = palette_scratch[j++] << (8-vi->palette_format);
- entries[i++] = palette_scratch[j++] << (8-vi->palette_format);
- entries[i++] = palette_scratch[j++] << (8-vi->palette_format);
- entries[i++] = 0;
- }
- }
- else
- {
- vi->vms.regs.eax = 0x4F09;
- vi->vms.regs.ebx = 0x01;
- vi->vms.regs.ecx = number;
- vi->vms.regs.edx = first;
- vi->vms.regs.es = POINTER_SEGMENT(vi->palette_scratch_base);
- vi->vms.regs.edi = POINTER_OFFSET(vi->palette_scratch_base);
- code = VbeDoInterrupt10(vi);
- if(code < 0)
- {
- vi->vga_palette = TRUE;
- goto retry;
- }
+ mark = Vm86MarkMemory (vi);
+ palette_base = Vm86AllocateMemory (vi, 4 * 256);
+ palette_scratch = &LM(vi, palette_base);
+
+ vi->vms.regs.eax = 0x4F09;
+ vi->vms.regs.ebx = 0x01;
+ vi->vms.regs.ecx = number;
+ vi->vms.regs.edx = first;
+ vi->vms.regs.es = POINTER_SEGMENT(palette_base);
+ vi->vms.regs.edi = POINTER_OFFSET(palette_base);
+ code = VbeDoInterrupt10(vi);
+ if(code >= 0)
+ {
for(i=0; i<number*4; i++)
- entries[i] = palette_scratch[i] << (8-vi->palette_format);
+ entries[i] = palette_scratch[i] << (8-vbe->palette_format);
}
+ Vm86ReleaseMemory (vi, mark);
return 0;
}
int
-VbeSetPaletteOptions(VbeInfoPtr vi, U8 bits, int wait)
+VbeSetPaletteOptions(Vm86InfoPtr vi, VbeInfoPtr vbe, U8 bits, int wait)
{
int code;
+
if(bits < 6 || bits > 8) {
- ErrorF("Impossible palette format %d\n", vi->palette_format);
+ ErrorF("Impossible palette format %d\n", bits);
return -1;
}
- if(bits != vi->palette_format) {
- vi->palette_format = 0;
+ if(bits != vbe->palette_format)
+ {
+ vbe->palette_format = 0;
vi->vms.regs.eax = 0x4F08;
vi->vms.regs.ebx = bits << 8;
code = VbeDoInterrupt10(vi);
if(code < 0)
return -1;
- vi->palette_format = bits;
+ vbe->palette_format = bits;
}
- vi->palette_wait = wait;
+ vbe->palette_wait = wait;
return 0;
}
static int
-VbeReallySetWindow(VbeInfoPtr vi, U8 window, U16 winnum)
+VbeReallySetWindow(Vm86InfoPtr vi, U8 window, U16 winnum)
{
int code;
vi->vms.regs.eax = 0x4F05;
@@ -564,82 +434,66 @@ VbeReallySetWindow(VbeInfoPtr vi, U8 window, U16 winnum)
}
void *
-VbeSetWindow(VbeInfoPtr vi, int offset, int purpose, int *size_return)
+VbeSetWindow(Vm86InfoPtr vi, VbeInfoPtr vbe, int offset, int purpose, int *size_return)
{
- VbeModeInfoBlock *vmib = (VbeModeInfoBlock*)&(LM(vi, vi->vmib_base));
- int window_size = vmib->WinSize * 1024;
+ int window_size = vbe->vmib.WinSize * 1024;
int code;
int winnum;
- if(vi->windowA_offset >= 0)
- if(vi->windowA_offset <= offset && vi->windowA_offset + window_size > offset)
- if(vmib->WinAAttributes & purpose)
- goto windowA;
+ if(vbe->windowA_offset >= 0)
+ if(vbe->windowA_offset <= offset && vbe->windowA_offset + window_size > offset)
+ if(vbe->vmib.WinAAttributes & purpose)
+ goto windowA;
- if(vi->windowB_offset >= 0)
- if(vi->windowB_offset <= offset && vi->windowB_offset + window_size > offset)
- if(vmib->WinBAttributes & purpose)
- goto windowB;
+ if(vbe->windowB_offset >= 0)
+ if(vbe->windowB_offset <= offset && vbe->windowB_offset + window_size > offset)
+ if(vbe->vmib.WinBAttributes & purpose)
+ goto windowB;
- if(!(vmib->WinBAttributes & purpose) ||
- !(vmib->WinBAttributes & VBE_WINDOW_RELOCATE))
- goto set_windowA;
+ if(!(vbe->vmib.WinBAttributes & purpose) ||
+ !(vbe->vmib.WinBAttributes & VBE_WINDOW_RELOCATE))
+ goto set_windowA;
- if(!(vmib->WinAAttributes & purpose) ||
- !(vmib->WinAAttributes & VBE_WINDOW_RELOCATE))
- goto set_windowB;
+ if(!(vbe->vmib.WinAAttributes & purpose) ||
+ !(vbe->vmib.WinAAttributes & VBE_WINDOW_RELOCATE))
+ goto set_windowB;
- if(vi->last_window)
- goto set_windowA;
+ if(vbe->last_window)
+ goto set_windowA;
else
- goto set_windowB;
+ goto set_windowB;
- set_windowA:
- winnum = offset / (vmib->WinGranularity * 1024);
+set_windowA:
+ winnum = offset / (vbe->vmib.WinGranularity * 1024);
code = VbeReallySetWindow(vi, 0, winnum);
if(code < 0) {
- ErrorF("Couldn't set window A to %d*%d\n",
- (int)winnum, (int)vmib->WinGranularity);
- return NULL;
- }
- vi->windowA_offset = winnum * vmib->WinGranularity * 1024;
- windowA:
- vi->last_window = 0;
- *size_return = vmib->WinSize * 1024 - (offset - vi->windowA_offset);
- return ((U8*)&(LM(vi, MAKE_POINTER(vmib->WinASegment, 0)))) +
- offset - vi->windowA_offset;
-
- set_windowB:
- winnum = offset / (vmib->WinGranularity * 1024);
+ ErrorF("Couldn't set window A to %d*%d\n",
+ (int)winnum, (int)vbe->vmib.WinGranularity);
+ return NULL;
+ }
+ vbe->windowA_offset = winnum * vbe->vmib.WinGranularity * 1024;
+windowA:
+ vbe->last_window = 0;
+ *size_return = vbe->vmib.WinSize * 1024 - (offset - vbe->windowA_offset);
+ return ((U8*)&(LM(vi, MAKE_POINTER(vbe->vmib.WinASegment, 0)))) + offset - vbe->windowA_offset;
+
+set_windowB:
+ winnum = offset / (vbe->vmib.WinGranularity * 1024);
code = VbeReallySetWindow(vi, 1, winnum);
if(code < 0) {
- ErrorF("Couldn't set window B to %d*%d\n",
- (int)winnum, (int)vmib->WinGranularity);
- return NULL;
+ ErrorF("Couldn't set window B to %d*%d\n",
+ (int)winnum, (int)vbe->vmib.WinGranularity);
+ return NULL;
}
- vi->windowB_offset = winnum * vmib->WinGranularity * 1024;
- windowB:
- vi->last_window = 1;
- *size_return = vmib->WinSize * 1024 - (offset - vi->windowB_offset);
- return ((U8*)&(LM(vi, MAKE_POINTER(vmib->WinBSegment, 0)))) + offset - vi->windowB_offset;
-}
-
-int
-VbeSetWritePlaneMask(VbeInfoPtr vi, int mask)
-{
- asm volatile ("outb %b0,%w1" : : "a" (2), "d" (0x3c4));
- asm volatile ("outb %b0,%w1" : : "a" (mask), "d" (0x3c5));
-}
-
-int
-VbeSetReadPlaneMap(VbeInfoPtr vi, int map)
-{
- asm volatile ("outb %b0,%w1" : : "a" (4), "d" (0x3ce));
- asm volatile ("outb %b0,%w1" : : "a" (map), "d" (0x3cf));
+ vbe->windowB_offset = winnum * vbe->vmib.WinGranularity * 1024;
+windowB:
+ vbe->last_window = 1;
+ *size_return = vbe->vmib.WinSize * 1024 - (offset - vbe->windowB_offset);
+ return ((U8*)&(LM(vi, MAKE_POINTER(vbe->vmib.WinBSegment, 0)))) + offset - vbe->windowB_offset;
}
int
-VbeReportInfo(VbeInfoPtr vi, VbeInfoBlock *vib)
+VbeReportVib(Vm86InfoPtr vi, VbeInfoBlock *vib)
{
U32 i, p;
unsigned char c;
@@ -649,9 +503,10 @@ VbeReportInfo(VbeInfoPtr vi, VbeInfoBlock *vib)
(vib->VbeVersion & 0xFF)+'0');
p = vib->OemStringPtr;
for(i = 0; 1; i++) {
- c = VbeMemory(vi, MAKE_POINTER_1(p+i));
+ c = Vm86Memory(vi, MAKE_POINTER_1(p+i));
if(!c) break;
- ErrorF("%c", c);
+ if (c >= ' ')
+ ErrorF("%c", c);
if (i > 32000) {
error = 1;
break;
@@ -669,7 +524,7 @@ VbeReportInfo(VbeInfoPtr vi, VbeInfoBlock *vib)
}
int
-VbeReportModeInfo(VbeInfoPtr vi, U16 mode, VbeModeInfoBlock *vmib)
+VbeReportModeInfo(Vm86InfoPtr vi, U16 mode, VbeModeInfoBlock *vmib)
{
int supported = (vmib->ModeAttributes&0x1)?1:0;
int colour = (vmib->ModeAttributes&0x8)?1:0;
@@ -725,526 +580,43 @@ VbeReportModeInfo(VbeInfoPtr vi, U16 mode, VbeModeInfoBlock *vmib)
ErrorF("\n");
return 0;
}
+
int
-VbeDoInterrupt10(VbeInfoPtr vi)
+VbeDoInterrupt10(Vm86InfoPtr vi)
{
int code;
int oldax;
oldax = vi->vms.regs.eax & 0xFFFF;
- code = VbeDoInterrupt(vi, 0x10);
-
+ code = Vm86DoInterrupt(vi, 0x10);
if(code < 0)
- return -1;
+ return -1;
if((vi->vms.regs.eax & 0xFFFF) != 0x4F && (oldax & 0xFF00) == 0x4F00) {
- ErrorF("Int 10h (0x%04X) failed: 0x%04X",
- oldax, vi->vms.regs.eax & 0xFFFF);
- if((oldax & 0xFF00) == 0x4F00) {
- switch((vi->vms.regs.eax & 0xFF00)>>8) {
- case 0:
- ErrorF(" (success)\n");
- break;
- case 1:
- ErrorF(" (function call failed)\n");
- break;
- case 2:
- ErrorF(" (function not supported on this hardware)\n");
- break;
- case 3:
- ErrorF(" (function call invalid in this video mode)\n");
- break;
- default:
- ErrorF(" (unknown error)\n");
- break;
- }
- return -1;
- } else {
- ErrorF("\n");
- }
+ ErrorF("Int 10h (0x%04X) failed: 0x%04X",
+ oldax, vi->vms.regs.eax & 0xFFFF);
+ if((oldax & 0xFF00) == 0x4F00) {
+ switch((vi->vms.regs.eax & 0xFF00)>>8) {
+ case 0:
+ ErrorF(" (success)\n");
+ return 0;
+ case 1:
+ ErrorF(" (function call failed)\n");
+ break;
+ case 2:
+ ErrorF(" (function not supported on this hardware)\n");
+ break;
+ case 3:
+ ErrorF(" (function call invalid in this video mode)\n");
+ break;
+ default:
+ ErrorF(" (unknown error)\n");
+ break;
+ } return -1;
+ } else {
+ ErrorF("\n");
+ }
}
return code;
}
-
-int
-VbeDoInterrupt(VbeInfoPtr 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;
-}
-
-static inline U8
-vm86_inb(U16 port)
-{
- U8 value;
- asm volatile ("inb %w1,%b0" : "=a" (value) : "d" (port));
- return value;
-}
-
-static inline U16
-vm86_inw(U16 port)
-{
- U16 value;
- asm volatile ("inw %w1,%w0" : "=a" (value) : "d" (port));
- return value;
-}
-
-static inline U32
-vm86_inl(U16 port)
-{
- U32 value;
- asm volatile ("inl %w1,%0" : "=a" (value) : "d" (port));
- return value;
-}
-
-static inline void
-vm86_outb(U16 port, U8 value)
-{
- asm volatile ("outb %b0,%w1" : : "a" (value), "d" (port));
-}
-
-static inline void
-vm86_outw(U16 port, U16 value)
-{
- asm volatile ("outw %w0,%w1" : : "a" (value), "d" (port));
-}
-
-static inline void
-vm86_outl(U16 port, U32 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(VbeInfoPtr 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(!VbeIsMemory(vi, MAKE_POINTER(regs->cs, regs->eip))) {
- ErrorF("Trying to execute unmapped memory\n");
- return -1;
- }
- opcode = VbeMemory(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(VbeMemory(vi, MAKE_POINTER(regs->cs, regs->eip+1))));
- INC_IP(2);
- break;
- case 0xE5: /* IN AX, imm8 */
- if(pref_66)
- regs->eax =
- vm86_inl(VbeMemory(vi, MAKE_POINTER(regs->cs, regs->eip+1)));
- else
- SET_16(regs->eax,
- vm86_inw(VbeMemory(vi, MAKE_POINTER(regs->cs, regs->eip+1))));
- INC_IP(2);
- break;
- case 0x6C: /* INSB */
- case 0x6D: /* INSW */
- if(opcode == 0x6C) {
- VbeWriteMemory(vi, MAKE_POINTER(regs->es, regs->edi),
- vm86_inb(regs->edx & 0xFFFF));
- size = 1;
- } else if(pref_66) {
- VbeWriteMemoryL(vi, MAKE_POINTER(regs->es, regs->edi),
- vm86_inl(regs->edx & 0xFFFF));
- size = 4;
- } else {
- VbeWriteMemoryW(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(VbeMemory(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(VbeMemory(vi, MAKE_POINTER(regs->cs, regs->eip+1)),
- regs->eax);
- else
- vm86_outw(VbeMemory(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,
- VbeMemory(vi, MAKE_POINTER(regs->es, regs->edi)));
- size = 1;
- } else if(pref_66) {
- vm86_outl(regs->edx & 0xFFFF,
- VbeMemory(vi, MAKE_POINTER(regs->es, regs->edi)));
- size = 4;
- } else {
- vm86_outw(regs->edx & 0xFFFF,
- VbeMemory(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(VbeInfoPtr 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) {
- VbeDebug(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");
- VbeDebug(vi);
- return -1;
- default:
- ErrorF("Unexpected result code 0x%X from vm86\n", code);
- VbeDebug(vi);
- return -1;
- }
- }
-}
-
-int
-VbeIsMemory(VbeInfoPtr 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
-VbeMemory(VbeInfoPtr 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
-VbeMemoryW(VbeInfoPtr 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
-VbeMemoryL(VbeInfoPtr 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
-VbeWriteMemory(VbeInfoPtr 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
-VbeWriteMemoryW(VbeInfoPtr 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
-VbeWriteMemoryL(VbeInfoPtr 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
-VbeAllocateMemory(VbeInfoPtr 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;
-}
-
-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;
- OsReleaseSignals ();
- return res;
-}
-
-void
-VbeDebug(VbeInfoPtr 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?"->":"",
- VbeMemory(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
diff --git a/hw/kdrive/vesa/vbe.h b/hw/kdrive/vesa/vbe.h
index 29210310a..2bc3aab2a 100644
--- a/hw/kdrive/vesa/vbe.h
+++ b/hw/kdrive/vesa/vbe.h
@@ -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 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
+VbeGetVib (Vm86InfoPtr vi, VbeInfoBlock *vib);
+
+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
diff --git a/hw/kdrive/vesa/vesa.c b/hw/kdrive/vesa/vesa.c
index fa5bfc62d..5f7f44237 100644
--- a/hw/kdrive/vesa/vesa.c
+++ b/hw/kdrive/vesa/vesa.c
@@ -30,6 +30,7 @@ Bool vesa_shadow = FALSE;
Bool vesa_linear_fb = TRUE;
Bool vesa_restore = FALSE;
Bool vesa_rotate = FALSE;
+Bool vesa_verbose = FALSE;
#define VesaPriv(scr) ((VesaScreenPrivPtr) (scr)->driver)
@@ -38,166 +39,216 @@ Bool vesa_rotate = FALSE;
#define vesaHeight(scr,vmib) (ScreenRotated(scr) ? vmib->XResolution : vmib->YResolution)
static Bool
-vesaModeSupported(VbeInfoPtr vi, VbeModeInfoBlock *vmib, Bool complain)
+vesaModeSupportable (VesaModePtr mode, Bool complain)
{
- if((vmib->ModeAttributes & 0x10) == 0) {
- if(complain)
- ErrorF("Text mode specified.\n");
- return FALSE;
+ if((mode->ModeAttributes & 0x10) == 0) {
+ if(complain)
+ ErrorF("Text mode specified.\n");
+ return FALSE;
}
- if(vmib->MemoryModel != 0x06 && vmib->MemoryModel != 0x04 && vmib->MemoryModel != 0x03) {
- if(complain)
- ErrorF("Unsupported memory model 0x%X\n", vmib->MemoryModel);
- return FALSE;
+ if(mode->MemoryModel != 0x06 && mode->MemoryModel != 0x04 && mode->MemoryModel != 0x03) {
+ if(complain)
+ ErrorF("Unsupported memory model 0x%X\n", mode->MemoryModel);
+ return FALSE;
}
- if((vmib->ModeAttributes & 0x80) == 0) {
- if ((vmib->WinAAttributes & 0x5) != 0x5) {
+ if((mode->ModeAttributes & 0x80) == 0) {
+ if ((mode->ModeAttributes & 0x40) != 0) {
if(complain)
ErrorF("Neither linear nor windowed framebuffer available in this mode\n");
return FALSE;
}
}
- if(!(vmib->ModeAttributes & 1)) {
- if(complain)
- ErrorF("Mode not supported on this hardware\n");
- return FALSE;
+ if(!(mode->ModeAttributes & 1)) {
+ if(complain)
+ ErrorF("Mode not supported on this hardware\n");
+ return FALSE;
}
return TRUE;
}
-Bool
-vesaListModes()
+static Bool
+vesaModeSupported (VesaCardPrivPtr priv, VesaModePtr mode, Bool complain)
{
- int code;
- VbeInfoPtr vi = NULL;
- VbeInfoBlock *vib;
- VbeModeInfoBlock *vmib;
- unsigned p, num_modes, i;
- CARD16 *modes_list = NULL;
-
- vi = VbeSetup();
- if(!vi)
- goto fail;
-
- vib = VbeGetInfo(vi);
- if(!vib)
- goto fail;
-
- VbeReportInfo(vi, vib);
- /* The spec says you need to copy the list */
- p = MAKE_POINTER_1(vib->VideoModePtr);
- num_modes = 0;
- while(VbeMemoryW(vi, p) != 0xFFFF) {
- num_modes++;
- p+=2;
- }
- modes_list = ALLOCATE_LOCAL(num_modes * sizeof(CARD16));
- if(!modes_list)
- goto fail;
- p = MAKE_POINTER_1(vib->VideoModePtr);
- for(i=0; i<num_modes; i++) {
- modes_list[i] = VbeMemoryW(vi, p);
- p += 2;
- }
-
- for(i=0; i<num_modes; i++) {
- vmib = VbeGetModeInfo(vi, modes_list[i]);
- if(!vmib)
- goto fail;
- if(vesa_force_mode || vesaModeSupported(vi, vmib, FALSE))
- VbeReportModeInfo(vi, modes_list[i], vmib);
- }
-
- if(modes_list)
- DEALLOCATE_LOCAL(modes_list);
- VbeCleanup(vi);
- return TRUE;
-
- fail:
- if(modes_list)
- DEALLOCATE_LOCAL(modes_list);
- VbeCleanup(vi);
- return FALSE;
+ if (!priv->vbeInfo && mode->vbe) {
+ if (complain)
+ ErrorF("VBE bios mode not usable.\n");
+ return FALSE;
+ }
+ return vesaModeSupportable (mode, complain);
}
-Bool
-vesaGetModes (KdCardInfo *card, VesaCardPrivPtr priv)
+void
+vesaReportMode (VesaModePtr mode)
{
- VesaModePtr mode;
- int nmode;
- unsigned int i;
- VbeInfoPtr vi = priv->vi;
- VbeInfoBlock *vib = priv->vib;
- VbeModeInfoBlock *vmib;
-
- /* The spec says you need to copy the list */
- i = MAKE_POINTER_1(vib->VideoModePtr);
- nmode = 0;
- while(VbeMemoryW(vi, i) != 0xFFFF) {
- nmode++;
- i+=2;
- }
- if (!nmode)
- return FALSE;
- priv->modes = xalloc (nmode * sizeof (VesaModeRec));
- if (!priv->modes)
- return FALSE;
- priv->nmode = nmode;
- i = MAKE_POINTER_1(vib->VideoModePtr);
- nmode = 0;
- while(nmode < priv->nmode) {
- priv->modes[nmode].mode = VbeMemoryW(vi, i);
- nmode++;
- i+=2;
- }
- i = MAKE_POINTER_1(vib->VideoModePtr);
- nmode = 0;
- while(nmode < priv->nmode) {
- vmib = VbeGetModeInfo(vi, priv->modes[nmode].mode);
- if(!vmib)
- break;
- priv->modes[nmode].vmib = *vmib;
- i += 2;
- nmode++;
+ int supported = (mode->ModeAttributes&MODE_SUPPORTED)?1:0;
+ int colour = (mode->ModeAttributes&MODE_COLOUR)?1:0;
+ int graphics = (mode->ModeAttributes&MODE_GRAPHICS)?1:0;
+ int vga_compatible = !((mode->ModeAttributes&MODE_VGA)?1:0);
+ int linear_fb = (mode->ModeAttributes&MODE_LINEAR)?1:0;
+
+ ErrorF("0x%04X: %dx%dx%d%s",
+ (unsigned)mode->mode,
+ (int)mode->XResolution, (int)mode->YResolution,
+ vesaDepth (mode),
+ colour?"":" (monochrome)");
+ switch(mode->MemoryModel) {
+ case MEMORY_TEXT:
+ ErrorF(" text mode");
+ break;
+ case MEMORY_CGA:
+ ErrorF(" CGA graphics");
+ break;
+ case MEMORY_HERCULES:
+ ErrorF(" Hercules graphics");
+ break;
+ case MEMORY_PLANAR:
+ ErrorF(" Planar (%d planes)", mode->NumberOfPlanes);
+ break;
+ case MEMORY_PSEUDO:
+ ErrorF(" PseudoColor");
+ break;
+ case MEMORY_NONCHAIN:
+ ErrorF(" Non-chain 4, 256 colour");
+ break;
+ case MEMORY_DIRECT:
+ if(mode->DirectColorModeInfo & MODE_DIRECT)
+ ErrorF(" DirectColor");
+ else
+ ErrorF(" TrueColor");
+ ErrorF(" [%d:%d:%d:%d]",
+ mode->RedMaskSize, mode->GreenMaskSize, mode->BlueMaskSize,
+ mode->RsvdMaskSize);
+ if(mode->DirectColorModeInfo & 2)
+ ErrorF(" (reserved bits are reserved)");
+ break;
+ case MEMORY_YUV:
+ ErrorF("YUV");
+ break;
+ default:
+ ErrorF("unknown MemoryModel 0x%X ", mode->MemoryModel);
}
- return TRUE;
+ if(!supported)
+ ErrorF(" (unsupported)");
+ else if(!linear_fb)
+ ErrorF(" (no linear framebuffer)");
+ ErrorF("\n");
}
+VesaModePtr
+vesaGetModes (Vm86InfoPtr vi, int *ret_nmode)
+{
+ VesaModePtr modes;
+ int nmode, nmodeVbe, nmodeVga;
+ int code;
+
+ code = VgaGetNmode (vi);
+ if (code <= 0)
+ nmodeVga = 0;
+ else
+ nmodeVga = code;
+
+ code = VbeGetNmode (vi);
+ if (code <= 0)
+ nmodeVbe = 0;
+ else
+ nmodeVbe = code;
+
+ nmode = nmodeVga + nmodeVbe;
+ if (nmode <= 0)
+ return 0;
+
+ modes = xalloc (nmode * sizeof (VesaModeRec));
+
+ if (nmodeVga)
+ {
+ code = VgaGetModes (vi, modes, nmodeVga);
+ if (code <= 0)
+ nmodeVga = 0;
+ else
+ nmodeVga = code;
+ }
+
+ if (nmodeVbe)
+ {
+ code = VbeGetModes (vi, modes + nmodeVga, nmodeVbe);
+ if (code <= 0)
+ nmodeVbe = 0;
+ else
+ nmodeVbe = code;
+ }
+
+ nmode = nmodeVga + nmodeVbe;
+
+ if (nmode == 0)
+ {
+ xfree (modes);
+ modes = 0;
+ return 0;
+ }
+ *ret_nmode = nmode;
+ return modes;
+}
Bool
vesaInitialize (KdCardInfo *card, VesaCardPrivPtr priv)
{
int code;
-
- priv->vi = VbeSetup();
- if(!priv->vi)
- goto fail;
-
- priv->vib = VbeGetInfo(priv->vi);
- if(!priv->vib)
- goto fail;
- code = VbeSetupStateBuffer(priv->vi);
- if(code < 0)
- goto fail;
-
- code = VbeSaveState(priv->vi);
- if(code<0)
- goto fail;
+ priv->vi = Vm86Setup();
+ if(!priv->vi)
+ goto fail;
- if (!vesaGetModes (card, priv))
+ priv->modes = vesaGetModes (priv->vi, &priv->nmode);
+
+ if (!priv->modes)
goto fail;
+
+ priv->vbeInfo = VbeInit (priv->vi);
card->driver = priv;
return TRUE;
- fail:
+fail:
if(priv->vi)
- VbeCleanup(priv->vi);
+ Vm86Cleanup(priv->vi);
return FALSE;
}
+void
+vesaListModes (void)
+{
+ Vm86InfoPtr vi;
+ VesaModePtr modes;
+ int nmode;
+ int n;
+
+ vi = Vm86Setup ();
+ if (!vi)
+ {
+ ErrorF ("Can't setup vm86\n");
+ }
+ else
+ {
+ modes = vesaGetModes (vi, &nmode);
+ if (!modes)
+ {
+ ErrorF ("No modes available\n");
+ }
+ else
+ {
+ VbeReportInfo (vi);
+ for (n = 0; n < nmode; n++)
+ {
+ if (vesa_force_mode || vesaModeSupportable (modes+n, 0))
+ vesaReportMode (modes+n);
+ }
+ xfree (modes);
+ }
+ Vm86Cleanup (vi);
+ }
+}
+
Bool
vesaCardInit(KdCardInfo *card)
{
@@ -217,19 +268,19 @@ vesaCardInit(KdCardInfo *card)
}
int
-vesaDepth (VbeModeInfoBlock *m)
+vesaDepth (VesaModePtr mode)
{
- if (m->MemoryModel == 0x06)
- return (m->RedMaskSize +
- m->GreenMaskSize +
- m->BlueMaskSize);
+ if (mode->MemoryModel == MEMORY_DIRECT)
+ return (mode->RedMaskSize +
+ mode->GreenMaskSize +
+ mode->BlueMaskSize);
else
- return m->BitsPerPixel;
+ return mode->BitsPerPixel;
}
Bool
-vesaModeGood (KdScreenInfo *screen,
- VbeModeInfoBlock *a)
+vesaModeGood (KdScreenInfo *screen,
+ VesaModePtr a)
{
if (vesaWidth(screen,a) <= screen->width &&
vesaHeight(screen,a) <= screen->height &&
@@ -242,8 +293,8 @@ vesaModeGood (KdScreenInfo *screen,
#define vabs(a) ((a) >= 0 ? (a) : -(a))
int
-vesaSizeError (KdScreenInfo *screen,
- VbeModeInfoBlock *a)
+vesaSizeError (KdScreenInfo *screen,
+ VesaModePtr a)
{
int xdist, ydist;
xdist = vabs (screen->width - vesaWidth(screen,a));
@@ -252,9 +303,9 @@ vesaSizeError (KdScreenInfo *screen,
}
Bool
-vesaModeBetter (KdScreenInfo *screen,
- VbeModeInfoBlock *a,
- VbeModeInfoBlock *b)
+vesaModeBetter (KdScreenInfo *screen,
+ VesaModePtr a,
+ VesaModePtr b)
{
int aerr, berr;
@@ -290,21 +341,21 @@ vesaSelectMode (KdScreenInfo *screen)
{
for (best = 0; best < priv->nmode; best++)
if (priv->modes[best].mode == vesa_video_mode &&
- (vesaModeSupported (priv->vi, &priv->modes[best].vmib, FALSE) ||
+ (vesaModeSupported (priv, &priv->modes[best], FALSE) ||
vesa_force_mode))
return &priv->modes[best];
}
for (best = 0; best < priv->nmode; best++)
{
- if (vesaModeSupported (priv->vi, &priv->modes[best].vmib, FALSE))
+ if (vesaModeSupported (priv, &priv->modes[best], FALSE))
break;
}
if (best == priv->nmode)
return 0;
for (i = best + 1; i < priv->nmode; i++)
- if (vesaModeSupported (priv->vi, &priv->modes[i].vmib, FALSE) &&
- vesaModeBetter (screen, &priv->modes[i].vmib,
- &priv->modes[best].vmib))
+ if (vesaModeSupported (priv, &priv->modes[i], FALSE) &&
+ vesaModeBetter (screen, &priv->modes[i],
+ &priv->modes[best]))
best = i;
return &priv->modes[best];
}
@@ -313,19 +364,43 @@ Bool
vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr)
{
VesaCardPrivPtr priv = screen->card->driver;
- VbeModeInfoBlock *vmib;
+ VesaModePtr mode;
Pixel allbits;
int depth;
- int bpp;
+ int bpp, fbbpp;
screen->driver = pscr;
pscr->rotate = FALSE;
if (screen->width < screen->height)
pscr->rotate = TRUE;
+
+ if (!screen->width || !screen->height)
+ {
+ screen->width = 640;
+ screen->height = 480;
+ }
+ if (!screen->fb[0].depth)
+ screen->fb[0].depth = 4;
+
+ if (vesa_verbose)
+ ErrorF ("Mode requested %dx%dx%d\n",
+ screen->width, screen->height, screen->fb[0].depth);
+
pscr->mode = vesaSelectMode (screen);
+
if (!pscr->mode)
+ {
+ if (vesa_verbose)
+ ErrorF ("No selectable mode\n");
return FALSE;
+ }
+ if (vesa_verbose)
+ {
+ ErrorF ("\t");
+ vesaReportMode (pscr->mode);
+ }
+
pscr->shadow = vesa_shadow;
pscr->origDepth = screen->fb[0].depth;
if (vesa_linear_fb)
@@ -333,21 +408,35 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr)
else
pscr->mapping = VESA_WINDOWED;
- vmib = &pscr->mode->vmib;
+ mode = pscr->mode;
- depth = vesaDepth (vmib);
- bpp = vmib->BitsPerPixel;
+ depth = vesaDepth (mode);
+ bpp = mode->BitsPerPixel;
- switch (vmib->MemoryModel) {
- case 0x06:
+ if (bpp > 24)
+ bpp = 32;
+ else if (bpp > 16)
+ bpp = 24;
+ else if (bpp > 8)
+ bpp = 16;
+ else if (bpp > 4)
+ bpp = 8;
+ else if (bpp > 1)
+ bpp = 4;
+ else
+ bpp = 1;
+ fbbpp = bpp;
+
+ switch (mode->MemoryModel) {
+ case MEMORY_DIRECT:
/* TrueColor or DirectColor */
screen->fb[0].visuals = (1 << TrueColor);
screen->fb[0].redMask =
- FbStipMask(vmib->RedFieldPosition, vmib->RedMaskSize);
+ FbStipMask(mode->RedFieldPosition, mode->RedMaskSize);
screen->fb[0].greenMask =
- FbStipMask(vmib->GreenFieldPosition, vmib->GreenMaskSize);
+ FbStipMask(mode->GreenFieldPosition, mode->GreenMaskSize);
screen->fb[0].blueMask =
- FbStipMask(vmib->BlueFieldPosition, vmib->BlueMaskSize);
+ FbStipMask(mode->BlueFieldPosition, mode->BlueMaskSize);
allbits =
screen->fb[0].redMask |
screen->fb[0].greenMask |
@@ -355,8 +444,14 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr)
depth = 32;
while (depth && !(allbits & (1 << (depth - 1))))
depth--;
+ if (vesa_verbose)
+ ErrorF ("\tTrue Color bpp %d depth %d red 0x%x green 0x%x blue 0x%x\n",
+ bpp, depth,
+ screen->fb[0].redMask,
+ screen->fb[0].greenMask,
+ screen->fb[0].blueMask);
break;
- case 0x04:
+ case MEMORY_PSEUDO:
/* PseudoColor */
screen->fb[0].visuals = ((1 << StaticGray) |
(1 << GrayScale) |
@@ -367,43 +462,73 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr)
screen->fb[0].blueMask = 0x00;
screen->fb[0].greenMask = 0x00;
screen->fb[0].redMask = 0x00;
+ if (vesa_verbose)
+ ErrorF ("\tPseudo Color bpp %d depth %d\n",
+ bpp, depth);
break;
- case 0x03:
+ case MEMORY_PLANAR:
/* 4 plane planar */
- screen->fb[0].visuals = (1 << StaticColor);
+ if (mode->ModeAttributes & MODE_COLOUR)
+ screen->fb[0].visuals = (1 << StaticColor);
+ else
+ screen->fb[0].visuals = (1 << StaticGray);
screen->fb[0].blueMask = 0x00;
screen->fb[0].greenMask = 0x00;
screen->fb[0].redMask = 0x00;
- bpp = screen->fb[0].bitsPerPixel;
- if (bpp != 8)
- bpp = 4;
- depth = bpp;
- pscr->mapping = VESA_PLANAR;
+ if (bpp == 4)
+ {
+ bpp = screen->fb[0].bitsPerPixel;
+ if (bpp != 8)
+ bpp = 4;
+ depth = bpp;
+ }
+ if (bpp == 1)
+ {
+ pscr->mapping = VESA_MONO;
+ if (vesa_verbose)
+ ErrorF ("\tMonochrome\n");
+ }
+ else
+ {
+ pscr->mapping = VESA_PLANAR;
+ if (vesa_verbose)
+ ErrorF ("\tStatic color bpp %d depth %d\n",
+ bpp, depth);
+ }
pscr->rotate = FALSE;
break;
default:
ErrorF("Unsupported VESA MemoryModel 0x%02X\n",
- vmib->MemoryModel);
+ mode->MemoryModel);
return FALSE;
}
- screen->width = vesaWidth(screen, vmib);
- screen->height = vesaHeight(screen, vmib);
+ screen->width = vesaWidth(screen, mode);
+ screen->height = vesaHeight(screen, mode);
screen->fb[0].depth = depth;
screen->fb[0].bitsPerPixel = bpp;
- screen->fb[0].byteStride = vmib->BytesPerScanLine;
- screen->fb[0].pixelStride = ((vmib->BytesPerScanLine * 8) /
- vmib->BitsPerPixel);
+ screen->fb[0].byteStride = mode->BytesPerScanLine;
+ screen->fb[0].pixelStride = ((mode->BytesPerScanLine * 8) / fbbpp);
- if (pscr->mapping == VESA_LINEAR && !(vmib->ModeAttributes & 0x80))
+ if (pscr->mapping == VESA_LINEAR && !(mode->ModeAttributes & MODE_LINEAR))
pscr->mapping = VESA_WINDOWED;
if (pscr->rotate)
pscr->shadow = TRUE;
switch (pscr->mapping) {
+ case VESA_MONO:
+ pscr->shadow = TRUE;
+ /* fall through */
case VESA_LINEAR:
- pscr->fb = VbeMapFramebuffer(priv->vi, vmib);
+ if (mode->vbe)
+ pscr->fb = VbeMapFramebuffer(priv->vi, priv->vbeInfo,
+ pscr->mode->mode,
+ &pscr->fb_size);
+ else
+ pscr->fb = VgaMapFramebuffer (priv->vi,
+ pscr->mode->mode,
+ &pscr->fb_size);
break;
case VESA_WINDOWED:
pscr->fb = NULL;
@@ -424,6 +549,10 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr)
if (pscr->shadow)
return KdShadowScreenInit (screen);
+ if (vesa_verbose)
+ ErrorF ("Mode selected %dx%dx%d\n",
+ screen->width, screen->height, screen->fb[0].depth);
+
return TRUE;
}
@@ -441,7 +570,7 @@ vesaScreenInit(KdScreenInfo *screen)
}
void *
-vesaWindowPlanar (ScreenPtr pScreen,
+vesaSetWindowPlanar(ScreenPtr pScreen,
CARD32 row,
CARD32 offset,
int mode,
@@ -450,25 +579,96 @@ vesaWindowPlanar (ScreenPtr pScreen,
KdScreenPriv(pScreen);
VesaCardPrivPtr priv = pScreenPriv->card->driver;
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
- VbeModeInfoBlock *vmib = &pscr->mode->vmib;
static int plane;
int winSize;
void *base;
- if (!pScreenPriv->enabled)
- return 0;
plane = offset & 3;
- VbeSetWritePlaneMask (priv->vi, (1 << plane));
+ VgaSetWritePlaneMask (priv->vi, (1 << plane));
offset = offset >> 2;
- base = VbeSetWindow (priv->vi,
- vmib->BytesPerScanLine * row + offset,
- mode,
- &winSize);
+ if (pscr->mode->vbe)
+ {
+ base = VbeSetWindow (priv->vi,
+ priv->vbeInfo,
+ pscr->mode->BytesPerScanLine * row + offset,
+ mode,
+ &winSize);
+ }
+ else
+ {
+ base = VgaSetWindow (priv->vi,
+ pscr->mode->mode,
+ pscr->mode->BytesPerScanLine * row + offset,
+ mode,
+ &winSize);
+ }
+ *size = (CARD32) winSize;
+ return base;
+}
+
+void *
+vesaSetWindowLinear (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size)
+{
+ KdScreenPriv(pScreen);
+ VesaCardPrivPtr priv = pScreenPriv->card->driver;
+ VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
+
+ *size = pscr->mode->BytesPerScanLine;
+ return (CARD8 *) pscr->fb + row * pscr->mode->BytesPerScanLine + offset;
+}
+
+void *
+vesaSetWindowWindowed (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size)
+{
+ KdScreenPriv(pScreen);
+ VesaCardPrivPtr priv = pScreenPriv->card->driver;
+ VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
+ int winSize;
+ void *base;
+
+ if (pscr->mode->vbe)
+ {
+ base = VbeSetWindow (priv->vi,
+ priv->vbeInfo,
+ pscr->mode->BytesPerScanLine * row + offset,
+ mode,
+ &winSize);
+ }
+ else
+ {
+ base = VgaSetWindow (priv->vi,
+ pscr->mode->mode,
+ pscr->mode->BytesPerScanLine * row + offset,
+ mode,
+ &winSize);
+ }
*size = (CARD32) winSize;
return base;
}
void *
+vesaWindowPlanar (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size)
+{
+ KdScreenPriv(pScreen);
+
+ if (!pScreenPriv->enabled)
+ return 0;
+ return vesaSetWindowPlanar (pScreen, row, offset, mode, size);
+}
+
+void *
vesaWindowLinear (ScreenPtr pScreen,
CARD32 row,
CARD32 offset,
@@ -476,14 +676,10 @@ vesaWindowLinear (ScreenPtr pScreen,
CARD32 *size)
{
KdScreenPriv(pScreen);
- VesaCardPrivPtr priv = pScreenPriv->card->driver;
- VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
- VbeModeInfoBlock *vmib = &pscr->mode->vmib;
if (!pScreenPriv->enabled)
return 0;
- *size = vmib->BytesPerScanLine;
- return (CARD8 *) pscr->fb + row * vmib->BytesPerScanLine + offset;
+ return vesaSetWindowLinear (pScreen, row, offset, mode, size);
}
void *
@@ -494,41 +690,114 @@ vesaWindowWindowed (ScreenPtr pScreen,
CARD32 *size)
{
KdScreenPriv(pScreen);
+
+ if (!pScreenPriv->enabled)
+ return 0;
+ return vesaSetWindowWindowed (pScreen, row, offset, mode, size);
+}
+
+#define vesaInvertBits32(v) { \
+ v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \
+ v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \
+ v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \
+}
+
+void *
+vesaWindowCga (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size)
+{
+ KdScreenPriv(pScreen);
VesaCardPrivPtr priv = pScreenPriv->card->driver;
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
- VbeModeInfoBlock *vmib = &pscr->mode->vmib;
- int winSize;
- void *base;
-
+ int line;
+
if (!pScreenPriv->enabled)
return 0;
- base = VbeSetWindow (priv->vi,
- vmib->BytesPerScanLine * row + offset,
- mode,
- &winSize);
- *size = (CARD32) winSize;
- return base;
+ *size = pscr->mode->BytesPerScanLine;
+ line = ((row & 1) << 13) + (row >> 1) * pscr->mode->BytesPerScanLine;
+ return (CARD8 *) pscr->fb + line + offset;
}
-static CARD16 vga16Colors[16][3] = {
-#if 0
- { 0, 0, 0, }, /* 0 */
- { 0, 0, 0x80,}, /* 1 */
- { 0, 0x80,0, }, /* 2 */
- { 0, 0x80,0x80,}, /* 3 */
- { 0x80,0, 0, }, /* 4 */
- { 0x80,0, 0x80,}, /* 5 */
- { 0x80,0x80,0, }, /* 6 */
- { 0xC0,0xC0,0xC0,}, /* 7 */
- { 0x80,0x80,0x80,}, /* 8 */
- { 0, 0, 0xFF,}, /* 9 */
- { 0, 0xFF,0 ,}, /* 10 */
- { 0, 0xFF,0xFF,}, /* 11 */
- { 0xFF,0, 0 ,}, /* 12 */
- { 0xFF,0, 0xFF,}, /* 13 */
- { 0xFF,0xFF,0 ,}, /* 14 */
- { 0xFF,0xFF,0xFF,}, /* 15 */
-#else
+void
+vesaUpdateMono (ScreenPtr pScreen,
+ PixmapPtr pShadow,
+ RegionPtr damage)
+{
+ shadowScrPriv(pScreen);
+ int nbox = REGION_NUM_RECTS (damage);
+ BoxPtr pbox = REGION_RECTS (damage);
+ FbBits *shaBase, *shaLine, *sha;
+ FbBits s;
+ FbStride shaStride;
+ int scrBase, scrLine, scr;
+ int shaBpp;
+ int x, y, w, h, width;
+ int i;
+ FbBits *winBase, *winLine, *win;
+ CARD32 winSize;
+ FbBits bits;
+ int plane;
+
+ fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp);
+ while (nbox--)
+ {
+ x = pbox->x1 * shaBpp;
+ y = pbox->y1;
+ w = (pbox->x2 - pbox->x1) * shaBpp;
+ h = pbox->y2 - pbox->y1;
+
+ scrLine = (x >> FB_SHIFT);
+ shaLine = shaBase + y * shaStride + (x >> FB_SHIFT);
+
+ x &= FB_MASK;
+ w = (w + x + FB_MASK) >> FB_SHIFT;
+
+ while (h--)
+ {
+ winSize = 0;
+ scrBase = 0;
+ width = w;
+ scr = scrLine;
+ sha = shaLine;
+ while (width) {
+ /* how much remains in this window */
+ i = scrBase + winSize - scr;
+ if (i <= 0 || scr < scrBase)
+ {
+ winBase = (FbBits *) (*pScrPriv->window) (pScreen,
+ y,
+ scr * sizeof (FbBits),
+ SHADOW_WINDOW_WRITE,
+ &winSize);
+ if(!winBase)
+ return;
+ scrBase = scr;
+ winSize /= sizeof (FbBits);
+ i = winSize;
+ }
+ win = winBase + (scr - scrBase);
+ if (i > width)
+ i = width;
+ width -= i;
+ scr += i;
+ while (i--)
+ {
+ bits = *sha++;
+ vesaInvertBits32(bits);
+ *win++ = bits;
+ }
+ }
+ shaLine += shaStride;
+ y++;
+ }
+ pbox++;
+ }
+}
+
+static const CARD16 vga16Colors[16][3] = {
{ 0, 0, 0, }, /* 0 */
{ 0, 0, 0xAA,}, /* 1 */
{ 0, 0xAA,0, }, /* 2 */
@@ -545,7 +814,6 @@ static CARD16 vga16Colors[16][3] = {
{ 0xFF,0x55,0xFF,}, /* 13 */
{ 0xFF,0xFF,0x55,}, /* 14 */
{ 0xFF,0xFF,0xFF,}, /* 15 */
-#endif
};
Bool
@@ -586,26 +854,20 @@ vesaInitScreen(ScreenPtr pScreen)
case VESA_PLANAR:
pScreen->CreateColormap = vesaCreateColormap16;
if (pScreenPriv->screen->fb[0].bitsPerPixel == 8)
- {
-#if 0
- int i;
-
- for (i = 0; i < pScreen->numVisuals; i++)
- {
- if (pScreen->visuals[i].nplanes ==
- pScreenPriv->screen->fb[0].depth)
- {
- pScreen->visuals[i].ColormapEntries = 16;
- }
- }
-#endif
update = shadowUpdatePlanar4x8;
- }
else
update = shadowUpdatePlanar4;
window = vesaWindowPlanar;
pscr->rotate = FALSE;
break;
+ case VESA_MONO:
+ update = vesaUpdateMono;
+ if (pscr->mode->mode < 8)
+ window = vesaWindowCga;
+ else
+ window = vesaWindowLinear;
+ pscr->rotate = FALSE;
+ break;
}
if (pscr->rotate)
{
@@ -629,55 +891,41 @@ Bool
vesaEnable(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
- VesaCardPrivPtr priv = pScreenPriv->card->driver;
+ VesaCardPrivPtr priv = pScreenPriv->card->driver;
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
- int code;
- int palette_wait = 0, palette_hi = 0;
- int i;
- int size;
- char *p;
+ int code;
+ int i;
+ CARD32 size;
+ char *p;
KdMouseMatrix m;
- code = VbeSetMode(priv->vi, pscr->mode->mode, pscr->mapping == VESA_LINEAR);
- if(code < 0)
- return FALSE;
-
+ if (pscr->mode->vbe)
{
- int p;
- CARD8 scratch[4] = {0x40,0x40,0x40,0};
- for (p = 0; p < 256; p++)
- {
- if (20 <= p && p < 21)
- {
- scratch[0] = 255;
- scratch[1] = 255;
- scratch[2] = 255;
- }
- else
- {
- scratch[0] = 0;
- scratch[1] = 0;
- scratch[2] = 0;
- }
- VbeSetPalette(priv->vi, p, 1, scratch);
- }
+ if (vesa_verbose)
+ ErrorF ("Enable VBE mode 0x%x\n", pscr->mode->mode);
+ code = VbeSetMode(priv->vi, priv->vbeInfo, pscr->mode->mode,
+ pscr->mapping == VESA_LINEAR);
+ }
+ else
+ {
+ if (vesa_verbose)
+ ErrorF ("Enable BIOS mode 0x%x\n", pscr->mode->mode);
+ code = VgaSetMode (priv->vi, pscr->mode->mode);
}
- if(priv->vib->Capabilities[0] & 1)
- palette_hi = 1;
- if(priv->vib->Capabilities[0] & 4)
- palette_wait = 1;
- if(palette_hi || palette_wait)
- VbeSetPaletteOptions(priv->vi, palette_hi?8:6, palette_wait);
-
+ if(code < 0)
+ return FALSE;
+
switch (pscr->mapping) {
+ case VESA_MONO:
+ VgaSetWritePlaneMask (priv->vi, 0x1);
case VESA_LINEAR:
memcpy (priv->text, pscr->fb, VESA_TEXT_SAVE);
break;
case VESA_WINDOWED:
for (i = 0; i < VESA_TEXT_SAVE;)
{
- p = VbeSetWindow(priv->vi, i, VBE_WINDOW_READ, &size);
+ p = vesaSetWindowWindowed (pScreen, 0, i, VBE_WINDOW_READ, &size);
if(!p) {
ErrorF("Couldn't set window for saving VGA font\n");
break;
@@ -689,10 +937,9 @@ vesaEnable(ScreenPtr pScreen)
}
break;
case VESA_PLANAR:
- p = VbeSetWindow (priv->vi, 0, VBE_WINDOW_READ, &size);
for (i = 0; i < 4; i++)
{
- VbeSetReadPlaneMap (priv->vi, i);
+ p = vesaSetWindowPlanar (pScreen, 0, i, VBE_WINDOW_READ, &size);
memcpy (((char *)priv->text) + i * (VESA_TEXT_SAVE/4), p,
(VESA_TEXT_SAVE/4));
}
@@ -716,19 +963,20 @@ void
vesaDisable(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
- VesaCardPrivPtr priv = pScreenPriv->card->driver;
+ VesaCardPrivPtr priv = pScreenPriv->card->driver;
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
- int i=0;
- int size;
- char *p;
+ int i=0;
+ CARD32 size;
+ char *p;
switch (pscr->mapping) {
case VESA_LINEAR:
+ case VESA_MONO:
memcpy(pscr->fb, priv->text, VESA_TEXT_SAVE);
break;
case VESA_WINDOWED:
while(i < VESA_TEXT_SAVE) {
- p = VbeSetWindow(priv->vi, i, VBE_WINDOW_WRITE, &size);
+ p = vesaSetWindowWindowed (pScreen, 0, i, VBE_WINDOW_WRITE, &size);
if(!p) {
ErrorF("Couldn't set window for restoring VGA font\n");
break;
@@ -740,10 +988,9 @@ vesaDisable(ScreenPtr pScreen)
}
break;
case VESA_PLANAR:
- p = VbeSetWindow (priv->vi, 0, VBE_WINDOW_WRITE, &size);
for (i = 0; i < 4; i++)
{
- VbeSetWritePlaneMask (priv->vi, 1 << i);
+ p = vesaSetWindowPlanar (pScreen, 0, i, VBE_WINDOW_WRITE, &size);
memcpy (p,
((char *)priv->text) + i * (VESA_TEXT_SAVE/4),
(VESA_TEXT_SAVE/4));
@@ -761,29 +1008,49 @@ vesaPreserve(KdCardInfo *card)
/* The framebuffer might not be valid at this point, so we cannot
save the VGA fonts now; we do it in vesaEnable. */
- code = VbeSaveState(priv->vi);
- if(code < 0)
- FatalError("Couldn't save state\n");
+ if (VbeGetMode (priv->vi, &priv->old_vbe_mode) < 0)
+ priv->old_vbe_mode = -1;
- return;
+ if (VgaGetMode (priv->vi, &priv->old_vga_mode) < 0)
+ priv->old_vga_mode = -1;
+
+ if (vesa_verbose)
+ ErrorF ("Previous modes: VBE 0x%x BIOS 0x%x\n",
+ priv->old_vbe_mode, priv->old_vga_mode);
}
void
vesaRestore(KdCardInfo *card)
{
VesaCardPrivPtr priv = card->driver;
- VbeRestoreState(priv->vi);
- return;
+ int n;
+
+ for (n = 0; n < priv->nmode; n++)
+ if (priv->modes[n].vbe && priv->modes[n].mode == (priv->old_vbe_mode&0x3fff))
+ break;
+
+ if (n < priv->nmode)
+ {
+ if (vesa_verbose)
+ ErrorF ("Restore VBE mode 0x%x\n", priv->old_vbe_mode);
+ VbeSetMode (priv->vi, priv->vbeInfo, priv->old_vbe_mode, 0);
+ }
+ else
+ {
+ if (vesa_verbose)
+ ErrorF ("Restore BIOS mode 0x%x\n", priv->old_vga_mode);
+ VgaSetMode (priv->vi, priv->old_vga_mode);
+ }
}
void
vesaCardFini(KdCardInfo *card)
{
VesaCardPrivPtr priv = card->driver;
- if (vesa_restore)
- VbeSetTextMode(priv->vi,3);
- VbeCleanup(priv->vi);
- return;
+
+ if (priv->vbeInfo)
+ VbeCleanup (priv->vi, priv->vbeInfo);
+ Vm86Cleanup(priv->vi);
}
void
@@ -793,14 +1060,47 @@ vesaScreenFini(KdScreenInfo *screen)
VesaCardPrivPtr priv = screen->card->driver;
if (pscr->fb)
- VbeUnmapFramebuffer(priv->vi, &pscr->mode->vmib, pscr->fb);
+ {
+ if (pscr->mode->vbe)
+ VbeUnmapFramebuffer(priv->vi, priv->vbeInfo, pscr->mode->mode, pscr->fb);
+ else
+ VgaUnmapFramebuffer (priv->vi);
+ }
if (pscr->shadow)
KdShadowScreenFini (screen);
screen->fb[0].depth = pscr->origDepth;
- return;
}
+int
+vesaSetPalette(VesaCardPrivPtr priv, int first, int number, U8 *entries)
+{
+ if (priv->vga_palette)
+ return VgaSetPalette (priv->vi, first, number, entries);
+ else
+ return VbeSetPalette (priv->vi, priv->vbeInfo, first, number, entries);
+}
+
+
+int
+vesaGetPalette(VesaCardPrivPtr priv, int first, int number, U8 *entries)
+{
+ int code;
+
+ if (priv->vga_palette)
+ code = VgaGetPalette (priv->vi, first, number, entries);
+ else
+ {
+ code = VbeGetPalette (priv->vi, priv->vbeInfo, first, number, entries);
+ if (code < 0)
+ {
+ priv->vga_palette = 1;
+ code = VgaGetPalette (priv->vi, first, number, entries);
+ }
+ }
+ return code;
+}
+
void
vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
{
@@ -841,15 +1141,15 @@ vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
*/
if (p < 16)
{
- VbeSetPalette (priv->vi, p, 1, scratch);
+ vesaSetPalette (priv, p, 1, scratch);
if (p >= 8)
- VbeSetPalette (priv->vi, p+0x30, 1, scratch);
+ vesaSetPalette (priv, p+0x30, 1, scratch);
else if (p == 6)
- VbeSetPalette (priv->vi, 0x14, 1, scratch);
+ vesaSetPalette (priv, 0x14, 1, scratch);
}
}
else
- VbeSetPalette(priv->vi, p, 1, scratch);
+ vesaSetPalette(priv, p, 1, scratch);
}
}
@@ -876,7 +1176,7 @@ vesaGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
}
for(i = 0; i<n; i++) {
- VbeGetPalette(priv->vi, pdefs[i].pixel, 1, scratch);
+ vesaGetPalette(priv, pdefs[i].pixel, 1, scratch);
pdefs[i].red = scratch[red]<<8;
pdefs[i].green = scratch[green]<<8;
pdefs[i].blue = scratch[blue]<<8;
@@ -907,8 +1207,8 @@ vesaProcessArgument (int argc, char **argv, int i)
} else if(!strcmp(argv[i], "-nolinear")) {
vesa_linear_fb = FALSE;
return 1;
- } else if(!strcmp(argv[i], "-restore")) {
- vesa_restore = TRUE;
+ } else if(!strcmp(argv[i], "-verbose")) {
+ vesa_verbose = TRUE;
return 1;
}
diff --git a/hw/kdrive/vesa/vesa.h b/hw/kdrive/vesa/vesa.h
index 8ded2ab67..9b521698d 100644
--- a/hw/kdrive/vesa/vesa.h
+++ b/hw/kdrive/vesa/vesa.h
@@ -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_
diff --git a/hw/kdrive/vesa/vesainit.c b/hw/kdrive/vesa/vesainit.c
index 580977058..0f640db2d 100644
--- a/hw/kdrive/vesa/vesainit.c
+++ b/hw/kdrive/vesa/vesainit.c
@@ -23,7 +23,7 @@ THE SOFTWARE.
#include "vesa.h"
-KdCardFuncs vesaFuncs = {
+const KdCardFuncs vesaFuncs = {
vesaCardInit, /* cardinit */
vesaScreenInit, /* scrinit */
vesaInitScreen, /* initScreen */
diff --git a/hw/kdrive/vesa/vga.c b/hw/kdrive/vesa/vga.c
new file mode 100644
index 000000000..24b23e885
--- /dev/null
+++ b/hw/kdrive/vesa/vga.c
@@ -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)
+{
+}
diff --git a/hw/kdrive/vesa/vga.h b/hw/kdrive/vesa/vga.h
new file mode 100644
index 000000000..0637c2177
--- /dev/null
+++ b/hw/kdrive/vesa/vga.h
@@ -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_ */
diff --git a/hw/kdrive/vesa/vm86.c b/hw/kdrive/vesa/vm86.c
new file mode 100644
index 000000000..4bb90daf2
--- /dev/null
+++ b/hw/kdrive/vesa/vm86.c
@@ -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
diff --git a/hw/kdrive/vesa/vm86.h b/hw/kdrive/vesa/vm86.h
new file mode 100644
index 000000000..c0338e9d2
--- /dev/null
+++ b/hw/kdrive/vesa/vm86.h
@@ -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_ */