4 * Copyright 2000 Egbert Eich
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>
12 #ifdef HAVE_XORG_CONFIG_H
13 #include <xorg-config.h>
20 #include <X11/extensions/dpmsconst.h>
22 #define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x)
24 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
28 #define B_O16(x) ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8))
29 #define B_O32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \
30 | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
32 #define L_ADD(x) (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00)
34 #define FARP(p) (((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff))
35 #define R16(v) ((v) & 0xffff)
37 static unsigned char * vbeReadEDID(vbeInfoPtr pVbe);
38 static Bool vbeProbeDDC(vbeInfoPtr pVbe);
40 static const char vbeVersionString[] = "VBE2";
43 VBEInit(xf86Int10InfoPtr pInt, int entityIndex)
45 return VBEExtendedInit(pInt, entityIndex, 0);
49 VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags)
53 ScrnInfoPtr pScrn = xf86FindScreenForEntity(entityIndex);
54 vbeControllerInfoPtr vbe = NULL;
55 Bool init_int10 = FALSE;
56 vbeInfoPtr vip = NULL;
59 if (!pScrn) return NULL;
60 screen = pScrn->scrnIndex;
63 if (!xf86LoadSubModule(pScrn, "int10"))
66 xf86DrvMsg(screen,X_INFO,"initializing int10\n");
67 pInt = xf86ExtendedInitInt10(entityIndex,Flags);
73 page = xf86Int10AllocPages(pInt,1,&RealOff);
74 if (!page) goto error;
75 vbe = (vbeControllerInfoPtr) page;
76 memcpy(vbe->VbeSignature,vbeVersionString,4);
79 pInt->es = SEG_ADDR(RealOff);
80 pInt->di = SEG_OFF(RealOff);
83 xf86ExecX86int10(pInt);
85 if ((pInt->ax & 0xff) != 0x4f) {
86 xf86DrvMsgVerb(screen,X_INFO,3,"VESA BIOS not detected\n");
90 switch (pInt->ax & 0xff00) {
92 xf86DrvMsg(screen,X_INFO,"VESA BIOS detected\n");
95 xf86DrvMsg(screen,X_INFO,"VESA BIOS function failed\n");
98 xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported\n");
101 xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported in current mode\n");
104 xf86DrvMsg(screen,X_INFO,"Invalid\n");
108 xf86DrvMsgVerb(screen, X_INFO, 4,
109 "VbeVersion is %d, OemStringPtr is 0x%08lx,\n"
110 "\tOemVendorNamePtr is 0x%08lx, OemProductNamePtr is 0x%08lx,\n"
111 "\tOemProductRevPtr is 0x%08lx\n",
112 vbe->VbeVersion, (unsigned long)vbe->OemStringPtr,
113 (unsigned long)vbe->OemVendorNamePtr,
114 (unsigned long)vbe->OemProductNamePtr,
115 (unsigned long)vbe->OemProductRevPtr);
117 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Version %i.%i\n",
118 VERSION(vbe->VbeVersion));
119 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Total Mem: %i kB\n",
121 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM: %s\n",
122 (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemStringPtr)));
124 if (B_O16(vbe->VbeVersion) >= 0x200) {
125 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Software Rev: %i.%i\n",
126 VERSION(vbe->OemSoftwareRev));
127 if (vbe->OemVendorNamePtr)
128 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Vendor: %s\n",
129 (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemVendorNamePtr)));
130 if (vbe->OemProductNamePtr)
131 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product: %s\n",
132 (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductNamePtr)));
133 if (vbe->OemProductRevPtr)
134 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product Rev: %s\n",
135 (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductRevPtr)));
137 vip = (vbeInfoPtr)xnfalloc(sizeof(vbeInfoRec));
138 vip->version = B_O16(vbe->VbeVersion);
140 vip->ddc = DDC_UNCHECKED;
142 vip->real_mode_base = RealOff;
144 vip->init_int10 = init_int10;
150 xf86Int10FreePages(pInt, page, 1);
157 vbeFree(vbeInfoPtr pVbe)
162 xf86Int10FreePages(pVbe->pInt10,pVbe->memory,pVbe->num_pages);
163 /* If we have initalized int10 we ought to free it, too */
164 if (pVbe->init_int10)
165 xf86FreeInt10(pVbe->pInt10);
171 vbeProbeDDC(vbeInfoPtr pVbe)
174 int screen = pVbe->pInt10->scrnIndex;
176 if (pVbe->ddc == DDC_NONE)
178 if (pVbe->ddc != DDC_UNCHECKED)
181 pVbe->pInt10->ax = 0x4F15;
182 pVbe->pInt10->bx = 0;
183 pVbe->pInt10->cx = 0;
184 pVbe->pInt10->es = 0;
185 pVbe->pInt10->di = 0;
186 pVbe->pInt10->num = 0x10;
188 xf86ExecX86int10(pVbe->pInt10);
190 if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
191 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC not supported\n");
192 pVbe->ddc = DDC_NONE;
196 switch ((pVbe->pInt10->ax >> 8) & 0xff) {
198 xf86DrvMsg(screen,X_INFO,"VESA VBE DDC supported\n");
199 switch (pVbe->pInt10->bx & 0x3) {
202 pVbe->ddc = DDC_NONE;
213 ddc_level = " 1 + 2";
218 pVbe->ddc = DDC_NONE;
221 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Level%s\n",ddc_level);
222 if (pVbe->pInt10->bx & 0x4) {
223 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Screen blanked"
224 "for data transfer\n");
225 pVbe->ddc_blank = TRUE;
227 pVbe->ddc_blank = FALSE;
229 xf86DrvMsgVerb(screen,X_INFO,3,
230 "VESA VBE DDC transfer in appr. %x sec.\n",
231 (pVbe->pInt10->bx >> 8) & 0xff);
242 static const OptionInfoRec VBEOptions[] = {
243 { VBEOPT_NOVBE, "NoVBE", OPTV_BOOLEAN, {0}, FALSE },
244 { VBEOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE },
245 { -1, NULL, OPTV_NONE, {0}, FALSE },
248 static unsigned char *
249 vbeReadEDID(vbeInfoPtr pVbe)
251 int RealOff = pVbe->real_mode_base;
252 pointer page = pVbe->memory;
253 unsigned char *tmp = NULL;
256 int screen = pVbe->pInt10->scrnIndex;
257 OptionInfoPtr options;
259 if (!page) return NULL;
261 options = xnfalloc(sizeof(VBEOptions));
262 (void)memcpy(options, VBEOptions, sizeof(VBEOptions));
263 xf86ProcessOptions(screen, xf86Screens[screen]->options, options);
264 xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe);
265 xf86GetOptValBool(options, VBEOPT_NODDC, &noddc);
267 if (novbe || noddc) return NULL;
269 if (!vbeProbeDDC(pVbe)) goto error;
271 memset(page,0,sizeof(vbeInfoPtr));
272 strcpy(page,vbeVersionString);
274 pVbe->pInt10->ax = 0x4F15;
275 pVbe->pInt10->bx = 0x01;
276 pVbe->pInt10->cx = 0;
277 pVbe->pInt10->dx = 0;
278 pVbe->pInt10->es = SEG_ADDR(RealOff);
279 pVbe->pInt10->di = SEG_OFF(RealOff);
280 pVbe->pInt10->num = 0x10;
282 xf86ExecX86int10(pVbe->pInt10);
284 if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
285 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC invalid\n");
288 switch (pVbe->pInt10->ax & 0xff00) {
290 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read successfully\n");
291 tmp = (unsigned char *)xnfalloc(128);
292 memcpy(tmp,page,128);
295 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read failed\n");
298 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC unkown failure %i\n",
299 pVbe->pInt10->ax & 0xff00);
308 vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule)
312 unsigned char *DDC_data = NULL;
314 if (!pVbe) return NULL;
315 if (pVbe->version < 0x200)
318 if (!(pModule = pDDCModule)) {
320 xf86LoadSubModule(xf86Screens[pVbe->pInt10->scrnIndex], "ddc");
325 DDC_data = vbeReadEDID(pVbe);
330 pMonitor = xf86InterpretEDID(pVbe->pInt10->scrnIndex, DDC_data);
333 xf86UnloadSubModule(pModule);
337 #define GET_UNALIGNED2(x) \
338 ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16)
341 VBEGetVBEInfo(vbeInfoPtr pVbe)
343 VbeInfoBlock *block = NULL;
346 CARD16 major, *modes;
348 memset(pVbe->memory, 0, sizeof(VbeInfoBlock));
352 AH := 4Fh Super VGA support
353 AL := 00h Return Super VGA information
354 ES:DI := Pointer to buffer
358 (All other registers are preserved)
361 ((char*)pVbe->memory)[0] = 'V';
362 ((char*)pVbe->memory)[1] = 'B';
363 ((char*)pVbe->memory)[2] = 'E';
364 ((char*)pVbe->memory)[3] = '2';
366 pVbe->pInt10->num = 0x10;
367 pVbe->pInt10->ax = 0x4f00;
368 pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
369 pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
370 xf86ExecX86int10(pVbe->pInt10);
372 if (R16(pVbe->pInt10->ax) != 0x4f)
375 block = calloc(sizeof(VbeInfoBlock), 1);
376 block->VESASignature[0] = ((char*)pVbe->memory)[0];
377 block->VESASignature[1] = ((char*)pVbe->memory)[1];
378 block->VESASignature[2] = ((char*)pVbe->memory)[2];
379 block->VESASignature[3] = ((char*)pVbe->memory)[3];
381 block->VESAVersion = *(CARD16*)(((char*)pVbe->memory) + 4);
382 major = (unsigned)block->VESAVersion >> 8;
384 pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 6));
385 str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
386 block->OEMStringPtr = strdup(str);
388 block->Capabilities[0] = ((char*)pVbe->memory)[10];
389 block->Capabilities[1] = ((char*)pVbe->memory)[11];
390 block->Capabilities[2] = ((char*)pVbe->memory)[12];
391 block->Capabilities[3] = ((char*)pVbe->memory)[13];
393 pModes = GET_UNALIGNED2((((char*)pVbe->memory) + 14));
394 modes = xf86int10Addr(pVbe->pInt10, FARP(pModes));
396 while (modes[i] != 0xffff)
398 block->VideoModePtr = malloc(sizeof(CARD16) * i + 1);
399 memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i);
400 block->VideoModePtr[i] = 0xffff;
402 block->TotalMemory = *(CARD16*)(((char*)pVbe->memory) + 18);
405 memcpy(&block->OemSoftwareRev, ((char*)pVbe->memory) + 20, 236);
407 block->OemSoftwareRev = *(CARD16*)(((char*)pVbe->memory) + 20);
408 pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 22));
409 str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
410 block->OemVendorNamePtr = strdup(str);
411 pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 26));
412 str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
413 block->OemProductNamePtr = strdup(str);
414 pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 30));
415 str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
416 block->OemProductRevPtr = strdup(str);
417 memcpy(&block->Reserved, ((char*)pVbe->memory) + 34, 222);
418 memcpy(&block->OemData, ((char*)pVbe->memory) + 256, 256);
425 VBEFreeVBEInfo(VbeInfoBlock *block)
427 free(block->OEMStringPtr);
428 free(block->VideoModePtr);
429 if (((unsigned)block->VESAVersion >> 8) >= 2) {
430 free(block->OemVendorNamePtr);
431 free(block->OemProductNamePtr);
432 free(block->OemProductRevPtr);
438 VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *block)
442 AH := 4Fh Super VGA support
443 AL := 02h Set Super VGA video mode
446 D9-D10 := Reserved (must be 0)
447 D11 := 0 Use current default refresh rate
448 := 1 Use user specified CRTC values for refresh rate
449 D12-13 Reserved for VBE/AF (must be 0)
450 D14 := 0 Use windowed frame buffer model
451 := 1 Use linear/flat frame buffer model
452 D15 := 0 Clear video memory
453 := 1 Don't clear video memory
454 ES:DI := Pointer to VbeCRTCInfoBlock structure
457 (All other registers are preserved)
459 pVbe->pInt10->num = 0x10;
460 pVbe->pInt10->ax = 0x4f02;
461 pVbe->pInt10->bx = mode;
463 pVbe->pInt10->bx |= 1 << 11;
464 memcpy(pVbe->memory, block, sizeof(VbeCRTCInfoBlock));
465 pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
466 pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
468 pVbe->pInt10->bx &= ~(1 << 11);
470 xf86ExecX86int10(pVbe->pInt10);
472 return (R16(pVbe->pInt10->ax) == 0x4f);
476 VBEGetVBEMode(vbeInfoPtr pVbe, int *mode)
480 AH := 4Fh Super VGA support
481 AL := 03h Return current video mode
485 BX := Current video mode
486 (All other registers are preserved)
488 pVbe->pInt10->num = 0x10;
489 pVbe->pInt10->ax = 0x4f03;
491 xf86ExecX86int10(pVbe->pInt10);
493 if (R16(pVbe->pInt10->ax) == 0x4f) {
494 *mode = R16(pVbe->pInt10->bx);
503 VBEGetModeInfo(vbeInfoPtr pVbe, int mode)
505 VbeModeInfoBlock *block = NULL;
507 memset(pVbe->memory, 0, sizeof(VbeModeInfoBlock));
511 AH := 4Fh Super VGA support
512 AL := 01h Return Super VGA mode information
513 CX := Super VGA video mode
514 (mode number must be one of those returned by Function 0)
515 ES:DI := Pointer to buffer
519 (All other registers are preserved)
521 pVbe->pInt10->num = 0x10;
522 pVbe->pInt10->ax = 0x4f01;
523 pVbe->pInt10->cx = mode;
524 pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
525 pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
526 xf86ExecX86int10(pVbe->pInt10);
527 if (R16(pVbe->pInt10->ax) != 0x4f)
530 block = malloc(sizeof(VbeModeInfoBlock));
532 memcpy(block, pVbe->memory, sizeof(*block));
538 VBEFreeModeInfo(VbeModeInfoBlock *block)
544 VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function,
545 pointer *memory, int *size, int *real_mode_pages)
549 AH := 4Fh Super VGA support
550 AL := 04h Save/restore Super VGA video state
551 DL := 00h Return save/restore state buffer size
552 CX := Requested states
553 D0 = Save/restore video hardware state
554 D1 = Save/restore video BIOS data state
555 D2 = Save/restore video DAC state
556 D3 = Save/restore Super VGA state
560 BX = Number of 64-byte blocks to hold the state buffer
561 (All other registers are preserved)
565 AH := 4Fh Super VGA support
566 AL := 04h Save/restore Super VGA video state
567 DL := 01h Save Super VGA video state
568 CX := Requested states (see above)
569 ES:BX := Pointer to buffer
573 (All other registers are preserved)
577 AH := 4Fh Super VGA support
578 AL := 04h Save/restore Super VGA video state
579 DL := 02h Restore Super VGA video state
580 CX := Requested states (see above)
581 ES:BX := Pointer to buffer
585 (All other registers are preserved)
588 if ((pVbe->version & 0xff00) > 0x100) {
589 int screen = pVbe->pInt10->scrnIndex;
590 if (function == MODE_QUERY ||
591 (function == MODE_SAVE && !*memory)) {
592 /* Query amount of memory to save state */
594 pVbe->pInt10->num = 0x10;
595 pVbe->pInt10->ax = 0x4f04;
596 pVbe->pInt10->dx = 0;
597 pVbe->pInt10->cx = 0x000f;
598 xf86ExecX86int10(pVbe->pInt10);
599 if (R16(pVbe->pInt10->ax) != 0x4f)
602 if (function == MODE_SAVE) {
603 int npages = (R16(pVbe->pInt10->bx) * 64) / 4096 + 1;
604 if ((*memory = xf86Int10AllocPages(pVbe->pInt10, npages,
605 real_mode_pages)) == NULL) {
606 xf86DrvMsg(screen, X_ERROR,
607 "Cannot allocate memory to save SVGA state.\n");
611 *size = pVbe->pInt10->bx * 64;
614 /* Save/Restore Super VGA state */
615 if (function != MODE_QUERY) {
617 if (!*memory) return FALSE;
618 pVbe->pInt10->num = 0x10;
619 pVbe->pInt10->ax = 0x4f04;
622 pVbe->pInt10->dx = 1;
625 pVbe->pInt10->dx = 2;
630 pVbe->pInt10->cx = 0x000f;
632 pVbe->pInt10->es = SEG_ADDR(*real_mode_pages);
633 pVbe->pInt10->bx = SEG_OFF(*real_mode_pages);
634 xf86ExecX86int10(pVbe->pInt10);
635 return (R16(pVbe->pInt10->ax) == 0x4f);
643 VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window)
647 AH := 4Fh Super VGA support
652 pVbe->pInt10->num = 0x10;
653 pVbe->pInt10->ax = 0x4f05;
654 pVbe->pInt10->bx = window;
655 pVbe->pInt10->dx = iBank;
656 xf86ExecX86int10(pVbe->pInt10);
658 if (R16(pVbe->pInt10->ax) != 0x4f)
665 VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, vbeScanwidthCommand command,
666 int width, int *pixels, int *bytes, int *max)
668 if (command < SCANWID_SET || command > SCANWID_GET_MAX)
673 AX := 4F06h VBE Set/Get Logical Scan Line Length
674 BL := 00h Set Scan Line Length in Pixels
675 := 01h Get Scan Line Length
676 := 02h Set Scan Line Length in Bytes
677 := 03h Get Maximum Scan Line Length
678 CX := If BL=00h Desired Width in Pixels
679 If BL=02h Desired Width in Bytes
680 (Ignored for Get Functions)
683 AX := VBE Return Status
684 BX := Bytes Per Scan Line
685 CX := Actual Pixels Per Scan Line
686 (truncated to nearest complete pixel)
687 DX := Maximum Number of Scan Lines
690 pVbe->pInt10->num = 0x10;
691 pVbe->pInt10->ax = 0x4f06;
692 pVbe->pInt10->bx = command;
693 if (command == SCANWID_SET || command == SCANWID_SET_BYTES)
694 pVbe->pInt10->cx = width;
695 xf86ExecX86int10(pVbe->pInt10);
697 if (R16(pVbe->pInt10->ax) != 0x4f)
700 if (command == SCANWID_GET || command == SCANWID_GET_MAX) {
702 *pixels = R16(pVbe->pInt10->cx);
704 *bytes = R16(pVbe->pInt10->bx);
706 *max = R16(pVbe->pInt10->dx);
713 VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace)
715 pVbe->pInt10->num = 0x10;
716 pVbe->pInt10->ax = 0x4f07;
717 pVbe->pInt10->bx = wait_retrace ? 0x80 : 0x00;
718 pVbe->pInt10->cx = x;
719 pVbe->pInt10->dx = y;
720 xf86ExecX86int10(pVbe->pInt10);
722 if (R16(pVbe->pInt10->ax) != 0x4f)
729 VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y)
731 pVbe->pInt10->num = 0x10;
732 pVbe->pInt10->ax = 0x4f07;
733 pVbe->pInt10->bx = 0x01;
734 xf86ExecX86int10(pVbe->pInt10);
736 if (R16(pVbe->pInt10->ax) != 0x4f)
739 *x = pVbe->pInt10->cx;
740 *y = pVbe->pInt10->dx;
746 VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits)
750 AX := 4F08h VBE Set/Get Palette Format
751 BL := 00h Set DAC Palette Format
752 := 01h Get DAC Palette Format
753 BH := Desired bits of color per primary
754 (Set DAC Palette Format only)
757 AX := VBE Return Status
758 BH := Current number of bits of color per primary
761 pVbe->pInt10->num = 0x10;
762 pVbe->pInt10->ax = 0x4f08;
764 pVbe->pInt10->bx = 0x01;
766 pVbe->pInt10->bx = (bits & 0x00ff) << 8;
767 xf86ExecX86int10(pVbe->pInt10);
769 if (R16(pVbe->pInt10->ax) != 0x4f)
772 return (bits != 0 ? bits : (pVbe->pInt10->bx >> 8) & 0x00ff);
776 VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num,
777 CARD32 *data, Bool secondary, Bool wait_retrace)
782 AX := 4F09h VBE Load/Unload Palette Data
783 BL := 00h Set Palette Data
784 := 01h Get Palette Data
785 := 02h Set Secondary Palette Data
786 := 03h Get Secondary Palette Data
787 := 80h Set Palette Data during Vertical Retrace
788 CX := Number of palette registers to update (to a maximum of 256)
789 DX := First of the palette registers to update (start)
790 ES:DI := Table of palette values (see below for format)
793 AX := VBE Return Status
798 BL := 00h Set Palette Data
799 := 80h Set Palette Data during Vertical Retrace
800 CX := Number of palette registers to update (to a maximum of 256)
801 DX := First of the palette registers to update (start)
802 ES:EDI := Table of palette values (see below for format)
803 DS := Selector for memory mapped registers
806 pVbe->pInt10->num = 0x10;
807 pVbe->pInt10->ax = 0x4f09;
809 pVbe->pInt10->bx = set && wait_retrace ? 0x80 : set ? 0 : 1;
811 pVbe->pInt10->bx = set ? 2 : 3;
812 pVbe->pInt10->cx = num;
813 pVbe->pInt10->dx = first;
814 pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
815 pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
817 memcpy(pVbe->memory, data, num * sizeof(CARD32));
818 xf86ExecX86int10(pVbe->pInt10);
820 if (R16(pVbe->pInt10->ax) != 0x4f)
826 data = malloc(num * sizeof(CARD32));
827 memcpy(data, pVbe->memory, num * sizeof(CARD32));
833 VBEGetVBEpmi(vbeInfoPtr pVbe)
839 AH := 4Fh Super VGA support
840 AL := 0Ah Protected Mode Interface
841 BL := 00h Return Protected Mode Table
845 ES := Real Mode Segment of Table
846 DI := Offset of Table
847 CX := Lenght of Table including protected mode code in bytes (for copying purposes)
848 (All other registers are preserved)
851 pVbe->pInt10->num = 0x10;
852 pVbe->pInt10->ax = 0x4f0a;
853 pVbe->pInt10->bx = 0;
854 pVbe->pInt10->di = 0;
855 xf86ExecX86int10(pVbe->pInt10);
857 if (R16(pVbe->pInt10->ax) != 0x4f)
860 pmi = malloc(sizeof(VBEpmi));
861 pmi->seg_tbl = R16(pVbe->pInt10->es);
862 pmi->tbl_off = R16(pVbe->pInt10->di);
863 pmi->tbl_len = R16(pVbe->pInt10->cx);
870 VBEBuildVbeModeList(vbeInfoPtr pVbe, VbeInfoBlock *vbe)
872 vbeModeInfoPtr ModeList = NULL;
875 while (vbe->VideoModePtr[i] != 0xffff) {
877 VbeModeInfoBlock *mode;
878 int id = vbe->VideoModePtr[i++];
881 if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
884 bpp = mode->BitsPerPixel;
886 m = xnfcalloc(sizeof(vbeModeInfoRec),1);
887 m->width = mode->XResolution;
888 m->height = mode->YResolution;
893 xf86DrvMsgVerb(pVbe->pInt10->scrnIndex, X_PROBED, 3,
894 "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n",
895 m->n, m->width, m->height, m->bpp);
899 VBEFreeModeInfo(mode);
905 VBECalcVbeModeIndex(vbeModeInfoPtr m, DisplayModePtr mode, int bpp)
909 && mode->HDisplay == m->width
910 && mode->VDisplay == m->height)
919 VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr,
920 vbeSaveRestoreFunction function)
922 Bool SaveSucc = FALSE;
924 if (VBE_VERSION_MAJOR(pVbe->version) > 1
925 && (function == MODE_SAVE || vbe_sr->pstate)) {
926 if (function == MODE_RESTORE)
927 memcpy(vbe_sr->state, vbe_sr->pstate, vbe_sr->stateSize);
928 ErrorF("VBESaveRestore\n");
929 if ((VBESaveRestore(pVbe,function,
930 (pointer)&vbe_sr->state,
931 &vbe_sr->stateSize,&vbe_sr->statePage))) {
932 if (function == MODE_SAVE) {
934 vbe_sr->stateMode = -1; /* invalidate */
935 /* don't rely on the memory not being touched */
936 if (vbe_sr->pstate == NULL)
937 vbe_sr->pstate = malloc(vbe_sr->stateSize);
938 memcpy(vbe_sr->pstate, vbe_sr->state, vbe_sr->stateSize);
940 ErrorF("VBESaveRestore done with success\n");
943 ErrorF("VBESaveRestore done\n");
946 if (function == MODE_SAVE && !SaveSucc)
947 (void)VBEGetVBEMode(pVbe, &vbe_sr->stateMode);
949 if (function == MODE_RESTORE && vbe_sr->stateMode != -1)
950 VBESetVBEMode(pVbe, vbe_sr->stateMode, NULL);
955 VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int clock)
959 AX := 4F0Bh VBE Get Pixel Clock
960 BL := 00h Get Pixel Clock
961 ECX := pixel clock in units of Hz
965 AX := VBE Return Status
966 ECX := Closest pixel clock
969 pVbe->pInt10->num = 0x10;
970 pVbe->pInt10->ax = 0x4f0b;
971 pVbe->pInt10->bx = 0x00;
972 pVbe->pInt10->cx = clock;
973 pVbe->pInt10->dx = mode;
974 xf86ExecX86int10(pVbe->pInt10);
976 if (R16(pVbe->pInt10->ax) != 0x4f)
979 return pVbe->pInt10->cx;
983 VBEDPMSSet(vbeInfoPtr pVbe, int mode)
988 BL := 01h Set Display Power State
989 BH := requested power state
992 AX := VBE Return Status
995 pVbe->pInt10->num = 0x10;
996 pVbe->pInt10->ax = 0x4f10;
997 pVbe->pInt10->bx = 0x01;
1001 case DPMSModeStandby:
1002 pVbe->pInt10->bx |= 0x100;
1004 case DPMSModeSuspend:
1005 pVbe->pInt10->bx |= 0x200;
1008 pVbe->pInt10->bx |= 0x400;
1011 xf86ExecX86int10(pVbe->pInt10);
1012 return (R16(pVbe->pInt10->ax) == 0x4f);
1016 VBEInterpretPanelID(int scrnIndex, struct vbePanelID *data)
1018 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1019 DisplayModePtr mode;
1020 const float PANEL_HZ = 60.0;
1025 xf86DrvMsg(scrnIndex, X_INFO, "PanelID returned panel resolution %dx%d\n",
1026 data->hsize, data->vsize);
1028 if (pScrn->monitor->nHsync || pScrn->monitor->nVrefresh)
1031 mode = xf86CVTMode(data->hsize, data->vsize, PANEL_HZ, 1, 0);
1033 pScrn->monitor->nHsync = 1;
1034 pScrn->monitor->hsync[0].lo = 31.5;
1035 pScrn->monitor->hsync[0].hi = (float)mode->Clock / (float)mode->HTotal;
1036 pScrn->monitor->nVrefresh = 1;
1037 pScrn->monitor->vrefresh[0].lo = 56.0;
1038 pScrn->monitor->vrefresh[0].hi =
1039 (float)mode->Clock*1000.0 / (float)mode->HTotal / (float)mode->VTotal;
1045 VBEReadPanelID(vbeInfoPtr pVbe)
1047 int RealOff = pVbe->real_mode_base;
1048 pointer page = pVbe->memory;
1050 int screen = pVbe->pInt10->scrnIndex;
1052 pVbe->pInt10->ax = 0x4F11;
1053 pVbe->pInt10->bx = 0x01;
1054 pVbe->pInt10->cx = 0;
1055 pVbe->pInt10->dx = 0;
1056 pVbe->pInt10->es = SEG_ADDR(RealOff);
1057 pVbe->pInt10->di = SEG_OFF(RealOff);
1058 pVbe->pInt10->num = 0x10;
1060 xf86ExecX86int10(pVbe->pInt10);
1062 if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
1063 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n");
1067 switch (pVbe->pInt10->ax & 0xff00) {
1069 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n");
1071 memcpy(tmp, page, 32);
1074 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n");
1077 xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n",
1078 pVbe->pInt10->ax & 0xff00);