123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- /*
- 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.
- */
- #ifdef HAVE_CONFIG_H
- #include <kdrive-config.h>
- #endif
- #include "vesa.h"
- static int VbeGetVib(Vm86InfoPtr vi, VbeInfoBlock * vib)
- {
- int code;
- int mark;
- int vib_base;
- VbeInfoBlock *vib_low;
- mark = Vm86MarkMemory(vi);
- vib_base = Vm86AllocateMemory(vi, sizeof(VbeInfoBlock));
- vib_low = (VbeInfoBlock *) & (LM(vi, vib_base));
- vi->vms.regs.eax = 0x4F00;
- vi->vms.regs.es = POINTER_SEGMENT(vib_base);
- vi->vms.regs.edi = POINTER_OFFSET(vib_base);
- memcpy(vib_low->VbeSignature, "VBE2", 4);
- code = VbeDoInterrupt10(vi);
- if (code >= 0) {
- if (memcmp(vib_low->VbeSignature, "VESA", 4) == 0)
- *vib = *vib_low;
- else
- code = -1;
- }
- Vm86ReleaseMemory(vi, mark);
- return code;
- }
- static int VbeGetVmib(Vm86InfoPtr vi, int mode, VbeModeInfoBlock * vmib)
- {
- int code;
- int mark;
- int vmib_base;
- VbeModeInfoBlock *vmib_low;
- mark = Vm86MarkMemory(vi);
- vmib_base = Vm86AllocateMemory(vi, sizeof(VbeModeInfoBlock));
- vmib_low = (VbeModeInfoBlock *) & (LM(vi, vmib_base));
- vi->vms.regs.eax = 0x4F01;
- vi->vms.regs.ecx = mode & 0xFFFF;
- vi->vms.regs.es = POINTER_SEGMENT(vmib_base);
- vi->vms.regs.edi = POINTER_OFFSET(vmib_base);
- code = VbeDoInterrupt10(vi);
- if (code >= 0)
- *vmib = *vmib_low;
- Vm86ReleaseMemory(vi, mark);
- return code;
- }
- static int VbeReportVib(Vm86InfoPtr vi, VbeInfoBlock * vib)
- {
- U32 i, p;
- unsigned char c;
- int error = 0;
- ErrorF("VBE version %c.%c (",
- ((vib->VbeVersion >> 8) & 0xFF) + '0',
- (vib->VbeVersion & 0xFF) + '0');
- p = vib->OemStringPtr;
- for (i = 0; 1; i++) {
- c = Vm86Memory(vi, MAKE_POINTER_1(p + i));
- if (!c)
- break;
- if (c >= ' ')
- 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 kilobytes\n", 64L * vib->TotalMemory);
- if (error)
- return -1;
- return 0;
- }
- #if 0
- static int VbeReportModeInfo(Vm86InfoPtr 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)",
- graphics ? "" : " (graphics)",
- vga_compatible ? "" : " (vga compatible)",
- linear_fb ? "" : " (linear frame buffer)");
- 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;
- }
- #endif
- void VbeReportInfo(Vm86InfoPtr vi)
- {
- VbeInfoBlock vib;
- int code;
- code = VbeGetVib(vi, &vib);
- if (code >= 0)
- VbeReportVib(vi, &vib);
- }
- int VbeGetNmode(Vm86InfoPtr vi)
- {
- VbeInfoBlock vib;
- int code;
- unsigned int p;
- int n;
- int mode;
- code = VbeGetVib(vi, &vib);
- if (code >= 0) {
- p = MAKE_POINTER_1(vib.VideoModePtr);
- for (n = 0;; n++) {
- mode = Vm86MemoryW(vi, p);
- if (mode == 0xffff)
- break;
- p += 2;
- }
- code = n;
- }
- return code;
- }
- int VbeGetModes(Vm86InfoPtr vi, VesaModePtr modes, int nmode)
- {
- VbeInfoBlock vib;
- int code;
- unsigned int p;
- int n;
- int mode;
- VbeModeInfoBlock vmib;
- code = VbeGetVib(vi, &vib);
- if (code < 0)
- return code;
- memset(modes, '\0', nmode * sizeof(VesaModeRec));
- p = MAKE_POINTER_1(vib.VideoModePtr);
- for (n = 0; n < nmode; n++) {
- mode = Vm86MemoryW(vi, p);
- if (mode == 0xffff)
- break;
- modes[n].mode = mode;
- modes[n].vbe = 1;
- p += 2;
- }
- nmode = n;
- for (n = 0; n < nmode; n++) {
- code = VbeGetVmib(vi, modes[n].mode, &vmib);
- if (code >= 0) {
- modes[n].ModeAttributes = vmib.ModeAttributes;
- modes[n].NumberOfPlanes = vmib.NumberOfPlanes;
- modes[n].BitsPerPixel = vmib.BitsPerPixel;
- modes[n].MemoryModel = vmib.MemoryModel;
- modes[n].RedMaskSize = vmib.RedMaskSize;
- modes[n].RedFieldPosition = vmib.RedFieldPosition;
- modes[n].GreenMaskSize = vmib.GreenMaskSize;
- modes[n].GreenFieldPosition = vmib.GreenFieldPosition;
- modes[n].BlueMaskSize = vmib.BlueMaskSize;
- modes[n].BlueFieldPosition = vmib.BlueFieldPosition;
- modes[n].RsvdMaskSize = vmib.RsvdMaskSize;
- modes[n].RsvdFieldPosition = vmib.RsvdFieldPosition;
- modes[n].DirectColorModeInfo = vmib.DirectColorModeInfo;
- modes[n].XResolution = vmib.XResolution;
- modes[n].YResolution = vmib.YResolution;
- modes[n].BytesPerScanLine = vmib.BytesPerScanLine;
- }
- }
- return nmode;
- }
- VbeInfoPtr VbeInit(Vm86InfoPtr vi)
- {
- VbeInfoPtr vbe;
- int code;
- VbeInfoBlock vib;
- code = VbeGetVib(vi, &vib);
- if (code < 0)
- return 0;
- vbe = malloc(sizeof(VbeInfoRec));
- if (!vbe)
- return 0;
- vbe->palette_format = 6;
- vbe->palette_wait = TRUE;
- return vbe;
- }
- void VbeCleanup(Vm86InfoPtr vi, VbeInfoPtr vbe)
- {
- free(vbe);
- }
- static int VbeSetPaletteOptions(Vm86InfoPtr vi, VbeInfoPtr vbe, U8 bits, int wait)
- {
- int code;
- if (bits < 6 || bits > 8) {
- ErrorF("Impossible palette format %d\n", bits);
- return -1;
- }
- if (bits != vbe->palette_format) {
- vbe->palette_format = 0;
- vi->vms.regs.eax = 0x4F08;
- vi->vms.regs.ebx = bits << 8;
- code = VbeDoInterrupt10(vi);
- if (code < 0)
- return -1;
- vbe->palette_format = bits;
- }
- vbe->palette_wait = wait;
- return 0;
- }
- int VbeSetMode(Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, int linear, int direct)
- {
- int code;
- VbeInfoBlock vib;
- int palette_wait = 0, palette_hi = 0;
- code = VbeGetVib(vi, &vib);
- if (code < 0)
- return -1;
- code = VbeGetVmib(vi, mode, &vbe->vmib);
- if (code < 0)
- return -1;
- mode = (mode & 0xffff) & ~0x8000;
- if (linear)
- mode |= 0x4000;
- vi->vms.regs.eax = 0x4F02;
- vi->vms.regs.ebx = mode;
- code = VbeDoInterrupt10(vi);
- if (code < 0)
- return -1;
- vbe->windowA_offset = vbe->windowB_offset = -1;
- vbe->last_window = 1;
- if (!direct) {
- if (vib.Capabilities[0] & 1)
- palette_hi = 1;
- if (vib.Capabilities[0] & 4)
- palette_wait = 1;
- if (palette_hi || palette_wait)
- VbeSetPaletteOptions(vi, vbe, palette_hi ? 8 : 6,
- palette_wait);
- }
- return 0;
- }
- int VbeGetMode(Vm86InfoPtr 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;
- }
- void *VbeMapFramebuffer(Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, int *ret_size,
- CARD32 * ret_phys)
- {
- U8 *fb;
- VbeInfoBlock vib;
- VbeModeInfoBlock vmib;
- int size;
- int pagesize = getpagesize();
- int before, after;
- if (VbeGetVib(vi, &vib) < 0)
- return 0;
- if (VbeGetVmib(vi, mode, &vmib) < 0)
- return 0;
- size = 1024 * 64L * vib.TotalMemory;
- *ret_size = size;
- *ret_phys = vmib.PhysBasePtr;
- before = vmib.PhysBasePtr % pagesize;
- after = pagesize - ((vmib.PhysBasePtr + size) % pagesize);
- if (after == pagesize)
- after = 0;
- fb = KdMapDevice(vmib.PhysBasePtr - before, before + size + after);
- if (fb == 0) {
- ErrorF("Failed to map framebuffer\n");
- return NULL;
- }
- KdSetMappedMode(vmib.PhysBasePtr - before, before + size + after,
- KD_MAPPED_MODE_FRAMEBUFFER);
- return fb + before;
- }
- void VbeUnmapFramebuffer(Vm86InfoPtr vi, VbeInfoPtr vbe, int mode, void *fb)
- {
- VbeInfoBlock vib;
- VbeModeInfoBlock vmib;
- int size;
- int pagesize = getpagesize();
- int before, after;
- if (VbeGetVib(vi, &vib) < 0)
- return;
- if (VbeGetVmib(vi, mode, &vmib) < 0)
- return;
- size = 1024 * 64L * vib.TotalMemory;
- before = vmib.PhysBasePtr % pagesize;
- after = pagesize - ((vmib.PhysBasePtr + size) % pagesize);
- if (after == pagesize)
- after = 0;
- fb = (void *)((char *)fb - before);
- KdUnmapDevice(fb, before + size + after);
- KdResetMappedMode(vmib.PhysBasePtr - before, before + size + after,
- KD_MAPPED_MODE_FRAMEBUFFER);
- }
- int
- VbeSetPalette(Vm86InfoPtr vi, VbeInfoPtr vbe, int first, int number,
- U8 * entries)
- {
- U8 *palette_scratch;
- int mark;
- int palette_base;
- int i, 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;
- }
- if (vbe->palette_format < 6 || vbe->palette_format > 8) {
- ErrorF("Impossible palette format %d\n", vbe->palette_format);
- return -1;
- }
- mark = Vm86MarkMemory(vi);
- palette_base = Vm86AllocateMemory(vi, 4 * 256);
- palette_scratch = &LM(vi, palette_base);
- for (i = 0; i < number * 4; i++)
- palette_scratch[i] = entries[i] >> (8 - vbe->palette_format);
- vi->vms.regs.eax = 0x4F09;
- if (vbe->palette_wait)
- vi->vms.regs.ebx = 0x80;
- else
- vi->vms.regs.ebx = 0x00;
- vi->vms.regs.ecx = number;
- vi->vms.regs.edx = first;
- vi->vms.regs.es = POINTER_SEGMENT(palette_base);
- vi->vms.regs.edi = POINTER_OFFSET(palette_base);
- code = VbeDoInterrupt10(vi);
- Vm86ReleaseMemory(vi, mark);
- if (code < 0)
- return -1;
- return 0;
- }
- int
- VbeGetPalette(Vm86InfoPtr vi, VbeInfoPtr vbe, int first, int number,
- U8 * entries)
- {
- U8 *palette_scratch;
- int mark;
- int palette_base;
- int i, 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;
- }
- if (vbe->palette_format < 6 || vbe->palette_format > 8) {
- ErrorF("Impossible palette format %d\n", vbe->palette_format);
- return -1;
- }
- mark = Vm86MarkMemory(vi);
- palette_base = Vm86AllocateMemory(vi, 4 * 256);
- palette_scratch = &LM(vi, palette_base);
- vi->vms.regs.eax = 0x4F09;
- vi->vms.regs.ebx = 0x01;
- vi->vms.regs.ecx = number;
- vi->vms.regs.edx = first;
- vi->vms.regs.es = POINTER_SEGMENT(palette_base);
- vi->vms.regs.edi = POINTER_OFFSET(palette_base);
- code = VbeDoInterrupt10(vi);
- if (code >= 0) {
- for (i = 0; i < number * 4; i++)
- entries[i] =
- palette_scratch[i] << (8 - vbe->palette_format);
- }
- Vm86ReleaseMemory(vi, mark);
- return 0;
- }
- static int VbeReallySetWindow(Vm86InfoPtr vi, U8 window, U16 winnum)
- {
- int code;
- vi->vms.regs.eax = 0x4F05;
- vi->vms.regs.ebx = window;
- vi->vms.regs.edx = winnum;
- code = VbeDoInterrupt10(vi);
- if (code < 0)
- return -1;
- return 0;
- }
- void *VbeSetWindow(Vm86InfoPtr vi, VbeInfoPtr vbe, int offset, int purpose,
- int *size_return)
- {
- int window_size = vbe->vmib.WinSize * 1024;
- int code;
- int winnum;
- if (vbe->windowA_offset >= 0)
- if (vbe->windowA_offset <= offset
- && vbe->windowA_offset + window_size > offset)
- if (vbe->vmib.WinAAttributes & purpose)
- goto windowA;
- if (vbe->windowB_offset >= 0)
- if (vbe->windowB_offset <= offset
- && vbe->windowB_offset + window_size > offset)
- if (vbe->vmib.WinBAttributes & purpose)
- goto windowB;
- if (!(vbe->vmib.WinBAttributes & purpose) ||
- !(vbe->vmib.WinBAttributes & VBE_WINDOW_RELOCATE))
- goto set_windowA;
- if (!(vbe->vmib.WinAAttributes & purpose) ||
- !(vbe->vmib.WinAAttributes & VBE_WINDOW_RELOCATE))
- goto set_windowB;
- if (vbe->last_window)
- goto set_windowA;
- else
- goto set_windowB;
- set_windowA:
- winnum = offset / (vbe->vmib.WinGranularity * 1024);
- code = VbeReallySetWindow(vi, 0, winnum);
- if (code < 0) {
- ErrorF("Couldn't set window A to %d*%d\n",
- (int)winnum, (int)vbe->vmib.WinGranularity);
- return NULL;
- }
- vbe->windowA_offset = winnum * vbe->vmib.WinGranularity * 1024;
- windowA:
- vbe->last_window = 0;
- *size_return =
- vbe->vmib.WinSize * 1024 - (offset - vbe->windowA_offset);
- return ((U8 *) & (LM(vi, MAKE_POINTER(vbe->vmib.WinASegment, 0)))) +
- offset - vbe->windowA_offset;
- set_windowB:
- winnum = offset / (vbe->vmib.WinGranularity * 1024);
- code = VbeReallySetWindow(vi, 1, winnum);
- if (code < 0) {
- ErrorF("Couldn't set window B to %d*%d\n",
- (int)winnum, (int)vbe->vmib.WinGranularity);
- return NULL;
- }
- vbe->windowB_offset = winnum * vbe->vmib.WinGranularity * 1024;
- windowB:
- vbe->last_window = 1;
- *size_return =
- vbe->vmib.WinSize * 1024 - (offset - vbe->windowB_offset);
- return ((U8 *) & (LM(vi, MAKE_POINTER(vbe->vmib.WinBSegment, 0)))) +
- offset - vbe->windowB_offset;
- }
- static const int VbeDPMSModes[4] = {
- 0x00, /* KD_DPMS_NORMAL */
- 0x01, /* KD_DPMS_STANDBY */
- 0x02, /* KD_DPMS_SUSPEND */
- 0x04, /* KD_DPMS_POWERDOWN */
- };
- Bool VbeDPMS(Vm86InfoPtr vi, int mode)
- {
- int code;
- /*
- * Check which modes are supported
- */
- vi->vms.regs.eax = 0x4f10;
- vi->vms.regs.ebx = 0x0000;
- vi->vms.regs.es = 0;
- vi->vms.regs.edi = 0;
- code = VbeDoInterrupt10(vi);
- if (code < 0) {
- ErrorF("No DPMS Support %d\n", code);
- return FALSE;
- }
- /* Skip this stage if it's not supported */
- if (((vi->vms.regs.ebx >> 4) & VbeDPMSModes[mode]) !=
- VbeDPMSModes[mode])
- return FALSE;
- /* Select this mode */
- vi->vms.regs.eax = 0x4f10;
- vi->vms.regs.ebx = (VbeDPMSModes[mode] << 8) | 0x01;
- code = VbeDoInterrupt10(vi);
- if (code < 0) {
- ErrorF("DPMS failed %d\n", code);
- return FALSE;
- }
- return TRUE;
- }
- static int VbeDoInterruptE6(Vm86InfoPtr vi)
- {
- int code;
- int oldax;
- oldax = vi->vms.regs.eax & 0xffff;
- code = Vm86DoPOST(vi);
- ErrorF("POST (0x%04X): 0x%04lX\n", oldax, vi->vms.regs.eax & 0xffff);
- return code;
- }
- Bool VbeBoot(Vm86InfoPtr vi)
- {
- int code;
- int bus = 1;
- int device = 0;
- int function = 0;
- vi->vms.regs.eax = (bus << 8) | (device << 3) | (function & 0x7);
- code = VbeDoInterruptE6(vi);
- ErrorF("Boot: %d\n", code);
- return TRUE;
- }
- int VbeDoInterrupt10(Vm86InfoPtr vi)
- {
- int code;
- int oldax;
- oldax = vi->vms.regs.eax & 0xFFFF;
- code = Vm86DoInterrupt(vi, 0x10);
- if (code < 0)
- return -1;
- if ((vi->vms.regs.eax & 0xFFFF) != 0x4F && (oldax & 0xFF00) == 0x4F00) {
- ErrorF("Int 10h (0x%04X) failed: 0x%04lX",
- oldax, vi->vms.regs.eax & 0xFFFF);
- if ((oldax & 0xFF00) == 0x4F00) {
- switch ((vi->vms.regs.eax & 0xFF00) >> 8) {
- case 0:
- ErrorF(" (success)\n");
- return 0;
- case 1:
- ErrorF(" (function call failed)\n");
- break;
- case 2:
- ErrorF
- (" (function not supported on this hardware)\n");
- break;
- case 3:
- ErrorF
- (" (function call invalid in this video mode)\n");
- break;
- default:
- ErrorF(" (unknown error)\n");
- break;
- }
- return -1;
- } else {
- ErrorF("\n");
- }
- }
- return code;
- }
|