49f77fff14
Save in a few special cases, _X_EXPORT should not be used in C source files. Instead, it should be used in headers, and the proper C source include that header. Some special cases are symbols that need to be shared between modules, but not expected to be used by external drivers, and symbols that are accessible via LoaderSymbol/dlopen. This patch also adds conditionally some new sdk header files, depending on extensions enabled. These files were added to match pattern for other extensions/modules, that is, have the headers "deciding" symbol visibility in the sdk. These headers are: o Xext/panoramiXsrv.h, Xext/panoramiX.h o fbpict.h (unconditionally) o vidmodeproc.h o mioverlay.h (unconditionally, used only by xaa) o xfixes.h (unconditionally, symbols required by dri2) LoaderSymbol and similar functions now don't have different prototypes, in loaderProcs.h and xf86Module.h, so that both headers can be included, without the need of defining IN_LOADER. xf86NewInputDevice() device prototype readded to xf86Xinput.h, but not exported (and with a comment about it).
1147 lines
30 KiB
C
1147 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 "vbe.h"
|
|
#include <X11/Xarch.h>
|
|
#define DPMS_SERVER
|
|
#include <X11/extensions/dpms.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;
|
|
pointer 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 initalized int10 we ought to free it, too */
|
|
if (pVbe->init_int10)
|
|
xf86FreeInt10(pVbe->pInt10);
|
|
xfree(pVbe);
|
|
return;
|
|
}
|
|
|
|
static Bool
|
|
vbeProbeDDC(vbeInfoPtr pVbe)
|
|
{
|
|
char *ddc_level;
|
|
int screen = pVbe->pInt10->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;
|
|
pointer page = pVbe->memory;
|
|
unsigned char *tmp = NULL;
|
|
Bool novbe = FALSE;
|
|
Bool noddc = FALSE;
|
|
int screen = pVbe->pInt10->scrnIndex;
|
|
OptionInfoPtr options;
|
|
|
|
if (!page) return NULL;
|
|
|
|
options = xnfalloc(sizeof(VBEOptions));
|
|
(void)memcpy(options, VBEOptions, sizeof(VBEOptions));
|
|
xf86ProcessOptions(screen, xf86Screens[screen]->options, options);
|
|
xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe);
|
|
xf86GetOptValBool(options, VBEOPT_NODDC, &noddc);
|
|
xfree(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 unkown failure %i\n",
|
|
pVbe->pInt10->ax & 0xff00);
|
|
break;
|
|
}
|
|
|
|
error:
|
|
return tmp;
|
|
}
|
|
|
|
xf86MonPtr
|
|
vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule)
|
|
{
|
|
xf86MonPtr pMonitor;
|
|
pointer pModule;
|
|
unsigned char *DDC_data = NULL;
|
|
|
|
if (!pVbe) return NULL;
|
|
if (pVbe->version < 0x200)
|
|
return NULL;
|
|
|
|
if (!(pModule = pDDCModule)) {
|
|
pModule =
|
|
xf86LoadSubModule(xf86Screens[pVbe->pInt10->scrnIndex], "ddc");
|
|
if (!pModule)
|
|
return NULL;
|
|
}
|
|
|
|
DDC_data = vbeReadEDID(pVbe);
|
|
|
|
if (!DDC_data)
|
|
return NULL;
|
|
|
|
pMonitor = xf86InterpretEDID(pVbe->pInt10->scrnIndex, DDC_data);
|
|
|
|
if (!pDDCModule)
|
|
xf86UnloadSubModule(pModule);
|
|
return pMonitor;
|
|
}
|
|
|
|
#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;
|
|
|
|
bzero(pVbe->memory, 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 = xcalloc(sizeof(VbeInfoBlock), 1);
|
|
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 = xalloc(sizeof(CARD16) * i + 1);
|
|
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)
|
|
{
|
|
xfree(block->OEMStringPtr);
|
|
xfree(block->VideoModePtr);
|
|
if (((unsigned)block->VESAVersion >> 8) >= 2) {
|
|
xfree(block->OemVendorNamePtr);
|
|
xfree(block->OemProductNamePtr);
|
|
xfree(block->OemProductRevPtr);
|
|
}
|
|
xfree(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;
|
|
|
|
bzero(pVbe->memory, 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 = xcalloc(sizeof(VbeModeInfoBlock), 1);
|
|
|
|
block->ModeAttributes = *(CARD16*)pVbe->memory;
|
|
block->WinAAttributes = ((char*)pVbe->memory)[2];
|
|
block->WinBAttributes = ((char*)pVbe->memory)[3];
|
|
block->WinGranularity = *(CARD16*)(((char*)pVbe->memory) + 4);
|
|
block->WinSize = *(CARD16*)(((char*)pVbe->memory) + 6);
|
|
block->WinASegment = *(CARD16*)(((char*)pVbe->memory) + 8);
|
|
block->WinBSegment = *(CARD16*)(((char*)pVbe->memory) + 10);
|
|
block->WinFuncPtr = *(CARD32*)(((char*)pVbe->memory) + 12);
|
|
block->BytesPerScanline = *(CARD16*)(((char*)pVbe->memory) + 16);
|
|
|
|
/* mandatory information for VBE 1.2 and above */
|
|
block->XResolution = *(CARD16*)(((char*)pVbe->memory) + 18);
|
|
block->YResolution = *(CARD16*)(((char*)pVbe->memory) + 20);
|
|
block->XCharSize = ((char*)pVbe->memory)[22];
|
|
block->YCharSize = ((char*)pVbe->memory)[23];
|
|
block->NumberOfPlanes = ((char*)pVbe->memory)[24];
|
|
block->BitsPerPixel = ((char*)pVbe->memory)[25];
|
|
block->NumberOfBanks = ((char*)pVbe->memory)[26];
|
|
block->MemoryModel = ((char*)pVbe->memory)[27];
|
|
block->BankSize = ((char*)pVbe->memory)[28];
|
|
block->NumberOfImages = ((char*)pVbe->memory)[29];
|
|
block->Reserved = ((char*)pVbe->memory)[30];
|
|
|
|
/* Direct color fields (required for direct/6 and YUV/7 memory models) */
|
|
block->RedMaskSize = ((char*)pVbe->memory)[31];
|
|
block->RedFieldPosition = ((char*)pVbe->memory)[32];
|
|
block->GreenMaskSize = ((char*)pVbe->memory)[33];
|
|
block->GreenFieldPosition = ((char*)pVbe->memory)[34];
|
|
block->BlueMaskSize = ((char*)pVbe->memory)[35];
|
|
block->BlueFieldPosition = ((char*)pVbe->memory)[36];
|
|
block->RsvdMaskSize = ((char*)pVbe->memory)[37];
|
|
block->RsvdFieldPosition = ((char*)pVbe->memory)[38];
|
|
block->DirectColorModeInfo = ((char*)pVbe->memory)[39];
|
|
|
|
/* Mandatory information for VBE 2.0 and above */
|
|
if (pVbe->version >= 0x200) {
|
|
block->PhysBasePtr = *(CARD32*)(((char*)pVbe->memory) + 40);
|
|
block->Reserved32 = *(CARD32*)(((char*)pVbe->memory) + 44);
|
|
block->Reserved16 = *(CARD16*)(((char*)pVbe->memory) + 48);
|
|
|
|
/* Mandatory information for VBE 3.0 and above */
|
|
if (pVbe->version >= 0x300) {
|
|
block->LinBytesPerScanLine = *(CARD16*)(((char*)pVbe->memory) + 50);
|
|
block->BnkNumberOfImagePages = ((char*)pVbe->memory)[52];
|
|
block->LinNumberOfImagePages = ((char*)pVbe->memory)[53];
|
|
block->LinRedMaskSize = ((char*)pVbe->memory)[54];
|
|
block->LinRedFieldPosition = ((char*)pVbe->memory)[55];
|
|
block->LinGreenMaskSize = ((char*)pVbe->memory)[56];
|
|
block->LinGreenFieldPosition = ((char*)pVbe->memory)[57];
|
|
block->LinBlueMaskSize = ((char*)pVbe->memory)[58];
|
|
block->LinBlueFieldPosition = ((char*)pVbe->memory)[59];
|
|
block->LinRsvdMaskSize = ((char*)pVbe->memory)[60];
|
|
block->LinRsvdFieldPosition = ((char*)pVbe->memory)[61];
|
|
block->MaxPixelClock = *(CARD32*)(((char*)pVbe->memory) + 62);
|
|
memcpy(&block->Reserved2, ((char*)pVbe->memory) + 66, 188);
|
|
}
|
|
else
|
|
memcpy(&block->LinBytesPerScanLine, ((char*)pVbe->memory) + 50, 206);
|
|
}
|
|
else
|
|
memcpy(&block->PhysBasePtr, ((char*)pVbe->memory) + 40, 216);
|
|
|
|
return (block);
|
|
}
|
|
|
|
void
|
|
VBEFreeModeInfo(VbeModeInfoBlock *block)
|
|
{
|
|
xfree(block);
|
|
}
|
|
|
|
Bool
|
|
VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function,
|
|
pointer *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->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 = xalloc(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 := Lenght 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 = xalloc(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 = xnfcalloc(sizeof(vbeModeInfoRec),1);
|
|
m->width = mode->XResolution;
|
|
m->height = mode->YResolution;
|
|
m->bpp = bpp;
|
|
m->n = id;
|
|
m->next = ModeList;
|
|
|
|
xf86DrvMsgVerb(pVbe->pInt10->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,
|
|
(pointer)&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 = xalloc(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(int scrnIndex, struct vbePanelID *data)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
|
DisplayModePtr mode;
|
|
const float PANEL_HZ = 60.0;
|
|
|
|
if (!data)
|
|
return;
|
|
|
|
xf86DrvMsg(scrnIndex, X_INFO, "PanelID returned panel resolution %dx%d\n",
|
|
data->hsize, data->vsize);
|
|
|
|
if (pScrn->monitor->nHsync || pScrn->monitor->nVrefresh)
|
|
return;
|
|
|
|
mode = xf86CVTMode(data->hsize, data->vsize, PANEL_HZ, 1, 0);
|
|
|
|
pScrn->monitor->nHsync = 1;
|
|
pScrn->monitor->hsync[0].lo = 31.5;
|
|
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;
|
|
|
|
xfree(mode);
|
|
}
|
|
|
|
struct vbePanelID *
|
|
VBEReadPanelID(vbeInfoPtr pVbe)
|
|
{
|
|
int RealOff = pVbe->real_mode_base;
|
|
pointer page = pVbe->memory;
|
|
void *tmp = NULL;
|
|
int screen = pVbe->pInt10->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;
|
|
}
|