1097 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1097 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
 | 
						|
/*
 | 
						|
 *                   XFree86 vbe module
 | 
						|
 *               Copyright 2000 Egbert Eich
 | 
						|
 *
 | 
						|
 * The mode query/save/set/restore functions from the vesa driver
 | 
						|
 * have been moved here.
 | 
						|
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 | 
						|
 * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_XORG_CONFIG_H
 | 
						|
#include <xorg-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include "xf86.h"
 | 
						|
#include "xf86Modes.h"
 | 
						|
#include "vbe.h"
 | 
						|
#include <X11/extensions/dpmsconst.h>
 | 
						|
 | 
						|
#define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x)
 | 
						|
 | 
						|
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
 | 
						|
#define B_O16(x)  (x)
 | 
						|
#define B_O32(x)  (x)
 | 
						|
#else
 | 
						|
#define B_O16(x)  ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8))
 | 
						|
#define B_O32(x)  ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \
 | 
						|
                  | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
 | 
						|
#endif
 | 
						|
#define L_ADD(x)  (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00)
 | 
						|
 | 
						|
#define FARP(p)		(((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff))
 | 
						|
#define R16(v)		((v) & 0xffff)
 | 
						|
 | 
						|
static unsigned char *vbeReadEDID(vbeInfoPtr pVbe);
 | 
						|
static Bool vbeProbeDDC(vbeInfoPtr pVbe);
 | 
						|
 | 
						|
static const char vbeVersionString[] = "VBE2";
 | 
						|
 | 
						|
vbeInfoPtr
 | 
						|
VBEInit(xf86Int10InfoPtr pInt, int entityIndex)
 | 
						|
{
 | 
						|
    return VBEExtendedInit(pInt, entityIndex, 0);
 | 
						|
}
 | 
						|
 | 
						|
vbeInfoPtr
 | 
						|
VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags)
 | 
						|
{
 | 
						|
    int RealOff;
 | 
						|
    void *page = NULL;
 | 
						|
    ScrnInfoPtr pScrn = xf86FindScreenForEntity(entityIndex);
 | 
						|
    vbeControllerInfoPtr vbe = NULL;
 | 
						|
    Bool init_int10 = FALSE;
 | 
						|
    vbeInfoPtr vip = NULL;
 | 
						|
    int screen;
 | 
						|
 | 
						|
    if (!pScrn)
 | 
						|
        return NULL;
 | 
						|
    screen = pScrn->scrnIndex;
 | 
						|
 | 
						|
    if (!pInt) {
 | 
						|
        if (!xf86LoadSubModule(pScrn, "int10"))
 | 
						|
            goto error;
 | 
						|
 | 
						|
        xf86DrvMsg(screen, X_INFO, "initializing int10\n");
 | 
						|
        pInt = xf86ExtendedInitInt10(entityIndex, Flags);
 | 
						|
        if (!pInt)
 | 
						|
            goto error;
 | 
						|
        init_int10 = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    page = xf86Int10AllocPages(pInt, 1, &RealOff);
 | 
						|
    if (!page)
 | 
						|
        goto error;
 | 
						|
    vbe = (vbeControllerInfoPtr) page;
 | 
						|
    memcpy(vbe->VbeSignature, vbeVersionString, 4);
 | 
						|
 | 
						|
    pInt->ax = 0x4F00;
 | 
						|
    pInt->es = SEG_ADDR(RealOff);
 | 
						|
    pInt->di = SEG_OFF(RealOff);
 | 
						|
    pInt->num = 0x10;
 | 
						|
 | 
						|
    xf86ExecX86int10(pInt);
 | 
						|
 | 
						|
    if ((pInt->ax & 0xff) != 0x4f) {
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA BIOS not detected\n");
 | 
						|
        goto error;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (pInt->ax & 0xff00) {
 | 
						|
    case 0:
 | 
						|
        xf86DrvMsg(screen, X_INFO, "VESA BIOS detected\n");
 | 
						|
        break;
 | 
						|
    case 0x100:
 | 
						|
        xf86DrvMsg(screen, X_INFO, "VESA BIOS function failed\n");
 | 
						|
        goto error;
 | 
						|
    case 0x200:
 | 
						|
        xf86DrvMsg(screen, X_INFO, "VESA BIOS not supported\n");
 | 
						|
        goto error;
 | 
						|
    case 0x300:
 | 
						|
        xf86DrvMsg(screen, X_INFO, "VESA BIOS not supported in current mode\n");
 | 
						|
        goto error;
 | 
						|
    default:
 | 
						|
        xf86DrvMsg(screen, X_INFO, "Invalid\n");
 | 
						|
        goto error;
 | 
						|
    }
 | 
						|
 | 
						|
    xf86DrvMsgVerb(screen, X_INFO, 4,
 | 
						|
                   "VbeVersion is %d, OemStringPtr is 0x%08lx,\n"
 | 
						|
                   "\tOemVendorNamePtr is 0x%08lx, OemProductNamePtr is 0x%08lx,\n"
 | 
						|
                   "\tOemProductRevPtr is 0x%08lx\n",
 | 
						|
                   vbe->VbeVersion, (unsigned long) vbe->OemStringPtr,
 | 
						|
                   (unsigned long) vbe->OemVendorNamePtr,
 | 
						|
                   (unsigned long) vbe->OemProductNamePtr,
 | 
						|
                   (unsigned long) vbe->OemProductRevPtr);
 | 
						|
 | 
						|
    xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE Version %i.%i\n",
 | 
						|
                   VERSION(vbe->VbeVersion));
 | 
						|
    xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE Total Mem: %i kB\n",
 | 
						|
                   vbe->TotalMem * 64);
 | 
						|
    xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE OEM: %s\n",
 | 
						|
                   (CARD8 *) xf86int10Addr(pInt, L_ADD(vbe->OemStringPtr)));
 | 
						|
 | 
						|
    if (B_O16(vbe->VbeVersion) >= 0x200) {
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE OEM Software Rev: %i.%i\n",
 | 
						|
                       VERSION(vbe->OemSoftwareRev));
 | 
						|
        if (vbe->OemVendorNamePtr)
 | 
						|
            xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE OEM Vendor: %s\n",
 | 
						|
                           (CARD8 *) xf86int10Addr(pInt,
 | 
						|
                                                   L_ADD(vbe->
 | 
						|
                                                         OemVendorNamePtr)));
 | 
						|
        if (vbe->OemProductNamePtr)
 | 
						|
            xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE OEM Product: %s\n",
 | 
						|
                           (CARD8 *) xf86int10Addr(pInt,
 | 
						|
                                                   L_ADD(vbe->
 | 
						|
                                                         OemProductNamePtr)));
 | 
						|
        if (vbe->OemProductRevPtr)
 | 
						|
            xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE OEM Product Rev: %s\n",
 | 
						|
                           (CARD8 *) xf86int10Addr(pInt,
 | 
						|
                                                   L_ADD(vbe->
 | 
						|
                                                         OemProductRevPtr)));
 | 
						|
    }
 | 
						|
    vip = (vbeInfoPtr) XNFalloc(sizeof(vbeInfoRec));
 | 
						|
    vip->version = B_O16(vbe->VbeVersion);
 | 
						|
    vip->pInt10 = pInt;
 | 
						|
    vip->ddc = DDC_UNCHECKED;
 | 
						|
    vip->memory = page;
 | 
						|
    vip->real_mode_base = RealOff;
 | 
						|
    vip->num_pages = 1;
 | 
						|
    vip->init_int10 = init_int10;
 | 
						|
 | 
						|
    return vip;
 | 
						|
 | 
						|
 error:
 | 
						|
    if (page)
 | 
						|
        xf86Int10FreePages(pInt, page, 1);
 | 
						|
    if (init_int10)
 | 
						|
        xf86FreeInt10(pInt);
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
vbeFree(vbeInfoPtr pVbe)
 | 
						|
{
 | 
						|
    if (!pVbe)
 | 
						|
        return;
 | 
						|
 | 
						|
    xf86Int10FreePages(pVbe->pInt10, pVbe->memory, pVbe->num_pages);
 | 
						|
    /* If we have initialized int10 we ought to free it, too */
 | 
						|
    if (pVbe->init_int10)
 | 
						|
        xf86FreeInt10(pVbe->pInt10);
 | 
						|
    free(pVbe);
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
vbeProbeDDC(vbeInfoPtr pVbe)
 | 
						|
{
 | 
						|
    const char *ddc_level;
 | 
						|
    int screen = pVbe->pInt10->pScrn->scrnIndex;
 | 
						|
 | 
						|
    if (pVbe->ddc == DDC_NONE)
 | 
						|
        return FALSE;
 | 
						|
    if (pVbe->ddc != DDC_UNCHECKED)
 | 
						|
        return TRUE;
 | 
						|
 | 
						|
    pVbe->pInt10->ax = 0x4F15;
 | 
						|
    pVbe->pInt10->bx = 0;
 | 
						|
    pVbe->pInt10->cx = 0;
 | 
						|
    pVbe->pInt10->es = 0;
 | 
						|
    pVbe->pInt10->di = 0;
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE DDC not supported\n");
 | 
						|
        pVbe->ddc = DDC_NONE;
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    switch ((pVbe->pInt10->ax >> 8) & 0xff) {
 | 
						|
    case 0:
 | 
						|
        xf86DrvMsg(screen, X_INFO, "VESA VBE DDC supported\n");
 | 
						|
        switch (pVbe->pInt10->bx & 0x3) {
 | 
						|
        case 0:
 | 
						|
            ddc_level = " none";
 | 
						|
            pVbe->ddc = DDC_NONE;
 | 
						|
            break;
 | 
						|
        case 1:
 | 
						|
            ddc_level = " 1";
 | 
						|
            pVbe->ddc = DDC_1;
 | 
						|
            break;
 | 
						|
        case 2:
 | 
						|
            ddc_level = " 2";
 | 
						|
            pVbe->ddc = DDC_2;
 | 
						|
            break;
 | 
						|
        case 3:
 | 
						|
            ddc_level = " 1 + 2";
 | 
						|
            pVbe->ddc = DDC_1_2;
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            ddc_level = "";
 | 
						|
            pVbe->ddc = DDC_NONE;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE DDC Level%s\n", ddc_level);
 | 
						|
        if (pVbe->pInt10->bx & 0x4) {
 | 
						|
            xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE DDC Screen blanked"
 | 
						|
                           "for data transfer\n");
 | 
						|
            pVbe->ddc_blank = TRUE;
 | 
						|
        }
 | 
						|
        else
 | 
						|
            pVbe->ddc_blank = FALSE;
 | 
						|
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3,
 | 
						|
                       "VESA VBE DDC transfer in appr. %x sec.\n",
 | 
						|
                       (pVbe->pInt10->bx >> 8) & 0xff);
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
typedef enum {
 | 
						|
    VBEOPT_NOVBE,
 | 
						|
    VBEOPT_NODDC
 | 
						|
} VBEOpts;
 | 
						|
 | 
						|
static const OptionInfoRec VBEOptions[] = {
 | 
						|
    {VBEOPT_NOVBE, "NoVBE", OPTV_BOOLEAN, {0}, FALSE},
 | 
						|
    {VBEOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE},
 | 
						|
    {-1, NULL, OPTV_NONE, {0}, FALSE},
 | 
						|
};
 | 
						|
 | 
						|
static unsigned char *
 | 
						|
vbeReadEDID(vbeInfoPtr pVbe)
 | 
						|
{
 | 
						|
    int RealOff = pVbe->real_mode_base;
 | 
						|
    void *page = pVbe->memory;
 | 
						|
    unsigned char *tmp = NULL;
 | 
						|
    Bool novbe = FALSE;
 | 
						|
    Bool noddc = FALSE;
 | 
						|
    ScrnInfoPtr pScrn = pVbe->pInt10->pScrn;
 | 
						|
    int screen = pScrn->scrnIndex;
 | 
						|
    OptionInfoPtr options;
 | 
						|
 | 
						|
    if (!page)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    options = XNFalloc(sizeof(VBEOptions));
 | 
						|
    (void) memcpy(options, VBEOptions, sizeof(VBEOptions));
 | 
						|
    xf86ProcessOptions(screen, pScrn->options, options);
 | 
						|
    xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe);
 | 
						|
    xf86GetOptValBool(options, VBEOPT_NODDC, &noddc);
 | 
						|
    free(options);
 | 
						|
    if (novbe || noddc)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    if (!vbeProbeDDC(pVbe))
 | 
						|
        goto error;
 | 
						|
 | 
						|
    memset(page, 0, sizeof(vbeInfoPtr));
 | 
						|
    strcpy(page, vbeVersionString);
 | 
						|
 | 
						|
    pVbe->pInt10->ax = 0x4F15;
 | 
						|
    pVbe->pInt10->bx = 0x01;
 | 
						|
    pVbe->pInt10->cx = 0;
 | 
						|
    pVbe->pInt10->dx = 0;
 | 
						|
    pVbe->pInt10->es = SEG_ADDR(RealOff);
 | 
						|
    pVbe->pInt10->di = SEG_OFF(RealOff);
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE DDC invalid\n");
 | 
						|
        goto error;
 | 
						|
    }
 | 
						|
    switch (pVbe->pInt10->ax & 0xff00) {
 | 
						|
    case 0x0:
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE DDC read successfully\n");
 | 
						|
        tmp = (unsigned char *) XNFalloc(128);
 | 
						|
        memcpy(tmp, page, 128);
 | 
						|
        break;
 | 
						|
    case 0x100:
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE DDC read failed\n");
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE DDC unknown failure %i\n",
 | 
						|
                       pVbe->pInt10->ax & 0xff00);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
 error:
 | 
						|
    return tmp;
 | 
						|
}
 | 
						|
 | 
						|
