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