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 <kdrive-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;
 | |
| }
 |