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