565. Support for multithreaded libraries on NetBSD when used in conjunction
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
This commit is contained in:
parent
f324486791
commit
3095deed77
16
hw/kdrive/vesa/Imakefile
Normal file
16
hw/kdrive/vesa/Imakefile
Normal file
|
@ -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()
|
63
hw/kdrive/vesa/Xvesa.man
Normal file
63
hw/kdrive/vesa/Xvesa.man
Normal file
|
@ -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.
|
775
hw/kdrive/vesa/vbe.c
Normal file
775
hw/kdrive/vesa/vbe.c
Normal file
|
@ -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
|
166
hw/kdrive/vesa/vbe.h
Normal file
166
hw/kdrive/vesa/vbe.h
Normal file
|
@ -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
|
313
hw/kdrive/vesa/vesa.c
Normal file
313
hw/kdrive/vesa/vesa.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
56
hw/kdrive/vesa/vesa.h
Normal file
56
hw/kdrive/vesa/vesa.h
Normal file
|
@ -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_
|
91
hw/kdrive/vesa/vesainit.c
Normal file
91
hw/kdrive/vesa/vesainit.c
Normal file
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user