1147 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1147 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
| 
 | |
| /*
 | |
|  *                   XFree86 vbe module
 | |
|  *               Copyright 2000 Egbert Eich
 | |
|  *
 | |
|  * The mode query/save/set/restore functions from the vesa driver 
 | |
|  * have been moved here.
 | |
|  * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 | |
|  * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br> 
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_XORG_CONFIG_H
 | |
| #include <xorg-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <string.h>
 | |
| 
 | |
| #include "xf86.h"
 | |
| #include "vbe.h"
 | |
| #include <X11/Xarch.h>
 | |
| #define DPMS_SERVER
 | |
| #include <X11/extensions/dpms.h>
 | |
| 
 | |
| #define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x)
 | |
| 
 | |
| #if X_BYTE_ORDER == X_LITTLE_ENDIAN
 | |
| #define B_O16(x)  (x) 
 | |
| #define B_O32(x)  (x)
 | |
| #else
 | |
| #define B_O16(x)  ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8))
 | |
| #define B_O32(x)  ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \
 | |
|                   | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
 | |
| #endif
 | |
| #define L_ADD(x)  (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00)
 | |
| 
 | |
| #define FARP(p)		(((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff))
 | |
| #define R16(v)		((v) & 0xffff)
 | |
| 
 | |
| static unsigned char * vbeReadEDID(vbeInfoPtr pVbe);
 | |
| static Bool vbeProbeDDC(vbeInfoPtr pVbe);
 | |
| 
 | |
| static const char vbeVersionString[] = "VBE2";
 | |
| 
 | |
| vbeInfoPtr
 | |
| VBEInit(xf86Int10InfoPtr pInt, int entityIndex)
 | |
| {
 | |
|     return VBEExtendedInit(pInt, entityIndex, 0);
 | |
| }
 | |
| 
 | |
| vbeInfoPtr
 | |
| VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags)
 | |
| {
 | |
|     int RealOff;
 | |
|     pointer page = NULL;
 | |
|     ScrnInfoPtr pScrn = xf86FindScreenForEntity(entityIndex);
 | |
|     vbeControllerInfoPtr vbe = NULL;
 | |
|     Bool init_int10 = FALSE;
 | |
|     vbeInfoPtr vip = NULL;
 | |
|     int screen;
 | |
| 
 | |
|     if (!pScrn) return NULL;
 | |
|     screen = pScrn->scrnIndex;
 | |
|     
 | |
|     if (!pInt) {
 | |
| 	if (!xf86LoadSubModule(pScrn, "int10"))
 | |
| 	    goto error;
 | |
| 
 | |
| 	xf86DrvMsg(screen,X_INFO,"initializing int10\n");
 | |
| 	pInt = xf86ExtendedInitInt10(entityIndex,Flags);
 | |
| 	if (!pInt)
 | |
| 	    goto error;
 | |
| 	init_int10 = TRUE;
 | |
|     }
 | |
|     
 | |
|     page = xf86Int10AllocPages(pInt,1,&RealOff);
 | |
|     if (!page) goto error;
 | |
|     vbe = (vbeControllerInfoPtr) page;    
 | |
|     memcpy(vbe->VbeSignature,vbeVersionString,4);
 | |
| 
 | |
|     pInt->ax = 0x4F00;
 | |
|     pInt->es = SEG_ADDR(RealOff);
 | |
|     pInt->di = SEG_OFF(RealOff);
 | |
|     pInt->num = 0x10;
 | |
|     
 | |
|     xf86ExecX86int10(pInt);
 | |
| 
 | |
|     if ((pInt->ax & 0xff) != 0x4f) {
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA BIOS not detected\n");
 | |
| 	goto error;
 | |
|     }
 | |
|     
 | |
|     switch (pInt->ax & 0xff00) {
 | |
|     case 0:
 | |
| 	xf86DrvMsg(screen,X_INFO,"VESA BIOS detected\n");
 | |
| 	break;
 | |
|     case 0x100:
 | |
| 	xf86DrvMsg(screen,X_INFO,"VESA BIOS function failed\n");
 | |
| 	goto error;
 | |
|     case 0x200:
 | |
| 	xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported\n");
 | |
| 	goto error;
 | |
|     case 0x300:
 | |
| 	xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported in current mode\n");
 | |
| 	goto error;
 | |
|     default:
 | |
| 	xf86DrvMsg(screen,X_INFO,"Invalid\n");
 | |
| 	goto error;
 | |
|     }
 | |
|     
 | |
|     xf86DrvMsgVerb(screen, X_INFO, 4,
 | |
| 		"VbeVersion is %d, OemStringPtr is 0x%08lx,\n"
 | |
| 		"\tOemVendorNamePtr is 0x%08lx, OemProductNamePtr is 0x%08lx,\n"
 | |
| 		"\tOemProductRevPtr is 0x%08lx\n",
 | |
| 		vbe->VbeVersion, (unsigned long)vbe->OemStringPtr,
 | |
| 		(unsigned long)vbe->OemVendorNamePtr,
 | |
| 		(unsigned long)vbe->OemProductNamePtr,
 | |
| 		(unsigned long)vbe->OemProductRevPtr);
 | |
| 
 | |
|     xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Version %i.%i\n",
 | |
| 		   VERSION(vbe->VbeVersion));
 | |
|     xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Total Mem: %i kB\n",
 | |
| 		   vbe->TotalMem * 64);
 | |
|     xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM: %s\n",
 | |
| 		   (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemStringPtr)));
 | |
|     
 | |
|     if (B_O16(vbe->VbeVersion) >= 0x200) {
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Software Rev: %i.%i\n",
 | |
| 		    VERSION(vbe->OemSoftwareRev));
 | |
| 	if (vbe->OemVendorNamePtr)
 | |
| 	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Vendor: %s\n",
 | |
| 		    (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemVendorNamePtr)));
 | |
| 	if (vbe->OemProductNamePtr)
 | |
| 	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product: %s\n",
 | |
| 		    (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductNamePtr)));
 | |
| 	if (vbe->OemProductRevPtr)
 | |
| 	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product Rev: %s\n",
 | |
| 		    (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductRevPtr)));
 | |
|     }
 | |
|     vip = (vbeInfoPtr)xnfalloc(sizeof(vbeInfoRec));
 | |
|     vip->version = B_O16(vbe->VbeVersion);
 | |
|     vip->pInt10 = pInt;
 | |
|     vip->ddc = DDC_UNCHECKED;
 | |
|     vip->memory = page;
 | |
|     vip->real_mode_base = RealOff;
 | |
|     vip->num_pages = 1;
 | |
|     vip->init_int10 = init_int10;
 | |
| 
 | |
|     return vip;
 | |
| 
 | |
|  error:
 | |
|     if (page)
 | |
| 	xf86Int10FreePages(pInt, page, 1);
 | |
|     if (init_int10)
 | |
| 	xf86FreeInt10(pInt);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| void
 | |
| vbeFree(vbeInfoPtr pVbe)
 | |
| {
 | |
|     if (!pVbe)
 | |
| 	return;
 | |
| 
 | |
|     xf86Int10FreePages(pVbe->pInt10,pVbe->memory,pVbe->num_pages);
 | |
|     /* If we have initalized int10 we ought to free it, too */
 | |