xf86MonPtr
 | 
						|
vbeDoEDID(vbeInfoPtr pVbe, void *unused)
 | 
						|
{
 | 
						|
    unsigned char *DDC_data = NULL;
 | 
						|
 | 
						|
    if (!pVbe)
 | 
						|
        return NULL;
 | 
						|
    if (pVbe->version < 0x102)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    DDC_data = vbeReadEDID(pVbe);
 | 
						|
 | 
						|
    if (!DDC_data)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    return xf86InterpretEDID(pVbe->pInt10->pScrn->scrnIndex, DDC_data);
 | 
						|
}
 | 
						|
 | 
						|
#define GET_UNALIGNED2(x) \
 | 
						|
            ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16)
 | 
						|
 | 
						|
VbeInfoBlock *
 | 
						|
VBEGetVBEInfo(vbeInfoPtr pVbe)
 | 
						|
{
 | 
						|
    VbeInfoBlock *block = NULL;
 | 
						|
    int i, pStr, pModes;
 | 
						|
    char *str;
 | 
						|
    CARD16 major, *modes;
 | 
						|
 | 
						|
    memset(pVbe->memory, 0, sizeof(VbeInfoBlock));
 | 
						|
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 00h     Return Super VGA information
 | 
						|
       ES:DI := Pointer to buffer
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX    := status
 | 
						|
       (All other registers are preserved)
 | 
						|
     */
 | 
						|
 | 
						|
    ((char *) pVbe->memory)[0] = 'V';
 | 
						|
    ((char *) pVbe->memory)[1] = 'B';
 | 
						|
    ((char *) pVbe->memory)[2] = 'E';
 | 
						|
    ((char *) pVbe->memory)[3] = '2';
 | 
						|
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f00;
 | 
						|
    pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | 
						|
    pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    block = calloc(1, sizeof(VbeInfoBlock));
 | 
						|
    block->VESASignature[0] = ((char *) pVbe->memory)[0];
 | 
						|
    block->VESASignature[1] = ((char *) pVbe->memory)[1];
 | 
						|
    block->VESASignature[2] = ((char *) pVbe->memory)[2];
 | 
						|
    block->VESASignature[3] = ((char *) pVbe->memory)[3];
 | 
						|
 | 
						|
    block->VESAVersion = *(CARD16 *) (((char *) pVbe->memory) + 4);
 | 
						|
    major = (unsigned) block->VESAVersion >> 8;
 | 
						|
 | 
						|
    pStr = GET_UNALIGNED2((((char *) pVbe->memory) + 6));
 | 
						|
    str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | 
						|
    block->OEMStringPtr = strdup(str);
 | 
						|
 | 
						|
    block->Capabilities[0] = ((char *) pVbe->memory)[10];
 | 
						|
    block->Capabilities[1] = ((char *) pVbe->memory)[11];
 | 
						|
    block->Capabilities[2] = ((char *) pVbe->memory)[12];
 | 
						|
    block->Capabilities[3] = ((char *) pVbe->memory)[13];
 | 
						|
 | 
						|
    pModes = GET_UNALIGNED2((((char *) pVbe->memory) + 14));
 | 
						|
    modes = xf86int10Addr(pVbe->pInt10, FARP(pModes));
 | 
						|
    i = 0;
 | 
						|
    while (modes[i] != 0xffff)
 | 
						|
        i++;
 | 
						|
    block->VideoModePtr = xallocarray(i + 1, sizeof(CARD16));
 | 
						|
    memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i);
 | 
						|
    block->VideoModePtr[i] = 0xffff;
 | 
						|
 | 
						|
    block->TotalMemory = *(CARD16 *) (((char *) pVbe->memory) + 18);
 | 
						|
 | 
						|
    if (major < 2)
 | 
						|
        memcpy(&block->OemSoftwareRev, ((char *) pVbe->memory) + 20, 236);
 | 
						|
    else {
 | 
						|
        block->OemSoftwareRev = *(CARD16 *) (((char *) pVbe->memory) + 20);
 | 
						|
        pStr = GET_UNALIGNED2((((char *) pVbe->memory) + 22));
 | 
						|
        str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | 
						|
        block->OemVendorNamePtr = strdup(str);
 | 
						|
        pStr = GET_UNALIGNED2((((char *) pVbe->memory) + 26));
 | 
						|
        str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | 
						|
        block->OemProductNamePtr = strdup(str);
 | 
						|
        pStr = GET_UNALIGNED2((((char *) pVbe->memory) + 30));
 | 
						|
        str = xf86int10Addr(pVbe->pInt10, FARP(pStr));
 | 
						|
        block->OemProductRevPtr = strdup(str);
 | 
						|
        memcpy(&block->Reserved, ((char *) pVbe->memory) + 34, 222);
 | 
						|
        memcpy(&block->OemData, ((char *) pVbe->memory) + 256, 256);
 | 
						|
    }
 | 
						|
 | 
						|
    return block;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
