summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Dawes <dawes@xfree86.org>2000-08-28 15:29:19 +0000
committerDavid Dawes <dawes@xfree86.org>2000-08-28 15:29:19 +0000
commit3095deed7701a1a14be85dff4a6994028b5a6d09 (patch)
tree3e10f8480c8d9aa364d22b04ee4a19dc6739e9f3
parentf32448679118b77825625aafdc4d6ae4d636cc21 (diff)
565. Support for multithreaded libraries on NetBSD when used in conjunctionxf-4_0_1c
with the GNU pth library (#4113, Chris Sekiya). 564. Add /usr/pkg/bin to NetBSD's DefaultUserPath (#4112, Bernd Ernesti). 563. Add a (Linux-specific) VESA driver for Keith's small X server (#4111, Juliusz Chroboczek). 562. Update Hungarian xkb maps (#A.145, Peter Soos). remove koi8-r encoding file since it's built-in
-rw-r--r--hw/kdrive/vesa/Imakefile16
-rw-r--r--hw/kdrive/vesa/Xvesa.man63
-rw-r--r--hw/kdrive/vesa/vbe.c775
-rw-r--r--hw/kdrive/vesa/vbe.h166
-rw-r--r--hw/kdrive/vesa/vesa.c313
-rw-r--r--hw/kdrive/vesa/vesa.h56
-rw-r--r--hw/kdrive/vesa/vesainit.c91
7 files changed, 1480 insertions, 0 deletions
diff --git a/hw/kdrive/vesa/Imakefile b/hw/kdrive/vesa/Imakefile
new file mode 100644
index 000000000..bcf8613cb
--- /dev/null
+++ b/hw/kdrive/vesa/Imakefile
@@ -0,0 +1,16 @@
+XCOMM $XFree86$
+
+#include <Server.tmpl>
+
+SRCS = vesa.c vesainit.c vbe.c
+
+OBJS = vesa.o vesainit.o vbe.o
+
+INCLUDES = -I.. -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
+ -I../../../fb -I../../../mi -I../../../include -I../../../os \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(vesa,$(OBJS))
+InstallManPage(Xvesa,$(MANDIR))
+DependTarget()
diff --git a/hw/kdrive/vesa/Xvesa.man b/hw/kdrive/vesa/Xvesa.man
new file mode 100644
index 000000000..eafd3539b
--- /dev/null
+++ b/hw/kdrive/vesa/Xvesa.man
@@ -0,0 +1,63 @@
+.\" $XFree86$
+.TH Xvesa 1
+.SH NAME
+Xvesa \- VESA VBE tiny X server
+.SH SYNOPSIS
+.B Xvesa
+.RI [ :display ]
+.RI [ option ...]
+.SH DESCRIPTION
+Xvesa is an X server for Linux on the x86 platform. Xvesa manipulates
+the video hardware by running the VESA BIOS in VM86 mode. It
+therefore runs untrusted code with full priviledges, and is one of the
+most insecure X servers available.
+.B Run at your own risk.
+.SH OPTIONS
+In addition to the normal tiny-X server's options (to be described in
+a separate man page),
+.B Xvesa
+accepts the following command line switches:
+.TP 8
+.B -mode \fIn\fB
+specifies the VESA video mode to use. If mode
+.I n
+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. The list of video modes that your BIOS claims to support
+can be obtained by using the
+.B -listmodes
+option.
+.TP 8
+.B -listmodes
+tells the server to list all supported video modes. If
+.B -force
+was specified before
+.BR -listmodes ,
+lists all the modes that your BIOS claims to support, even those that
+the
+.B Xvesa
+server won't be able to use.
+.TP 8
+.B -force
+tells the server to disable some sanity checks and use the specified
+mode even if the BIOS claims not to support it.
+.SH KEYBOARD
+Xvesa handles the keyboard in the same manner as the
+.B Xfbdev
+Linux X server. See Xfbdev(1) (not yet written) for more information.
+.SH BUGS
+.B Xvesa
+opens all IO ports and runs your VESA BIOS, which may safely be
+assumed to be buggy. Allowing your users to run
+.B Xvesa
+is a major security hole. Allowing yourself to run
+.B Xvesa
+is probably a mistake.
+.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.
diff --git a/hw/kdrive/vesa/vbe.c b/hw/kdrive/vesa/vbe.c
new file mode 100644
index 000000000..1fdbc288f
--- /dev/null
+++ b/hw/kdrive/vesa/vbe.c
@@ -0,0 +1,775 @@
+/*
+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.
+*/
+/* $XFree86$ */
+
+#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"
+
+#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 MM(vi,i) ((char*)vi->magicMem)[i-MAGICMEM_BASE]
+#define MMW(vi,i) (*(U16*)(&MM(vi,i)))
+#define HM(vi,i) ((char*)vi->hiMem)[i-HIMEM_BASE]
+#define HMW(vi,i) (*(U16*)(&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 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) {
+ munmap(magicMem, MAGICMEM_SIZE);
+ munmap(loMem, LOMEM_SIZE);
+ goto fail;
+ }
+
+ vi = xalloc(sizeof(VbeInfoRec));
+ if (!vi)
+ goto unmapfail;
+
+ vi->devmem = devmem;
+ vi->devzero = devzero;
+ vi->magicMem = magicMem;
+ vi->loMem = loMem;
+ vi->hiMem = hiMem;
+ vi->fb = NULL;
+ 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;
+
+ 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;
+}
+
+void
+VbeCleanup(VbeInfoPtr vi)
+{
+ if(vi->fb)
+ VbeUnmapFramebuffer(vi);
+ munmap(vi->magicMem, MAGICMEM_SIZE);
+ munmap(vi->loMem, LOMEM_SIZE);
+ munmap(vi->hiMem, HIMEM_SIZE);
+ xfree(vi);
+}
+
+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;
+}
+
+VbeModeInfoBlock *
+VbeGetModeInfo(VbeInfoPtr vi, int mode)
+{
+ 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;
+ }
+ 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;
+}
+
+int
+VbeSetMode(VbeInfoPtr vi, int mode)
+{
+ int code;
+
+ vi->vms.regs.eax = 0x4F02;
+ vi->vms.regs.ebx = (mode & 0xFFFF) | 0xC000;
+ code = VbeDoInterrupt10(vi);
+ if(code < 0)
+ return -1;
+ return 0;
+}
+
+int
+VbeGetMode(VbeInfoPtr vi, int *mode)
+{
+ int code;
+ vi->vms.regs.eax = 0x4F03;
+ code = VbeDoInterrupt10(vi);
+ if(code < 0)
+ return - 1;
+ *mode = vi->vms.regs.ebx & 0xFFFF;
+ return 0;
+}
+
+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;
+}
+
+int
+VbeSaveState(VbeInfoPtr vi)
+{
+ 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;
+}
+
+int
+VbeRestoreState(VbeInfoPtr vi)
+{
+ 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);
+ code = VbeDoInterrupt10(vi);
+ if(code < 0)
+ return -1;
+ return 0;
+}
+
+void *
+VbeMapFramebuffer(VbeInfoPtr vi) {
+ U8 *fb;
+ VbeModeInfoBlock *vmib = (VbeModeInfoBlock*)&(LM(vi, vi->vmib_base));
+ int size;
+ int pagesize = getpagesize(), before, after;
+
+ size = vmib->BytesPerScanLine * vmib->YResolution;
+
+ 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);
+ return NULL;
+ }
+
+ vi->fb = fb;
+ vi->fb_size = before + size + after;
+ return fb + before;
+}
+
+int
+VbeUnmapFramebuffer(VbeInfoPtr vi)
+{
+ int code;
+ if(!vi->fb)
+ ErrorF("Unmapping frambuffer not mapped\n");
+ code = munmap(vi->fb, vi->fb_size);
+ 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;
+}
+
+int
+VbeSetPalette(VbeInfoPtr vi, int first, int number, U8 *entries)
+{
+ U8 *palette_scratch;
+ int i, 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);
+ return -1;
+ }
+
+ 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);
+ code = VbeDoInterrupt10(vi);
+ if(code < 0)
+ return -1;
+ return 0;
+}
+
+int
+VbeGetPalette(VbeInfoPtr vi, int first, int number, U8 *entries)
+{
+ U8 *palette_scratch;
+ int i, code;
+
+ code = PreparePalette(vi);
+ if(code < 0)
+ return -1;
+
+ 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);
+ return -1;
+ }
+
+ 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)
+ return -1;
+
+ for(i=0; i<number*4; i++)
+ entries[i] = palette_scratch[i] << (8-vi->palette_format);
+
+ return 0;
+}
+
+int
+VbeSetPaletteOptions(VbeInfoPtr vi, U8 bits, int wait)
+{
+ int code;
+ if(bits < 6 || bits > 8) {
+ ErrorF("Impossible palette format %d\n", vi->palette_format);
+ return -1;
+ }
+ ErrorF("Setting palette format to %d\n", vi->palette_format);
+ if(bits != vi->palette_format) {
+ vi->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;
+ }
+ vi->palette_wait = wait;
+ return 0;
+}
+
+int
+VbeReportInfo(VbeInfoPtr vi, VbeInfoBlock *vib)
+{
+ U32 i, p;
+ unsigned char c;
+ int error;
+ ErrorF("VBE version %c.%c (",
+ ((vib->VbeVersion >> 8) & 0xFF) + '0',
+ (vib->VbeVersion & 0xFF)+'0');
+ p = vib->OemStringPtr;
+ for(i = 0; 1; i++) {
+ c = VbeMemory(vi, MAKE_POINTER_1(p+i));
+ if(!c) break;
+ ErrorF("%c", c);
+ if (i > 32000) {
+ error = 1;
+ break;
+ }
+ }
+ ErrorF(")\n");
+ ErrorF("DAC is %s, controller is %sVGA compatible%s\n",
+ (vib->Capabilities[0]&1)?"fixed":"switchable",
+ (vib->Capabilities[0]&2)?"not ":"",
+ (vib->Capabilities[0]&3)?", RAMDAC causes snow":"");
+ ErrorF("Total memory: %lu bytes\n", 64L*vib->TotalMemory);
+ if(error)
+ return -1;
+ return 0;
+}
+
+int
+VbeReportModeInfo(VbeInfoPtr vi, U16 mode, VbeModeInfoBlock *vmib)
+{
+ int supported = (vmib->ModeAttributes&0x1)?1:0;
+ int colour = (vmib->ModeAttributes&0x8)?1:0;
+ int graphics = (vmib->ModeAttributes&0x10)?1:0;
+ int vga_compatible = !((vmib->ModeAttributes&0x20)?1:0);
+ int linear_fb = (vmib->ModeAttributes&0x80)?1:0;
+
+ ErrorF("0x%04X: %dx%dx%d%s",
+ (unsigned)mode,
+ (int)vmib->XResolution, (int)vmib->YResolution,
+ (int)vmib->BitsPerPixel,
+ colour?"":" (monochrome)");
+ switch(vmib->MemoryModel) {
+ case 0:
+ ErrorF(" text mode (%dx%d)",
+ (int)vmib->XCharSize, (int)vmib->YCharSize);
+ break;
+ case 1:
+ ErrorF(" CGA graphics");
+ break;
+ case 2:
+ ErrorF(" Hercules graphics");
+ break;
+ case 3:
+ ErrorF(" Planar (%d planes)", vmib->NumberOfPlanes);
+ break;
+ case 4:
+ ErrorF(" PseudoColor");
+ break;
+ case 5:
+ ErrorF(" Non-chain 4, 256 colour");
+ break;
+ case 6:
+ if(vmib->DirectColorModeInfo & 1)
+ ErrorF(" DirectColor");
+ else
+ ErrorF(" TrueColor");
+ ErrorF(" [%d:%d:%d:%d]",
+ vmib->RedMaskSize, vmib->GreenMaskSize, vmib->BlueMaskSize,
+ vmib->RsvdMaskSize);
+ if(vmib->DirectColorModeInfo & 2)
+ ErrorF(" (reserved bits are reserved)");
+ break;
+ case 7: ErrorF("YUV");
+ break;
+ default:
+ ErrorF("unknown MemoryModel 0x%X ", vmib->MemoryModel);
+ }
+ if(!supported)
+ ErrorF(" (unsupported)");
+ else if(!linear_fb)
+ ErrorF(" (no linear framebuffer)");
+ ErrorF("\n");
+ return 0;
+}
+int
+VbeDoInterrupt10(VbeInfoPtr vi)
+{
+ int code;
+ int oldax;
+
+ oldax = vi->vms.regs.eax & 0xFFFF;
+
+ code = VbeDoInterrupt(vi, 0x10);
+
+ if(code < 0)
+ return -1;
+
+ if((vi->vms.regs.eax & 0xFFFF) != 0x4F) {
+ 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");
+ }
+ }
+ 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;
+ code = vm86_loop(vi);
+ 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 int
+vm86_loop(VbeInfoPtr vi)
+{
+ int code;
+ while(1) {
+ code = vm86old(&vi->vms);
+ switch(VM86_TYPE(code)) {
+ case VM86_SIGNAL:
+ continue;
+ case VM86_UNKNOWN:
+ ErrorF("Unhandled GP fault in VM86 code\n",
+ VM86_ARG(code));
+ 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");
+ return -1;
+ default:
+ ErrorF("Unexpected result code 0x%X from vm86\n", code);
+ }
+ }
+}
+
+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;
+ }
+}
+
+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);
+ }
+}
+
+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;
+ return res;
+}
+
+#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
new file mode 100644
index 000000000..1b6c9630e
--- /dev/null
+++ b/hw/kdrive/vesa/vbe.h
@@ -0,0 +1,166 @@
+/*
+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.
+*/
+/* $XFree86$ */
+
+#ifndef _VBE_H
+#define _VBE_H
+
+#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, *fb;
+ U32 fb_size;
+ 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;
+} VbeInfoRec, *VbeInfoPtr;
+
+typedef struct _VbeInfoBlock {
+ U8 VbeSignature[4]; /* VBE Signature */
+ U16 VbeVersion; /* VBE Version */
+ U32 OemStringPtr; /* Pointer to OEM String */
+ U8 Capabilities[4]; /* Capabilities of graphics controller */
+ U32 VideoModePtr; /* Pointer to VideoModeList */
+ U16 TotalMemory; /* Number of 64kb memory blocks */
+/* Added for VBE 2.0 */
+ U16 OemSoftwareRev; /* VBE implementation Software revision */
+ U32 OemVendorNamePtr; /* Pointer to Vendor Name String */
+ U32 OemProductNamePtr; /* Pointer to Product Name String */
+ U32 OemProductRevPtr; /* Pointer to Product Revision String */
+ U8 Reserved[222]; /* Reserved for VBE implementation */
+ U8 OemData[256]; /* Data Area for OEM Strings*/
+} __attribute__((packed)) VbeInfoBlock;
+
+typedef struct _VbeModeInfoBlock {
+/* Mandatory information for all VBE revisions */
+ U16 ModeAttributes; /* mode attributes */
+ U8 WinAAttributes; /* window A attributes */
+ U8 WinBAttributes; /* window B attributes */
+ U16 WinGranularity; /* window granularity */
+ U16 WinSize; /* window size */
+ U16 WinASegment; /* window A start segment */
+ U16 WinBSegment; /* window B start segment */
+ U32 WinFuncPtr; /* pointer to window function */
+ U16 BytesPerScanLine; /* bytes per scan line */
+/* Mandatory information for VBE 1.2 and above */
+ U16 XResolution; /* horizontal resolution */
+ U16 YResolution; /* vertical resolution */
+ U8 XCharSize; /* character cell width in pixels */
+ U8 YCharSize; /* character cell height in pixels */
+ U8 NumberOfPlanes; /* number of memory planes */
+ U8 BitsPerPixel; /* bits per pixel */
+ U8 NumberOfBanks; /* number of banks */
+ U8 MemoryModel; /* memory model type */
+ U8 BankSize; /* bank size in KB */
+ U8 NumberOfImagePages; /* number of images */
+ U8 Reserved; /* reserved for page function */
+/* Direct Color fields (required for direct/6 and YUV/7 memory models) */
+ U8 RedMaskSize; /* size of direct color red mask in bits */
+ U8 RedFieldPosition; /* bit position of lsb of red mask */
+ U8 GreenMaskSize; /* size of direct color green mask in bits */
+ U8 GreenFieldPosition; /* bit position of lsb of green mask */
+ U8 BlueMaskSize; /* size of direct color blue mask in bits */
+ U8 BlueFieldPosition; /* bit position of lsb of blue mask */
+ U8 RsvdMaskSize; /* size of direct color reserved mask bits*/
+ U8 RsvdFieldPosition; /* bit position of lsb of reserved mask */
+ U8 DirectColorModeInfo; /* direct color mode attributes */
+/* Mandatory information for VBE 2.0 and above */
+ U32 PhysBasePtr; /* physical address for flat memory fb */
+ U32 OffScreenMemOffset; /* pointer to start of off screen memory */
+ U16 OffScreenMemSize; /* amount of off screen memory in 1k units */
+ U8 Reserved2[206]; /* remainder of ModeInfoBlock */
+} __attribute__((packed)) VbeModeInfoBlock;
+
+
+typedef struct _SupVbeInfoBlock {
+ U8 SupVbeSignature[7]; /* Supplemental VBE Signature */
+ U16 SupVbeVersion; /* Supplemental VBE Version*/
+ U8 SupVbeSubFunc[8]; /* Bitfield of supported subfunctions */
+ U16 OemSoftwareRev; /* OEM Software revision */
+ U32 OemVendorNamePtr; /* Pointer to Vendor Name String */
+ U32 OemProductNamePtr; /* Pointer to Product Name String */
+ U32 OemProductRevPtr; /* Pointer to Product Revision String */
+ U32 OemStringPtr; /* Pointer to OEM String */
+ 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 VbeGetMode(VbeInfoPtr vi, int *mode);
+int VbeSetupStateBuffer(VbeInfoPtr vi);
+int VbeSaveState(VbeInfoPtr vi);
+int VbeRestoreState(VbeInfoPtr vi);
+void *VbeMapFramebuffer(VbeInfoPtr vi);
+int VbeUnmapFrambuffer(VbeInfoPtr vi);
+int VbeSetPalette(VbeInfoPtr vi, int first, int number, U8 *entries);
+int VbeSetPaletteOptions(VbeInfoPtr vi, U8 bits, int wait);
+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);
+void VbeWriteMemory(VbeInfoPtr, U32, U8);
+int VbeAllocateMemory(VbeInfoPtr, int);
+#endif
diff --git a/hw/kdrive/vesa/vesa.c b/hw/kdrive/vesa/vesa.c
new file mode 100644
index 000000000..cb72ea74d
--- /dev/null
+++ b/hw/kdrive/vesa/vesa.c
@@ -0,0 +1,313 @@
+/*
+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.
+*/
+/* $XFree86$ */
+
+#include "vesa.h"
+
+#define DEFAULT_MODE 0x115
+
+int vesa_video_mode = DEFAULT_MODE;
+Bool vesa_force_mode = FALSE;
+
+static Bool
+vesaModeSupported(VbeInfoPtr vi, VbeModeInfoBlock *vmib, Bool complain)
+{
+ if((vmib->ModeAttributes & 0x10) == 0) {
+ if(complain)
+ ErrorF("Text mode specified.\n");
+ return FALSE;
+ }
+ if(vmib->MemoryModel != 0x06 && vmib->MemoryModel != 0x04) {
+ if(complain)
+ ErrorF("Unsupported memory model 0x%X\n", vmib->MemoryModel);
+ return FALSE;
+ }
+ if((vmib->ModeAttributes & 0x80) == 0) {
+ if(complain)
+ ErrorF("No linear framebuffer available in this mode\n");
+ return FALSE;
+ }
+ if(!(vmib->ModeAttributes&1)) {
+ if(complain)
+ ErrorF("Mode not supported on this hardware\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+Bool
+vesaListModes()
+{
+ int code;
+ VbeInfoPtr vi = NULL;
+ VbeInfoBlock *vib;
+ VbeModeInfoBlock *vmib;
+ unsigned i;
+
+ vi = VbeSetup();
+ if(!vi)
+ goto fail;
+
+ vib = VbeGetInfo(vi);
+ if(!vib)
+ goto fail;
+
+ VbeReportInfo(vi, vib);
+ i = MAKE_POINTER_1(vib->VideoModePtr);
+
+ while(VbeMemoryW(vi, i) != 0xFFFF) {
+ vmib = VbeGetModeInfo(vi, VbeMemoryW(vi, i));
+ if(!vmib)
+ goto fail;
+ if(vesa_force_mode || vesaModeSupported(vi, vmib, FALSE))
+ VbeReportModeInfo(vi, VbeMemoryW(vi, i), vmib);
+ i+=2;
+ }
+
+ VbeCleanup(vi);
+ return TRUE;
+
+ fail:
+ VbeCleanup(vi);
+ return FALSE;
+}
+
+Bool
+vesaCardInit(KdCardInfo *card)
+{
+ VesaPrivPtr priv;
+ int code;
+
+ priv = xalloc(sizeof(VesaPrivRec));
+ if(!priv)
+ goto fail;
+
+ priv->mode = vesa_video_mode;
+
+ priv->vi = VbeSetup();
+ if(!priv->vi)
+ goto fail;
+
+ priv->vib = VbeGetInfo(priv->vi);
+ if(!priv->vib)
+ goto fail;
+
+ priv->vmib = VbeGetModeInfo(priv->vi, priv->mode);
+ if(!priv->vmib)
+ goto fail;
+
+ if(!vesa_force_mode && !vesaModeSupported(priv->vi, priv->vmib, TRUE))
+ goto fail;
+
+ code = VbeSetupStateBuffer(priv->vi);
+ if(code < 0)
+ goto fail;
+
+ code = VbeSaveState(priv->vi);
+ if(code<0)
+ goto fail;
+
+ priv->fb = VbeMapFramebuffer(priv->vi);
+ if(!priv->vi)
+ goto fail;
+
+ card->driver = priv;
+
+ return TRUE;
+
+ fail:
+ if(priv) {
+ if(priv->vi)
+ VbeCleanup(priv->vi);
+ xfree(priv);
+ }
+ return FALSE;
+}
+
+Bool
+vesaScreenInit(KdScreenInfo *screen)
+{
+ VesaPrivPtr priv = screen->card->driver;
+ Pixel allbits;
+ int depth;
+
+ screen->width = priv->vmib->XResolution;
+ screen->height = priv->vmib->YResolution;
+ screen->fb[0].depth = priv->vmib->BitsPerPixel;
+ screen->fb[0].bitsPerPixel = priv->vmib->BitsPerPixel;
+ screen->fb[0].byteStride = priv->vmib->BytesPerScanLine;
+ screen->fb[0].pixelStride =
+ (priv->vmib->BytesPerScanLine * 8) / priv->vmib->BitsPerPixel;
+
+ if(priv->vmib->MemoryModel == 0x06) {
+ /* TrueColor or DirectColor */
+ screen->fb[0].visuals = (1 << TrueColor);
+ screen->fb[0].redMask =
+ FbStipMask(priv->vmib->RedFieldPosition, priv->vmib->RedMaskSize);
+ screen->fb[0].greenMask =
+ FbStipMask(priv->vmib->GreenFieldPosition, priv->vmib->GreenMaskSize);
+ screen->fb[0].blueMask =
+ FbStipMask(priv->vmib->BlueFieldPosition, priv->vmib->BlueMaskSize);
+ allbits =
+ screen->fb[0].redMask |
+ screen->fb[0].greenMask |
+ screen->fb[0].blueMask;
+ depth = 32;
+ while (depth && !(allbits & (1 << (depth - 1))))
+ depth--;
+ screen->fb[0].depth = depth;
+ } else if (priv->vmib->MemoryModel == 0x04) {
+ /* PseudoColor */
+ screen->fb[0].visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ screen->fb[0].blueMask = 0x00;
+ screen->fb[0].greenMask = 0x00;
+ screen->fb[0].redMask = 0x00;
+ } else {
+ ErrorF("Unsupported VESA MemoryModel 0x%02X\n",
+ priv->vmib->MemoryModel);
+ return FALSE;
+ }
+
+ screen->rate = 72;
+ screen->fb[0].frameBuffer = (CARD8 *)(priv->fb);
+
+ return TRUE;
+}
+
+Bool
+vesaInitScreen(ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+void
+vesaEnable(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ VesaPrivPtr priv = pScreenPriv->card->driver;
+ int code;
+ int palette_wait = 0, palette_hi = 0;
+
+ code = VbeSetMode(priv->vi, priv->mode);
+ if(code < 0)
+ FatalError("Couldn't set mode\n");
+
+ 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);
+
+ return;
+}
+
+void
+vesaDisable(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ VesaPrivPtr priv = pScreenPriv->card->driver;
+
+}
+
+void
+vesaPreserve(KdCardInfo *card)
+{
+ VesaPrivPtr priv = card->driver;
+ int code;
+
+ code = VbeSaveState(priv->vi);
+ if(code < 0)
+ FatalError("Couldn't save state\n");
+
+ return;
+}
+
+void
+vesaRestore(KdCardInfo *card)
+{
+ VesaPrivPtr priv = card->driver;
+ VbeRestoreState(priv->vi);
+ return;
+}
+
+void
+vesaCardFini(KdCardInfo *card)
+{
+ VesaPrivPtr priv = card->driver;
+ VbeUnmapFramebuffer(priv->vi);
+ VbeCleanup(priv->vi);
+ return;
+}
+
+void
+vesaScreenFini(KdScreenInfo *screen)
+{
+ return;
+}
+
+void
+vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ VesaPrivPtr priv = pScreenPriv->card->driver;
+ int i, j, k;
+ CARD8 scratch[4*256];
+
+ i = 0;
+ while(i < n) {
+ j = i + 1;
+ /* For some reason, doing more than one entry at a time breaks */
+ while(j < n && pdefs[j].pixel == pdefs[j-1].pixel + 1 && j - i < 1)
+ j++;
+ for(k=0; k<(j - i); k++) {
+ /* The opposite of what the spec says? */
+ scratch[k+3] = 0;
+ scratch[k+2] = pdefs[i+k].red >> 8;
+ scratch[k+1] = pdefs[i+k].green >> 8;
+ scratch[k+0] = pdefs[i+k].blue >> 8;
+ }
+ VbeSetPalette(priv->vi, pdefs[i].pixel, j - i, scratch);
+ i = j;
+ }
+}
+
+void
+vesaGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ VesaPrivPtr priv = pScreenPriv->card->driver;
+ int first, i, j, k;
+ CARD8 scratch[4];
+
+ for(i = 0; i<n; i++) {
+ VbeGetPalette(priv->vi, pdefs[i].pixel, 1, scratch);
+ pdefs[i].red = scratch[2]<<8;
+ pdefs[i].green = scratch[1]<<8;
+ pdefs[i].blue = scratch[0]<<8;
+ }
+}
diff --git a/hw/kdrive/vesa/vesa.h b/hw/kdrive/vesa/vesa.h
new file mode 100644
index 000000000..d6306bb56
--- /dev/null
+++ b/hw/kdrive/vesa/vesa.h
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+/* $XFree86$ */
+
+#ifndef _VESA_H_
+#define _VESA_H_
+
+#include "kdrive.h"
+#include <sys/vm86.h>
+#include "vbe.h"
+
+typedef struct _VesaPriv {
+ int mode;
+ VbeInfoPtr vi;
+ VbeInfoBlock *vib;
+ VbeModeInfoBlock *vmib;
+ void *fb;
+} VesaPrivRec, *VesaPrivPtr;
+
+extern int vesa_video_mode;
+extern Bool vesa_force_mode;
+
+Bool vesaListModes(void);
+Bool vesaInitialize(KdCardInfo *card, VesaPrivPtr priv);
+Bool vesaCardInit(KdCardInfo *card);
+Bool vesaScreenInit(KdScreenInfo *screen);
+Bool vesaInitScreen(ScreenPtr pScreen);
+void 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);
+
+#endif _VESA_H_
diff --git a/hw/kdrive/vesa/vesainit.c b/hw/kdrive/vesa/vesainit.c
new file mode 100644
index 000000000..58fe3fed6
--- /dev/null
+++ b/hw/kdrive/vesa/vesainit.c
@@ -0,0 +1,91 @@
+/*
+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.
+*/
+/* $XFree86$ */
+
+#include "vesa.h"
+
+KdCardFuncs vesaFuncs = {
+ vesaCardInit, /* cardinit */
+ vesaScreenInit, /* scrinit */
+ vesaInitScreen, /* initScreen */
+ vesaPreserve, /* preserve */
+ vesaEnable, /* enable */
+ 0, /* dpms */
+ vesaDisable, /* disable */
+ vesaRestore, /* restore */
+ vesaScreenFini, /* scrfini */
+ vesaCardFini, /* cardfini */
+
+ 0, /* initCursor */
+ 0, /* enableCursor */
+ 0, /* disableCursor */
+ 0, /* finiCursor */
+ 0, /* recolorCursor */
+
+ 0, /* initAccel */
+ 0, /* enableAccel */
+ 0, /* syncAccel */
+ 0, /* disableAccel */
+ 0, /* finiAccel */
+
+ vesaGetColors, /* getColors */
+ vesaPutColors, /* putColors */
+};
+
+void
+InitCard(char *name)
+{
+ KdCardAttr attr;
+ KdCardInfoAdd(&vesaFuncs, &attr, 0);
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput(&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+int
+ddxProcessArgument (int argc, char **argv, int i)
+{
+ if(!strcmp(argv[i], "-mode")) {
+ if(i+1 < argc) {
+ vesa_video_mode = strtol(argv[i+1], NULL, 0);
+ } else
+ UseMsg();
+ return 2;
+ } else if(!strcmp(argv[i], "-force")) {
+ vesa_force_mode = TRUE;
+ return 1;
+ } else if(!strcmp(argv[i], "-listmodes")) {
+ vesaListModes();
+ exit(0);
+ }
+
+ return KdProcessArgument(argc, argv, i);
+}