|     if (pVbe->init_int10) 
 | |
| 	xf86FreeInt10(pVbe->pInt10);
 | |
|     xfree(pVbe);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| vbeProbeDDC(vbeInfoPtr pVbe)
 | |
| {
 | |
|     char *ddc_level;
 | |
|     int screen = pVbe->pInt10->scrnIndex;
 | |
|     
 | |
|     if (pVbe->ddc == DDC_NONE)
 | |
| 	return FALSE;
 | |
|     if (pVbe->ddc != DDC_UNCHECKED)
 | |
| 	return TRUE;
 | |
| 
 | |
|     pVbe->pInt10->ax = 0x4F15;
 | |
|     pVbe->pInt10->bx = 0;
 | |
|     pVbe->pInt10->cx = 0;
 | |
|     pVbe->pInt10->es = 0;
 | |
|     pVbe->pInt10->di = 0;
 | |
|     pVbe->pInt10->num = 0x10;
 | |
| 
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
 | |
|         xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC not supported\n");
 | |
| 	pVbe->ddc = DDC_NONE;
 | |
| 	return FALSE;
 | |
|     }
 | |
| 
 | |
|     switch ((pVbe->pInt10->ax >> 8) & 0xff) {
 | |
|     case 0:
 | |
| 	xf86DrvMsg(screen,X_INFO,"VESA VBE DDC supported\n");
 | |
| 	switch (pVbe->pInt10->bx & 0x3) {
 | |
| 	case 0:
 | |
|   	    ddc_level = " none"; 
 | |
| 	    pVbe->ddc = DDC_NONE;
 | |
| 	    break;
 | |
| 	case 1:
 | |
|   	    ddc_level = " 1";
 | |
| 	    pVbe->ddc = DDC_1;
 | |
| 	    break;
 | |
| 	case 2:
 | |
|   	    ddc_level = " 2"; 
 | |
| 	    pVbe->ddc = DDC_2;
 | |
| 	    break;
 | |
| 	case 3:
 | |
|   	    ddc_level = " 1 + 2"; 
 | |
| 	    pVbe->ddc = DDC_1_2;
 | |
| 	    break;
 | |
| 	default:
 | |
|  	    ddc_level = "";
 | |
| 	    pVbe->ddc = DDC_NONE;
 | |
| 	    break;
 | |
| 	}
 | |
|   	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Level%s\n",ddc_level); 
 | |
|   	if (pVbe->pInt10->bx & 0x4) {
 | |
|     	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Screen blanked" 
 | |
|     			"for data transfer\n"); 
 | |
|     	    pVbe->ddc_blank = TRUE;
 | |
|     	}  else
 | |
|     	    pVbe->ddc_blank = FALSE;
 | |
| 	    
 | |
|   	xf86DrvMsgVerb(screen,X_INFO,3,
 | |
| 		       "VESA VBE DDC transfer in appr. %x sec.\n", 
 | |
| 		       (pVbe->pInt10->bx >> 8) & 0xff); 
 | |
|     }
 | |
|     
 | |
|     return TRUE; 
 | |
| }
 | |
| 
 | |
| typedef enum {
 | |
|   VBEOPT_NOVBE,
 | |
|     VBEOPT_NODDC
 | |
| } VBEOpts;
 | |
| 
 | |
| static const OptionInfoRec VBEOptions[] = {
 | |
|     { VBEOPT_NOVBE,	"NoVBE",	OPTV_BOOLEAN,	{0},	FALSE },
 | |
|     { VBEOPT_NODDC,	"NoDDC",	OPTV_BOOLEAN,	{0},	FALSE },
 | |
|     { -1,		NULL,		OPTV_NONE,	{0},	FALSE },
 | |
| };
 | |
| 
 | |
| static unsigned char *
 | |
| vbeReadEDID(vbeInfoPtr pVbe)
 | |
| {
 | |
|     int RealOff = pVbe->real_mode_base;
 | |
|     pointer page = pVbe->memory;
 | |
|     unsigned char *tmp = NULL;
 | |
|     Bool novbe = FALSE;
 | |
|     Bool noddc = FALSE;
 | |
|     int screen = pVbe->pInt10->scrnIndex;
 | |
|     OptionInfoPtr options;
 | |
| 
 | |
|     if (!page) return NULL;
 | |
| 
 | |
|     options = xnfalloc(sizeof(VBEOptions));
 | |
|     (void)memcpy(options, VBEOptions, sizeof(VBEOptions));
 | |
|     xf86ProcessOptions(screen, xf86Screens[screen]->options, options);
 | |
|     xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe);
 | |
|     xf86GetOptValBool(options, VBEOPT_NODDC, &noddc);
 | |