VBEFreeVBEInfo(VbeInfoBlock * block)
 | 
						|
{
 | 
						|
    free(block->OEMStringPtr);
 | 
						|
    free(block->VideoModePtr);
 | 
						|
    if (((unsigned) block->VESAVersion >> 8) >= 2) {
 | 
						|
        free(block->OemVendorNamePtr);
 | 
						|
        free(block->OemProductNamePtr);
 | 
						|
        free(block->OemProductRevPtr);
 | 
						|
    }
 | 
						|
    free(block);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock * block)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 02h     Set Super VGA video mode
 | 
						|
       BX    := Video mode
 | 
						|
       D0-D8  := Mode number
 | 
						|
       D9-D10 := Reserved (must be 0)
 | 
						|
       D11    := 0 Use current default refresh rate
 | 
						|
       := 1 Use user specified CRTC values for refresh rate
 | 
						|
       D12-13   Reserved for VBE/AF (must be 0)
 | 
						|
       D14    := 0 Use windowed frame buffer model
 | 
						|
       := 1 Use linear/flat frame buffer model
 | 
						|
       D15    := 0 Clear video memory
 | 
						|
       := 1 Don't clear video memory
 | 
						|
       ES:DI := Pointer to VbeCRTCInfoBlock structure
 | 
						|
 | 
						|
       Output: AX = Status
 | 
						|
       (All other registers are preserved)
 | 
						|
     */
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f02;
 | 
						|
    pVbe->pInt10->bx = mode;
 | 
						|
    if (block) {
 | 
						|
        pVbe->pInt10->bx |= 1 << 11;
 | 
						|
        memcpy(pVbe->memory, block, sizeof(VbeCRTCInfoBlock));
 | 
						|
        pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | 
						|
        pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | 
						|
    }
 | 
						|
    else
 | 
						|
        pVbe->pInt10->bx &= ~(1 << 11);
 | 
						|
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    return (R16(pVbe->pInt10->ax) == 0x4f);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBEGetVBEMode(vbeInfoPtr pVbe, int *mode)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AH := 4Fh        Super VGA support
 | 
						|
       AL := 03h        Return current video mode
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX := Status
 | 
						|
       BX := Current video mode
 | 
						|
       (All other registers are preserved)
 | 
						|
     */
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f03;
 | 
						|
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) == 0x4f) {
 | 
						|
        *mode = R16(pVbe->pInt10->bx);
 | 
						|
 | 
						|
        return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
VbeModeInfoBlock *
 | 
						|
VBEGetModeInfo(vbeInfoPtr pVbe, int mode)
 | 
						|
{
 | 
						|
    VbeModeInfoBlock *block = NULL;
 | 
						|
 | 
						|
    memset(pVbe->memory, 0, sizeof(VbeModeInfoBlock));
 | 
						|
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 01h     Return Super VGA mode information
 | 
						|
       CX    :=         Super VGA video mode
 | 
						|
       (mode number must be one of those returned by Function 0)
 | 
						|
       ES:DI := Pointer to buffer
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX    := status
 | 
						|
       (All other registers are preserved)
 | 
						|
     */
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f01;
 | 
						|
    pVbe->pInt10->cx = mode;
 | 
						|
    pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | 
						|
    pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    block = malloc(sizeof(VbeModeInfoBlock));
 | 
						|
    if (block)
 | 
						|
        memcpy(block, pVbe->memory, sizeof(*block));
 | 
						|
 | 
						|
    return block;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
VBEFreeModeInfo(VbeModeInfoBlock * block)
 | 
						|
{
 | 
						|
    free(block);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function,
 | 
						|
               void **memory, int *size, int *real_mode_pages)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 04h     Save/restore Super VGA video state
 | 
						|
       DL    := 00h     Return save/restore state buffer size
 | 
						|
       CX    := Requested states
 | 
						|
       D0 = Save/restore video hardware state
 | 
						|
       D1 = Save/restore video BIOS data state
 | 
						|
       D2 = Save/restore video DAC state
 | 
						|
       D3 = Save/restore Super VGA state
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX = Status
 | 
						|
       BX = Number of 64-byte blocks to hold the state buffer
 | 
						|
       (All other registers are preserved)
 | 
						|
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 04h     Save/restore Super VGA video state
 | 
						|
       DL    := 01h     Save Super VGA video state
 | 
						|
       CX    := Requested states (see above)
 | 
						|
       ES:BX := Pointer to buffer
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX    := Status
 | 
						|
       (All other registers are preserved)
 | 
						|
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 04h     Save/restore Super VGA video state
 | 
						|
       DL    := 02h     Restore Super VGA video state
 | 
						|
       CX    := Requested states (see above)
 | 
						|
       ES:BX := Pointer to buffer
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX     := Status
 | 
						|
       (All other registers are preserved)
 | 
						|
     */
 | 
						|
 | 
						|
    if ((pVbe->version & 0xff00) > 0x100) {
 | 
						|
        int screen = pVbe->pInt10->pScrn->scrnIndex;
 | 
						|
 | 
						|
        if (function == MODE_QUERY || (function == MODE_SAVE && !*memory)) {
 | 
						|
            /* Query amount of memory to save state */
 | 
						|
 | 
						|
            pVbe->pInt10->num = 0x10;
 | 
						|
            pVbe->pInt10->ax = 0x4f04;
 | 
						|
            pVbe->pInt10->dx = 0;
 | 
						|
            pVbe->pInt10->cx = 0x000f;
 | 
						|
            xf86ExecX86int10(pVbe->pInt10);
 | 
						|
            if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
                return FALSE;
 | 
						|
 | 
						|
            if (function == MODE_SAVE) {
 | 
						|
                int npages = (R16(pVbe->pInt10->bx) * 64) / 4096 + 1;
 | 
						|
 | 
						|
                if ((*memory = xf86Int10AllocPages(pVbe->pInt10, npages,
 | 
						|
                                                   real_mode_pages)) == NULL) {
 | 
						|
                    xf86DrvMsg(screen, X_ERROR,
 | 
						|
                               "Cannot allocate memory to save SVGA state.\n");
 | 
						|
                    return FALSE;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            *size = pVbe->pInt10->bx * 64;
 | 
						|
        }
 | 
						|
 | 
						|
        /* Save/Restore Super VGA state */
 | 
						|
        if (function != MODE_QUERY) {
 | 
						|
 | 
						|
            if (!*memory)
 | 
						|
                return FALSE;
 | 
						|
            pVbe->pInt10->num = 0x10;
 | 
						|
            pVbe->pInt10->ax = 0x4f04;
 | 
						|
            switch (function) {
 | 
						|
            case MODE_SAVE:
 | 
						|
                pVbe->pInt10->dx = 1;
 | 
						|
                break;
 | 
						|
            case MODE_RESTORE:
 | 
						|
                pVbe->pInt10->dx = 2;
 | 
						|
                break;
 | 
						|
            case MODE_QUERY:
 | 
						|
                return FALSE;
 | 
						|
            }
 | 
						|
            pVbe->pInt10->cx = 0x000f;
 | 
						|
 | 
						|
            pVbe->pInt10->es = SEG_ADDR(*real_mode_pages);
 | 
						|
            pVbe->pInt10->bx = SEG_OFF(*real_mode_pages);
 | 
						|
            xf86ExecX86int10(pVbe->pInt10);
 | 
						|
            return (R16(pVbe->pInt10->ax) == 0x4f);
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 05h
 | 
						|
 | 
						|
       Output:
 | 
						|
     */
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f05;
 | 
						|
    pVbe->pInt10->bx = window;
 | 
						|
    pVbe->pInt10->dx = iBank;
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, vbeScanwidthCommand command,
 | 
						|
                               int width, int *pixels, int *bytes, int *max)
 | 
						|
{
 | 
						|
    if (command < SCANWID_SET || command > SCANWID_GET_MAX)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AX := 4F06h VBE Set/Get Logical Scan Line Length
 | 
						|
       BL := 00h Set Scan Line Length in Pixels
 | 
						|
       := 01h Get Scan Line Length
 | 
						|
       := 02h Set Scan Line Length in Bytes
 | 
						|
       := 03h Get Maximum Scan Line Length
 | 
						|
       CX := If BL=00h Desired Width in Pixels
 | 
						|
       If BL=02h Desired Width in Bytes
 | 
						|
       (Ignored for Get Functions)
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX := VBE Return Status
 | 
						|
       BX := Bytes Per Scan Line
 | 
						|
       CX := Actual Pixels Per Scan Line
 | 
						|
       (truncated to nearest complete pixel)
 | 
						|
       DX := Maximum Number of Scan Lines
 | 
						|
     */
 | 
						|
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f06;
 | 
						|
    pVbe->pInt10->bx = command;
 | 
						|
    if (command == SCANWID_SET || command == SCANWID_SET_BYTES)
 | 
						|
        pVbe->pInt10->cx = width;
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (command == SCANWID_GET || command == SCANWID_GET_MAX) {
 | 
						|
        if (pixels)
 | 
						|
            *pixels = R16(pVbe->pInt10->cx);
 | 
						|
        if (bytes)
 | 
						|
            *bytes = R16(pVbe->pInt10->bx);
 | 
						|
        if (max)
 | 
						|
            *max = R16(pVbe->pInt10->dx);
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace)
 | 
						|
{
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f07;
 | 
						|
    pVbe->pInt10->bx = wait_retrace ? 0x80 : 0x00;
 | 
						|
    pVbe->pInt10->cx = x;
 | 
						|
    pVbe->pInt10->dx = y;
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y)
 | 
						|
{
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f07;
 | 
						|
    pVbe->pInt10->bx = 0x01;
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    *x = pVbe->pInt10->cx;
 | 
						|
    *y = pVbe->pInt10->dx;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AX := 4F08h VBE Set/Get Palette Format
 | 
						|
       BL := 00h Set DAC Palette Format
 | 
						|
       := 01h Get DAC Palette Format
 | 
						|
       BH := Desired bits of color per primary
 | 
						|
       (Set DAC Palette Format only)
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX := VBE Return Status
 | 
						|
       BH := Current number of bits of color per primary
 | 
						|
     */
 | 
						|
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f08;
 | 
						|
    if (!bits)
 | 
						|
        pVbe->pInt10->bx = 0x01;
 | 
						|
    else
 | 
						|
        pVbe->pInt10->bx = (bits & 0x00ff) << 8;
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    return (bits != 0 ? bits : (pVbe->pInt10->bx >> 8) & 0x00ff);
 | 
						|
}
 | 
						|
 | 
						|
CARD32 *
 | 
						|
VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num,
 | 
						|
                     CARD32 *data, Bool secondary, Bool wait_retrace)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       (16-bit)
 | 
						|
       AX    := 4F09h VBE Load/Unload Palette Data
 | 
						|
       BL    := 00h Set Palette Data
 | 
						|
       := 01h Get Palette Data
 | 
						|
       := 02h Set Secondary Palette Data
 | 
						|
       := 03h Get Secondary Palette Data
 | 
						|
       := 80h Set Palette Data during Vertical Retrace
 | 
						|
       CX    := Number of palette registers to update (to a maximum of 256)
 | 
						|
       DX    := First of the palette registers to update (start)
 | 
						|
       ES:DI := Table of palette values (see below for format)
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX    := VBE Return Status
 | 
						|
 | 
						|
       Input:
 | 
						|
       (32-bit)
 | 
						|
       BL     := 00h Set Palette Data
 | 
						|
       := 80h Set Palette Data during Vertical Retrace
 | 
						|
       CX     := Number of palette registers to update (to a maximum of 256)
 | 
						|
       DX     := First of the palette registers to update (start)
 | 
						|
       ES:EDI := Table of palette values (see below for format)
 | 
						|
       DS     := Selector for memory mapped registers
 | 
						|
     */
 | 
						|
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f09;
 | 
						|
    if (!secondary)
 | 
						|
        pVbe->pInt10->bx = set && wait_retrace ? 0x80 : set ? 0 : 1;
 | 
						|
    else
 | 
						|
        pVbe->pInt10->bx = set ? 2 : 3;
 | 
						|
    pVbe->pInt10->cx = num;
 | 
						|
    pVbe->pInt10->dx = first;
 | 
						|
    pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
 | 
						|
    pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
 | 
						|
    if (set)
 | 
						|
        memcpy(pVbe->memory, data, num * sizeof(CARD32));
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    if (set)
 | 
						|
        return data;
 | 
						|
 | 
						|
    data = xallocarray(num, sizeof(CARD32));
 | 
						|
    memcpy(data, pVbe->memory, num * sizeof(CARD32));
 | 
						|
 | 
						|
    return data;
 | 
						|
}
 | 
						|
 | 
						|
VBEpmi *
 | 
						|
VBEGetVBEpmi(vbeInfoPtr pVbe)
 | 
						|
{
 | 
						|
    VBEpmi *pmi;
 | 
						|
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AH    := 4Fh     Super VGA support
 | 
						|
       AL    := 0Ah     Protected Mode Interface
 | 
						|
       BL    := 00h     Return Protected Mode Table
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX    := Status
 | 
						|
       ES    := Real Mode Segment of Table
 | 
						|
       DI    := Offset of Table
 | 
						|
       CX    := Length of Table including protected mode code in bytes (for copying purposes)
 | 
						|
       (All other registers are preserved)
 | 
						|
     */
 | 
						|
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f0a;
 | 
						|
    pVbe->pInt10->bx = 0;
 | 
						|
    pVbe->pInt10->di = 0;
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    pmi = malloc(sizeof(VBEpmi));
 | 
						|
    pmi->seg_tbl = R16(pVbe->pInt10->es);
 | 
						|
    pmi->tbl_off = R16(pVbe->pInt10->di);
 | 
						|
    pmi->tbl_len = R16(pVbe->pInt10->cx);
 | 
						|
 | 
						|
    return pmi;
 | 
						|
}
 | 
						|
 | 
						|
#if 0
 | 
						|
vbeModeInfoPtr
 | 
						|
VBEBuildVbeModeList(vbeInfoPtr pVbe, VbeInfoBlock * vbe)
 | 
						|
{
 | 
						|
    vbeModeInfoPtr ModeList = NULL;
 | 
						|
 | 
						|
    int i = 0;
 | 
						|
 | 
						|
    while (vbe->VideoModePtr[i] != 0xffff) {
 | 
						|
        vbeModeInfoPtr m;
 | 
						|
        VbeModeInfoBlock *mode;
 | 
						|
        int id = vbe->VideoModePtr[i++];
 | 
						|
        int bpp;
 | 
						|
 | 
						|
        if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
 | 
						|
            continue;
 | 
						|
 | 
						|
        bpp = mode->BitsPerPixel;
 | 
						|
 | 
						|
        m = XNFcallocarray(1, sizeof(vbeModeInfoRec));
 | 
						|
        m->width = mode->XResolution;
 | 
						|
        m->height = mode->YResolution;
 | 
						|
        m->bpp = bpp;
 | 
						|
        m->n = id;
 | 
						|
        m->next = ModeList;
 | 
						|
 | 
						|
        xf86DrvMsgVerb(pVbe->pInt10->pScrn->scrnIndex, X_PROBED, 3,
 | 
						|
                       "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n",
 | 
						|
                       m->n, m->width, m->height, m->bpp);
 | 
						|
 | 
						|
        ModeList = m;
 | 
						|
 | 
						|
        VBEFreeModeInfo(mode);
 | 
						|
    }
 | 
						|
    return ModeList;
 | 
						|
}
 | 
						|
 | 
						|
unsigned short
 | 
						|
VBECalcVbeModeIndex(vbeModeInfoPtr m, DisplayModePtr mode, int bpp)
 | 
						|
{
 | 
						|
    while (m) {
 | 
						|
        if (bpp == m->bpp
 | 
						|
            && mode->HDisplay == m->width && mode->VDisplay == m->height)
 | 
						|
            return m->n;
 | 
						|
        m = m->next;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
void
 | 
						|
VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr,
 | 
						|
                   vbeSaveRestoreFunction function)
 | 
						|
{
 | 
						|
    Bool SaveSucc = FALSE;
 | 
						|
 | 
						|
    if (VBE_VERSION_MAJOR(pVbe->version) > 1
 | 
						|
        && (function == MODE_SAVE || vbe_sr->pstate)) {
 | 
						|
        if (function == MODE_RESTORE)
 | 
						|
            memcpy(vbe_sr->state, vbe_sr->pstate, vbe_sr->stateSize);
 | 
						|
        ErrorF("VBESaveRestore\n");
 | 
						|
        if ((VBESaveRestore(pVbe, function,
 | 
						|
                            (void *) &vbe_sr->state,
 | 
						|
                            &vbe_sr->stateSize, &vbe_sr->statePage))) {
 | 
						|
            if (function == MODE_SAVE) {
 | 
						|
                SaveSucc = TRUE;
 | 
						|
                vbe_sr->stateMode = -1; /* invalidate */
 | 
						|
                /* don't rely on the memory not being touched */
 | 
						|
                if (vbe_sr->pstate == NULL)
 | 
						|
                    vbe_sr->pstate = malloc(vbe_sr->stateSize);
 | 
						|
                memcpy(vbe_sr->pstate, vbe_sr->state, vbe_sr->stateSize);
 | 
						|
            }
 | 
						|
            ErrorF("VBESaveRestore done with success\n");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        ErrorF("VBESaveRestore done\n");
 | 
						|
    }
 | 
						|
 | 
						|
    if (function == MODE_SAVE && !SaveSucc)
 | 
						|
        (void) VBEGetVBEMode(pVbe, &vbe_sr->stateMode);
 | 
						|
 | 
						|
    if (function == MODE_RESTORE && vbe_sr->stateMode != -1)
 | 
						|
        VBESetVBEMode(pVbe, vbe_sr->stateMode, NULL);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int clock)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AX := 4F0Bh VBE Get Pixel Clock
 | 
						|
       BL := 00h Get Pixel Clock
 | 
						|
       ECX := pixel clock in units of Hz
 | 
						|
       DX := mode number
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX := VBE Return Status
 | 
						|
       ECX := Closest pixel clock
 | 
						|
     */
 | 
						|
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f0b;
 | 
						|
    pVbe->pInt10->bx = 0x00;
 | 
						|
    pVbe->pInt10->cx = clock;
 | 
						|
    pVbe->pInt10->dx = mode;
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if (R16(pVbe->pInt10->ax) != 0x4f)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    return pVbe->pInt10->cx;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
VBEDPMSSet(vbeInfoPtr pVbe, int mode)
 | 
						|
{
 | 
						|
    /*
 | 
						|
       Input:
 | 
						|
       AX := 4F10h DPMS
 | 
						|
       BL := 01h Set Display Power State
 | 
						|
       BH := requested power state
 | 
						|
 | 
						|
       Output:
 | 
						|
       AX := VBE Return Status
 | 
						|
     */
 | 
						|
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
    pVbe->pInt10->ax = 0x4f10;
 | 
						|
    pVbe->pInt10->bx = 0x01;
 | 
						|
    switch (mode) {
 | 
						|
    case DPMSModeOn:
 | 
						|
        break;
 | 
						|
    case DPMSModeStandby:
 | 
						|
        pVbe->pInt10->bx |= 0x100;
 | 
						|
        break;
 | 
						|
    case DPMSModeSuspend:
 | 
						|
        pVbe->pInt10->bx |= 0x200;
 | 
						|
        break;
 | 
						|
    case DPMSModeOff:
 | 
						|
        pVbe->pInt10->bx |= 0x400;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
    return (R16(pVbe->pInt10->ax) == 0x4f);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
VBEInterpretPanelID(ScrnInfoPtr pScrn, struct vbePanelID *data)
 | 
						|
{
 | 
						|
    DisplayModePtr mode;
 | 
						|
    const float PANEL_HZ = 60.0;
 | 
						|
 | 
						|
    if (!data)
 | 
						|
        return;
 | 
						|
 | 
						|
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PanelID returned panel resolution %dx%d\n",
 | 
						|
               data->hsize, data->vsize);
 | 
						|
 | 
						|
    if (pScrn->monitor->nHsync || pScrn->monitor->nVrefresh)
 | 
						|
        return;
 | 
						|
 | 
						|
    if (data->hsize < 320 || data->vsize < 240) {
 | 
						|
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "...which I refuse to believe\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    mode = xf86CVTMode(data->hsize, data->vsize, PANEL_HZ, 1, 0);
 | 
						|
 | 
						|
    pScrn->monitor->nHsync = 1;
 | 
						|
    pScrn->monitor->hsync[0].lo = 29.37;
 | 
						|
    pScrn->monitor->hsync[0].hi = (float) mode->Clock / (float) mode->HTotal;
 | 
						|
    pScrn->monitor->nVrefresh = 1;
 | 
						|
    pScrn->monitor->vrefresh[0].lo = 56.0;
 | 
						|
    pScrn->monitor->vrefresh[0].hi =
 | 
						|
        (float) mode->Clock * 1000.0 / (float) mode->HTotal /
 | 
						|
        (float) mode->VTotal;
 | 
						|
 | 
						|
    if (pScrn->monitor->vrefresh[0].hi < 59.47)
 | 
						|
        pScrn->monitor->vrefresh[0].hi = 59.47;
 | 
						|
 | 
						|
    free(mode);
 | 
						|
}
 | 
						|
 | 
						|
struct vbePanelID *
 | 
						|
VBEReadPanelID(vbeInfoPtr pVbe)
 | 
						|
{
 | 
						|
    int RealOff = pVbe->real_mode_base;
 | 
						|
    void *page = pVbe->memory;
 | 
						|
    void *tmp = NULL;
 | 
						|
    int screen = pVbe->pInt10->pScrn->scrnIndex;
 | 
						|
 | 
						|
    pVbe->pInt10->ax = 0x4F11;
 | 
						|
    pVbe->pInt10->bx = 0x01;
 | 
						|
    pVbe->pInt10->cx = 0;
 | 
						|
    pVbe->pInt10->dx = 0;
 | 
						|
    pVbe->pInt10->es = SEG_ADDR(RealOff);
 | 
						|
    pVbe->pInt10->di = SEG_OFF(RealOff);
 | 
						|
    pVbe->pInt10->num = 0x10;
 | 
						|
 | 
						|
    xf86ExecX86int10(pVbe->pInt10);
 | 
						|
 | 
						|
    if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE PanelID invalid\n");
 | 
						|
        goto error;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (pVbe->pInt10->ax & 0xff00) {
 | 
						|
    case 0x0:
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3,
 | 
						|
                       "VESA VBE PanelID read successfully\n");
 | 
						|
        tmp = XNFalloc(32);
 | 
						|
        memcpy(tmp, page, 32);
 | 
						|
        break;
 | 
						|
    case 0x100:
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3, "VESA VBE PanelID read failed\n");
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        xf86DrvMsgVerb(screen, X_INFO, 3,
 | 
						|
                       "VESA VBE PanelID unknown failure %i\n",
 | 
						|
                       pVbe->pInt10->ax & 0xff00);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
 error:
 | 
						|
    return tmp;
 | 
						|
}
 |