Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / vbe / vbe.c
CommitLineData
a09e091a
JB
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
38static unsigned char *vbeReadEDID(vbeInfoPtr pVbe);
39static Bool vbeProbeDDC(vbeInfoPtr pVbe);
40
41static const char vbeVersionString[] = "VBE2";
42
43vbeInfoPtr
44VBEInit(xf86Int10InfoPtr pInt, int entityIndex)
45{
46 return VBEExtendedInit(pInt, entityIndex, 0);
47}
48
49vbeInfoPtr
50VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags)
51{
52 int RealOff;
53 pointer 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
165void
166vbeFree(vbeInfoPtr pVbe)
167{
168 if (!pVbe)
169 return;
170
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);
175 free(pVbe);
176 return;
177}
178
179static Bool
180vbeProbeDDC(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
247typedef enum {
248 VBEOPT_NOVBE,
249 VBEOPT_NODDC
250} VBEOpts;
251
252static 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
258static unsigned char *
259vbeReadEDID(vbeInfoPtr pVbe)
260{
261 int RealOff = pVbe->real_mode_base;
262 pointer 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 unkown failure %i\n",
313 pVbe->pInt10->ax & 0xff00);
314 break;
315 }
316
317 error:
318 return tmp;
319}
320
321xf86MonPtr
322vbeDoEDID(vbeInfoPtr pVbe, pointer unused)
323{
324 unsigned char *DDC_data = NULL;
325
326 if (!pVbe)
327 return NULL;
328 if (pVbe->version < 0x200)
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
342VbeInfoBlock *
343VBEGetVBEInfo(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 = malloc(sizeof(CARD16) * (i + 1));
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
426void
427VBEFreeVBEInfo(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
439Bool
440VBESetVBEMode(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
478Bool
479VBEGetVBEMode(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
505VbeModeInfoBlock *
506VBEGetModeInfo(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
540void
541VBEFreeModeInfo(VbeModeInfoBlock * block)
542{
543 free(block);
544}
545
546Bool
547VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function,
548 pointer *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
645Bool
646VBEBankSwitch(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
667Bool
668VBESetGetLogicalScanlineLength(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
715Bool
716VBESetDisplayStart(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
731Bool
732VBEGetDisplayStart(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
748int
749VBESetGetDACPaletteFormat(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
778CARD32 *
779VBESetGetPaletteData(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 = malloc(num * sizeof(CARD32));
829 memcpy(data, pVbe->memory, num * sizeof(CARD32));
830
831 return data;
832}
833
834VBEpmi *
835VBEGetVBEpmi(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 := Lenght 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
871vbeModeInfoPtr
872VBEBuildVbeModeList(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
907unsigned short
908VBECalcVbeModeIndex(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
920void
921VBEVesaSaveRestore(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 (pointer) &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
956int
957VBEGetPixelClock(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
984Bool
985VBEDPMSSet(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
1017void
1018VBEInterpretPanelID(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
1054struct vbePanelID *
1055VBEReadPanelID(vbeInfoPtr pVbe)
1056{
1057 int RealOff = pVbe->real_mode_base;
1058 pointer 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}