|     xfree(options);
 | |
|     if (novbe || noddc) return NULL;
 | |
|     
 | |
|     if (!vbeProbeDDC(pVbe)) goto error;
 | |
| 
 | |
|     memset(page,0,sizeof(vbeInfoPtr));
 | |
|     strcpy(page,vbeVersionString);
 | |
| 
 | |
|     pVbe->pInt10->ax = 0x4F15;
 | |
|     pVbe->pInt10->bx = 0x01;
 | |
|     pVbe->pInt10->cx = 0;
 | |
|     pVbe->pInt10->dx = 0;
 | |
|     pVbe->pInt10->es = SEG_ADDR(RealOff);
 | |
|     pVbe->pInt10->di = SEG_OFF(RealOff);
 | |
|     pVbe->pInt10->num = 0x10;
 | |
| 
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
 | |
|         xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC invalid\n");
 | |
| 	goto error;
 | |
|     }
 | |
|     switch (pVbe->pInt10->ax & 0xff00) {
 | |
|     case 0x0:
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read successfully\n");
 | |
|   	tmp = (unsigned char *)xnfalloc(128); 
 | |
|   	memcpy(tmp,page,128); 
 | |
| 	break;
 | |
|     case 0x100:
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read failed\n");	
 | |
| 	break;
 | |
|     default:
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC unkown failure %i\n",
 | |
| 		       pVbe->pInt10->ax & 0xff00);
 | |
| 	break;
 | |
|     }
 | |
|     
 | |
|  error:
 | |
|     return tmp;
 | |
| }
 | |
| 
 | |
| xf86MonPtr
 | |
| vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule)
 | |
| {
 | |
|     xf86MonPtr    pMonitor;
 | |
|     pointer       pModule;
 | |
|     unsigned char *DDC_data = NULL;
 | |
|     
 | |
|     if (!pVbe) return NULL;
 | |
|     if (pVbe->version < 0x200)
 | |
| 	return NULL;
 | |
| 
 | |
|     if (!(pModule = pDDCModule)) {
 | |
| 	pModule =
 | |
| 	    xf86LoadSubModule(xf86Screens[pVbe->pInt10->scrnIndex], "ddc");
 | |
| 	if (!pModule)
 | |
| 	    return NULL;
 | |
|     }
 | |
|         
 | |
|     DDC_data = vbeReadEDID(pVbe);
 | |
| 
 | |
|     if (!DDC_data) 
 | |
| 	return NULL;
 | |
|     
 | |
|     pMonitor = xf86InterpretEDID(pVbe->pInt10->scrnIndex, DDC_data);
 | |
| 
 | |
|     if (!pDDCModule)
 | |
|         xf86UnloadSubModule(pModule);
 | |
|     return pMonitor;
 | |
| }
 | |
| 
 | |
| #define GET_UNALIGNED2(x) \
 | |
|             ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16)
 | |
| 
 | |
| VbeInfoBlock *
 | |
| VBEGetVBEInfo(vbeInfoPtr pVbe)
 | |
| {
 | |
|     VbeInfoBlock *block = NULL;
 | |
|     int i, pStr, pModes;
 | |
|     char *str;
 | |
|     CARD16 major, *modes;
 | |
| 
 | |
|     bzero(pVbe->memory, sizeof(VbeInfoBlock));
 | |
| 
 | |
|     /*
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 00h	Return Super VGA information
 | |
| 	ES:DI := Pointer to buffer
 | |
| 
 | |
|     Output:
 | |
| 	AX    := status
 | |
| 	(All other registers are preserved)
 | |
|      */
 | |
| 
 | |
|     ((char*)pVbe->memory)[0] = 'V';
 | |
|     ((char*)pVbe->memory)[1] = 'B';
 | |
|     ((char*)pVbe->memory)[2] = 'E';
 | |
|     ((char*)pVbe->memory)[3] = '2';
 | |
| 
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f00;
 | |
|     pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | |
|     pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (NULL);
 | |
| 
 | |
|     block = xcalloc(sizeof(VbeInfoBlock), 1);
 | |
|     block->VESASignature[0] = ((char*)pVbe->memory)[0];
 | |
|     block->VESASignature[1] = ((char*)pVbe->memory)[1];
 | |
|     block->VESASignature[2] = ((char*)pVbe->memory)[2];
 | |
|     block->VESASignature[3] = ((char*)pVbe->memory)[3];
 | |
| 
 | |
|     block->VESAVersion = *(CARD16*)(((char*)pVbe->memory) + 4);
 | |
|     major = (unsigned)block->VESAVersion >> 8;
 | |
| 
 | |
|     pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 6));
 | |
|     str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | |
|     block->OEMStringPtr = strdup(str);
 | |
| 
 | |
|     block->Capabilities[0] = ((char*)pVbe->memory)[10];
 | |
|     block->Capabilities[1] = ((char*)pVbe->memory)[11];
 | |
|     block->Capabilities[2] = ((char*)pVbe->memory)[12];
 | |
|     block->Capabilities[3] = ((char*)pVbe->memory)[13];
 | |
| 
 | |
|     pModes = GET_UNALIGNED2((((char*)pVbe->memory) + 14));
 | |
|     modes = xf86int10Addr(pVbe->pInt10, FARP(pModes));
 | |
|     i = 0;
 | |
|     while (modes[i] != 0xffff)
 | |
| 	i++;
 | |
|     block->VideoModePtr = xalloc(sizeof(CARD16) * i + 1);
 | |
|     memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i);
 | |
|     block->VideoModePtr[i] = 0xffff;
 | |
| 
 | |
|     block->TotalMemory = *(CARD16*)(((char*)pVbe->memory) + 18);
 | |
| 
 | |
|     if (major < 2)
 | |
| 	memcpy(&block->OemSoftwareRev, ((char*)pVbe->memory) + 20, 236);
 | |
|     else {
 | |
| 	block->OemSoftwareRev = *(CARD16*)(((char*)pVbe->memory) + 20);
 | |
| 	pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 22));
 | |
