diff options
Diffstat (limited to 'hw/kdrive/vesa/vga.c')
-rw-r--r-- | hw/kdrive/vesa/vga.c | 240 |
1 files changed, 240 insertions, 0 deletions
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) +{ +} |