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>
19 #include "xf86Modes.h"
21 #include <X11/extensions/dpmsconst.h>
23 #define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x)
25 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
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))
33 #define L_ADD(x) (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00)
35 #define FARP(p) (((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff))
36 #define R16(v) ((v) & 0xffff)
38 static unsigned char *vbeReadEDID(vbeInfoPtr pVbe
);
39 static Bool
vbeProbeDDC(vbeInfoPtr pVbe
);
41 static const char vbeVersionString
[] = "VBE2";
44 VBEInit(xf86Int10InfoPtr pInt
, int entityIndex
)
46 return VBEExtendedInit(pInt
, entityIndex
, 0);
50 VBEExtendedInit(xf86Int10InfoPtr pInt
, int entityIndex
, int Flags
)
54 ScrnInfoPtr pScrn
= xf86FindScreenForEntity(entityIndex
);
55 vbeControllerInfoPtr vbe
= NULL
;
56 Bool init_int10
= FALSE
;
57 vbeInfoPtr vip
= NULL
;
62 screen
= pScrn
->scrnIndex
;
65 if (!xf86LoadSubModule(pScrn
, "int10"))
68 xf86DrvMsg(screen
, X_INFO
, "initializing int10\n");
69 pInt
= xf86ExtendedInitInt10(entityIndex
, Flags
);
75 page
= xf86Int10AllocPages(pInt
, 1, &RealOff
);
78 vbe
= (vbeControllerInfoPtr
) page
;
79 memcpy(vbe
->VbeSignature
, vbeVersionString
, 4);
82 pInt
->es
= SEG_ADDR(RealOff
);
83 pInt
->di
= SEG_OFF(RealOff
);
86 xf86ExecX86int10(pInt
);
88 if ((pInt
->ax
& 0xff) != 0x4f) {
89 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA BIOS not detected\n");
93 switch (pInt
->ax
& 0xff00) {
95 xf86DrvMsg(screen
, X_INFO
, "VESA BIOS detected\n");
98 xf86DrvMsg(screen
, X_INFO
, "VESA BIOS function failed\n");
101 xf86DrvMsg(screen
, X_INFO
, "VESA BIOS not supported\n");
104 xf86DrvMsg(screen
, X_INFO
, "VESA BIOS not supported in current mode\n");
107 xf86DrvMsg(screen
, X_INFO
, "Invalid\n");
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
);
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",
124 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE OEM: %s\n",
125 (CARD8
*) xf86int10Addr(pInt
, L_ADD(vbe
->OemStringPtr
)));
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
,
135 if (vbe
->OemProductNamePtr
)
136 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE OEM Product: %s\n",
137 (CARD8
*) xf86int10Addr(pInt
,
139 OemProductNamePtr
)));
140 if (vbe
->OemProductRevPtr
)
141 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE OEM Product Rev: %s\n",
142 (CARD8
*) xf86int10Addr(pInt
,
146 vip
= (vbeInfoPtr
) xnfalloc(sizeof(vbeInfoRec
));
147 vip
->version
= B_O16(vbe
->VbeVersion
);
149 vip
->ddc
= DDC_UNCHECKED
;
151 vip
->real_mode_base
= RealOff
;
153 vip
->init_int10
= init_int10
;
159 xf86Int10FreePages(pInt
, page
, 1);
166 vbeFree(vbeInfoPtr pVbe
)
171 xf86Int10FreePages(pVbe
->pInt10
, pVbe
->memory
, pVbe
->num_pages
);
172 /* If we have initalized int10 we ought to free it, too */
173 if (pVbe
->init_int10
)
174 xf86FreeInt10(pVbe
->pInt10
);
180 vbeProbeDDC(vbeInfoPtr pVbe
)
182 const char *ddc_level
;
183 int screen
= pVbe
->pInt10
->pScrn
->scrnIndex
;
185 if (pVbe
->ddc
== DDC_NONE
)
187 if (pVbe
->ddc
!= DDC_UNCHECKED
)
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;
197 xf86ExecX86int10(pVbe
->pInt10
);
199 if ((pVbe
->pInt10
->ax
& 0xff) != 0x4f) {
200 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE DDC not supported\n");
201 pVbe
->ddc
= DDC_NONE
;
205 switch ((pVbe
->pInt10
->ax
>> 8) & 0xff) {
207 xf86DrvMsg(screen
, X_INFO
, "VESA VBE DDC supported\n");
208 switch (pVbe
->pInt10
->bx
& 0x3) {
211 pVbe
->ddc
= DDC_NONE
;
222 ddc_level
= " 1 + 2";
227 pVbe
->ddc
= DDC_NONE
;
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
;
237 pVbe
->ddc_blank
= FALSE
;
239 xf86DrvMsgVerb(screen
, X_INFO
, 3,
240 "VESA VBE DDC transfer in appr. %x sec.\n",
241 (pVbe
->pInt10
->bx
>> 8) & 0xff);
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
},
258 static unsigned char *
259 vbeReadEDID(vbeInfoPtr pVbe
)
261 int RealOff
= pVbe
->real_mode_base
;
262 pointer page
= pVbe
->memory
;
263 unsigned char *tmp
= NULL
;
266 ScrnInfoPtr pScrn
= pVbe
->pInt10
->pScrn
;
267 int screen
= pScrn
->scrnIndex
;
268 OptionInfoPtr options
;
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
);
282 if (!vbeProbeDDC(pVbe
))
285 memset(page
, 0, sizeof(vbeInfoPtr
));
286 strcpy(page
, vbeVersionString
);
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;
296 xf86ExecX86int10(pVbe
->pInt10
);
298 if ((pVbe
->pInt10
->ax
& 0xff) != 0x4f) {
299 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE DDC invalid\n");
302 switch (pVbe
->pInt10
->ax
& 0xff00) {
304 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE DDC read successfully\n");
305 tmp
= (unsigned char *) xnfalloc(128);
306 memcpy(tmp
, page
, 128);
309 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE DDC read failed\n");
312 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE DDC unkown failure %i\n",
313 pVbe
->pInt10
->ax
& 0xff00);
322 vbeDoEDID(vbeInfoPtr pVbe
, pointer unused
)
324 unsigned char *DDC_data
= NULL
;
328 if (pVbe
->version
< 0x200)
331 DDC_data
= vbeReadEDID(pVbe
);
336 return xf86InterpretEDID(pVbe
->pInt10
->pScrn
->scrnIndex
, DDC_data
);
339 #define GET_UNALIGNED2(x) \
340 ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16)
343 VBEGetVBEInfo(vbeInfoPtr pVbe
)
345 VbeInfoBlock
*block
= NULL
;
348 CARD16 major
, *modes
;
350 memset(pVbe
->memory
, 0, sizeof(VbeInfoBlock
));
354 AH := 4Fh Super VGA support
355 AL := 00h Return Super VGA information
356 ES:DI := Pointer to buffer
360 (All other registers are preserved)
363 ((char *) pVbe
->memory
)[0] = 'V';
364 ((char *) pVbe
->memory
)[1] = 'B';
365 ((char *) pVbe
->memory
)[2] = 'E';
366 ((char *) pVbe
->memory
)[3] = '2';
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
);
374 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
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];
383 block
->VESAVersion
= *(CARD16
*) (((char *) pVbe
->memory
) + 4);
384 major
= (unsigned) block
->VESAVersion
>> 8;
386 pStr
= GET_UNALIGNED2((((char *) pVbe
->memory
) + 6));
387 str
= xf86int10Addr(pVbe
->pInt10
, FARP(pStr
));
388 block
->OEMStringPtr
= strdup(str
);
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];
395 pModes
= GET_UNALIGNED2((((char *) pVbe
->memory
) + 14));
396 modes
= xf86int10Addr(pVbe
->pInt10
, FARP(pModes
));
398 while (modes
[i
] != 0xffff)
400 block
->VideoModePtr
= malloc(sizeof(CARD16
) * (i
+ 1));
401 memcpy(block
->VideoModePtr
, modes
, sizeof(CARD16
) * i
);
402 block
->VideoModePtr
[i
] = 0xffff;
404 block
->TotalMemory
= *(CARD16
*) (((char *) pVbe
->memory
) + 18);
407 memcpy(&block
->OemSoftwareRev
, ((char *) pVbe
->memory
) + 20, 236);
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);
427 VBEFreeVBEInfo(VbeInfoBlock
* block
)
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
);
440 VBESetVBEMode(vbeInfoPtr pVbe
, int mode
, VbeCRTCInfoBlock
* block
)
444 AH := 4Fh Super VGA support
445 AL := 02h Set Super VGA video mode
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
459 (All other registers are preserved)
461 pVbe
->pInt10
->num
= 0x10;
462 pVbe
->pInt10
->ax
= 0x4f02;
463 pVbe
->pInt10
->bx
= mode
;
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
);
471 pVbe
->pInt10
->bx
&= ~(1 << 11);
473 xf86ExecX86int10(pVbe
->pInt10
);
475 return (R16(pVbe
->pInt10
->ax
) == 0x4f);
479 VBEGetVBEMode(vbeInfoPtr pVbe
, int *mode
)
483 AH := 4Fh Super VGA support
484 AL := 03h Return current video mode
488 BX := Current video mode
489 (All other registers are preserved)
491 pVbe
->pInt10
->num
= 0x10;
492 pVbe
->pInt10
->ax
= 0x4f03;
494 xf86ExecX86int10(pVbe
->pInt10
);
496 if (R16(pVbe
->pInt10
->ax
) == 0x4f) {
497 *mode
= R16(pVbe
->pInt10
->bx
);
506 VBEGetModeInfo(vbeInfoPtr pVbe
, int mode
)
508 VbeModeInfoBlock
*block
= NULL
;
510 memset(pVbe
->memory
, 0, sizeof(VbeModeInfoBlock
));
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
522 (All other registers are preserved)
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)
533 block
= malloc(sizeof(VbeModeInfoBlock
));
535 memcpy(block
, pVbe
->memory
, sizeof(*block
));
541 VBEFreeModeInfo(VbeModeInfoBlock
* block
)
547 VBESaveRestore(vbeInfoPtr pVbe
, vbeSaveRestoreFunction function
,
548 pointer
*memory
, int *size
, int *real_mode_pages
)
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
563 BX = Number of 64-byte blocks to hold the state buffer
564 (All other registers are preserved)
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
575 (All other registers are preserved)
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
586 (All other registers are preserved)
589 if ((pVbe
->version
& 0xff00) > 0x100) {
590 int screen
= pVbe
->pInt10
->pScrn
->scrnIndex
;
592 if (function
== MODE_QUERY
|| (function
== MODE_SAVE
&& !*memory
)) {
593 /* Query amount of memory to save state */
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)
603 if (function
== MODE_SAVE
) {
604 int npages
= (R16(pVbe
->pInt10
->bx
) * 64) / 4096 + 1;
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");
613 *size
= pVbe
->pInt10
->bx
* 64;
616 /* Save/Restore Super VGA state */
617 if (function
!= MODE_QUERY
) {
621 pVbe
->pInt10
->num
= 0x10;
622 pVbe
->pInt10
->ax
= 0x4f04;
625 pVbe
->pInt10
->dx
= 1;
628 pVbe
->pInt10
->dx
= 2;
633 pVbe
->pInt10
->cx
= 0x000f;
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);
646 VBEBankSwitch(vbeInfoPtr pVbe
, unsigned int iBank
, int window
)
650 AH := 4Fh Super VGA support
655 pVbe
->pInt10
->num
= 0x10;
656 pVbe
->pInt10
->ax
= 0x4f05;
657 pVbe
->pInt10
->bx
= window
;
658 pVbe
->pInt10
->dx
= iBank
;
659 xf86ExecX86int10(pVbe
->pInt10
);
661 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
668 VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe
, vbeScanwidthCommand command
,
669 int width
, int *pixels
, int *bytes
, int *max
)
671 if (command
< SCANWID_SET
|| command
> SCANWID_GET_MAX
)
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)
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
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
);
700 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
703 if (command
== SCANWID_GET
|| command
== SCANWID_GET_MAX
) {
705 *pixels
= R16(pVbe
->pInt10
->cx
);
707 *bytes
= R16(pVbe
->pInt10
->bx
);
709 *max
= R16(pVbe
->pInt10
->dx
);
716 VBESetDisplayStart(vbeInfoPtr pVbe
, int x
, int y
, Bool wait_retrace
)
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
);
725 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
732 VBEGetDisplayStart(vbeInfoPtr pVbe
, int *x
, int *y
)
734 pVbe
->pInt10
->num
= 0x10;
735 pVbe
->pInt10
->ax
= 0x4f07;
736 pVbe
->pInt10
->bx
= 0x01;
737 xf86ExecX86int10(pVbe
->pInt10
);
739 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
742 *x
= pVbe
->pInt10
->cx
;
743 *y
= pVbe
->pInt10
->dx
;
749 VBESetGetDACPaletteFormat(vbeInfoPtr pVbe
, int bits
)
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)
760 AX := VBE Return Status
761 BH := Current number of bits of color per primary
764 pVbe
->pInt10
->num
= 0x10;
765 pVbe
->pInt10
->ax
= 0x4f08;
767 pVbe
->pInt10
->bx
= 0x01;
769 pVbe
->pInt10
->bx
= (bits
& 0x00ff) << 8;
770 xf86ExecX86int10(pVbe
->pInt10
);
772 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
775 return (bits
!= 0 ? bits
: (pVbe
->pInt10
->bx
>> 8) & 0x00ff);
779 VBESetGetPaletteData(vbeInfoPtr pVbe
, Bool set
, int first
, int num
,
780 CARD32
*data
, Bool secondary
, Bool wait_retrace
)
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)
796 AX := VBE Return Status
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
808 pVbe
->pInt10
->num
= 0x10;
809 pVbe
->pInt10
->ax
= 0x4f09;
811 pVbe
->pInt10
->bx
= set
&& wait_retrace
? 0x80 : set
? 0 : 1;
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
);
819 memcpy(pVbe
->memory
, data
, num
* sizeof(CARD32
));
820 xf86ExecX86int10(pVbe
->pInt10
);
822 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
828 data
= malloc(num
* sizeof(CARD32
));
829 memcpy(data
, pVbe
->memory
, num
* sizeof(CARD32
));
835 VBEGetVBEpmi(vbeInfoPtr pVbe
)
841 AH := 4Fh Super VGA support
842 AL := 0Ah Protected Mode Interface
843 BL := 00h Return Protected Mode Table
847 ES := Real Mode Segment of Table
848 DI := Offset of Table
849 CX := Lenght of Table including protected mode code in bytes (for copying purposes)
850 (All other registers are preserved)
853 pVbe
->pInt10
->num
= 0x10;
854 pVbe
->pInt10
->ax
= 0x4f0a;
855 pVbe
->pInt10
->bx
= 0;
856 pVbe
->pInt10
->di
= 0;
857 xf86ExecX86int10(pVbe
->pInt10
);
859 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
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
);
872 VBEBuildVbeModeList(vbeInfoPtr pVbe
, VbeInfoBlock
* vbe
)
874 vbeModeInfoPtr ModeList
= NULL
;
878 while (vbe
->VideoModePtr
[i
] != 0xffff) {
880 VbeModeInfoBlock
*mode
;
881 int id
= vbe
->VideoModePtr
[i
++];
884 if ((mode
= VBEGetModeInfo(pVbe
, id
)) == NULL
)
887 bpp
= mode
->BitsPerPixel
;
889 m
= xnfcalloc(sizeof(vbeModeInfoRec
), 1);
890 m
->width
= mode
->XResolution
;
891 m
->height
= mode
->YResolution
;
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
);
902 VBEFreeModeInfo(mode
);
908 VBECalcVbeModeIndex(vbeModeInfoPtr m
, DisplayModePtr mode
, int bpp
)
912 && mode
->HDisplay
== m
->width
&& mode
->VDisplay
== m
->height
)
921 VBEVesaSaveRestore(vbeInfoPtr pVbe
, vbeSaveRestorePtr vbe_sr
,
922 vbeSaveRestoreFunction function
)
924 Bool SaveSucc
= FALSE
;
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 (pointer
) &vbe_sr
->state
,
933 &vbe_sr
->stateSize
, &vbe_sr
->statePage
))) {
934 if (function
== MODE_SAVE
) {
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
);
942 ErrorF("VBESaveRestore done with success\n");
945 ErrorF("VBESaveRestore done\n");
948 if (function
== MODE_SAVE
&& !SaveSucc
)
949 (void) VBEGetVBEMode(pVbe
, &vbe_sr
->stateMode
);
951 if (function
== MODE_RESTORE
&& vbe_sr
->stateMode
!= -1)
952 VBESetVBEMode(pVbe
, vbe_sr
->stateMode
, NULL
);
957 VBEGetPixelClock(vbeInfoPtr pVbe
, int mode
, int clock
)
961 AX := 4F0Bh VBE Get Pixel Clock
962 BL := 00h Get Pixel Clock
963 ECX := pixel clock in units of Hz
967 AX := VBE Return Status
968 ECX := Closest pixel clock
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
);
978 if (R16(pVbe
->pInt10
->ax
) != 0x4f)
981 return pVbe
->pInt10
->cx
;
985 VBEDPMSSet(vbeInfoPtr pVbe
, int mode
)
990 BL := 01h Set Display Power State
991 BH := requested power state
994 AX := VBE Return Status
997 pVbe
->pInt10
->num
= 0x10;
998 pVbe
->pInt10
->ax
= 0x4f10;
999 pVbe
->pInt10
->bx
= 0x01;
1003 case DPMSModeStandby
:
1004 pVbe
->pInt10
->bx
|= 0x100;
1006 case DPMSModeSuspend
:
1007 pVbe
->pInt10
->bx
|= 0x200;
1010 pVbe
->pInt10
->bx
|= 0x400;
1013 xf86ExecX86int10(pVbe
->pInt10
);
1014 return (R16(pVbe
->pInt10
->ax
) == 0x4f);
1018 VBEInterpretPanelID(ScrnInfoPtr pScrn
, struct vbePanelID
*data
)
1020 DisplayModePtr mode
;
1021 const float PANEL_HZ
= 60.0;
1026 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "PanelID returned panel resolution %dx%d\n",
1027 data
->hsize
, data
->vsize
);
1029 if (pScrn
->monitor
->nHsync
|| pScrn
->monitor
->nVrefresh
)
1032 if (data
->hsize
< 320 || data
->vsize
< 240) {
1033 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "...which I refuse to believe\n");
1037 mode
= xf86CVTMode(data
->hsize
, data
->vsize
, PANEL_HZ
, 1, 0);
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
;
1048 if (pScrn
->monitor
->vrefresh
[0].hi
< 59.47)
1049 pScrn
->monitor
->vrefresh
[0].hi
= 59.47;
1055 VBEReadPanelID(vbeInfoPtr pVbe
)
1057 int RealOff
= pVbe
->real_mode_base
;
1058 pointer page
= pVbe
->memory
;
1060 int screen
= pVbe
->pInt10
->pScrn
->scrnIndex
;
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;
1070 xf86ExecX86int10(pVbe
->pInt10
);
1072 if ((pVbe
->pInt10
->ax
& 0xff) != 0x4f) {
1073 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE PanelID invalid\n");
1077 switch (pVbe
->pInt10
->ax
& 0xff00) {
1079 xf86DrvMsgVerb(screen
, X_INFO
, 3,
1080 "VESA VBE PanelID read successfully\n");
1082 memcpy(tmp
, page
, 32);
1085 xf86DrvMsgVerb(screen
, X_INFO
, 3, "VESA VBE PanelID read failed\n");
1088 xf86DrvMsgVerb(screen
, X_INFO
, 3,
1089 "VESA VBE PanelID unknown failure %i\n",
1090 pVbe
->pInt10
->ax
& 0xff00);