| 	str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | |
| 	block->OemVendorNamePtr = strdup(str);
 | |
| 	pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 26));
 | |
| 	str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | |
| 	block->OemProductNamePtr = strdup(str);
 | |
| 	pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 30));
 | |
| 	str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | |
| 	block->OemProductRevPtr = strdup(str);
 | |
| 	memcpy(&block->Reserved, ((char*)pVbe->memory) + 34, 222);
 | |
| 	memcpy(&block->OemData, ((char*)pVbe->memory) + 256, 256);
 | |
|     }
 | |
| 
 | |
|     return (block);
 | |
| }
 | |
| 
 | |
| void
 | |
| VBEFreeVBEInfo(VbeInfoBlock *block)
 | |
| {
 | |
|     xfree(block->OEMStringPtr);
 | |
|     xfree(block->VideoModePtr);
 | |
|     if (((unsigned)block->VESAVersion >> 8) >= 2) {
 | |
| 	xfree(block->OemVendorNamePtr);
 | |
| 	xfree(block->OemProductNamePtr);
 | |
| 	xfree(block->OemProductRevPtr);
 | |
|     }
 | |
|     xfree(block);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *block)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 02h	Set Super VGA video mode
 | |
| 	BX    := Video mode
 | |
| 	    D0-D8  := Mode number
 | |
| 	    D9-D10 := Reserved (must be 0)
 | |
| 	    D11    := 0 Use current default refresh rate
 | |
| 		   := 1 Use user specified CRTC values for refresh rate
 | |
| 	    D12-13	Reserved for VBE/AF (must be 0)
 | |
| 	    D14    := 0 Use windowed frame buffer model
 | |
| 		   := 1 Use linear/flat frame buffer model
 | |
| 	    D15    := 0 Clear video memory
 | |
| 		   := 1 Don't clear video memory
 | |
| 	ES:DI := Pointer to VbeCRTCInfoBlock structure
 | |
| 
 | |
|     Output: AX = Status
 | |
| 	(All other registers are preserved)
 | |
|     */
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f02;
 | |
|     pVbe->pInt10->bx = mode;
 | |
|     if (block) {
 | |
| 	pVbe->pInt10->bx |= 1 << 11;
 | |
| 	memcpy(pVbe->memory, block, sizeof(VbeCRTCInfoBlock));
 | |
| 	pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | |
| 	pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | |
|     } else
 | |
| 	pVbe->pInt10->bx &= ~(1 << 11);
 | |
| 
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     return (R16(pVbe->pInt10->ax) == 0x4f);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBEGetVBEMode(vbeInfoPtr pVbe, int *mode)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
| 	AH := 4Fh	Super VGA support
 | |
| 	AL := 03h	Return current video mode
 | |
| 
 | |
|     Output:
 | |
| 	AX := Status
 | |
| 	BX := Current video mode
 | |
| 	(All other registers are preserved)
 | |
|     */
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f03;
 | |
| 
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) == 0x4f) {
 | |
| 	*mode = R16(pVbe->pInt10->bx);
 | |
| 
 | |
| 	return (TRUE);
 | |
|     }
 | |
| 
 | |
|     return (FALSE);
 | |
| }
 | |
| 
 | |
| VbeModeInfoBlock *
 | |
| VBEGetModeInfo(vbeInfoPtr pVbe, int mode)
 | |
