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