XORG_NV/sun-src/xc/programs/Xserver/hw/xfree86/vbe/vbe.c
changeset 31 6fef7fb81fc7
equal deleted inserted replaced
30:09d07a831488 31:6fef7fb81fc7
       
     1 /* $XFree86: xc/programs/Xserver/hw/xfree86/vbe/vbe.c,v 1.2tsi Exp $ */
       
     2 
       
     3 /*
       
     4  *                   XFree86 vbe module
       
     5  *               Copyright 2000 Egbert Eich
       
     6  *
       
     7  * The mode query/save/set/restore functions from the vesa driver 
       
     8  * have been moved here.
       
     9  * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
       
    10  * Authors: Paulo César Pereira de Andrade <[email protected]> 
       
    11  */
       
    12 
       
    13 #ifdef HAVE_XORG_CONFIG_H
       
    14 #include <xorg-config.h>
       
    15 #endif
       
    16 
       
    17 #include "xf86.h"
       
    18 #include "xf86_ansic.h"
       
    19 #include "vbe.h"
       
    20 #include <X11/Xarch.h>
       
    21 #define DPMS_SERVER
       
    22 #include <X11/extensions/dpms.h>
       
    23 
       
    24 #define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x)
       
    25 
       
    26 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
       
    27 #define B_O16(x)  (x) 
       
    28 #define B_O32(x)  (x)
       
    29 #else
       
    30 #define B_O16(x)  ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8))
       
    31 #define B_O32(x)  ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \
       
    32                   | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
       
    33 #endif
       
    34 #define L_ADD(x)  (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00)
       
    35 
       
    36 #define FARP(p)		(((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff))
       
    37 #define R16(v)		((v) & 0xffff)
       
    38 
       
    39 static unsigned char * vbeReadEDID(vbeInfoPtr pVbe);
       
    40 static Bool vbeProbeDDC(vbeInfoPtr pVbe);
       
    41 
       
    42 const char *vbe_ddcSymbols[] = {
       
    43     "xf86InterpretEDID",
       
    44     NULL
       
    45 };
       
    46 
       
    47 static const char vbeVersionString[] = "VBE2";
       
    48 
       
    49 vbeInfoPtr
       
    50 VBEInit(xf86Int10InfoPtr pInt, int entityIndex)
       
    51 {
       
    52     return VBEExtendedInit(pInt, entityIndex, 0);
       
    53 }
       
    54 
       
    55 vbeInfoPtr
       
    56 VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags)
       
    57 {
       
    58     int RealOff;
       
    59     pointer page = NULL;
       
    60     ScrnInfoPtr pScrn = xf86FindScreenForEntity(entityIndex);
       
    61     vbeControllerInfoPtr vbe = NULL;
       
    62     Bool init_int10 = FALSE;
       
    63     vbeInfoPtr vip = NULL;
       
    64     int screen;
       
    65 
       
    66     if (!pScrn) return NULL;
       
    67     screen = pScrn->scrnIndex;
       
    68     
       
    69     if (!pInt) {
       
    70 	if (!xf86LoadSubModule(pScrn, "int10"))
       
    71 	    goto error;
       
    72 
       
    73 	xf86DrvMsg(screen,X_INFO,"initializing int10\n");
       
    74 	pInt = xf86ExtendedInitInt10(entityIndex,Flags);
       
    75 	if (!pInt)
       
    76 	    goto error;
       
    77 	init_int10 = TRUE;
       
    78     }
       
    79     
       
    80     page = xf86Int10AllocPages(pInt,1,&RealOff);
       
    81     if (!page) goto error;
       
    82     vbe = (vbeControllerInfoPtr) page;    
       
    83     memcpy(vbe->VbeSignature,vbeVersionString,4);
       
    84 
       
    85     pInt->ax = 0x4F00;
       
    86     pInt->es = SEG_ADDR(RealOff);
       
    87     pInt->di = SEG_OFF(RealOff);
       
    88     pInt->num = 0x10;
       
    89     
       
    90     xf86ExecX86int10(pInt);
       
    91 
       
    92     if ((pInt->ax & 0xff) != 0x4f) {
       
    93 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA BIOS not detected\n");
       
    94 	goto error;
       
    95     }
       
    96     
       
    97     switch (pInt->ax & 0xff00) {
       
    98     case 0:
       
    99 	xf86DrvMsg(screen,X_INFO,"VESA BIOS detected\n");
       
   100 	break;
       
   101     case 0x100:
       
   102 	xf86DrvMsg(screen,X_INFO,"VESA BIOS function failed\n");
       
   103 	goto error;
       
   104     case 0x200:
       
   105 	xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported\n");
       
   106 	goto error;
       
   107     case 0x300:
       
   108 	xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported in current mode\n");
       
   109 	goto error;
       
   110     default:
       
   111 	xf86DrvMsg(screen,X_INFO,"Invalid\n");
       
   112 	goto error;
       
   113     }
       
   114     
       
   115     xf86DrvMsgVerb(screen, X_INFO, 4,
       
   116 		"VbeVersion is %d, OemStringPtr is 0x%08lx,\n"
       
   117 		"\tOemVendorNamePtr is 0x%08lx, OemProductNamePtr is 0x%08lx,\n"
       
   118 		"\tOemProductRevPtr is 0x%08lx\n",
       
   119 		vbe->VbeVersion, (unsigned long)vbe->OemStringPtr,
       
   120 		(unsigned long)vbe->OemVendorNamePtr,
       
   121 		(unsigned long)vbe->OemProductNamePtr,
       
   122 		(unsigned long)vbe->OemProductRevPtr);
       
   123 
       
   124     xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Version %i.%i\n",
       
   125 		   VERSION(vbe->VbeVersion));
       
   126     xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Total Mem: %i kB\n",
       
   127 		   vbe->TotalMem * 64);
       
   128     xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM: %s\n",
       
   129 		   (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemStringPtr)));
       
   130     
       
   131     if (B_O16(vbe->VbeVersion) >= 0x200) {
       
   132 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Software Rev: %i.%i\n",
       
   133 		    VERSION(vbe->OemSoftwareRev));
       
   134 	if (vbe->OemVendorNamePtr)
       
   135 	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Vendor: %s\n",
       
   136 		    (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemVendorNamePtr)));
       
   137 	if (vbe->OemProductNamePtr)
       
   138 	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product: %s\n",
       
   139 		    (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductNamePtr)));
       
   140 	if (vbe->OemProductRevPtr)
       
   141 	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product Rev: %s\n",
       
   142 		    (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductRevPtr)));
       
   143     }
       
   144     vip = (vbeInfoPtr)xnfalloc(sizeof(vbeInfoRec));
       
   145     vip->version = B_O16(vbe->VbeVersion);
       
   146     vip->pInt10 = pInt;
       
   147     vip->ddc = DDC_UNCHECKED;
       
   148     vip->memory = page;
       
   149     vip->real_mode_base = RealOff;
       
   150     vip->num_pages = 1;
       
   151     vip->init_int10 = init_int10;
       
   152 
       
   153     return vip;
       
   154 
       
   155  error:
       
   156     if (page)
       
   157 	xf86Int10FreePages(pInt, page, 1);
       
   158     if (init_int10)
       
   159 	xf86FreeInt10(pInt);
       
   160     return NULL;
       
   161 }
       
   162 
       
   163 void
       
   164 vbeFree(vbeInfoPtr pVbe)
       
   165 {
       
   166     if (!pVbe)
       
   167 	return;
       
   168 
       
   169     xf86Int10FreePages(pVbe->pInt10,pVbe->memory,pVbe->num_pages);
       
   170     /* If we have initalized int10 we ought to free it, too */
       
   171     if (pVbe->init_int10) 
       
   172 	xf86FreeInt10(pVbe->pInt10);
       
   173     xfree(pVbe);
       
   174     return;
       
   175 }
       
   176 
       
   177 static Bool
       
   178 vbeProbeDDC(vbeInfoPtr pVbe)
       
   179 {
       
   180     char *ddc_level;
       
   181     int screen = pVbe->pInt10->scrnIndex;
       
   182     
       
   183     if (!pVbe || (pVbe->ddc == DDC_NONE))
       
   184 	return FALSE;
       
   185     if (pVbe->ddc != DDC_UNCHECKED)
       
   186 	return TRUE;
       
   187 
       
   188     pVbe->pInt10->ax = 0x4F15;
       
   189     pVbe->pInt10->bx = 0;
       
   190     pVbe->pInt10->cx = 0;
       
   191     pVbe->pInt10->es = 0;
       
   192     pVbe->pInt10->di = 0;
       
   193     pVbe->pInt10->num = 0x10;
       
   194 
       
   195     xf86ExecX86int10(pVbe->pInt10);
       
   196 
       
   197     if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
       
   198         xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC not supported\n");
       
   199 	pVbe->ddc = DDC_NONE;
       
   200 	return FALSE;
       
   201     }
       
   202 
       
   203     switch ((pVbe->pInt10->ax >> 8) & 0xff) {
       
   204     case 0:
       
   205 	xf86DrvMsg(screen,X_INFO,"VESA VBE DDC supported\n");
       
   206 	switch (pVbe->pInt10->bx & 0x3) {
       
   207 	case 0:
       
   208   	    ddc_level = " none"; 
       
   209 	    pVbe->ddc = DDC_NONE;
       
   210 	    break;
       
   211 	case 1:
       
   212   	    ddc_level = " 1";
       
   213 	    pVbe->ddc = DDC_1;
       
   214 	    break;
       
   215 	case 2:
       
   216   	    ddc_level = " 2"; 
       
   217 	    pVbe->ddc = DDC_2;
       
   218 	    break;
       
   219 	case 3:
       
   220   	    ddc_level = " 1 + 2"; 
       
   221 	    pVbe->ddc = DDC_1_2;
       
   222 	    break;
       
   223 	default:
       
   224  	    ddc_level = "";
       
   225 	    pVbe->ddc = DDC_NONE;
       
   226 	    break;
       
   227 	}
       
   228   	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Level%s\n",ddc_level); 
       
   229   	if (pVbe->pInt10->bx & 0x4) {
       
   230     	    xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Screen blanked" 
       
   231     			"for data transfer\n"); 
       
   232     	    pVbe->ddc_blank = TRUE;
       
   233     	}  else
       
   234     	    pVbe->ddc_blank = FALSE;
       
   235 	    
       
   236   	xf86DrvMsgVerb(screen,X_INFO,3,
       
   237 		       "VESA VBE DDC transfer in appr. %x sec.\n", 
       
   238 		       (pVbe->pInt10->bx >> 8) & 0xff); 
       
   239     }
       
   240     
       
   241     return TRUE; 
       
   242 }
       
   243 
       
   244 typedef enum {
       
   245   VBEOPT_NOVBE,
       
   246     VBEOPT_NODDC
       
   247 } VBEOpts;
       
   248 
       
   249 static const OptionInfoRec VBEOptions[] = {
       
   250     { VBEOPT_NOVBE,	"NoVBE",	OPTV_BOOLEAN,	{0},	FALSE },
       
   251     { VBEOPT_NODDC,	"NoDDC",	OPTV_BOOLEAN,	{0},	FALSE },
       
   252     { -1,		NULL,		OPTV_NONE,	{0},	FALSE },
       
   253 };
       
   254 
       
   255 static unsigned char *
       
   256 vbeReadEDID(vbeInfoPtr pVbe)
       
   257 {
       
   258     int RealOff = pVbe->real_mode_base;
       
   259     pointer page = pVbe->memory;
       
   260     unsigned char *tmp = NULL;
       
   261     Bool novbe = FALSE;
       
   262     Bool noddc = FALSE;
       
   263     int screen = pVbe->pInt10->scrnIndex;
       
   264     OptionInfoPtr options;
       
   265 
       
   266     if (!page) return NULL;
       
   267 
       
   268     options = xnfalloc(sizeof(VBEOptions));
       
   269     (void)memcpy(options, VBEOptions, sizeof(VBEOptions));
       
   270     xf86ProcessOptions(screen, xf86Screens[screen]->options, options);
       
   271     xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe);
       
   272     xf86GetOptValBool(options, VBEOPT_NODDC, &noddc);
       
   273     xfree(options);
       
   274     if (novbe || noddc) return NULL;
       
   275     
       
   276     if (!vbeProbeDDC(pVbe)) goto error;
       
   277 
       
   278     memset(page,0,sizeof(vbeInfoPtr));
       
   279     strcpy(page,vbeVersionString);
       
   280 
       
   281     pVbe->pInt10->ax = 0x4F15;
       
   282     pVbe->pInt10->bx = 0x01;
       
   283     pVbe->pInt10->cx = 0;
       
   284     pVbe->pInt10->dx = 0;
       
   285     pVbe->pInt10->es = SEG_ADDR(RealOff);
       
   286     pVbe->pInt10->di = SEG_OFF(RealOff);
       
   287     pVbe->pInt10->num = 0x10;
       
   288 
       
   289     xf86ExecX86int10(pVbe->pInt10);
       
   290 
       
   291     if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
       
   292         xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC invalid\n");
       
   293 	goto error;
       
   294     }
       
   295     switch (pVbe->pInt10->ax & 0xff00) {
       
   296     case 0x0:
       
   297 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read successfully\n");
       
   298   	tmp = (unsigned char *)xnfalloc(128); 
       
   299   	memcpy(tmp,page,128); 
       
   300 	break;
       
   301     case 0x100:
       
   302 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read failed\n");	
       
   303 	break;
       
   304     default:
       
   305 	xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC unkown failure %i\n",
       
   306 		       pVbe->pInt10->ax & 0xff00);
       
   307 	break;
       
   308     }
       
   309     
       
   310  error:
       
   311     return tmp;
       
   312 }
       
   313 
       
   314 xf86MonPtr
       
   315 vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule)
       
   316 {
       
   317     xf86MonPtr    pMonitor;
       
   318     pointer       pModule;
       
   319     unsigned char *DDC_data = NULL;
       
   320     ScrnInfoPtr   scrp;
       
   321     
       
   322     if (!pVbe) return NULL;
       
   323     if (pVbe->version < 0x200)
       
   324 	return NULL;
       
   325 
       
   326     scrp = xf86Screens[pVbe->pInt10->scrnIndex];
       
   327 
       
   328     if (!(pModule = pDDCModule)) {
       
   329 	pModule =
       
   330 	    xf86LoadSubModule(scrp, "ddc");
       
   331 	if (!pModule)
       
   332 	    return NULL;
       
   333 
       
   334 	xf86LoaderReqSymLists(vbe_ddcSymbols, NULL);
       
   335     }
       
   336         
       
   337     DDC_data = vbeReadEDID(pVbe);
       
   338 
       
   339     if (!DDC_data) 
       
   340 	return NULL;
       
   341     
       
   342     pMonitor = xf86InterpretEDID(pVbe->pInt10->scrnIndex, DDC_data);
       
   343 
       
   344     if (pMonitor) {
       
   345 	xf86DrvMsg(scrp->scrnIndex, X_PROBED,
       
   346 	"VBE DDC detected a %s:\n", pMonitor->features.input_type ?
       
   347 	"DFP" : "CRT");
       
   348 	xf86PrintEDID(pMonitor);
       
   349 	xf86DrvMsg(scrp->scrnIndex, X_INFO, "end of VBE DDC Monitor info\n");
       
   350     }
       
   351 
       
   352     if (!pDDCModule)
       
   353         xf86UnloadSubModule(pModule);
       
   354     return pMonitor;
       
   355 }
       
   356 
       
   357 #define GET_UNALIGNED2(x) \
       
   358             ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16)
       
   359 
       
   360 VbeInfoBlock *
       
   361 VBEGetVBEInfo(vbeInfoPtr pVbe)
       
   362 {
       
   363     VbeInfoBlock *block = NULL;
       
   364     int i, pStr, pModes;
       
   365     char *str;
       
   366     CARD16 major, *modes;
       
   367 
       
   368     bzero(pVbe->memory, sizeof(VbeInfoBlock));
       
   369 
       
   370     /*
       
   371     Input:
       
   372 	AH    := 4Fh	Super VGA support
       
   373 	AL    := 00h	Return Super VGA information
       
   374 	ES:DI := Pointer to buffer
       
   375 
       
   376     Output:
       
   377 	AX    := status
       
   378 	(All other registers are preserved)
       
   379      */
       
   380 
       
   381     ((char*)pVbe->memory)[0] = 'V';
       
   382     ((char*)pVbe->memory)[1] = 'B';
       
   383     ((char*)pVbe->memory)[2] = 'E';
       
   384     ((char*)pVbe->memory)[3] = '2';
       
   385 
       
   386     pVbe->pInt10->num = 0x10;
       
   387     pVbe->pInt10->ax = 0x4f00;
       
   388     pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
       
   389     pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
       
   390     xf86ExecX86int10(pVbe->pInt10);
       
   391 
       
   392     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   393 	return (NULL);
       
   394 
       
   395     block = xcalloc(sizeof(VbeInfoBlock), 1);
       
   396     block->VESASignature[0] = ((char*)pVbe->memory)[0];
       
   397     block->VESASignature[1] = ((char*)pVbe->memory)[1];
       
   398     block->VESASignature[2] = ((char*)pVbe->memory)[2];
       
   399     block->VESASignature[3] = ((char*)pVbe->memory)[3];
       
   400 
       
   401     block->VESAVersion = *(CARD16*)(((char*)pVbe->memory) + 4);
       
   402     major = (unsigned)block->VESAVersion >> 8;
       
   403 
       
   404     pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 6));
       
   405     str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
       
   406     block->OEMStringPtr = strdup(str);
       
   407 
       
   408     block->Capabilities[0] = ((char*)pVbe->memory)[10];
       
   409     block->Capabilities[1] = ((char*)pVbe->memory)[11];
       
   410     block->Capabilities[2] = ((char*)pVbe->memory)[12];
       
   411     block->Capabilities[3] = ((char*)pVbe->memory)[13];
       
   412 
       
   413     pModes = GET_UNALIGNED2((((char*)pVbe->memory) + 14));
       
   414     modes = xf86int10Addr(pVbe->pInt10, FARP(pModes));
       
   415     i = 0;
       
   416     while (modes[i] != 0xffff)
       
   417 	i++;
       
   418     block->VideoModePtr = xalloc(sizeof(CARD16) * i + 1);
       
   419     memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i);
       
   420     block->VideoModePtr[i] = 0xffff;
       
   421 
       
   422     block->TotalMemory = *(CARD16*)(((char*)pVbe->memory) + 18);
       
   423 
       
   424     if (major < 2)
       
   425 	memcpy(&block->OemSoftwareRev, ((char*)pVbe->memory) + 20, 236);
       
   426     else {
       
   427 	block->OemSoftwareRev = *(CARD16*)(((char*)pVbe->memory) + 20);
       
   428 	pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 22));
       
   429 	str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
       
   430 	block->OemVendorNamePtr = strdup(str);
       
   431 	pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 26));
       
   432 	str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
       
   433 	block->OemProductNamePtr = strdup(str);
       
   434 	pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 30));
       
   435 	str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
       
   436 	block->OemProductRevPtr = strdup(str);
       
   437 	memcpy(&block->Reserved, ((char*)pVbe->memory) + 34, 222);
       
   438 	memcpy(&block->OemData, ((char*)pVbe->memory) + 256, 256);
       
   439     }
       
   440 
       
   441     return (block);
       
   442 }
       
   443 
       
   444 void
       
   445 VBEFreeVBEInfo(VbeInfoBlock *block)
       
   446 {
       
   447     xfree(block->OEMStringPtr);
       
   448     xfree(block->VideoModePtr);
       
   449     if (((unsigned)block->VESAVersion >> 8) >= 2) {
       
   450 	xfree(block->OemVendorNamePtr);
       
   451 	xfree(block->OemProductNamePtr);
       
   452 	xfree(block->OemProductRevPtr);
       
   453     }
       
   454     xfree(block);
       
   455 }
       
   456 
       
   457 Bool
       
   458 VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *block)
       
   459 {
       
   460     /*
       
   461     Input:
       
   462 	AH    := 4Fh	Super VGA support
       
   463 	AL    := 02h	Set Super VGA video mode
       
   464 	BX    := Video mode
       
   465 	    D0-D8  := Mode number
       
   466 	    D9-D10 := Reserved (must be 0)
       
   467 	    D11    := 0 Use current default refresh rate
       
   468 		   := 1 Use user specified CRTC values for refresh rate
       
   469 	    D12-13	Reserved for VBE/AF (must be 0)
       
   470 	    D14    := 0 Use windowed frame buffer model
       
   471 		   := 1 Use linear/flat frame buffer model
       
   472 	    D15    := 0 Clear video memory
       
   473 		   := 1 Don't clear video memory
       
   474 	ES:DI := Pointer to VbeCRTCInfoBlock structure
       
   475 
       
   476     Output: AX = Status
       
   477 	(All other registers are preserved)
       
   478     */
       
   479     pVbe->pInt10->num = 0x10;
       
   480     pVbe->pInt10->ax = 0x4f02;
       
   481     pVbe->pInt10->bx = mode;
       
   482     if (block) {
       
   483 	pVbe->pInt10->bx |= 1 << 11;
       
   484 	memcpy(pVbe->memory, block, sizeof(VbeCRTCInfoBlock));
       
   485 	pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
       
   486 	pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
       
   487     } else
       
   488 	pVbe->pInt10->bx &= ~(1 << 11);
       
   489 
       
   490     xf86ExecX86int10(pVbe->pInt10);
       
   491 
       
   492     return (R16(pVbe->pInt10->ax) == 0x4f);
       
   493 }
       
   494 
       
   495 Bool
       
   496 VBEGetVBEMode(vbeInfoPtr pVbe, int *mode)
       
   497 {
       
   498     /*
       
   499     Input:
       
   500 	AH := 4Fh	Super VGA support
       
   501 	AL := 03h	Return current video mode
       
   502 
       
   503     Output:
       
   504 	AX := Status
       
   505 	BX := Current video mode
       
   506 	(All other registers are preserved)
       
   507     */
       
   508     pVbe->pInt10->num = 0x10;
       
   509     pVbe->pInt10->ax = 0x4f03;
       
   510 
       
   511     xf86ExecX86int10(pVbe->pInt10);
       
   512 
       
   513     if (R16(pVbe->pInt10->ax) == 0x4f) {
       
   514 	*mode = R16(pVbe->pInt10->bx);
       
   515 
       
   516 	return (TRUE);
       
   517     }
       
   518 
       
   519     return (FALSE);
       
   520 }
       
   521 
       
   522 VbeModeInfoBlock *
       
   523 VBEGetModeInfo(vbeInfoPtr pVbe, int mode)
       
   524 {
       
   525     VbeModeInfoBlock *block = NULL;
       
   526 
       
   527     bzero(pVbe->memory, sizeof(VbeModeInfoBlock));
       
   528 
       
   529     /*
       
   530     Input:
       
   531 	AH    := 4Fh	Super VGA support
       
   532 	AL    := 01h	Return Super VGA mode information
       
   533 	CX    := 	Super VGA video mode
       
   534 			(mode number must be one of those returned by Function 0)
       
   535 	ES:DI := Pointer to buffer
       
   536 
       
   537     Output:
       
   538 	AX    := status
       
   539 	(All other registers are preserved)
       
   540      */
       
   541     pVbe->pInt10->num = 0x10;
       
   542     pVbe->pInt10->ax = 0x4f01;
       
   543     pVbe->pInt10->cx = mode;
       
   544     pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
       
   545     pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
       
   546     xf86ExecX86int10(pVbe->pInt10);
       
   547     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   548 	return (NULL);
       
   549 
       
   550     block = xcalloc(sizeof(VbeModeInfoBlock), 1);
       
   551 
       
   552     block->ModeAttributes = *(CARD16*)pVbe->memory;
       
   553     block->WinAAttributes = ((char*)pVbe->memory)[2];
       
   554     block->WinBAttributes = ((char*)pVbe->memory)[3];
       
   555     block->WinGranularity = *(CARD16*)(((char*)pVbe->memory) + 4);
       
   556     block->WinSize = *(CARD16*)(((char*)pVbe->memory) + 6);
       
   557     block->WinASegment = *(CARD16*)(((char*)pVbe->memory) + 8);
       
   558     block->WinBSegment = *(CARD16*)(((char*)pVbe->memory) + 10);
       
   559     block->WinFuncPtr = *(CARD32*)(((char*)pVbe->memory) + 12);
       
   560     block->BytesPerScanline = *(CARD16*)(((char*)pVbe->memory) + 16);
       
   561 
       
   562     /* mandatory information for VBE 1.2 and above */
       
   563     block->XResolution = *(CARD16*)(((char*)pVbe->memory) + 18);
       
   564     block->YResolution = *(CARD16*)(((char*)pVbe->memory) + 20);
       
   565     block->XCharSize = ((char*)pVbe->memory)[22];
       
   566     block->YCharSize = ((char*)pVbe->memory)[23];
       
   567     block->NumberOfPlanes = ((char*)pVbe->memory)[24];
       
   568     block->BitsPerPixel = ((char*)pVbe->memory)[25];
       
   569     block->NumberOfBanks = ((char*)pVbe->memory)[26];
       
   570     block->MemoryModel = ((char*)pVbe->memory)[27];
       
   571     block->BankSize = ((char*)pVbe->memory)[28];
       
   572     block->NumberOfImages = ((char*)pVbe->memory)[29];
       
   573     block->Reserved = ((char*)pVbe->memory)[30];
       
   574 
       
   575     /* Direct color fields (required for direct/6 and YUV/7 memory models) */
       
   576     block->RedMaskSize = ((char*)pVbe->memory)[31];
       
   577     block->RedFieldPosition = ((char*)pVbe->memory)[32];
       
   578     block->GreenMaskSize = ((char*)pVbe->memory)[33];
       
   579     block->GreenFieldPosition = ((char*)pVbe->memory)[34];
       
   580     block->BlueMaskSize = ((char*)pVbe->memory)[35];
       
   581     block->BlueFieldPosition = ((char*)pVbe->memory)[36];
       
   582     block->RsvdMaskSize = ((char*)pVbe->memory)[37];
       
   583     block->RsvdFieldPosition = ((char*)pVbe->memory)[38];
       
   584     block->DirectColorModeInfo = ((char*)pVbe->memory)[39];
       
   585 
       
   586     /* Mandatory information for VBE 2.0 and above */
       
   587     if (pVbe->version >= 0x200) {
       
   588 	block->PhysBasePtr = *(CARD32*)(((char*)pVbe->memory) + 40);
       
   589 	block->Reserved32 = *(CARD32*)(((char*)pVbe->memory) + 44);
       
   590 	block->Reserved16 = *(CARD16*)(((char*)pVbe->memory) + 48);
       
   591 
       
   592 	/* Mandatory information for VBE 3.0 and above */
       
   593 	if (pVbe->version >= 0x300) {
       
   594 	    block->LinBytesPerScanLine = *(CARD16*)(((char*)pVbe->memory) + 50);
       
   595 	    block->BnkNumberOfImagePages = ((char*)pVbe->memory)[52];
       
   596 	    block->LinNumberOfImagePages = ((char*)pVbe->memory)[53];
       
   597 	    block->LinRedMaskSize = ((char*)pVbe->memory)[54];
       
   598 	    block->LinRedFieldPosition = ((char*)pVbe->memory)[55];
       
   599 	    block->LinGreenMaskSize = ((char*)pVbe->memory)[56];
       
   600 	    block->LinGreenFieldPosition = ((char*)pVbe->memory)[57];
       
   601 	    block->LinBlueMaskSize = ((char*)pVbe->memory)[58];
       
   602 	    block->LinBlueFieldPosition = ((char*)pVbe->memory)[59];
       
   603 	    block->LinRsvdMaskSize = ((char*)pVbe->memory)[60];
       
   604 	    block->LinRsvdFieldPosition = ((char*)pVbe->memory)[61];
       
   605 	    block->MaxPixelClock = *(CARD32*)(((char*)pVbe->memory) + 62);
       
   606 	    memcpy(&block->Reserved2, ((char*)pVbe->memory) + 66, 188);
       
   607 	}
       
   608 	else
       
   609 	memcpy(&block->LinBytesPerScanLine, ((char*)pVbe->memory) + 50, 206);
       
   610     }
       
   611     else
       
   612 	memcpy(&block->PhysBasePtr, ((char*)pVbe->memory) + 40, 216);
       
   613 
       
   614     return (block);
       
   615 }
       
   616 
       
   617 void
       
   618 VBEFreeModeInfo(VbeModeInfoBlock *block)
       
   619 {
       
   620     xfree(block);
       
   621 }
       
   622 
       
   623 Bool
       
   624 VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function, 
       
   625 	       pointer *memory, int *size, int *real_mode_pages)
       
   626 {
       
   627     /*
       
   628     Input:
       
   629 	AH    := 4Fh	Super VGA support
       
   630 	AL    := 04h	Save/restore Super VGA video state
       
   631 	DL    := 00h	Return save/restore state buffer size
       
   632 	CX    := Requested states
       
   633 		D0 = Save/restore video hardware state
       
   634 		D1 = Save/restore video BIOS data state
       
   635 		D2 = Save/restore video DAC state
       
   636 		D3 = Save/restore Super VGA state
       
   637 
       
   638     Output:
       
   639 	AX = Status
       
   640 	BX = Number of 64-byte blocks to hold the state buffer
       
   641 	(All other registers are preserved)
       
   642 
       
   643 
       
   644     Input:
       
   645 	AH    := 4Fh	Super VGA support
       
   646 	AL    := 04h	Save/restore Super VGA video state
       
   647 	DL    := 01h	Save Super VGA video state
       
   648 	CX    := Requested states (see above)
       
   649 	ES:BX := Pointer to buffer
       
   650 
       
   651     Output:
       
   652 	AX    := Status
       
   653 	(All other registers are preserved)
       
   654 
       
   655 
       
   656     Input:
       
   657 	AH    := 4Fh	Super VGA support
       
   658 	AL    := 04h	Save/restore Super VGA video state
       
   659 	DL    := 02h	Restore Super VGA video state
       
   660 	CX    := Requested states (see above)
       
   661 	ES:BX := Pointer to buffer
       
   662 
       
   663     Output:
       
   664 	AX     := Status
       
   665 	(All other registers are preserved)
       
   666      */
       
   667 
       
   668     if ((pVbe->version & 0xff00) > 0x100) {
       
   669         int screen = pVbe->pInt10->scrnIndex;
       
   670         if (function == MODE_QUERY ||
       
   671 	    (function == MODE_SAVE && !*memory)) {
       
   672 	    /* Query amount of memory to save state */
       
   673 
       
   674 	    pVbe->pInt10->num = 0x10;
       
   675 	    pVbe->pInt10->ax = 0x4f04;
       
   676 	    pVbe->pInt10->dx = 0;
       
   677 	    pVbe->pInt10->cx = 0x000f;
       
   678 	    xf86ExecX86int10(pVbe->pInt10);
       
   679 	    if (R16(pVbe->pInt10->ax) != 0x4f)
       
   680 	        return (FALSE);
       
   681 
       
   682 	    if (function == MODE_SAVE) {
       
   683 	        int npages = (R16(pVbe->pInt10->bx) * 64) / 4096 + 1;
       
   684 		if ((*memory = xf86Int10AllocPages(pVbe->pInt10, npages,
       
   685 						   real_mode_pages)) == NULL) {
       
   686 		    xf86DrvMsg(screen, X_ERROR,
       
   687 			       "Cannot allocate memory to save SVGA state.\n");
       
   688 		    return (FALSE);
       
   689 		}
       
   690 	    }
       
   691 	    *size = pVbe->pInt10->bx * 64;
       
   692 	}
       
   693 
       
   694 	/* Save/Restore Super VGA state */
       
   695 	if (function != MODE_QUERY) {
       
   696 	    
       
   697 	    if (!*memory) return FALSE;
       
   698 	    pVbe->pInt10->num = 0x10;
       
   699 	    pVbe->pInt10->ax = 0x4f04;
       
   700 	    switch (function) {
       
   701 	    case MODE_SAVE:
       
   702 	      pVbe->pInt10->dx = 1;
       
   703 	      break;
       
   704 	    case MODE_RESTORE:
       
   705 	      pVbe->pInt10->dx = 2;
       
   706 	      break;
       
   707 	    case MODE_QUERY:
       
   708 	      return FALSE;
       
   709 	    }
       
   710 	    pVbe->pInt10->cx = 0x000f;
       
   711 	    
       
   712 	    pVbe->pInt10->es = SEG_ADDR(*real_mode_pages);
       
   713 	    pVbe->pInt10->bx = SEG_OFF(*real_mode_pages);
       
   714 	    xf86ExecX86int10(pVbe->pInt10);
       
   715 	    return (R16(pVbe->pInt10->ax) == 0x4f);
       
   716 
       
   717 	}
       
   718     }
       
   719     return TRUE;
       
   720 }
       
   721 
       
   722 Bool
       
   723 VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window)
       
   724 {
       
   725     /*
       
   726     Input:
       
   727 	AH    := 4Fh	Super VGA support
       
   728 	AL    := 05h
       
   729 
       
   730     Output:
       
   731      */
       
   732     pVbe->pInt10->num = 0x10;
       
   733     pVbe->pInt10->ax = 0x4f05;
       
   734     pVbe->pInt10->bx = window;
       
   735     pVbe->pInt10->dx = iBank;
       
   736     xf86ExecX86int10(pVbe->pInt10);
       
   737 
       
   738     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   739 	return (FALSE);
       
   740 
       
   741     return (TRUE);
       
   742 }
       
   743 
       
   744 Bool
       
   745 VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, vbeScanwidthCommand command,
       
   746 				int width, int *pixels, int *bytes, int *max)
       
   747 {
       
   748     if (command < SCANWID_SET || command > SCANWID_GET_MAX)
       
   749 	return (FALSE);
       
   750 
       
   751     /*
       
   752     Input:
       
   753 	AX := 4F06h VBE Set/Get Logical Scan Line Length
       
   754 	BL := 00h Set Scan Line Length in Pixels
       
   755 	   := 01h Get Scan Line Length
       
   756 	   := 02h Set Scan Line Length in Bytes
       
   757 	   := 03h Get Maximum Scan Line Length
       
   758 	CX := If BL=00h Desired Width in Pixels
       
   759 	      If BL=02h Desired Width in Bytes
       
   760 	      (Ignored for Get Functions)
       
   761 
       
   762     Output:
       
   763 	AX := VBE Return Status
       
   764 	BX := Bytes Per Scan Line
       
   765 	CX := Actual Pixels Per Scan Line
       
   766 	      (truncated to nearest complete pixel)
       
   767 	DX := Maximum Number of Scan Lines
       
   768      */
       
   769 
       
   770     pVbe->pInt10->num = 0x10;
       
   771     pVbe->pInt10->ax = 0x4f06;
       
   772     pVbe->pInt10->bx = command;
       
   773     if (command == SCANWID_SET || command == SCANWID_SET_BYTES)
       
   774 	pVbe->pInt10->cx = width;
       
   775     xf86ExecX86int10(pVbe->pInt10);
       
   776 
       
   777     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   778 	return (FALSE);
       
   779 
       
   780     if (command == SCANWID_GET || command == SCANWID_GET_MAX) {
       
   781 	if (pixels)
       
   782 	    *pixels = R16(pVbe->pInt10->cx);
       
   783 	if (bytes)
       
   784 	    *bytes = R16(pVbe->pInt10->bx);
       
   785 	if (max)
       
   786 	    *max = R16(pVbe->pInt10->dx);
       
   787     }
       
   788 
       
   789     return (TRUE);
       
   790 }
       
   791 
       
   792 Bool
       
   793 VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace)
       
   794 {
       
   795     pVbe->pInt10->num = 0x10;
       
   796     pVbe->pInt10->ax = 0x4f07;
       
   797     pVbe->pInt10->bx = wait_retrace ? 0x80 : 0x00;
       
   798     pVbe->pInt10->cx = x;
       
   799     pVbe->pInt10->dx = y;
       
   800     xf86ExecX86int10(pVbe->pInt10);
       
   801 
       
   802     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   803 	return (FALSE);
       
   804 
       
   805     return (TRUE);
       
   806 }
       
   807 
       
   808 Bool
       
   809 VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y)
       
   810 {
       
   811     pVbe->pInt10->num = 0x10;
       
   812     pVbe->pInt10->ax = 0x4f07;
       
   813     pVbe->pInt10->bx = 0x01;
       
   814     xf86ExecX86int10(pVbe->pInt10);
       
   815 
       
   816     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   817 	return (FALSE);
       
   818 
       
   819     *x = pVbe->pInt10->cx;
       
   820     *y = pVbe->pInt10->dx;
       
   821 
       
   822     return (TRUE);
       
   823 }
       
   824 
       
   825 int
       
   826 VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits)
       
   827 {
       
   828     /*
       
   829     Input:
       
   830 	AX := 4F08h VBE Set/Get Palette Format
       
   831 	BL := 00h Set DAC Palette Format
       
   832 	   := 01h Get DAC Palette Format
       
   833 	BH := Desired bits of color per primary
       
   834 	      (Set DAC Palette Format only)
       
   835 
       
   836     Output:
       
   837 	AX := VBE Return Status
       
   838 	BH := Current number of bits of color per primary
       
   839      */
       
   840 
       
   841     pVbe->pInt10->num = 0x10;
       
   842     pVbe->pInt10->ax = 0x4f08;
       
   843     if (!bits)
       
   844 	pVbe->pInt10->bx = 0x01;
       
   845     else 
       
   846 	pVbe->pInt10->bx = (bits & 0x00ff) << 8;
       
   847     xf86ExecX86int10(pVbe->pInt10);
       
   848 
       
   849     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   850 	return (0);
       
   851 
       
   852     return (bits != 0 ? bits : (pVbe->pInt10->bx >> 8) & 0x00ff);
       
   853 }
       
   854 
       
   855 CARD32 *
       
   856 VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num,
       
   857 		      CARD32 *data, Bool secondary, Bool wait_retrace)
       
   858 {
       
   859     /*
       
   860     Input:
       
   861     (16-bit)
       
   862 	AX    := 4F09h VBE Load/Unload Palette Data
       
   863 	BL    := 00h Set Palette Data
       
   864 	      := 01h Get Palette Data
       
   865 	      := 02h Set Secondary Palette Data
       
   866 	      := 03h Get Secondary Palette Data
       
   867 	      := 80h Set Palette Data during Vertical Retrace
       
   868 	CX    := Number of palette registers to update (to a maximum of 256)
       
   869 	DX    := First of the palette registers to update (start)
       
   870 	ES:DI := Table of palette values (see below for format)
       
   871 
       
   872     Output:
       
   873 	AX    := VBE Return Status
       
   874 
       
   875 
       
   876     Input:
       
   877     (32-bit)
       
   878 	BL     := 00h Set Palette Data
       
   879 	       := 80h Set Palette Data during Vertical Retrace
       
   880 	CX     := Number of palette registers to update (to a maximum of 256)
       
   881 	DX     := First of the palette registers to update (start)
       
   882 	ES:EDI := Table of palette values (see below for format)
       
   883 	DS     := Selector for memory mapped registers
       
   884      */
       
   885 
       
   886     pVbe->pInt10->num = 0x10;
       
   887     pVbe->pInt10->ax = 0x4f09;
       
   888     if (!secondary)
       
   889 	pVbe->pInt10->bx = set && wait_retrace ? 0x80 : set ? 0 : 1;
       
   890     else
       
   891 	pVbe->pInt10->bx = set ? 2 : 3;
       
   892     pVbe->pInt10->cx = num;
       
   893     pVbe->pInt10->dx = first;
       
   894     pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
       
   895     pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
       
   896     if (set)
       
   897 	memcpy(pVbe->memory, data, num * sizeof(CARD32));
       
   898     xf86ExecX86int10(pVbe->pInt10);
       
   899 
       
   900     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   901 	return (NULL);
       
   902 
       
   903     if (set)
       
   904 	return (data);
       
   905 
       
   906     data = xalloc(num * sizeof(CARD32));
       
   907     memcpy(data, pVbe->memory, num * sizeof(CARD32));
       
   908 
       
   909     return (data);
       
   910 }
       
   911 
       
   912 VBEpmi *
       
   913 VBEGetVBEpmi(vbeInfoPtr pVbe)
       
   914 {
       
   915     VBEpmi *pmi;
       
   916 
       
   917     /*
       
   918     Input:
       
   919 	AH    := 4Fh	Super VGA support
       
   920 	AL    := 0Ah	Protected Mode Interface
       
   921 	BL    := 00h	Return Protected Mode Table
       
   922 
       
   923     Output:
       
   924 	AX    := Status
       
   925 	ES    := Real Mode Segment of Table
       
   926 	DI    := Offset of Table
       
   927 	CX    := Lenght of Table including protected mode code in bytes (for copying purposes)
       
   928 	(All other registers are preserved)
       
   929      */
       
   930 
       
   931     pVbe->pInt10->num = 0x10;
       
   932     pVbe->pInt10->ax = 0x4f0a;
       
   933     pVbe->pInt10->bx = 0;
       
   934     pVbe->pInt10->di = 0;
       
   935     xf86ExecX86int10(pVbe->pInt10);
       
   936 
       
   937     if (R16(pVbe->pInt10->ax) != 0x4f)
       
   938 	return (NULL);
       
   939 
       
   940     pmi = xalloc(sizeof(VBEpmi));
       
   941     pmi->seg_tbl = R16(pVbe->pInt10->es);
       
   942     pmi->tbl_off = R16(pVbe->pInt10->di);
       
   943     pmi->tbl_len = R16(pVbe->pInt10->cx);
       
   944 
       
   945     return (pmi);
       
   946 }
       
   947 
       
   948 #if 0
       
   949 vbeModeInfoPtr
       
   950 VBEBuildVbeModeList(vbeInfoPtr pVbe, VbeInfoBlock *vbe)
       
   951 {
       
   952     vbeModeInfoPtr ModeList = NULL;
       
   953 
       
   954     int i = 0;
       
   955     while (vbe->VideoModePtr[i] != 0xffff) {
       
   956 	vbeModeInfoPtr m;
       
   957 	VbeModeInfoBlock *mode;
       
   958 	int id = vbe->VideoModePtr[i++];
       
   959 	int bpp;
       
   960 
       
   961 	if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
       
   962 	    continue;
       
   963 
       
   964  	bpp = mode->BitsPerPixel;
       
   965 
       
   966 	m = xnfcalloc(sizeof(vbeModeInfoRec),1);
       
   967 	m->width = mode->XResolution;
       
   968 	m->height = mode->YResolution;
       
   969 	m->bpp = bpp;
       
   970 	m->n = id;
       
   971 	m->next = ModeList;
       
   972 
       
   973 	xf86DrvMsgVerb(pVbe->pInt10->scrnIndex, X_PROBED, 3,
       
   974 		       "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n",
       
   975 		       m->n, m->width, m->height, m->bpp);
       
   976 
       
   977 	ModeList = m;
       
   978 
       
   979 	VBEFreeModeInfo(mode);
       
   980     }
       
   981     return ModeList;
       
   982 }
       
   983 
       
   984 unsigned short 
       
   985 VBECalcVbeModeIndex(vbeModeInfoPtr m, DisplayModePtr mode, int bpp)
       
   986 {
       
   987     while (m) {
       
   988 	if (bpp == m->bpp 
       
   989 	    && mode->HDisplay == m->width 
       
   990 	    && mode->VDisplay == m->height)
       
   991 	    return m->n;
       
   992 	m = m->next;
       
   993     }
       
   994     return 0;
       
   995 }
       
   996 #endif
       
   997 
       
   998 void
       
   999 VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr,
       
  1000 		  vbeSaveRestoreFunction function)
       
  1001 {
       
  1002     Bool SaveSucc = FALSE;
       
  1003 
       
  1004     if (VBE_VERSION_MAJOR(pVbe->version) > 1
       
  1005 	&& (function == MODE_SAVE || vbe_sr->pstate)) {
       
  1006 	if (function == MODE_RESTORE)
       
  1007 	    memcpy(vbe_sr->state, vbe_sr->pstate, vbe_sr->stateSize);
       
  1008 	ErrorF("VBESaveRestore\n");
       
  1009 	if ((VBESaveRestore(pVbe,function,
       
  1010 			    (pointer)&vbe_sr->state,
       
  1011 			    &vbe_sr->stateSize,&vbe_sr->statePage))) {
       
  1012 	    if (function == MODE_SAVE) {
       
  1013 		SaveSucc = TRUE;
       
  1014 		vbe_sr->stateMode = -1; /* invalidate */
       
  1015 		/* don't rely on the memory not being touched */
       
  1016 		if (vbe_sr->pstate == NULL)
       
  1017 		    vbe_sr->pstate = xalloc(vbe_sr->stateSize);
       
  1018 		memcpy(vbe_sr->pstate, vbe_sr->state, vbe_sr->stateSize);
       
  1019 	    }
       
  1020 	    ErrorF("VBESaveRestore done with success\n");
       
  1021 	    return;
       
  1022 	}
       
  1023 	ErrorF("VBESaveRestore done\n");
       
  1024     } 
       
  1025     
       
  1026     if (function == MODE_SAVE && !SaveSucc)
       
  1027 	    (void)VBEGetVBEMode(pVbe, &vbe_sr->stateMode);
       
  1028 	
       
  1029     if (function == MODE_RESTORE && vbe_sr->stateMode != -1)
       
  1030 	    VBESetVBEMode(pVbe, vbe_sr->stateMode, NULL);
       
  1031 
       
  1032 }
       
  1033 
       
  1034 int
       
  1035 VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int clock)
       
  1036 {
       
  1037     /*
       
  1038     Input:
       
  1039 	AX := 4F0Bh VBE Get Pixel Clock
       
  1040 	BL := 01h Get Pixel Clock
       
  1041 	ECX := pixel clock in units of Hz
       
  1042         DX := mode number
       
  1043      
       
  1044     Output:
       
  1045 	AX := VBE Return Status
       
  1046 	ECX := Closest pixel clock
       
  1047      */
       
  1048 
       
  1049     pVbe->pInt10->num = 0x10;
       
  1050     pVbe->pInt10->ax = 0x4f0b;
       
  1051     pVbe->pInt10->bx = 0x01;
       
  1052     pVbe->pInt10->cx = clock;
       
  1053     pVbe->pInt10->dx = mode;
       
  1054     xf86ExecX86int10(pVbe->pInt10);
       
  1055 
       
  1056     if (R16(pVbe->pInt10->ax) != 0x4f)
       
  1057 	return (0);
       
  1058 
       
  1059     return (pVbe->pInt10->cx);
       
  1060 }
       
  1061 
       
  1062 Bool
       
  1063 VBEDPMSSet(vbeInfoPtr pVbe, int mode)
       
  1064 {
       
  1065     /*
       
  1066     Input:
       
  1067 	AX := 4F10h DPMS
       
  1068 	BL := 01h Set Display Power State
       
  1069 	BH := requested power state
       
  1070      
       
  1071     Output:
       
  1072 	AX := VBE Return Status
       
  1073      */
       
  1074 
       
  1075     pVbe->pInt10->num = 0x10;
       
  1076     pVbe->pInt10->ax = 0x4f10;
       
  1077     pVbe->pInt10->bx = 0x01;
       
  1078     switch (mode) {
       
  1079     case DPMSModeOn:
       
  1080 	break;
       
  1081     case DPMSModeStandby:
       
  1082 	pVbe->pInt10->bx |= 0x100;
       
  1083 	break;
       
  1084     case DPMSModeSuspend:
       
  1085 	pVbe->pInt10->bx |= 0x200;
       
  1086 	break;
       
  1087     case DPMSModeOff:
       
  1088 	pVbe->pInt10->bx |= 0x400;
       
  1089 	break;
       
  1090     }
       
  1091     xf86ExecX86int10(pVbe->pInt10);
       
  1092     return (R16(pVbe->pInt10->ax) == 0x4f);
       
  1093 }
       
  1094