| {
 | |
|     VbeModeInfoBlock *block = NULL;
 | |
| 
 | |
|     bzero(pVbe->memory, sizeof(VbeModeInfoBlock));
 | |
| 
 | |
|     /*
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 01h	Return Super VGA mode information
 | |
| 	CX    := 	Super VGA video mode
 | |
| 			(mode number must be one of those returned by Function 0)
 | |
| 	ES:DI := Pointer to buffer
 | |
| 
 | |
|     Output:
 | |
| 	AX    := status
 | |
| 	(All other registers are preserved)
 | |
|      */
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f01;
 | |
|     pVbe->pInt10->cx = mode;
 | |
|     pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | |
|     pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (NULL);
 | |
| 
 | |
|     block = xcalloc(sizeof(VbeModeInfoBlock), 1);
 | |
| 
 | |
|     block->ModeAttributes = *(CARD16*)pVbe->memory;
 | |
|     block->WinAAttributes = ((char*)pVbe->memory)[2];
 | |
|     block->WinBAttributes = ((char*)pVbe->memory)[3];
 | |
|     block->WinGranularity = *(CARD16*)(((char*)pVbe->memory) + 4);
 | |
|     block->WinSize = *(CARD16*)(((char*)pVbe->memory) + 6);
 | |
|     block->WinASegment = *(CARD16*)(((char*)pVbe->memory) + 8);
 | |
|     block->WinBSegment = *(CARD16*)(((char*)pVbe->memory) + 10);
 | |
|     block->WinFuncPtr = *(CARD32*)(((char*)pVbe->memory) + 12);
 | |
|     block->BytesPerScanline = *(CARD16*)(((char*)pVbe->memory) + 16);
 | |
| 
 | |
|     /* mandatory information for VBE 1.2 and above */
 | |
|     block->XResolution = *(CARD16*)(((char*)pVbe->memory) + 18);
 | |
|     block->YResolution = *(CARD16*)(((char*)pVbe->memory) + 20);
 | |
|     block->XCharSize = ((char*)pVbe->memory)[22];
 | |
|     block->YCharSize = ((char*)pVbe->memory)[23];
 | |
|     block->NumberOfPlanes = ((char*)pVbe->memory)[24];
 | |
|     block->BitsPerPixel = ((char*)pVbe->memory)[25];
 | |
|     block->NumberOfBanks = ((char*)pVbe->memory)[26];
 | |
|     block->MemoryModel = ((char*)pVbe->memory)[27];
 | |
|     block->BankSize = ((char*)pVbe->memory)[28];
 | |
|     block->NumberOfImages = ((char*)pVbe->memory)[29];
 | |
|     block->Reserved = ((char*)pVbe->memory)[30];
 | |
| 
 | |
|     /* Direct color fields (required for direct/6 and YUV/7 memory models) */
 | |
|     block->RedMaskSize = ((char*)pVbe->memory)[31];
 | |
|     block->RedFieldPosition = ((char*)pVbe->memory)[32];
 | |
|     block->GreenMaskSize = ((char*)pVbe->memory)[33];
 | |
|     block->GreenFieldPosition = ((char*)pVbe->memory)[34];
 | |
|     block->BlueMaskSize = ((char*)pVbe->memory)[35];
 | |
|     block->BlueFieldPosition = ((char*)pVbe->memory)[36];
 | |
|     block->RsvdMaskSize = ((char*)pVbe->memory)[37];
 | |
|     block->RsvdFieldPosition = ((char*)pVbe->memory)[38];
 | |
|     block->DirectColorModeInfo = ((char*)pVbe->memory)[39];
 | |
| 
 | |
|     /* Mandatory information for VBE 2.0 and above */
 | |
|     if (pVbe->version >= 0x200) {
 | |
| 	block->PhysBasePtr = *(CARD32*)(((char*)pVbe->memory) + 40);
 | |
| 	block->Reserved32 = *(CARD32*)(((char*)pVbe->memory) + 44);
 | |
| 	block->Reserved16 = *(CARD16*)(((char*)pVbe->memory) + 48);
 | |
| 
 | |
| 	/* Mandatory information for VBE 3.0 and above */
 | |
| 	if (pVbe->version >= 0x300) {
 | |
| 	    block->LinBytesPerScanLine = *(CARD16*)(((char*)pVbe->memory) + 50);
 | |
| 	    block->BnkNumberOfImagePages = ((char*)pVbe->memory)[52];
 | |
| 	    block->LinNumberOfImagePages = ((char*)pVbe->memory)[53];
 | |
| 	    block->LinRedMaskSize = ((char*)pVbe->memory)[54];
 | |
| 	    block->LinRedFieldPosition = ((char*)pVbe->memory)[55];
 | |
| 	    block->LinGreenMaskSize = ((char*)pVbe->memory)[56];
 | |
| 	    block->LinGreenFieldPosition = ((char*)pVbe->memory)[57];
 | |
| 	    block->LinBlueMaskSize = ((char*)pVbe->memory)[58];
 | |
| 	    block->LinBlueFieldPosition = ((char*)pVbe->memory)[59];
 | |
| 	    block->LinRsvdMaskSize = ((char*)pVbe->memory)[60];
 | |
| 	    block->LinRsvdFieldPosition = ((char*)pVbe->memory)[61];
 | |
| 	    block->MaxPixelClock = *(CARD32*)(((char*)pVbe->memory) + 62);
 | |
| 	    memcpy(&block->Reserved2, ((char*)pVbe->memory) + 66, 188);
 | |
| 	}
 | |
| 	else
 | |
| 	memcpy(&block->LinBytesPerScanLine, ((char*)pVbe->memory) + 50, 206);
 | |
|     }
 | |
|     else
 | |
| 	memcpy(&block->PhysBasePtr, ((char*)pVbe->memory) + 40, 216);
 | |
| 
 | |
|     return (block);
 | |
| }
 | |
| 
 | |
| void
 | |
| VBEFreeModeInfo(VbeModeInfoBlock *block)
 | |
| {
 | |
|     xfree(block);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function, 
 | |
| 	       pointer *memory, int *size, int *real_mode_pages)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 04h	Save/restore Super VGA video state
 | |
| 	DL    := 00h	Return save/restore state buffer size
 | |
| 	CX    := Requested states
 | |
| 		D0 = Save/restore video hardware state
 | |
| 		D1 = Save/restore video BIOS data state
 | |
| 		D2 = Save/restore video DAC state
 | |
| 		D3 = Save/restore Super VGA state
 | |
| 
 | |
|     Output:
 | |
| 	AX = Status
 | |
| 	BX = Number of 64-byte blocks to hold the state buffer
 | |
| 	(All other registers are preserved)
 | |
| 
 | |
| 
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 04h	Save/restore Super VGA video state
 | |
| 	DL    := 01h	Save Super VGA video state
 | |
| 	CX    := Requested states (see above)
 | |
| 	ES:BX := Pointer to buffer
 | |
| 
 | |
|     Output:
 | |
| 	AX    := Status
 | |
| 	(All other registers are preserved)
 | |
| 
 | |
| 
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 04h	Save/restore Super VGA video state
 | |
| 	DL    := 02h	Restore Super VGA video state
 | |
| 	CX    := Requested states (see above)
 | |
| 	ES:BX := Pointer to buffer
 | |
| 
 | |
|     Output:
 | |
| 	AX     := Status
 | |
| 	(All other registers are preserved)
 | |
|      */
 | |
| 
 | |
