708 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			708 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
/* 
 | 
						|
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.
 | 
						|
*/
 | 
						|
/* $RCSId: xc/programs/Xserver/hw/kdrive/vesa/vbe.c,v 1.9 2001/05/29 04:54:12 keithp Exp $ */
 | 
						|
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#include <config.h>
 | 
						|
#endif
 | 
						|
#include "vesa.h"
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
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 = xalloc (sizeof (VbeInfoRec));
 | 
						|
    if (!vbe)
 | 
						|
	return 0;
 | 
						|
    vbe->palette_format = 6;
 | 
						|
    vbe->palette_wait = TRUE;
 | 
						|
    return vbe;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
VbeCleanup (Vm86InfoPtr vi, VbeInfoPtr vbe)
 | 
						|
{
 | 
						|
    xfree (vbe);
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}   
 | 
						|
        
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
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%04X",
 | 
						|
	       oldax, vi->vms.regs.eax & 0xFFFF);
 | 
						|
	if((oldax & 0xFF00) == 0x4F00) {
 | 
						|
	    switch((vi->vms.regs.eax & 0xFF00)>>8) {
 | 
						|
	    case 0: 
 | 
						|
		ErrorF(" (success)\n"); 
 | 
						|
		return 0;
 | 
						|
	    case 1: 
 | 
						|
		ErrorF(" (function call failed)\n"); 
 | 
						|
		break;
 | 
						|
	    case 2: 
 | 
						|
		ErrorF(" (function not supported on this hardware)\n"); 
 | 
						|
		break;
 | 
						|
	    case 3: 
 | 
						|
		ErrorF(" (function call invalid in this video mode)\n"); 
 | 
						|
		break;
 | 
						|
	    default: 
 | 
						|
		ErrorF(" (unknown error)\n"); 
 | 
						|
		break;
 | 
						|
	    }	    return -1;
 | 
						|
	} else {
 | 
						|
	    ErrorF("\n");
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return code;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
VbeDoInterruptE6(Vm86InfoPtr vi)
 | 
						|
{
 | 
						|
    int code;
 | 
						|
    int oldax;
 | 
						|
 | 
						|
    oldax = vi->vms.regs.eax & 0xffff;
 | 
						|
    
 | 
						|
    code = Vm86DoPOST (vi);
 | 
						|
    ErrorF("POST (0x%04X): 0x%04X\n",
 | 
						|
	   oldax, vi->vms.regs.eax & 0xffff);
 | 
						|
    return code;
 | 
						|
}
 |