1706f2543Smrg 2706f2543Smrg/* 3706f2543Smrg * XFree86 vbe module 4706f2543Smrg * Copyright 2000 Egbert Eich 5706f2543Smrg * 6706f2543Smrg * The mode query/save/set/restore functions from the vesa driver 7706f2543Smrg * have been moved here. 8706f2543Smrg * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) 9706f2543Smrg * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br> 10706f2543Smrg */ 11706f2543Smrg 12706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 13706f2543Smrg#include <xorg-config.h> 14706f2543Smrg#endif 15706f2543Smrg 16706f2543Smrg#include <string.h> 17706f2543Smrg 18706f2543Smrg#include "xf86.h" 19706f2543Smrg#include "xf86Modes.h" 20706f2543Smrg#include "vbe.h" 21706f2543Smrg#include <X11/extensions/dpmsconst.h> 22706f2543Smrg 23706f2543Smrg#define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x) 24706f2543Smrg 25706f2543Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 26706f2543Smrg#define B_O16(x) (x) 27706f2543Smrg#define B_O32(x) (x) 28706f2543Smrg#else 29706f2543Smrg#define B_O16(x) ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8)) 30706f2543Smrg#define B_O32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \ 31706f2543Smrg | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)) 32706f2543Smrg#endif 33706f2543Smrg#define L_ADD(x) (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00) 34706f2543Smrg 35706f2543Smrg#define FARP(p) (((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff)) 36706f2543Smrg#define R16(v) ((v) & 0xffff) 37706f2543Smrg 38706f2543Smrgstatic unsigned char * vbeReadEDID(vbeInfoPtr pVbe); 39706f2543Smrgstatic Bool vbeProbeDDC(vbeInfoPtr pVbe); 40706f2543Smrg 41706f2543Smrgstatic const char vbeVersionString[] = "VBE2"; 42706f2543Smrg 43706f2543SmrgvbeInfoPtr 44706f2543SmrgVBEInit(xf86Int10InfoPtr pInt, int entityIndex) 45706f2543Smrg{ 46706f2543Smrg return VBEExtendedInit(pInt, entityIndex, 0); 47706f2543Smrg} 48706f2543Smrg 49706f2543SmrgvbeInfoPtr 50706f2543SmrgVBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags) 51706f2543Smrg{ 52706f2543Smrg int RealOff; 53706f2543Smrg pointer page = NULL; 54706f2543Smrg ScrnInfoPtr pScrn = xf86FindScreenForEntity(entityIndex); 55706f2543Smrg vbeControllerInfoPtr vbe = NULL; 56706f2543Smrg Bool init_int10 = FALSE; 57706f2543Smrg vbeInfoPtr vip = NULL; 58706f2543Smrg int screen; 59706f2543Smrg 60706f2543Smrg if (!pScrn) return NULL; 61706f2543Smrg screen = pScrn->scrnIndex; 62706f2543Smrg 63706f2543Smrg if (!pInt) { 64706f2543Smrg if (!xf86LoadSubModule(pScrn, "int10")) 65706f2543Smrg goto error; 66706f2543Smrg 67706f2543Smrg xf86DrvMsg(screen,X_INFO,"initializing int10\n"); 68706f2543Smrg pInt = xf86ExtendedInitInt10(entityIndex,Flags); 69706f2543Smrg if (!pInt) 70706f2543Smrg goto error; 71706f2543Smrg init_int10 = TRUE; 72706f2543Smrg } 73706f2543Smrg 74706f2543Smrg page = xf86Int10AllocPages(pInt,1,&RealOff); 75706f2543Smrg if (!page) goto error; 76706f2543Smrg vbe = (vbeControllerInfoPtr) page; 77706f2543Smrg memcpy(vbe->VbeSignature,vbeVersionString,4); 78706f2543Smrg 79706f2543Smrg pInt->ax = 0x4F00; 80706f2543Smrg pInt->es = SEG_ADDR(RealOff); 81706f2543Smrg pInt->di = SEG_OFF(RealOff); 82706f2543Smrg pInt->num = 0x10; 83706f2543Smrg 84706f2543Smrg xf86ExecX86int10(pInt); 85706f2543Smrg 86706f2543Smrg if ((pInt->ax & 0xff) != 0x4f) { 87706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA BIOS not detected\n"); 88706f2543Smrg goto error; 89706f2543Smrg } 90706f2543Smrg 91706f2543Smrg switch (pInt->ax & 0xff00) { 92706f2543Smrg case 0: 93706f2543Smrg xf86DrvMsg(screen,X_INFO,"VESA BIOS detected\n"); 94706f2543Smrg break; 95706f2543Smrg case 0x100: 96706f2543Smrg xf86DrvMsg(screen,X_INFO,"VESA BIOS function failed\n"); 97706f2543Smrg goto error; 98706f2543Smrg case 0x200: 99706f2543Smrg xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported\n"); 100706f2543Smrg goto error; 101706f2543Smrg case 0x300: 102706f2543Smrg xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported in current mode\n"); 103706f2543Smrg goto error; 104706f2543Smrg default: 105706f2543Smrg xf86DrvMsg(screen,X_INFO,"Invalid\n"); 106706f2543Smrg goto error; 107706f2543Smrg } 108706f2543Smrg 109706f2543Smrg xf86DrvMsgVerb(screen, X_INFO, 4, 110706f2543Smrg "VbeVersion is %d, OemStringPtr is 0x%08lx,\n" 111706f2543Smrg "\tOemVendorNamePtr is 0x%08lx, OemProductNamePtr is 0x%08lx,\n" 112706f2543Smrg "\tOemProductRevPtr is 0x%08lx\n", 113706f2543Smrg vbe->VbeVersion, (unsigned long)vbe->OemStringPtr, 114706f2543Smrg (unsigned long)vbe->OemVendorNamePtr, 115706f2543Smrg (unsigned long)vbe->OemProductNamePtr, 116706f2543Smrg (unsigned long)vbe->OemProductRevPtr); 117706f2543Smrg 118706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Version %i.%i\n", 119706f2543Smrg VERSION(vbe->VbeVersion)); 120706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Total Mem: %i kB\n", 121706f2543Smrg vbe->TotalMem * 64); 122706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM: %s\n", 123706f2543Smrg (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemStringPtr))); 124706f2543Smrg 125706f2543Smrg if (B_O16(vbe->VbeVersion) >= 0x200) { 126706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Software Rev: %i.%i\n", 127706f2543Smrg VERSION(vbe->OemSoftwareRev)); 128706f2543Smrg if (vbe->OemVendorNamePtr) 129706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Vendor: %s\n", 130706f2543Smrg (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemVendorNamePtr))); 131706f2543Smrg if (vbe->OemProductNamePtr) 132706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product: %s\n", 133706f2543Smrg (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductNamePtr))); 134706f2543Smrg if (vbe->OemProductRevPtr) 135706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product Rev: %s\n", 136706f2543Smrg (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductRevPtr))); 137706f2543Smrg } 138706f2543Smrg vip = (vbeInfoPtr)xnfalloc(sizeof(vbeInfoRec)); 139706f2543Smrg vip->version = B_O16(vbe->VbeVersion); 140706f2543Smrg vip->pInt10 = pInt; 141706f2543Smrg vip->ddc = DDC_UNCHECKED; 142706f2543Smrg vip->memory = page; 143706f2543Smrg vip->real_mode_base = RealOff; 144706f2543Smrg vip->num_pages = 1; 145706f2543Smrg vip->init_int10 = init_int10; 146706f2543Smrg 147706f2543Smrg return vip; 148706f2543Smrg 149706f2543Smrg error: 150706f2543Smrg if (page) 151706f2543Smrg xf86Int10FreePages(pInt, page, 1); 152706f2543Smrg if (init_int10) 153706f2543Smrg xf86FreeInt10(pInt); 154706f2543Smrg return NULL; 155706f2543Smrg} 156706f2543Smrg 157706f2543Smrgvoid 158706f2543SmrgvbeFree(vbeInfoPtr pVbe) 159706f2543Smrg{ 160706f2543Smrg if (!pVbe) 161706f2543Smrg return; 162706f2543Smrg 163706f2543Smrg xf86Int10FreePages(pVbe->pInt10,pVbe->memory,pVbe->num_pages); 164706f2543Smrg /* If we have initalized int10 we ought to free it, too */ 165706f2543Smrg if (pVbe->init_int10) 166706f2543Smrg xf86FreeInt10(pVbe->pInt10); 167706f2543Smrg free(pVbe); 168706f2543Smrg return; 169706f2543Smrg} 170706f2543Smrg 171706f2543Smrgstatic Bool 172706f2543SmrgvbeProbeDDC(vbeInfoPtr pVbe) 173706f2543Smrg{ 174706f2543Smrg char *ddc_level; 175706f2543Smrg int screen = pVbe->pInt10->scrnIndex; 176706f2543Smrg 177706f2543Smrg if (pVbe->ddc == DDC_NONE) 178706f2543Smrg return FALSE; 179706f2543Smrg if (pVbe->ddc != DDC_UNCHECKED) 180706f2543Smrg return TRUE; 181706f2543Smrg 182706f2543Smrg pVbe->pInt10->ax = 0x4F15; 183706f2543Smrg pVbe->pInt10->bx = 0; 184706f2543Smrg pVbe->pInt10->cx = 0; 185706f2543Smrg pVbe->pInt10->es = 0; 186706f2543Smrg pVbe->pInt10->di = 0; 187706f2543Smrg pVbe->pInt10->num = 0x10; 188706f2543Smrg 189706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 190706f2543Smrg 191706f2543Smrg if ((pVbe->pInt10->ax & 0xff) != 0x4f) { 192706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC not supported\n"); 193706f2543Smrg pVbe->ddc = DDC_NONE; 194706f2543Smrg return FALSE; 195706f2543Smrg } 196706f2543Smrg 197706f2543Smrg switch ((pVbe->pInt10->ax >> 8) & 0xff) { 198706f2543Smrg case 0: 199706f2543Smrg xf86DrvMsg(screen,X_INFO,"VESA VBE DDC supported\n"); 200706f2543Smrg switch (pVbe->pInt10->bx & 0x3) { 201706f2543Smrg case 0: 202706f2543Smrg ddc_level = " none"; 203706f2543Smrg pVbe->ddc = DDC_NONE; 204706f2543Smrg break; 205706f2543Smrg case 1: 206706f2543Smrg ddc_level = " 1"; 207706f2543Smrg pVbe->ddc = DDC_1; 208706f2543Smrg break; 209706f2543Smrg case 2: 210706f2543Smrg ddc_level = " 2"; 211706f2543Smrg pVbe->ddc = DDC_2; 212706f2543Smrg break; 213706f2543Smrg case 3: 214706f2543Smrg ddc_level = " 1 + 2"; 215706f2543Smrg pVbe->ddc = DDC_1_2; 216706f2543Smrg break; 217706f2543Smrg default: 218706f2543Smrg ddc_level = ""; 219706f2543Smrg pVbe->ddc = DDC_NONE; 220706f2543Smrg break; 221706f2543Smrg } 222706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Level%s\n",ddc_level); 223706f2543Smrg if (pVbe->pInt10->bx & 0x4) { 224706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Screen blanked" 225706f2543Smrg "for data transfer\n"); 226706f2543Smrg pVbe->ddc_blank = TRUE; 227706f2543Smrg } else 228706f2543Smrg pVbe->ddc_blank = FALSE; 229706f2543Smrg 230706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3, 231706f2543Smrg "VESA VBE DDC transfer in appr. %x sec.\n", 232706f2543Smrg (pVbe->pInt10->bx >> 8) & 0xff); 233706f2543Smrg } 234706f2543Smrg 235706f2543Smrg return TRUE; 236706f2543Smrg} 237706f2543Smrg 238706f2543Smrgtypedef enum { 239706f2543Smrg VBEOPT_NOVBE, 240706f2543Smrg VBEOPT_NODDC 241706f2543Smrg} VBEOpts; 242706f2543Smrg 243706f2543Smrgstatic const OptionInfoRec VBEOptions[] = { 244706f2543Smrg { VBEOPT_NOVBE, "NoVBE", OPTV_BOOLEAN, {0}, FALSE }, 245706f2543Smrg { VBEOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, 246706f2543Smrg { -1, NULL, OPTV_NONE, {0}, FALSE }, 247706f2543Smrg}; 248706f2543Smrg 249706f2543Smrgstatic unsigned char * 250706f2543SmrgvbeReadEDID(vbeInfoPtr pVbe) 251706f2543Smrg{ 252706f2543Smrg int RealOff = pVbe->real_mode_base; 253706f2543Smrg pointer page = pVbe->memory; 254706f2543Smrg unsigned char *tmp = NULL; 255706f2543Smrg Bool novbe = FALSE; 256706f2543Smrg Bool noddc = FALSE; 257706f2543Smrg int screen = pVbe->pInt10->scrnIndex; 258706f2543Smrg OptionInfoPtr options; 259706f2543Smrg 260706f2543Smrg if (!page) return NULL; 261706f2543Smrg 262706f2543Smrg options = xnfalloc(sizeof(VBEOptions)); 263706f2543Smrg (void)memcpy(options, VBEOptions, sizeof(VBEOptions)); 264706f2543Smrg xf86ProcessOptions(screen, xf86Screens[screen]->options, options); 265706f2543Smrg xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe); 266706f2543Smrg xf86GetOptValBool(options, VBEOPT_NODDC, &noddc); 267706f2543Smrg free(options); 268706f2543Smrg if (novbe || noddc) return NULL; 269706f2543Smrg 270706f2543Smrg if (!vbeProbeDDC(pVbe)) goto error; 271706f2543Smrg 272706f2543Smrg memset(page,0,sizeof(vbeInfoPtr)); 273706f2543Smrg strcpy(page,vbeVersionString); 274706f2543Smrg 275706f2543Smrg pVbe->pInt10->ax = 0x4F15; 276706f2543Smrg pVbe->pInt10->bx = 0x01; 277706f2543Smrg pVbe->pInt10->cx = 0; 278706f2543Smrg pVbe->pInt10->dx = 0; 279706f2543Smrg pVbe->pInt10->es = SEG_ADDR(RealOff); 280706f2543Smrg pVbe->pInt10->di = SEG_OFF(RealOff); 281706f2543Smrg pVbe->pInt10->num = 0x10; 282706f2543Smrg 283706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 284706f2543Smrg 285706f2543Smrg if ((pVbe->pInt10->ax & 0xff) != 0x4f) { 286706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC invalid\n"); 287706f2543Smrg goto error; 288706f2543Smrg } 289706f2543Smrg switch (pVbe->pInt10->ax & 0xff00) { 290706f2543Smrg case 0x0: 291706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read successfully\n"); 292706f2543Smrg tmp = (unsigned char *)xnfalloc(128); 293706f2543Smrg memcpy(tmp,page,128); 294706f2543Smrg break; 295706f2543Smrg case 0x100: 296706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read failed\n"); 297706f2543Smrg break; 298706f2543Smrg default: 299706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC unkown failure %i\n", 300706f2543Smrg pVbe->pInt10->ax & 0xff00); 301706f2543Smrg break; 302706f2543Smrg } 303706f2543Smrg 304706f2543Smrg error: 305706f2543Smrg return tmp; 306706f2543Smrg} 307706f2543Smrg 308706f2543Smrgxf86MonPtr 309706f2543SmrgvbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule) 310706f2543Smrg{ 311706f2543Smrg xf86MonPtr pMonitor; 312706f2543Smrg pointer pModule; 313706f2543Smrg unsigned char *DDC_data = NULL; 314706f2543Smrg 315706f2543Smrg if (!pVbe) return NULL; 316706f2543Smrg if (pVbe->version < 0x200) 317706f2543Smrg return NULL; 318706f2543Smrg 319706f2543Smrg if (!(pModule = pDDCModule)) { 320706f2543Smrg pModule = 321706f2543Smrg xf86LoadSubModule(xf86Screens[pVbe->pInt10->scrnIndex], "ddc"); 322706f2543Smrg if (!pModule) 323706f2543Smrg return NULL; 324706f2543Smrg } 325706f2543Smrg 326706f2543Smrg DDC_data = vbeReadEDID(pVbe); 327706f2543Smrg 328706f2543Smrg if (!DDC_data) 329706f2543Smrg return NULL; 330706f2543Smrg 331706f2543Smrg pMonitor = xf86InterpretEDID(pVbe->pInt10->scrnIndex, DDC_data); 332706f2543Smrg 333706f2543Smrg if (!pDDCModule) 334706f2543Smrg xf86UnloadSubModule(pModule); 335706f2543Smrg return pMonitor; 336706f2543Smrg} 337706f2543Smrg 338706f2543Smrg#define GET_UNALIGNED2(x) \ 339706f2543Smrg ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16) 340706f2543Smrg 341706f2543SmrgVbeInfoBlock * 342706f2543SmrgVBEGetVBEInfo(vbeInfoPtr pVbe) 343706f2543Smrg{ 344706f2543Smrg VbeInfoBlock *block = NULL; 345706f2543Smrg int i, pStr, pModes; 346706f2543Smrg char *str; 347706f2543Smrg CARD16 major, *modes; 348706f2543Smrg 349706f2543Smrg memset(pVbe->memory, 0, sizeof(VbeInfoBlock)); 350706f2543Smrg 351706f2543Smrg /* 352706f2543Smrg Input: 353706f2543Smrg AH := 4Fh Super VGA support 354706f2543Smrg AL := 00h Return Super VGA information 355706f2543Smrg ES:DI := Pointer to buffer 356706f2543Smrg 357706f2543Smrg Output: 358706f2543Smrg AX := status 359706f2543Smrg (All other registers are preserved) 360706f2543Smrg */ 361706f2543Smrg 362706f2543Smrg ((char*)pVbe->memory)[0] = 'V'; 363706f2543Smrg ((char*)pVbe->memory)[1] = 'B'; 364706f2543Smrg ((char*)pVbe->memory)[2] = 'E'; 365706f2543Smrg ((char*)pVbe->memory)[3] = '2'; 366706f2543Smrg 367706f2543Smrg pVbe->pInt10->num = 0x10; 368706f2543Smrg pVbe->pInt10->ax = 0x4f00; 369706f2543Smrg pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); 370706f2543Smrg pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); 371706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 372706f2543Smrg 373706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 374706f2543Smrg return NULL; 375706f2543Smrg 376706f2543Smrg block = calloc(sizeof(VbeInfoBlock), 1); 377706f2543Smrg block->VESASignature[0] = ((char*)pVbe->memory)[0]; 378706f2543Smrg block->VESASignature[1] = ((char*)pVbe->memory)[1]; 379706f2543Smrg block->VESASignature[2] = ((char*)pVbe->memory)[2]; 380706f2543Smrg block->VESASignature[3] = ((char*)pVbe->memory)[3]; 381706f2543Smrg 382706f2543Smrg block->VESAVersion = *(CARD16*)(((char*)pVbe->memory) + 4); 383706f2543Smrg major = (unsigned)block->VESAVersion >> 8; 384706f2543Smrg 385706f2543Smrg pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 6)); 386706f2543Smrg str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); 387706f2543Smrg block->OEMStringPtr = strdup(str); 388706f2543Smrg 389706f2543Smrg block->Capabilities[0] = ((char*)pVbe->memory)[10]; 390706f2543Smrg block->Capabilities[1] = ((char*)pVbe->memory)[11]; 391706f2543Smrg block->Capabilities[2] = ((char*)pVbe->memory)[12]; 392706f2543Smrg block->Capabilities[3] = ((char*)pVbe->memory)[13]; 393706f2543Smrg 394706f2543Smrg pModes = GET_UNALIGNED2((((char*)pVbe->memory) + 14)); 395706f2543Smrg modes = xf86int10Addr(pVbe->pInt10, FARP(pModes)); 396706f2543Smrg i = 0; 397706f2543Smrg while (modes[i] != 0xffff) 398706f2543Smrg i++; 399706f2543Smrg block->VideoModePtr = malloc(sizeof(CARD16) * (i + 1)); 400706f2543Smrg memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i); 401706f2543Smrg block->VideoModePtr[i] = 0xffff; 402706f2543Smrg 403706f2543Smrg block->TotalMemory = *(CARD16*)(((char*)pVbe->memory) + 18); 404706f2543Smrg 405706f2543Smrg if (major < 2) 406706f2543Smrg memcpy(&block->OemSoftwareRev, ((char*)pVbe->memory) + 20, 236); 407706f2543Smrg else { 408706f2543Smrg block->OemSoftwareRev = *(CARD16*)(((char*)pVbe->memory) + 20); 409706f2543Smrg pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 22)); 410706f2543Smrg str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); 411706f2543Smrg block->OemVendorNamePtr = strdup(str); 412706f2543Smrg pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 26)); 413706f2543Smrg str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); 414706f2543Smrg block->OemProductNamePtr = strdup(str); 415706f2543Smrg pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 30)); 416706f2543Smrg str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); 417706f2543Smrg block->OemProductRevPtr = strdup(str); 418706f2543Smrg memcpy(&block->Reserved, ((char*)pVbe->memory) + 34, 222); 419706f2543Smrg memcpy(&block->OemData, ((char*)pVbe->memory) + 256, 256); 420706f2543Smrg } 421706f2543Smrg 422706f2543Smrg return block; 423706f2543Smrg} 424706f2543Smrg 425706f2543Smrgvoid 426706f2543SmrgVBEFreeVBEInfo(VbeInfoBlock *block) 427706f2543Smrg{ 428706f2543Smrg free(block->OEMStringPtr); 429706f2543Smrg free(block->VideoModePtr); 430706f2543Smrg if (((unsigned)block->VESAVersion >> 8) >= 2) { 431706f2543Smrg free(block->OemVendorNamePtr); 432706f2543Smrg free(block->OemProductNamePtr); 433706f2543Smrg free(block->OemProductRevPtr); 434706f2543Smrg } 435706f2543Smrg free(block); 436706f2543Smrg} 437706f2543Smrg 438706f2543SmrgBool 439706f2543SmrgVBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *block) 440706f2543Smrg{ 441706f2543Smrg /* 442706f2543Smrg Input: 443706f2543Smrg AH := 4Fh Super VGA support 444706f2543Smrg AL := 02h Set Super VGA video mode 445706f2543Smrg BX := Video mode 446706f2543Smrg D0-D8 := Mode number 447706f2543Smrg D9-D10 := Reserved (must be 0) 448706f2543Smrg D11 := 0 Use current default refresh rate 449706f2543Smrg := 1 Use user specified CRTC values for refresh rate 450706f2543Smrg D12-13 Reserved for VBE/AF (must be 0) 451706f2543Smrg D14 := 0 Use windowed frame buffer model 452706f2543Smrg := 1 Use linear/flat frame buffer model 453706f2543Smrg D15 := 0 Clear video memory 454706f2543Smrg := 1 Don't clear video memory 455706f2543Smrg ES:DI := Pointer to VbeCRTCInfoBlock structure 456706f2543Smrg 457706f2543Smrg Output: AX = Status 458706f2543Smrg (All other registers are preserved) 459706f2543Smrg */ 460706f2543Smrg pVbe->pInt10->num = 0x10; 461706f2543Smrg pVbe->pInt10->ax = 0x4f02; 462706f2543Smrg pVbe->pInt10->bx = mode; 463706f2543Smrg if (block) { 464706f2543Smrg pVbe->pInt10->bx |= 1 << 11; 465706f2543Smrg memcpy(pVbe->memory, block, sizeof(VbeCRTCInfoBlock)); 466706f2543Smrg pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); 467706f2543Smrg pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); 468706f2543Smrg } else 469706f2543Smrg pVbe->pInt10->bx &= ~(1 << 11); 470706f2543Smrg 471706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 472706f2543Smrg 473706f2543Smrg return (R16(pVbe->pInt10->ax) == 0x4f); 474706f2543Smrg} 475706f2543Smrg 476706f2543SmrgBool 477706f2543SmrgVBEGetVBEMode(vbeInfoPtr pVbe, int *mode) 478706f2543Smrg{ 479706f2543Smrg /* 480706f2543Smrg Input: 481706f2543Smrg AH := 4Fh Super VGA support 482706f2543Smrg AL := 03h Return current video mode 483706f2543Smrg 484706f2543Smrg Output: 485706f2543Smrg AX := Status 486706f2543Smrg BX := Current video mode 487706f2543Smrg (All other registers are preserved) 488706f2543Smrg */ 489706f2543Smrg pVbe->pInt10->num = 0x10; 490706f2543Smrg pVbe->pInt10->ax = 0x4f03; 491706f2543Smrg 492706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 493706f2543Smrg 494706f2543Smrg if (R16(pVbe->pInt10->ax) == 0x4f) { 495706f2543Smrg *mode = R16(pVbe->pInt10->bx); 496706f2543Smrg 497706f2543Smrg return TRUE; 498706f2543Smrg } 499706f2543Smrg 500706f2543Smrg return FALSE; 501706f2543Smrg} 502706f2543Smrg 503706f2543SmrgVbeModeInfoBlock * 504706f2543SmrgVBEGetModeInfo(vbeInfoPtr pVbe, int mode) 505706f2543Smrg{ 506706f2543Smrg VbeModeInfoBlock *block = NULL; 507706f2543Smrg 508706f2543Smrg memset(pVbe->memory, 0, sizeof(VbeModeInfoBlock)); 509706f2543Smrg 510706f2543Smrg /* 511706f2543Smrg Input: 512706f2543Smrg AH := 4Fh Super VGA support 513706f2543Smrg AL := 01h Return Super VGA mode information 514706f2543Smrg CX := Super VGA video mode 515706f2543Smrg (mode number must be one of those returned by Function 0) 516706f2543Smrg ES:DI := Pointer to buffer 517706f2543Smrg 518706f2543Smrg Output: 519706f2543Smrg AX := status 520706f2543Smrg (All other registers are preserved) 521706f2543Smrg */ 522706f2543Smrg pVbe->pInt10->num = 0x10; 523706f2543Smrg pVbe->pInt10->ax = 0x4f01; 524706f2543Smrg pVbe->pInt10->cx = mode; 525706f2543Smrg pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); 526706f2543Smrg pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); 527706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 528706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 529706f2543Smrg return NULL; 530706f2543Smrg 531706f2543Smrg block = malloc(sizeof(VbeModeInfoBlock)); 532706f2543Smrg if (block) 533706f2543Smrg memcpy(block, pVbe->memory, sizeof(*block)); 534706f2543Smrg 535706f2543Smrg return block; 536706f2543Smrg} 537706f2543Smrg 538706f2543Smrgvoid 539706f2543SmrgVBEFreeModeInfo(VbeModeInfoBlock *block) 540706f2543Smrg{ 541706f2543Smrg free(block); 542706f2543Smrg} 543706f2543Smrg 544706f2543SmrgBool 545706f2543SmrgVBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function, 546706f2543Smrg pointer *memory, int *size, int *real_mode_pages) 547706f2543Smrg{ 548706f2543Smrg /* 549706f2543Smrg Input: 550706f2543Smrg AH := 4Fh Super VGA support 551706f2543Smrg AL := 04h Save/restore Super VGA video state 552706f2543Smrg DL := 00h Return save/restore state buffer size 553706f2543Smrg CX := Requested states 554706f2543Smrg D0 = Save/restore video hardware state 555706f2543Smrg D1 = Save/restore video BIOS data state 556706f2543Smrg D2 = Save/restore video DAC state 557706f2543Smrg D3 = Save/restore Super VGA state 558706f2543Smrg 559706f2543Smrg Output: 560706f2543Smrg AX = Status 561706f2543Smrg BX = Number of 64-byte blocks to hold the state buffer 562706f2543Smrg (All other registers are preserved) 563706f2543Smrg 564706f2543Smrg 565706f2543Smrg Input: 566706f2543Smrg AH := 4Fh Super VGA support 567706f2543Smrg AL := 04h Save/restore Super VGA video state 568706f2543Smrg DL := 01h Save Super VGA video state 569706f2543Smrg CX := Requested states (see above) 570706f2543Smrg ES:BX := Pointer to buffer 571706f2543Smrg 572706f2543Smrg Output: 573706f2543Smrg AX := Status 574706f2543Smrg (All other registers are preserved) 575706f2543Smrg 576706f2543Smrg 577706f2543Smrg Input: 578706f2543Smrg AH := 4Fh Super VGA support 579706f2543Smrg AL := 04h Save/restore Super VGA video state 580706f2543Smrg DL := 02h Restore Super VGA video state 581706f2543Smrg CX := Requested states (see above) 582706f2543Smrg ES:BX := Pointer to buffer 583706f2543Smrg 584706f2543Smrg Output: 585706f2543Smrg AX := Status 586706f2543Smrg (All other registers are preserved) 587706f2543Smrg */ 588706f2543Smrg 589706f2543Smrg if ((pVbe->version & 0xff00) > 0x100) { 590706f2543Smrg int screen = pVbe->pInt10->scrnIndex; 591706f2543Smrg if (function == MODE_QUERY || 592706f2543Smrg (function == MODE_SAVE && !*memory)) { 593706f2543Smrg /* Query amount of memory to save state */ 594706f2543Smrg 595706f2543Smrg pVbe->pInt10->num = 0x10; 596706f2543Smrg pVbe->pInt10->ax = 0x4f04; 597706f2543Smrg pVbe->pInt10->dx = 0; 598706f2543Smrg pVbe->pInt10->cx = 0x000f; 599706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 600706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 601706f2543Smrg return FALSE; 602706f2543Smrg 603706f2543Smrg if (function == MODE_SAVE) { 604706f2543Smrg int npages = (R16(pVbe->pInt10->bx) * 64) / 4096 + 1; 605706f2543Smrg if ((*memory = xf86Int10AllocPages(pVbe->pInt10, npages, 606706f2543Smrg real_mode_pages)) == NULL) { 607706f2543Smrg xf86DrvMsg(screen, X_ERROR, 608706f2543Smrg "Cannot allocate memory to save SVGA state.\n"); 609706f2543Smrg return FALSE; 610706f2543Smrg } 611706f2543Smrg } 612706f2543Smrg *size = pVbe->pInt10->bx * 64; 613706f2543Smrg } 614706f2543Smrg 615706f2543Smrg /* Save/Restore Super VGA state */ 616706f2543Smrg if (function != MODE_QUERY) { 617706f2543Smrg 618706f2543Smrg if (!*memory) return FALSE; 619706f2543Smrg pVbe->pInt10->num = 0x10; 620706f2543Smrg pVbe->pInt10->ax = 0x4f04; 621706f2543Smrg switch (function) { 622706f2543Smrg case MODE_SAVE: 623706f2543Smrg pVbe->pInt10->dx = 1; 624706f2543Smrg break; 625706f2543Smrg case MODE_RESTORE: 626706f2543Smrg pVbe->pInt10->dx = 2; 627706f2543Smrg break; 628706f2543Smrg case MODE_QUERY: 629706f2543Smrg return FALSE; 630706f2543Smrg } 631706f2543Smrg pVbe->pInt10->cx = 0x000f; 632706f2543Smrg 633706f2543Smrg pVbe->pInt10->es = SEG_ADDR(*real_mode_pages); 634706f2543Smrg pVbe->pInt10->bx = SEG_OFF(*real_mode_pages); 635706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 636706f2543Smrg return (R16(pVbe->pInt10->ax) == 0x4f); 637706f2543Smrg 638706f2543Smrg } 639706f2543Smrg } 640706f2543Smrg return TRUE; 641706f2543Smrg} 642706f2543Smrg 643706f2543SmrgBool 644706f2543SmrgVBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window) 645706f2543Smrg{ 646706f2543Smrg /* 647706f2543Smrg Input: 648706f2543Smrg AH := 4Fh Super VGA support 649706f2543Smrg AL := 05h 650706f2543Smrg 651706f2543Smrg Output: 652706f2543Smrg */ 653706f2543Smrg pVbe->pInt10->num = 0x10; 654706f2543Smrg pVbe->pInt10->ax = 0x4f05; 655706f2543Smrg pVbe->pInt10->bx = window; 656706f2543Smrg pVbe->pInt10->dx = iBank; 657706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 658706f2543Smrg 659706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 660706f2543Smrg return FALSE; 661706f2543Smrg 662706f2543Smrg return TRUE; 663706f2543Smrg} 664706f2543Smrg 665706f2543SmrgBool 666706f2543SmrgVBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, vbeScanwidthCommand command, 667706f2543Smrg int width, int *pixels, int *bytes, int *max) 668706f2543Smrg{ 669706f2543Smrg if (command < SCANWID_SET || command > SCANWID_GET_MAX) 670706f2543Smrg return FALSE; 671706f2543Smrg 672706f2543Smrg /* 673706f2543Smrg Input: 674706f2543Smrg AX := 4F06h VBE Set/Get Logical Scan Line Length 675706f2543Smrg BL := 00h Set Scan Line Length in Pixels 676706f2543Smrg := 01h Get Scan Line Length 677706f2543Smrg := 02h Set Scan Line Length in Bytes 678706f2543Smrg := 03h Get Maximum Scan Line Length 679706f2543Smrg CX := If BL=00h Desired Width in Pixels 680706f2543Smrg If BL=02h Desired Width in Bytes 681706f2543Smrg (Ignored for Get Functions) 682706f2543Smrg 683706f2543Smrg Output: 684706f2543Smrg AX := VBE Return Status 685706f2543Smrg BX := Bytes Per Scan Line 686706f2543Smrg CX := Actual Pixels Per Scan Line 687706f2543Smrg (truncated to nearest complete pixel) 688706f2543Smrg DX := Maximum Number of Scan Lines 689706f2543Smrg */ 690706f2543Smrg 691706f2543Smrg pVbe->pInt10->num = 0x10; 692706f2543Smrg pVbe->pInt10->ax = 0x4f06; 693706f2543Smrg pVbe->pInt10->bx = command; 694706f2543Smrg if (command == SCANWID_SET || command == SCANWID_SET_BYTES) 695706f2543Smrg pVbe->pInt10->cx = width; 696706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 697706f2543Smrg 698706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 699706f2543Smrg return FALSE; 700706f2543Smrg 701706f2543Smrg if (command == SCANWID_GET || command == SCANWID_GET_MAX) { 702706f2543Smrg if (pixels) 703706f2543Smrg *pixels = R16(pVbe->pInt10->cx); 704706f2543Smrg if (bytes) 705706f2543Smrg *bytes = R16(pVbe->pInt10->bx); 706706f2543Smrg if (max) 707706f2543Smrg *max = R16(pVbe->pInt10->dx); 708706f2543Smrg } 709706f2543Smrg 710706f2543Smrg return TRUE; 711706f2543Smrg} 712706f2543Smrg 713706f2543SmrgBool 714706f2543SmrgVBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace) 715706f2543Smrg{ 716706f2543Smrg pVbe->pInt10->num = 0x10; 717706f2543Smrg pVbe->pInt10->ax = 0x4f07; 718706f2543Smrg pVbe->pInt10->bx = wait_retrace ? 0x80 : 0x00; 719706f2543Smrg pVbe->pInt10->cx = x; 720706f2543Smrg pVbe->pInt10->dx = y; 721706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 722706f2543Smrg 723706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 724706f2543Smrg return FALSE; 725706f2543Smrg 726706f2543Smrg return TRUE; 727706f2543Smrg} 728706f2543Smrg 729706f2543SmrgBool 730706f2543SmrgVBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y) 731706f2543Smrg{ 732706f2543Smrg pVbe->pInt10->num = 0x10; 733706f2543Smrg pVbe->pInt10->ax = 0x4f07; 734706f2543Smrg pVbe->pInt10->bx = 0x01; 735706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 736706f2543Smrg 737706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 738706f2543Smrg return FALSE; 739706f2543Smrg 740706f2543Smrg *x = pVbe->pInt10->cx; 741706f2543Smrg *y = pVbe->pInt10->dx; 742706f2543Smrg 743706f2543Smrg return TRUE; 744706f2543Smrg} 745706f2543Smrg 746706f2543Smrgint 747706f2543SmrgVBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits) 748706f2543Smrg{ 749706f2543Smrg /* 750706f2543Smrg Input: 751706f2543Smrg AX := 4F08h VBE Set/Get Palette Format 752706f2543Smrg BL := 00h Set DAC Palette Format 753706f2543Smrg := 01h Get DAC Palette Format 754706f2543Smrg BH := Desired bits of color per primary 755706f2543Smrg (Set DAC Palette Format only) 756706f2543Smrg 757706f2543Smrg Output: 758706f2543Smrg AX := VBE Return Status 759706f2543Smrg BH := Current number of bits of color per primary 760706f2543Smrg */ 761706f2543Smrg 762706f2543Smrg pVbe->pInt10->num = 0x10; 763706f2543Smrg pVbe->pInt10->ax = 0x4f08; 764706f2543Smrg if (!bits) 765706f2543Smrg pVbe->pInt10->bx = 0x01; 766706f2543Smrg else 767706f2543Smrg pVbe->pInt10->bx = (bits & 0x00ff) << 8; 768706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 769706f2543Smrg 770706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 771706f2543Smrg return 0; 772706f2543Smrg 773706f2543Smrg return (bits != 0 ? bits : (pVbe->pInt10->bx >> 8) & 0x00ff); 774706f2543Smrg} 775706f2543Smrg 776706f2543SmrgCARD32 * 777706f2543SmrgVBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num, 778706f2543Smrg CARD32 *data, Bool secondary, Bool wait_retrace) 779706f2543Smrg{ 780706f2543Smrg /* 781706f2543Smrg Input: 782706f2543Smrg (16-bit) 783706f2543Smrg AX := 4F09h VBE Load/Unload Palette Data 784706f2543Smrg BL := 00h Set Palette Data 785706f2543Smrg := 01h Get Palette Data 786706f2543Smrg := 02h Set Secondary Palette Data 787706f2543Smrg := 03h Get Secondary Palette Data 788706f2543Smrg := 80h Set Palette Data during Vertical Retrace 789706f2543Smrg CX := Number of palette registers to update (to a maximum of 256) 790706f2543Smrg DX := First of the palette registers to update (start) 791706f2543Smrg ES:DI := Table of palette values (see below for format) 792706f2543Smrg 793706f2543Smrg Output: 794706f2543Smrg AX := VBE Return Status 795706f2543Smrg 796706f2543Smrg 797706f2543Smrg Input: 798706f2543Smrg (32-bit) 799706f2543Smrg BL := 00h Set Palette Data 800706f2543Smrg := 80h Set Palette Data during Vertical Retrace 801706f2543Smrg CX := Number of palette registers to update (to a maximum of 256) 802706f2543Smrg DX := First of the palette registers to update (start) 803706f2543Smrg ES:EDI := Table of palette values (see below for format) 804706f2543Smrg DS := Selector for memory mapped registers 805706f2543Smrg */ 806706f2543Smrg 807706f2543Smrg pVbe->pInt10->num = 0x10; 808706f2543Smrg pVbe->pInt10->ax = 0x4f09; 809706f2543Smrg if (!secondary) 810706f2543Smrg pVbe->pInt10->bx = set && wait_retrace ? 0x80 : set ? 0 : 1; 811706f2543Smrg else 812706f2543Smrg pVbe->pInt10->bx = set ? 2 : 3; 813706f2543Smrg pVbe->pInt10->cx = num; 814706f2543Smrg pVbe->pInt10->dx = first; 815706f2543Smrg pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); 816706f2543Smrg pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); 817706f2543Smrg if (set) 818706f2543Smrg memcpy(pVbe->memory, data, num * sizeof(CARD32)); 819706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 820706f2543Smrg 821706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 822706f2543Smrg return NULL; 823706f2543Smrg 824706f2543Smrg if (set) 825706f2543Smrg return data; 826706f2543Smrg 827706f2543Smrg data = malloc(num * sizeof(CARD32)); 828706f2543Smrg memcpy(data, pVbe->memory, num * sizeof(CARD32)); 829706f2543Smrg 830706f2543Smrg return data; 831706f2543Smrg} 832706f2543Smrg 833706f2543SmrgVBEpmi * 834706f2543SmrgVBEGetVBEpmi(vbeInfoPtr pVbe) 835706f2543Smrg{ 836706f2543Smrg VBEpmi *pmi; 837706f2543Smrg 838706f2543Smrg /* 839706f2543Smrg Input: 840706f2543Smrg AH := 4Fh Super VGA support 841706f2543Smrg AL := 0Ah Protected Mode Interface 842706f2543Smrg BL := 00h Return Protected Mode Table 843706f2543Smrg 844706f2543Smrg Output: 845706f2543Smrg AX := Status 846706f2543Smrg ES := Real Mode Segment of Table 847706f2543Smrg DI := Offset of Table 848706f2543Smrg CX := Lenght of Table including protected mode code in bytes (for copying purposes) 849706f2543Smrg (All other registers are preserved) 850706f2543Smrg */ 851706f2543Smrg 852706f2543Smrg pVbe->pInt10->num = 0x10; 853706f2543Smrg pVbe->pInt10->ax = 0x4f0a; 854706f2543Smrg pVbe->pInt10->bx = 0; 855706f2543Smrg pVbe->pInt10->di = 0; 856706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 857706f2543Smrg 858706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 859706f2543Smrg return NULL; 860706f2543Smrg 861706f2543Smrg pmi = malloc(sizeof(VBEpmi)); 862706f2543Smrg pmi->seg_tbl = R16(pVbe->pInt10->es); 863706f2543Smrg pmi->tbl_off = R16(pVbe->pInt10->di); 864706f2543Smrg pmi->tbl_len = R16(pVbe->pInt10->cx); 865706f2543Smrg 866706f2543Smrg return pmi; 867706f2543Smrg} 868706f2543Smrg 869706f2543Smrg#if 0 870706f2543SmrgvbeModeInfoPtr 871706f2543SmrgVBEBuildVbeModeList(vbeInfoPtr pVbe, VbeInfoBlock *vbe) 872706f2543Smrg{ 873706f2543Smrg vbeModeInfoPtr ModeList = NULL; 874706f2543Smrg 875706f2543Smrg int i = 0; 876706f2543Smrg while (vbe->VideoModePtr[i] != 0xffff) { 877706f2543Smrg vbeModeInfoPtr m; 878706f2543Smrg VbeModeInfoBlock *mode; 879706f2543Smrg int id = vbe->VideoModePtr[i++]; 880706f2543Smrg int bpp; 881706f2543Smrg 882706f2543Smrg if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) 883706f2543Smrg continue; 884706f2543Smrg 885706f2543Smrg bpp = mode->BitsPerPixel; 886706f2543Smrg 887706f2543Smrg m = xnfcalloc(sizeof(vbeModeInfoRec),1); 888706f2543Smrg m->width = mode->XResolution; 889706f2543Smrg m->height = mode->YResolution; 890706f2543Smrg m->bpp = bpp; 891706f2543Smrg m->n = id; 892706f2543Smrg m->next = ModeList; 893706f2543Smrg 894706f2543Smrg xf86DrvMsgVerb(pVbe->pInt10->scrnIndex, X_PROBED, 3, 895706f2543Smrg "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n", 896706f2543Smrg m->n, m->width, m->height, m->bpp); 897706f2543Smrg 898706f2543Smrg ModeList = m; 899706f2543Smrg 900706f2543Smrg VBEFreeModeInfo(mode); 901706f2543Smrg } 902706f2543Smrg return ModeList; 903706f2543Smrg} 904706f2543Smrg 905706f2543Smrgunsigned short 906706f2543SmrgVBECalcVbeModeIndex(vbeModeInfoPtr m, DisplayModePtr mode, int bpp) 907706f2543Smrg{ 908706f2543Smrg while (m) { 909706f2543Smrg if (bpp == m->bpp 910706f2543Smrg && mode->HDisplay == m->width 911706f2543Smrg && mode->VDisplay == m->height) 912706f2543Smrg return m->n; 913706f2543Smrg m = m->next; 914706f2543Smrg } 915706f2543Smrg return 0; 916706f2543Smrg} 917706f2543Smrg#endif 918706f2543Smrg 919706f2543Smrgvoid 920706f2543SmrgVBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr, 921706f2543Smrg vbeSaveRestoreFunction function) 922706f2543Smrg{ 923706f2543Smrg Bool SaveSucc = FALSE; 924706f2543Smrg 925706f2543Smrg if (VBE_VERSION_MAJOR(pVbe->version) > 1 926706f2543Smrg && (function == MODE_SAVE || vbe_sr->pstate)) { 927706f2543Smrg if (function == MODE_RESTORE) 928706f2543Smrg memcpy(vbe_sr->state, vbe_sr->pstate, vbe_sr->stateSize); 929706f2543Smrg ErrorF("VBESaveRestore\n"); 930706f2543Smrg if ((VBESaveRestore(pVbe,function, 931706f2543Smrg (pointer)&vbe_sr->state, 932706f2543Smrg &vbe_sr->stateSize,&vbe_sr->statePage))) { 933706f2543Smrg if (function == MODE_SAVE) { 934706f2543Smrg SaveSucc = TRUE; 935706f2543Smrg vbe_sr->stateMode = -1; /* invalidate */ 936706f2543Smrg /* don't rely on the memory not being touched */ 937706f2543Smrg if (vbe_sr->pstate == NULL) 938706f2543Smrg vbe_sr->pstate = malloc(vbe_sr->stateSize); 939706f2543Smrg memcpy(vbe_sr->pstate, vbe_sr->state, vbe_sr->stateSize); 940706f2543Smrg } 941706f2543Smrg ErrorF("VBESaveRestore done with success\n"); 942706f2543Smrg return; 943706f2543Smrg } 944706f2543Smrg ErrorF("VBESaveRestore done\n"); 945706f2543Smrg } 946706f2543Smrg 947706f2543Smrg if (function == MODE_SAVE && !SaveSucc) 948706f2543Smrg (void)VBEGetVBEMode(pVbe, &vbe_sr->stateMode); 949706f2543Smrg 950706f2543Smrg if (function == MODE_RESTORE && vbe_sr->stateMode != -1) 951706f2543Smrg VBESetVBEMode(pVbe, vbe_sr->stateMode, NULL); 952706f2543Smrg 953706f2543Smrg} 954706f2543Smrg 955706f2543Smrgint 956706f2543SmrgVBEGetPixelClock(vbeInfoPtr pVbe, int mode, int clock) 957706f2543Smrg{ 958706f2543Smrg /* 959706f2543Smrg Input: 960706f2543Smrg AX := 4F0Bh VBE Get Pixel Clock 961706f2543Smrg BL := 00h Get Pixel Clock 962706f2543Smrg ECX := pixel clock in units of Hz 963706f2543Smrg DX := mode number 964706f2543Smrg 965706f2543Smrg Output: 966706f2543Smrg AX := VBE Return Status 967706f2543Smrg ECX := Closest pixel clock 968706f2543Smrg */ 969706f2543Smrg 970706f2543Smrg pVbe->pInt10->num = 0x10; 971706f2543Smrg pVbe->pInt10->ax = 0x4f0b; 972706f2543Smrg pVbe->pInt10->bx = 0x00; 973706f2543Smrg pVbe->pInt10->cx = clock; 974706f2543Smrg pVbe->pInt10->dx = mode; 975706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 976706f2543Smrg 977706f2543Smrg if (R16(pVbe->pInt10->ax) != 0x4f) 978706f2543Smrg return 0; 979706f2543Smrg 980706f2543Smrg return pVbe->pInt10->cx; 981706f2543Smrg} 982706f2543Smrg 983706f2543SmrgBool 984706f2543SmrgVBEDPMSSet(vbeInfoPtr pVbe, int mode) 985706f2543Smrg{ 986706f2543Smrg /* 987706f2543Smrg Input: 988706f2543Smrg AX := 4F10h DPMS 989706f2543Smrg BL := 01h Set Display Power State 990706f2543Smrg BH := requested power state 991706f2543Smrg 992706f2543Smrg Output: 993706f2543Smrg AX := VBE Return Status 994706f2543Smrg */ 995706f2543Smrg 996706f2543Smrg pVbe->pInt10->num = 0x10; 997706f2543Smrg pVbe->pInt10->ax = 0x4f10; 998706f2543Smrg pVbe->pInt10->bx = 0x01; 999706f2543Smrg switch (mode) { 1000706f2543Smrg case DPMSModeOn: 1001706f2543Smrg break; 1002706f2543Smrg case DPMSModeStandby: 1003706f2543Smrg pVbe->pInt10->bx |= 0x100; 1004706f2543Smrg break; 1005706f2543Smrg case DPMSModeSuspend: 1006706f2543Smrg pVbe->pInt10->bx |= 0x200; 1007706f2543Smrg break; 1008706f2543Smrg case DPMSModeOff: 1009706f2543Smrg pVbe->pInt10->bx |= 0x400; 1010706f2543Smrg break; 1011706f2543Smrg } 1012706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 1013706f2543Smrg return (R16(pVbe->pInt10->ax) == 0x4f); 1014706f2543Smrg} 1015706f2543Smrg 1016706f2543Smrgvoid 1017706f2543SmrgVBEInterpretPanelID(int scrnIndex, struct vbePanelID *data) 1018706f2543Smrg{ 1019706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1020706f2543Smrg DisplayModePtr mode; 1021706f2543Smrg const float PANEL_HZ = 60.0; 1022706f2543Smrg 1023706f2543Smrg if (!data) 1024706f2543Smrg return; 1025706f2543Smrg 1026706f2543Smrg xf86DrvMsg(scrnIndex, X_INFO, "PanelID returned panel resolution %dx%d\n", 1027706f2543Smrg data->hsize, data->vsize); 1028706f2543Smrg 1029706f2543Smrg if (pScrn->monitor->nHsync || pScrn->monitor->nVrefresh) 1030706f2543Smrg return; 1031706f2543Smrg 1032706f2543Smrg if (data->hsize < 320 || data->vsize < 240) { 1033706f2543Smrg xf86DrvMsg(scrnIndex, X_INFO, "...which I refuse to believe\n"); 1034706f2543Smrg return; 1035706f2543Smrg } 1036706f2543Smrg 1037706f2543Smrg mode = xf86CVTMode(data->hsize, data->vsize, PANEL_HZ, 1, 0); 1038706f2543Smrg 1039706f2543Smrg pScrn->monitor->nHsync = 1; 1040706f2543Smrg pScrn->monitor->hsync[0].lo = 29.37; 1041706f2543Smrg pScrn->monitor->hsync[0].hi = (float)mode->Clock / (float)mode->HTotal; 1042706f2543Smrg pScrn->monitor->nVrefresh = 1; 1043706f2543Smrg pScrn->monitor->vrefresh[0].lo = 56.0; 1044706f2543Smrg pScrn->monitor->vrefresh[0].hi = 1045706f2543Smrg (float)mode->Clock*1000.0 / (float)mode->HTotal / (float)mode->VTotal; 1046706f2543Smrg 1047706f2543Smrg if (pScrn->monitor->vrefresh[0].hi < 59.47) 1048706f2543Smrg pScrn->monitor->vrefresh[0].hi = 59.47; 1049706f2543Smrg 1050706f2543Smrg free(mode); 1051706f2543Smrg} 1052706f2543Smrg 1053706f2543Smrgstruct vbePanelID * 1054706f2543SmrgVBEReadPanelID(vbeInfoPtr pVbe) 1055706f2543Smrg{ 1056706f2543Smrg int RealOff = pVbe->real_mode_base; 1057706f2543Smrg pointer page = pVbe->memory; 1058706f2543Smrg void *tmp = NULL; 1059706f2543Smrg int screen = pVbe->pInt10->scrnIndex; 1060706f2543Smrg 1061706f2543Smrg pVbe->pInt10->ax = 0x4F11; 1062706f2543Smrg pVbe->pInt10->bx = 0x01; 1063706f2543Smrg pVbe->pInt10->cx = 0; 1064706f2543Smrg pVbe->pInt10->dx = 0; 1065706f2543Smrg pVbe->pInt10->es = SEG_ADDR(RealOff); 1066706f2543Smrg pVbe->pInt10->di = SEG_OFF(RealOff); 1067706f2543Smrg pVbe->pInt10->num = 0x10; 1068706f2543Smrg 1069706f2543Smrg xf86ExecX86int10(pVbe->pInt10); 1070706f2543Smrg 1071706f2543Smrg if ((pVbe->pInt10->ax & 0xff) != 0x4f) { 1072706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n"); 1073706f2543Smrg goto error; 1074706f2543Smrg } 1075706f2543Smrg 1076706f2543Smrg switch (pVbe->pInt10->ax & 0xff00) { 1077706f2543Smrg case 0x0: 1078706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n"); 1079706f2543Smrg tmp = xnfalloc(32); 1080706f2543Smrg memcpy(tmp, page, 32); 1081706f2543Smrg break; 1082706f2543Smrg case 0x100: 1083706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n"); 1084706f2543Smrg break; 1085706f2543Smrg default: 1086706f2543Smrg xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n", 1087706f2543Smrg pVbe->pInt10->ax & 0xff00); 1088706f2543Smrg break; 1089706f2543Smrg } 1090706f2543Smrg 1091706f2543Smrgerror: 1092706f2543Smrg return tmp; 1093706f2543Smrg} 1094