|     if ((pVbe->version & 0xff00) > 0x100) {
 | |
|         int screen = pVbe->pInt10->scrnIndex;
 | |
|         if (function == MODE_QUERY ||
 | |
| 	    (function == MODE_SAVE && !*memory)) {
 | |
| 	    /* Query amount of memory to save state */
 | |
| 
 | |
| 	    pVbe->pInt10->num = 0x10;
 | |
| 	    pVbe->pInt10->ax = 0x4f04;
 | |
| 	    pVbe->pInt10->dx = 0;
 | |
| 	    pVbe->pInt10->cx = 0x000f;
 | |
| 	    xf86ExecX86int10(pVbe->pInt10);
 | |
| 	    if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	        return (FALSE);
 | |
| 
 | |
| 	    if (function == MODE_SAVE) {
 | |
| 	        int npages = (R16(pVbe->pInt10->bx) * 64) / 4096 + 1;
 | |
| 		if ((*memory = xf86Int10AllocPages(pVbe->pInt10, npages,
 | |
| 						   real_mode_pages)) == NULL) {
 | |
| 		    xf86DrvMsg(screen, X_ERROR,
 | |
| 			       "Cannot allocate memory to save SVGA state.\n");
 | |
| 		    return (FALSE);
 | |
| 		}
 | |
| 	    }
 | |
| 	    *size = pVbe->pInt10->bx * 64;
 | |
| 	}
 | |
| 
 | |
| 	/* Save/Restore Super VGA state */
 | |
| 	if (function != MODE_QUERY) {
 | |
| 	    
 | |
| 	    if (!*memory) return FALSE;
 | |
| 	    pVbe->pInt10->num = 0x10;
 | |
| 	    pVbe->pInt10->ax = 0x4f04;
 | |
| 	    switch (function) {
 | |
| 	    case MODE_SAVE:
 | |
| 	      pVbe->pInt10->dx = 1;
 | |
| 	      break;
 | |
| 	    case MODE_RESTORE:
 | |
| 	      pVbe->pInt10->dx = 2;
 | |
| 	      break;
 | |
| 	    case MODE_QUERY:
 | |
| 	      return FALSE;
 | |
| 	    }
 | |
| 	    pVbe->pInt10->cx = 0x000f;
 | |
| 	    
 | |
| 	    pVbe->pInt10->es = SEG_ADDR(*real_mode_pages);
 | |
| 	    pVbe->pInt10->bx = SEG_OFF(*real_mode_pages);
 | |
| 	    xf86ExecX86int10(pVbe->pInt10);
 | |
| 	    return (R16(pVbe->pInt10->ax) == 0x4f);
 | |
| 
 | |
| 	}
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 05h
 | |
| 
 | |
|     Output:
 | |
|      */
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f05;
 | |
|     pVbe->pInt10->bx = window;
 | |
|     pVbe->pInt10->dx = iBank;
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (FALSE);
 | |
| 
 | |
|     return (TRUE);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, vbeScanwidthCommand command,
 | |
| 				int width, int *pixels, int *bytes, int *max)
 | |
| {
 | |
|     if (command < SCANWID_SET || command > SCANWID_GET_MAX)
 | |
| 	return (FALSE);
 | |
| 
 | |
|     /*
 | |
|     Input:
 | |
| 	AX := 4F06h VBE Set/Get Logical Scan Line Length
 | |
| 	BL := 00h Set Scan Line Length in Pixels
 | |
| 	   := 01h Get Scan Line Length
 | |
| 	   := 02h Set Scan Line Length in Bytes
 | |
| 	   := 03h Get Maximum Scan Line Length
 | |
| 	CX := If BL=00h Desired Width in Pixels
 | |
| 	      If BL=02h Desired Width in Bytes
 | |
| 	      (Ignored for Get Functions)
 | |
| 
 | |
|     Output:
 | |
| 	AX := VBE Return Status
 | |
| 	BX := Bytes Per Scan Line
 | |
| 	CX := Actual Pixels Per Scan Line
 | |
| 	      (truncated to nearest complete pixel)
 | |
| 	DX := Maximum Number of Scan Lines
 | |
|      */
 | |
| 
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f06;
 | |
|     pVbe->pInt10->bx = command;
 | |
|     if (command == SCANWID_SET || command == SCANWID_SET_BYTES)
 | |
| 	pVbe->pInt10->cx = width;
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (FALSE);
 | |
| 
 | |
|     if (command == SCANWID_GET || command == SCANWID_GET_MAX) {
 | |
| 	if (pixels)
 | |
| 	    *pixels = R16(pVbe->pInt10->cx);
 | |
| 	if (bytes)
 | |
| 	    *bytes = R16(pVbe->pInt10->bx);
 | |
| 	if (max)
 | |
| 	    *max = R16(pVbe->pInt10->dx);
 | |
|     }
 | |
| 
 | |
|     return (TRUE);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace)
 | |
| {
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f07;
 | |
|     pVbe->pInt10->bx = wait_retrace ? 0x80 : 0x00;
 | |
|     pVbe->pInt10->cx = x;
 | |
|     pVbe->pInt10->dx = y;
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (FALSE);
 | |
| 
 | |
|     return (TRUE);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y)
 | |
| {
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f07;
 | |
|     pVbe->pInt10->bx = 0x01;
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (FALSE);
 | |
| 
 | |
|     *x = pVbe->pInt10->cx;
 | |
|     *y = pVbe->pInt10->dx;
 | |
| 
 | |
|     return (TRUE);
 | |
| }
 | |
| 
 | |
| int
 | |
| VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
| 	AX := 4F08h VBE Set/Get Palette Format
 | |
| 	BL := 00h Set DAC Palette Format
 | |
| 	   := 01h Get DAC Palette Format
 | |
| 	BH := Desired bits of color per primary
 | |
| 	      (Set DAC Palette Format only)
 | |
| 
 | |
|     Output:
 | |
| 	AX := VBE Return Status
 | |
| 	BH := Current number of bits of color per primary
 | |
|      */
 | |
| 
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f08;
 | |
|     if (!bits)
 | |
| 	pVbe->pInt10->bx = 0x01;
 | |
|     else 
 | |
| 	pVbe->pInt10->bx = (bits & 0x00ff) << 8;
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (0);
 | |
| 
 | |
|     return (bits != 0 ? bits : (pVbe->pInt10->bx >> 8) & 0x00ff);
 | |
| }
 | |
| 
 | |
| CARD32 *
 | |
| VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num,
 | |
| 		      CARD32 *data, Bool secondary, Bool wait_retrace)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
|     (16-bit)
 | |
| 	AX    := 4F09h VBE Load/Unload Palette Data
 | |
| 	BL    := 00h Set Palette Data
 | |
| 	      := 01h Get Palette Data
 | |
| 	      := 02h Set Secondary Palette Data
 | |
| 	      := 03h Get Secondary Palette Data
 | |
| 	      := 80h Set Palette Data during Vertical Retrace
 | |
| 	CX    := Number of palette registers to update (to a maximum of 256)
 | |
| 	DX    := First of the palette registers to update (start)
 | |
