xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

vbe.c (30743B)


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