xenocara/driver/xf86-video-mga/src/mga_esc.c
2008-07-29 20:02:36 +00:00

794 lines
19 KiB
C

/****************************************************************************
* mga_esc.c
*
* ESC call implementation
*
* (C) Matrox Graphics, Inc.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef USEMGAHAL
/* All drivers should typically include these */
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
/* All drivers need this */
#include "compiler.h"
/* Drivers for PCI hardware need this */
#include "xf86PciInfo.h"
/* Drivers that need to access the PCI config space directly need this */
#include "xf86Pci.h"
/* All drivers initialising the SW cursor need this */
#include "mipointer.h"
/* All drivers implementing backing store need this */
#include "mibstore.h"
#include "micmap.h"
#include "xf86DDC.h"
#include "xf86RAC.h"
#include "vbe.h"
#include "fb.h"
#include "dixstruct.h"
#include "mga_reg.h"
#include "mga.h"
#include "mga_macros.h"
/* ESC */
LPMGAMODEINFO pMgaModeInfo[2] = {NULL};
MGAMODEINFO TmpMgaModeInfo[2] = {{0}};
/* ESC Implementation */
static void EscHLeft(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscHRight(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscVUp(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscVDown(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscHLarger(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscHSmaller(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscVTaller(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscVSmaller(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscRefresh(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscRestoreVidParm(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscRead(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscWrite(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscHal(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscTest(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static void EscMerged(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode);
static LPMGAMODEINFO GetModeInfoPtr(ULONG ulScreen);
static void GetVideoParameterStr(LPMGAMODEINFO pModeInfo, char *sResult);
static Bool convertNumber(unsigned long *pulNumber, char *sNumber);
static MGAEscFuncRec FunctionTable[] = {
{"hal", EscHal},
{"test", EscTest},
{"read", EscRead},
{"write", EscWrite},
{"left", EscHLeft},
{"right", EscHRight},
{"down", EscVDown},
{"up", EscVUp},
{"h+", EscHLarger},
{"h-", EscHSmaller},
{"v+", EscVTaller},
{"v-", EscVSmaller},
{"refresh", EscRefresh},
{"undo", EscRestoreVidParm},
{"merged", EscMerged},
{NULL,NULL}
};
void MGAFillDisplayModeStruct(DisplayModePtr pMode, LPMGAMODEINFO pModeInfo)
{
pMode->Clock = pModeInfo->ulPixClock;
pMode->HDisplay = pModeInfo->ulDispWidth;
pMode->HSyncStart = pModeInfo->ulDispWidth
+ pModeInfo->ulHFPorch;
pMode->HSyncEnd = pModeInfo->ulDispWidth
+ pModeInfo->ulHFPorch
+ pModeInfo->ulHSync;
pMode->HTotal = pModeInfo->ulDispWidth
+ pModeInfo->ulHFPorch
+ pModeInfo->ulHSync
+ pModeInfo->ulHBPorch;
pMode->VDisplay = pModeInfo->ulDispHeight;
pMode->VSyncStart = pModeInfo->ulDispHeight
+ pModeInfo->ulVFPorch;
pMode->VSyncEnd = pModeInfo->ulDispHeight
+ pModeInfo->ulVFPorch
+ pModeInfo->ulVSync;
pMode->VTotal = pModeInfo->ulDispHeight
+ pModeInfo->ulVFPorch
+ pModeInfo->ulVSync
+ pModeInfo->ulVBPorch;
pMode->VRefresh = pModeInfo->ulRefreshRate;
}
static LPMGAMODEINFO GetModeInfoPtr(ULONG ulScreen)
{
if ( !TmpMgaModeInfo[ulScreen].ulDispWidth )
{
TmpMgaModeInfo[ulScreen] = *pMgaModeInfo[ulScreen];
}
return &TmpMgaModeInfo[ulScreen];
}
static void GetVideoParameterStr(LPMGAMODEINFO pModeInfo, char *sResult)
{
sprintf(sResult, "%d %d %d %d %d %d %d %d %d %d %d",
pModeInfo->ulDispWidth,
pModeInfo->ulDispHeight,
pModeInfo->ulBpp,
pModeInfo->ulPixClock,
pModeInfo->ulHFPorch,
pModeInfo->ulHSync,
pModeInfo->ulHBPorch,
pModeInfo->ulVFPorch,
pModeInfo->ulVSync,
pModeInfo->ulVBPorch,
pModeInfo->flSignalMode);
}
static float GetVRefresh(LPMGAMODEINFO pModeInfo)
{
ULONG ulHTotal;
ULONG ulVTotal;
ulHTotal =
pModeInfo->ulDispWidth +
pModeInfo->ulHFPorch +
pModeInfo->ulHSync +
pModeInfo->ulHBPorch;
ulVTotal =
pModeInfo->ulDispHeight +
pModeInfo->ulVFPorch +
pModeInfo->ulVSync +
pModeInfo->ulVBPorch;
return ((float)pModeInfo->ulPixClock * 1000.0) / (ulHTotal * ulVTotal);
}
static void EscHal(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMGA = MGAPTR(pScrn);
if(pMGA->HALLoaded)
strcpy(sResult, "YES");
else
strcpy(sResult, "NO");
}
static void EscTest(ScrnInfoPtr pScrn, unsigned long *param, char
*sResult, DisplayModePtr pMode)
{
strcpy(sResult, "YES");
}
static void EscMerged(ScrnInfoPtr pScrn, unsigned long *param, char
*sResult, DisplayModePtr pMode)
{
strcpy(sResult, "YES");
}
static void EscRead(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
ULONG ulSource, ulAddr, ulData;
UCHAR ucIndex;
if ( (param[0] & 0xffff) < 2 )
{
strcpy(sResult, "#error 1");
return;
}
ulSource = param[1] >> 16;
ulAddr = param[1] & 0xffff;
switch( ulSource )
{
case 0:
ulData = INREG(ulAddr);
sprintf(sResult, "MGA[%04X] = 0x%08X", ulAddr, ulData);
break;
case 1:
ucIndex = INREG8(0x3c00);
OUTREG8(0x3c00, (UCHAR)ulAddr);
ulData = (ULONG)INREG8(0x3c0a);
OUTREG8(0x3c00, ucIndex);
sprintf(sResult, "DAC[%02X] = 0x%02X", ulAddr, ulData);
break;
case 2:
ucIndex = INREG8(0x1fd4);
OUTREG8(0x1fd4, (UCHAR)ulAddr);
ulData = (ULONG)INREG8(0x1fd5);
OUTREG8(0x1fd4, ucIndex);
sprintf(sResult, "CRTC[%02X] = 0x%02X", ulAddr, ulData);
break;
case 3:
ucIndex = INREG8(0x1fde);
OUTREG8(0x1fde, (UCHAR)ulAddr);
ulData = (ULONG)INREG8(0x1fdf);
OUTREG8(0x1fde, ucIndex);
sprintf(sResult, "CRTCEXT[%02X] = 0x%02X", ulAddr, ulData);
break;
default:
strcpy(sResult, "ERROR# 2");
break;
}
}
static void EscWrite(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
ULONG ulSource, ulAddr, ulData;
UCHAR ucIndex;
if ( (param[0] & 0xffff) < 3 )
{
strcpy(sResult, "#error 1");
return;
}
ulSource = param[1] >> 16;
ulAddr = param[1] & 0xffff;
ulData = param[2];
switch( ulSource )
{
case 0:
OUTREG(ulAddr, ulData);
strcpy(sResult, "OK");
break;
case 1:
ucIndex = INREG8(0x3c00);
OUTREG8(0x3c00, (UCHAR)ulAddr);
OUTREG8(0x3c0a, (UCHAR)ulData);
OUTREG8(0x3c00, ucIndex);
strcpy(sResult, "OK");
break;
case 2:
ucIndex = INREG8(0x1fd4);
OUTREG8(0x1fd4, (UCHAR)ulAddr);
OUTREG8(0x1fd5, (UCHAR)ulData);
OUTREG8(0x1fd4, ucIndex);
strcpy(sResult, "OK");
break;
case 3:
ucIndex = INREG8(0x1fde);
OUTREG8(0x1fde, (UCHAR)ulAddr);
OUTREG8(0x1fdf, (UCHAR)ulData);
OUTREG8(0x1fde, ucIndex);
strcpy(sResult, "OK");
break;
default:
strcpy(sResult, "ERROR# 2");
break;
}
}
static void EscHLeft(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if (pModeInfo->ulHBPorch > (8 * param[1]) )
{
pModeInfo->ulHBPorch -=8 * param[1];
pModeInfo->ulHFPorch +=8 * param[1];
MGASetMode(pMga->pBoard, pModeInfo);
}
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscHRight(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if (pModeInfo->ulHFPorch > (8 * param[1]) )
{
pModeInfo->ulHFPorch -=8 * param[1];
pModeInfo->ulHBPorch +=8 * param[1];
MGASetMode(pMga->pBoard, pModeInfo);
}
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscVUp(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if (pModeInfo->ulVBPorch > (param[1]) )
{
pModeInfo->ulVBPorch -= param[1];
pModeInfo->ulVFPorch += param[1];
MGASetMode(pMga->pBoard, pModeInfo);
}
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscVDown(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if (pModeInfo->ulVFPorch >= (param[1]) )
{
pModeInfo->ulVFPorch -= param[1];
pModeInfo->ulVBPorch += param[1];
MGASetMode(pMga->pBoard, pModeInfo);
}
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscHLarger(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
float fRefresh, fPixelClock;
ULONG ulStep;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if ((param[0] & 0xffff) > 1)
{
ulStep = param[1] * 8;
}
else
{
ulStep = 8;
}
fRefresh = GetVRefresh(pModeInfo);
fPixelClock = (float)pModeInfo->ulPixClock;
if (pModeInfo->ulHBPorch >= ulStep )
{
pModeInfo->ulHBPorch -= ulStep;
}
else
{
pModeInfo->ulHBPorch = 0;
}
pModeInfo->ulPixClock = (ULONG)( (fRefresh * fPixelClock) / GetVRefresh(pModeInfo));
MGASetMode(pMga->pBoard, pModeInfo);
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscHSmaller(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
float fRefresh, fPixelClock;
ULONG ulStep;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if ((param[0] & 0xffff) > 1)
{
ulStep = param[1] * 8;
}
else
{
ulStep = 8;
}
fRefresh = GetVRefresh(pModeInfo);
fPixelClock = (float)pModeInfo->ulPixClock;
pModeInfo->ulHBPorch += ulStep;
pModeInfo->ulPixClock = (ULONG)( (fRefresh * fPixelClock) / GetVRefresh(pModeInfo));
MGASetMode(pMga->pBoard, pModeInfo);
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscVTaller(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
float fRefresh, fPixelClock;
ULONG ulStep;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if ((param[0] & 0xffff) > 1)
{
ulStep = param[1];
}
else
{
ulStep = 1;
}
fRefresh = GetVRefresh(pModeInfo);
fPixelClock = (float)pModeInfo->ulPixClock;
if (pModeInfo->ulVBPorch >= ulStep )
{
pModeInfo->ulVBPorch -= ulStep;
}
else
{
pModeInfo->ulVBPorch = 0;
}
pModeInfo->ulPixClock = (ULONG)( (fRefresh * fPixelClock) / GetVRefresh(pModeInfo));
MGASetMode(pMga->pBoard, pModeInfo);
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscVSmaller(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
float fRefresh, fPixelClock;
ULONG ulStep;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if ((param[0] & 0xffff) > 1)
{
ulStep = param[1];
}
else
{
ulStep = 1;
}
fRefresh = GetVRefresh(pModeInfo);
fPixelClock = (float)pModeInfo->ulPixClock;
pModeInfo->ulVFPorch += ulStep;
pModeInfo->ulPixClock = (ULONG)( (fRefresh * fPixelClock) / GetVRefresh(pModeInfo));
MGASetMode(pMga->pBoard, pModeInfo);
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscRefresh(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
LPMGAMODEINFO pModeInfo;
float fRefresh, fPixelClock;
pModeInfo = GetModeInfoPtr(param[0] >> 16);
if ( !pMgaModeInfo )
{
strcpy(sResult, "#error 1");
return;
}
if ((param[0] & 0xffff) < 2)
{
strcpy(sResult, "#error 1");
return;
}
fRefresh = GetVRefresh(pModeInfo);
fPixelClock = (float)pModeInfo->ulPixClock;
pModeInfo->ulPixClock = (ULONG)( ((float)param[1] * fPixelClock) / fRefresh);
pModeInfo->ulRefreshRate = param[1];
MGASetMode(pMga->pBoard, pModeInfo);
MGAFillDisplayModeStruct(pMode, pModeInfo);
GetVideoParameterStr(pModeInfo, sResult);
}
static void EscRestoreVidParm(ScrnInfoPtr pScrn, unsigned long *param, char *sResult, DisplayModePtr pMode)
{
MGAPtr pMga = MGAPTR(pScrn);
TmpMgaModeInfo[param[0] >> 16].ulDispWidth = 0;
MGASetMode(pMga->pBoard, pMgaModeInfo[param[0] >> 16]);
MGAFillDisplayModeStruct(pMode, pMgaModeInfo[param[0] >> 16]);
GetVideoParameterStr(pMgaModeInfo[param[0] >> 16], sResult);
}
static Bool convertNumber(unsigned long *pulNumber, char *sNumber)
{
unsigned long i, ulDigit, shiftHex;
Bool bResult = TRUE;
if (sNumber == NULL)
{
return FALSE;
}
/* Convert number */
if ( (sNumber[0] == '0') && (sNumber[1] == 'x') )
{
shiftHex = 0;
*pulNumber = 0;
for (i = strlen(sNumber) - 1; i > 1; i--)
{
if (shiftHex > 28)
{
bResult = FALSE;
break;
}
if ( !isxdigit(sNumber[i]) )
{
bResult = FALSE;
break;
}
ulDigit = toupper(sNumber[i]) - '0';
if (ulDigit > 9)
{
ulDigit -= 7;
}
*pulNumber += ulDigit << shiftHex;
shiftHex += 4;
}
}
else
{
for (i = 0; i < strlen(sNumber); i++)
{
if ( !isdigit(sNumber[i]) )
{
bResult = FALSE;
break;
}
}
*pulNumber = atoi(sNumber);
}
return bResult;
}
static Bool GetEscCommand(char *cmdline, EscCmdStruct *escCmd)
{
unsigned long i, paramIndex, ulHI;
Bool bResult;
char *pParameter, *function;
bResult = TRUE; /* success */
function = strtok(cmdline, " \t\n,");
escCmd->parameters[0] = 0;
if (function)
{
/* Find Screen */
if (function[1] == ':' )
{
escCmd->parameters[0] = (unsigned long)(function[0] - '0') << 16;
strncpy(escCmd->function, function+2, 32);
}
else
{
strncpy(escCmd->function, function, 32);
}
}
else
{
strcpy(escCmd->function, "#ERROR -1");
escCmd->parameters[0] = 0;
return FALSE;
}
paramIndex = 1;
while ( (pParameter = strtok(NULL, " \t\n,")) != NULL )
{
if (paramIndex > 31)
{
/* 32 parameters supported */
break;
}
i = 0;
while(pParameter[i] && pParameter[i] != ':')
{
i++;
}
if ( pParameter[i] )
{
pParameter[i] = '\0';
bResult = convertNumber(&escCmd->parameters[paramIndex], &pParameter[i+1]);
bResult |= convertNumber(&ulHI, pParameter);
escCmd->parameters[paramIndex] &= 0xffff;
escCmd->parameters[paramIndex] += ulHI << 16;
pParameter[i] = ':';
}
else
{
bResult = convertNumber(&escCmd->parameters[paramIndex], pParameter);
}
if (!bResult)
{
break;
}
paramIndex++;
}
escCmd->parameters[0] += paramIndex;
return bResult;
}
void MGAExecuteEscCmd(ScrnInfoPtr pScrn, char *cmdline , char *sResult, DisplayModePtr pMode)
{
int i = 0;
int ulScreen = 0;
MGAPtr pMga = MGAPTR(pScrn);
EscCmdStruct EscCmd;
if (pMga->SecondCrtc)
{
ulScreen = 1;
}
else
{
ulScreen = 0;
}
if (FunctionTable[0].function && GetEscCommand(cmdline, &EscCmd) )
{
i = 0;
while ( FunctionTable[i].function && strcmp(FunctionTable[i].function, EscCmd.function) )
{
i++;
}
if (FunctionTable[i].function)
{
EscCmd.parameters[0] &= 0xffff;
EscCmd.parameters[0] |= ulScreen << 16;
FunctionTable[i].funcptr(pScrn, EscCmd.parameters, sResult, pMode);
}
else
{
strcpy(sResult, "error# -1");
}
}
else
{
strcpy(sResult, "error# -1");
}
}
#else
int mga_foo;
#endif