| 	ES:DI := Table of palette values (see below for format)
 | |
| 
 | |
|     Output:
 | |
| 	AX    := VBE Return Status
 | |
| 
 | |
| 
 | |
|     Input:
 | |
|     (32-bit)
 | |
| 	BL     := 00h Set Palette Data
 | |
| 	       := 80h Set Palette Data during Vertical Retrace
 | |
| 	CX     := Number of palette registers to update (to a maximum of 256)
 | |
| 	DX     := First of the palette registers to update (start)
 | |
| 	ES:EDI := Table of palette values (see below for format)
 | |
| 	DS     := Selector for memory mapped registers
 | |
|      */
 | |
| 
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f09;
 | |
|     if (!secondary)
 | |
| 	pVbe->pInt10->bx = set && wait_retrace ? 0x80 : set ? 0 : 1;
 | |
|     else
 | |
| 	pVbe->pInt10->bx = set ? 2 : 3;
 | |
|     pVbe->pInt10->cx = num;
 | |
|     pVbe->pInt10->dx = first;
 | |
|     pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | |
|     pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | |
|     if (set)
 | |
| 	memcpy(pVbe->memory, data, num * sizeof(CARD32));
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (NULL);
 | |
| 
 | |
|     if (set)
 | |
| 	return (data);
 | |
| 
 | |
|     data = xalloc(num * sizeof(CARD32));
 | |
|     memcpy(data, pVbe->memory, num * sizeof(CARD32));
 | |
| 
 | |
|     return (data);
 | |
| }
 | |
| 
 | |
| VBEpmi *
 | |
| VBEGetVBEpmi(vbeInfoPtr pVbe)
 | |
| {
 | |
|     VBEpmi *pmi;
 | |
| 
 | |
|     /*
 | |
|     Input:
 | |
| 	AH    := 4Fh	Super VGA support
 | |
| 	AL    := 0Ah	Protected Mode Interface
 | |
| 	BL    := 00h	Return Protected Mode Table
 | |
| 
 | |
|     Output:
 | |
| 	AX    := Status
 | |
| 	ES    := Real Mode Segment of Table
 | |
| 	DI    := Offset of Table
 | |
| 	CX    := Lenght of Table including protected mode code in bytes (for copying purposes)
 | |
| 	(All other registers are preserved)
 | |
|      */
 | |
| 
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f0a;
 | |
|     pVbe->pInt10->bx = 0;
 | |
|     pVbe->pInt10->di = 0;
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (NULL);
 | |
| 
 | |
|     pmi = xalloc(sizeof(VBEpmi));
 | |
|     pmi->seg_tbl = R16(pVbe->pInt10->es);
 | |
|     pmi->tbl_off = R16(pVbe->pInt10->di);
 | |
|     pmi->tbl_len = R16(pVbe->pInt10->cx);
 | |
| 
 | |
|     return (pmi);
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| vbeModeInfoPtr
 | |
| VBEBuildVbeModeList(vbeInfoPtr pVbe, VbeInfoBlock *vbe)
 | |
| {
 | |
|     vbeModeInfoPtr ModeList = NULL;
 | |
| 
 | |
|     int i = 0;
 | |
|     while (vbe->VideoModePtr[i] != 0xffff) {
 | |
| 	vbeModeInfoPtr m;
 | |
| 	VbeModeInfoBlock *mode;
 | |
| 	int id = vbe->VideoModePtr[i++];
 | |
| 	int bpp;
 | |
| 
 | |
| 	if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
 | |
| 	    continue;
 | |
| 
 | |
|  	bpp = mode->BitsPerPixel;
 | |
| 
 | |
| 	m = xnfcalloc(sizeof(vbeModeInfoRec),1);
 | |
| 	m->width = mode->XResolution;
 | |
| 	m->height = mode->YResolution;
 | |
| 	m->bpp = bpp;
 | |
| 	m->n = id;
 | |
| 	m->next = ModeList;
 | |
| 
 | |
| 	xf86DrvMsgVerb(pVbe->pInt10->scrnIndex, X_PROBED, 3,
 | |
| 		       "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n",
 | |
| 		       m->n, m->width, m->height, m->bpp);
 | |
| 
 | |
| 	ModeList = m;
 | |
| 
 | |
| 	VBEFreeModeInfo(mode);
 | |
|     }
 | |
|     return ModeList;
 | |
| }
 | |
| 
 | |
| unsigned short 
 | |
| VBECalcVbeModeIndex(vbeModeInfoPtr m, DisplayModePtr mode, int bpp)
 | |
| {
 | |
|     while (m) {
 | |
| 	if (bpp == m->bpp 
 | |
| 	    && mode->HDisplay == m->width 
 | |
| 	    && mode->VDisplay == m->height)
 | |
| 	    return m->n;
 | |
| 	m = m->next;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void
 | |
| VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr,
 | |
| 		  vbeSaveRestoreFunction function)
 | |
| {
 | |
|     Bool SaveSucc = FALSE;
 | |
| 
 | |
|     if (VBE_VERSION_MAJOR(pVbe->version) > 1
 | |
| 	&& (function == MODE_SAVE || vbe_sr->pstate)) {
 | |
| 	if (function == MODE_RESTORE)
 | |
| 	    memcpy(vbe_sr->state, vbe_sr->pstate, vbe_sr->stateSize);
 | |
| 	ErrorF("VBESaveRestore\n");
 | |
| 	if ((VBESaveRestore(pVbe,function,
 | |
| 			    (pointer)&vbe_sr->state,
 | |
| 			    &vbe_sr->stateSize,&vbe_sr->statePage))) {
 | |
| 	    if (function == MODE_SAVE) {
 | |
| 		SaveSucc = TRUE;
 | |
| 		vbe_sr->stateMode = -1; /* invalidate */
 | |
| 		/* don't rely on the memory not being touched */
 | |
| 		if (vbe_sr->pstate == NULL)
 | |
| 		    vbe_sr->pstate = xalloc(vbe_sr->stateSize);
 | |
| 		memcpy(vbe_sr->pstate, vbe_sr->state, vbe_sr->stateSize);
 | |
| 	    }
 | |
| 	    ErrorF("VBESaveRestore done with success\n");
 | |
| 	    return;
 | |
| 	}
 | |
| 	ErrorF("VBESaveRestore done\n");
 | |
|     } 
 | |
|     
 | |
|     if (function == MODE_SAVE && !SaveSucc)
 | |
| 	    (void)VBEGetVBEMode(pVbe, &vbe_sr->stateMode);
 | |
| 	
 | |
|     if (function == MODE_RESTORE && vbe_sr->stateMode != -1)
 | |
| 	    VBESetVBEMode(pVbe, vbe_sr->stateMode, NULL);
 | |
| 
 | |
| }
 | |
| 
 | |
| int
 | |
| VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int clock)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
| 	AX := 4F0Bh VBE Get Pixel Clock
 | |
| 	BL := 00h Get Pixel Clock
 | |
| 	ECX := pixel clock in units of Hz
 | |
|         DX := mode number
 | |
|      
 | |
|     Output:
 | |
| 	AX := VBE Return Status
 | |
| 	ECX := Closest pixel clock
 | |
|      */
 | |
| 
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f0b;
 | |
|     pVbe->pInt10->bx = 0x00;
 | |
|     pVbe->pInt10->cx = clock;
 | |
|     pVbe->pInt10->dx = mode;
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if (R16(pVbe->pInt10->ax) != 0x4f)
 | |
| 	return (0);
 | |
| 
 | |
|     return (pVbe->pInt10->cx);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| VBEDPMSSet(vbeInfoPtr pVbe, int mode)
 | |
| {
 | |
|     /*
 | |
|     Input:
 | |
| 	AX := 4F10h DPMS
 | |
| 	BL := 01h Set Display Power State
 | |
| 	BH := requested power state
 | |
|      
 | |
|     Output:
 | |
| 	AX := VBE Return Status
 | |
|      */
 | |
| 
 | |
|     pVbe->pInt10->num = 0x10;
 | |
|     pVbe->pInt10->ax = 0x4f10;
 | |
|     pVbe->pInt10->bx = 0x01;
 | |
|     switch (mode) {
 | |
|     case DPMSModeOn:
 | |
| 	break;
 | |
|     case DPMSModeStandby:
 | |
| 	pVbe->pInt10->bx |= 0x100;
 | |
| 	break;
 | |
|     case DPMSModeSuspend:
 | |
| 	pVbe->pInt10->bx |= 0x200;
 | |
| 	break;
 | |
|     case DPMSModeOff:
 | |
| 	pVbe->pInt10->bx |= 0x400;
 | |
| 	break;
 | |
|     }
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
|     return (R16(pVbe->pInt10->ax) == 0x4f);
 | |
| }
 | |
| 
 | |
| void
 | |
| VBEInterpretPanelID(int scrnIndex, struct vbePanelID *data)
 | |
| {
 | |
|     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
 | |
|     DisplayModePtr mode;
 | |
|     const float PANEL_HZ = 60.0;
 | |
| 
 | |
|     if (!data)
 | |
| 	return;
 | |
| 
 | |
|     xf86DrvMsg(scrnIndex, X_INFO, "PanelID returned panel resolution %dx%d\n",
 | |
| 	    data->hsize, data->vsize);
 | |
| 
 | |
|     if (pScrn->monitor->nHsync || pScrn->monitor->nVrefresh)
 | |
| 	return;
 | |
| 
 | |
|     mode = xf86CVTMode(data->hsize, data->vsize, PANEL_HZ, 1, 0);
 | |
| 
 | |
|     pScrn->monitor->nHsync = 1;
 | |
|     pScrn->monitor->hsync[0].lo = 31.5;
 | |
|     pScrn->monitor->hsync[0].hi = (float)mode->Clock / (float)mode->HTotal;
 | |
|     pScrn->monitor->nVrefresh = 1;
 | |
|     pScrn->monitor->vrefresh[0].lo = 56.0;
 | |
|     pScrn->monitor->vrefresh[0].hi =
 | |
| 	(float)mode->Clock*1000.0 / (float)mode->HTotal / (float)mode->VTotal;
 | |
| 
 | |
|     xfree(mode);
 | |
| }
 | |
| 
 | |
| struct vbePanelID *
 | |
| VBEReadPanelID(vbeInfoPtr pVbe)
 | |
| {
 | |
|     int RealOff = pVbe->real_mode_base;
 | |
|     pointer page = pVbe->memory;
 | |
|     void *tmp = NULL;
 | |
|     int screen = pVbe->pInt10->scrnIndex;
 | |
| 
 | |
|     pVbe->pInt10->ax = 0x4F11;
 | |
|     pVbe->pInt10->bx = 0x01;
 | |
|     pVbe->pInt10->cx = 0;
 | |
|     pVbe->pInt10->dx = 0;
 | |
|     pVbe->pInt10->es = SEG_ADDR(RealOff);
 | |
|     pVbe->pInt10->di = SEG_OFF(RealOff);
 | |
|     pVbe->pInt10->num = 0x10;
 | |
| 
 | |
|     xf86ExecX86int10(pVbe->pInt10);
 | |
| 
 | |
|     if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n");
 | |
| 	goto error;
 | |
|     }
 | |
| 
 | |
|     switch (pVbe->pInt10->ax & 0xff00) {
 | |
|     case 0x0:
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n");
 | |
| 	tmp = xnfalloc(32); 
 | |
| 	memcpy(tmp, page, 32); 
 | |
| 	break;
 | |
|     case 0x100:
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n");       
 | |
| 	break;
 | |
|     default:
 | |
| 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n",
 | |
| 		       pVbe->pInt10->ax & 0xff00);
 | |
| 	break;
 | |
|     }
 | |
| 
 | |
| error:
 | |
|     return tmp;
 | |
| }
 |