You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2287 lines
83 KiB
2287 lines
83 KiB
|
|
|
|
#include "precomp.h"
|
|
|
|
#if PAL_SUPPORT
|
|
|
|
|
|
|
|
void Init3D_Info(PDEV*,PVOID);
|
|
ULONG GetDisplayMode(PDEV* ,PVOID ) ;
|
|
ULONG AccessDevice(PDEV* , PVOID, PVOID ) ;
|
|
ULONG GetConfiguration(PDEV* ,PVOID ) ;
|
|
ULONG WriteRegFnct(PDEV* ,PVOID ) ;
|
|
ULONG ReadRegFnct(PDEV* ,PVOID , PVOID) ;
|
|
void I2CAccess_New(PDEV* ,LPI2CSTRUCT_NEW , LPI2CSTRUCT_NEW ) ;
|
|
BYTE ReverseByte(BYTE ) ;
|
|
WORD Ack(PDEV*, WORD , BOOL ) ;
|
|
void Start(PDEV*, WORD ) ;
|
|
void Stop(PDEV*, WORD ) ;
|
|
void I2CDelay(PDEV*, WORD) ;
|
|
void WriteByteI2C(PDEV*, WORD , BYTE ) ;
|
|
BYTE ReadByteI2C(PDEV*,WORD ) ;
|
|
BOOL DisableOvl(PDEV* ) ;
|
|
ULONG AllocOffscreenMem(PDEV* , PVOID , PVOID) ;
|
|
ULONG DeallocOffscreenMem(PDEV* ) ;
|
|
ULONG AllocOffscreenMem(PDEV* , PVOID , PVOID ) ;
|
|
void WriteVT264Reg(PDEV* , WORD , BYTE , DWORD );
|
|
DWORD ReadVT264Reg(PDEV* , WORD , BYTE ) ;
|
|
void WriteI2CData(PDEV* , WORD , BYTE );
|
|
ULONG ReallocMemory(PDEV* ) ;
|
|
void SetI2CDataDirection(PDEV* , WORD, BOOL ) ;
|
|
void WriteI2CClock(PDEV* , WORD , BYTE ) ;
|
|
VOID DbgExtRegsDump(PDEV* );
|
|
VOID TempFnct(PDEV* );
|
|
VOID DeallocDirectDraw(PDEV* ) ;
|
|
VOID ResetPalindrome(PDEV* ,PDEV* );
|
|
|
|
|
|
|
|
|
|
|
|
REGSBT819INFO RegsBT819[NUM_BT819_REGS] = { /* Register's Name*/
|
|
{ 1, STATUS, 0, 0x7F, 0, 0, 0, 0 }, // 0 - PRES
|
|
{ 1, STATUS, 1, 0xBF, 0, 0, 0, 0 }, // 1 - HLOC
|
|
{ 1, STATUS, 2, 0xDF, 0, 0, 0, 0 }, // 2 - FIELD
|
|
{ 1, STATUS, 3, 0xEF, 0, 0, 0, 0 }, // 3 - NUML
|
|
{ 1, STATUS, 4, 0xF7, 0, 0, 0, 0 }, // 4 - CSEL
|
|
{ 1, STATUS, 6, 0xFD, 0, 0, 0, 0 }, // 5 - LOF
|
|
{ 1, STATUS, 7, 0xFE, 0, 0, 0, 0 }, // 6 - COF
|
|
|
|
{ 1, IFORM, 0, 0x7F, 0, 0, 0, 0 }, // 7 - HACTIVE_I
|
|
{ 2, IFORM, 1, 0x9F, 0, 0, 0, 0 }, // 8 - MUXEL
|
|
{ 2, IFORM, 3, 0xE7, 0, 0, 0, 0 }, // 9 - XTSEL
|
|
{ 2, IFORM, 6, 0xFC, 0, 0, 0, 0 }, // 10 - FORMAT
|
|
|
|
{ 1, TDEC, 0, 0x7F, 0, 0, 0, 0 }, // 11 - DEC_FIELD
|
|
{ 7, TDEC, 1, 0x80, 0, 0, 0, 0 }, // 12 - DEC_RAT
|
|
|
|
{ 10, VDELAY_LO, 0, 0x00, CROP, 0, 0x3F, 0 }, // 13 - VDELAY
|
|
{ 10, VACTIVE_LO, 0, 0x00, CROP, 2, 0xCF, 0 }, // 14 - VACTIVE
|
|
{ 10, HDELAY_LO, 0, 0x00, CROP, 4, 0xF3, 0 }, // 15 - HDELAY
|
|
{ 10, HACTIVE_LO, 0, 0x00, CROP, 6, 0xFC, 0 }, // 16 - HACTIVE
|
|
|
|
{ 16, HSCALE_LO, 0, 0x00, HSCALE_HI, 0, 0x00, 0 }, // 17 - HSCALE
|
|
|
|
{ 8, BRIGHT, 0, 0x00, 0, 0, 0, 0 }, // 18 - BRIGHT
|
|
|
|
{ 1, CONTROL, 0, 0x7F, 0, 0, 0, 0 }, // 19 - LNOTCH
|
|
{ 1, CONTROL, 1, 0xBF, 0, 0, 0, 0 }, // 20 - COMP
|
|
{ 1, CONTROL, 2, 0xDF, 0, 0, 0, 0 }, // 21 - LDEC
|
|
{ 1, CONTROL, 3, 0xEF, 0, 0, 0, 0 }, // 22 - CBSENSE
|
|
{ 1, CONTROL, 4, 0xF7, 0, 0, 0, 0 }, // 23 - INTERP
|
|
{ 9, CONTRAST_LO, 0, 0x00, CONTROL, 5, 0xFB, 0 }, // 24 - CON
|
|
{ 9, SAT_U_LO, 0, 0x00, CONTROL, 6, 0xFD, 0 }, // 25 - SAT_U
|
|
{ 9, SAT_V_LO, 0, 0x00, CONTROL, 7, 0xFE, 0 }, // 26 - SAT_V
|
|
|
|
{ 8, HUE, 0, 0x00, 0, 0, 0, 0 }, // 27 - HUE
|
|
|
|
{ 1, OFORM, 0, 0x7F, 0, 0, 0, 0 }, // 28 - RANGE
|
|
{ 2, OFORM, 1, 0x9F, 0, 0, 0, 0 }, // 29 - RND
|
|
{ 1, OFORM, 3, 0xEF, 0, 0, 0, 0 }, // 30 - FIFO_BURST
|
|
{ 1, OFORM, 4, 0xF7, 0, 0, 0, 0 }, // 31 - CODE
|
|
{ 1, OFORM, 5, 0xFB, 0, 0, 0, 0 }, // 32 - LEN
|
|
{ 1, OFORM, 6, 0xFD, 0, 0, 0, 0 }, // 33 - SPI
|
|
{ 1, OFORM, 7, 0xFE, 0, 0, 0, 0 }, // 34 - FULL
|
|
|
|
{ 1, VSCALE_HI, 0, 0x7F, 0, 0, 0, 0 }, // 35 - LINE
|
|
{ 1, VSCALE_HI, 1, 0xBF, 0, 0, 0, 0 }, // 36 - COMB
|
|
{ 1, VSCALE_HI, 2, 0xDF, 0, 0, 0, 0 }, // 37 - INT
|
|
|
|
{ 13,VSCALE_LO, 0, 0x00, VSCALE_HI, 3, 0xE0, 0 }, // 38 - VSCALE
|
|
|
|
{ 1, VPOLE, 0, 0x7F, 0, 0, 0, 0 }, // 39 - OUTEN
|
|
{ 1, VPOLE, 1, 0xBF, 0, 0, 0, 0 }, // 40 - VALID_PIN
|
|
{ 1, VPOLE, 2, 0xDF, 0, 0, 0, 0 }, // 41 - AFF_PIN
|
|
{ 1, VPOLE, 3, 0xEF, 0, 0, 0, 0 }, // 42 - CBFLAG_PIN
|
|
{ 1, VPOLE, 4, 0xF7, 0, 0, 0, 0 }, // 43 - FIELD_PIN
|
|
{ 1, VPOLE, 5, 0xFB, 0, 0, 0, 0 }, // 44 - ACTIVE_PIN
|
|
{ 1, VPOLE, 6, 0xFD, 0, 0, 0, 0 }, // 45 - HRESET_PIN
|
|
{ 1, VPOLE, 7, 0xFE, 0, 0, 0, 0 }, // 46 - VRESET_PIN
|
|
|
|
{ 4, IDCODE, 0, 0, 0, 0, 0, READONLY }, // 47 - PART_ID
|
|
{ 4, IDCODE, 4, 0, 0, 0, 0, READONLY }, // 48 - PART_REV
|
|
|
|
{ 8, ADELAY, 0, 0x00, 0, 0, 0, 0 }, // 49 - ADELAY
|
|
{ 8, BDELAY, 0, 0x00, 0, 0, 0, 0 }, // 50 - BDELAY
|
|
|
|
|
|
{ 2, ADC, 0, 0x3F, 0, 0, 0, 0 }, // 51 - CLAMP
|
|
{ 1, ADC, 2, 0xDF, 0, 0, 0, 0 }, // 52 - SYNC_T
|
|
{ 1, ADC, 3, 0xEF, 0, 0, 0, 0 }, // 53 - AGC_EN
|
|
{ 1, ADC, 4, 0xF7, 0, 0, 0, 0 }, // 54 - CLK_SLEEP
|
|
{ 1, ADC, 5, 0xFB, 0, 0, 0, 0 }, // 55 - Y_SLEEP
|
|
{ 1, ADC, 6, 0xFD, 0, 0, 0, 0 }, // 56 - C_SLEEP
|
|
|
|
{ 8, SRESET, 0, 0x00, 0, 0, 0, 0 }, // 57 - SRESET
|
|
};
|
|
|
|
|
|
// enable, disable the hardware for video capture, query the maximum width of the capture
|
|
ULONG VideoCaptureFnct(PDEV* ppdev,PVOID pvIn, PVOID pvOut)
|
|
{
|
|
VIDEOCAPTUREDATA * pBiosCapture, *pBiosCaptureOut;
|
|
|
|
VIDEO_CAPTURE VideoCaptureDataIn, VideoCaptureDataOut;
|
|
DWORD ReturnedDataLength ;
|
|
|
|
pBiosCapture= ( VIDEOCAPTUREDATA *)pvIn;
|
|
VideoCaptureDataIn.dwSubFunct= pBiosCapture->dwSubFunc;
|
|
VideoCaptureDataIn.dwCaptureWidth=0;
|
|
VideoCaptureDataIn.dwCaptureMode=pBiosCapture->dwCaptureMode;
|
|
|
|
switch( pBiosCapture->dwSubFunc)
|
|
{
|
|
case 0:
|
|
DISPDBG((DEBUG_ESC_2, "IOCTL_VIDEO_CAPTURE: requested subfunct = ENABLE"));
|
|
break;
|
|
case 1:
|
|
DISPDBG((DEBUG_ESC_2, "IOCTL_VIDEO_CAPTURE: requested subfunct = DISABLE"));
|
|
break;
|
|
case 2:
|
|
DISPDBG((DEBUG_ESC_2, "IOCTL_VIDEO_CAPTURE: requested subfunct = QUERY"));
|
|
DISPDBG((DEBUG_ESC_2, "IOCTL_VIDEO_CAPTURE: requested mode = %d", pBiosCapture->dwCaptureMode));
|
|
break;
|
|
default:
|
|
DISPDBG((DEBUG_ESC_2, "IOCTL_VIDEO_CAPTURE: requested subfunct = Wrong Parameter"));
|
|
}
|
|
|
|
if (!AtiDeviceIoControl(ppdev->hDriver,
|
|
IOCTL_VIDEO_ATI_CAPTURE,
|
|
&VideoCaptureDataIn,
|
|
sizeof(VIDEO_CAPTURE),
|
|
&VideoCaptureDataOut,
|
|
sizeof(VIDEO_CAPTURE),
|
|
&ReturnedDataLength))
|
|
{
|
|
DISPDBG((0, "bInitializeATI - Failed IOCTL_VIDEO_ATI_CAPTURE"));
|
|
return 0; // the CWDDE is require a -1, but in win32 we have the return type ULONG
|
|
}
|
|
DISPDBG((DEBUG_ESC_2, "IOCTL_VIDEO_CAPTURE: maximum capture width returned= %d", VideoCaptureDataOut.dwCaptureWidth));
|
|
pBiosCaptureOut= ( VIDEOCAPTUREDATA *)pvOut;
|
|
if( pBiosCapture->dwSubFunc==2)
|
|
pBiosCaptureOut->dwCaptureWidth=VideoCaptureDataOut.dwCaptureWidth;
|
|
else
|
|
pBiosCaptureOut->dwCaptureWidth=pBiosCapture->dwCaptureWidth;
|
|
|
|
pBiosCaptureOut ->dwSubFunc=pBiosCapture->dwSubFunc;
|
|
pBiosCaptureOut ->dwSize=pBiosCapture->dwSize;
|
|
pBiosCaptureOut ->dwCaptureHeight=pBiosCapture->dwCaptureHeight;
|
|
pBiosCaptureOut ->fccFormat=pBiosCapture->fccFormat;
|
|
pBiosCaptureOut ->dwBitMasks[1]=pBiosCapture->dwBitMasks[1];
|
|
pBiosCaptureOut ->dwBitMasks[2]=pBiosCapture->dwBitMasks[2];
|
|
pBiosCaptureOut ->dwBitMasks[3]=pBiosCapture->dwBitMasks[3];
|
|
pBiosCaptureOut ->dwCaptureMode=pBiosCapture->dwCaptureMode;
|
|
|
|
return 1 ;
|
|
}
|
|
|
|
|
|
// this function is requested for 3D driver init
|
|
void Init3D_Info(PDEV* ppdev,PVOID pvOut)
|
|
{
|
|
PHX2DHWINFO *pphx; /* Pointer to the structure containing info for 3D driver */
|
|
|
|
pphx = (PHX2DHWINFO *) pvOut;
|
|
// initialize the structure
|
|
memset( pvOut, 0, sizeof(PHX2DHWINFO));
|
|
// set size
|
|
pphx->dwSize=sizeof(PHX2DHWINFO);
|
|
// set ASIC type
|
|
pphx->dwChipID=ppdev->iAsic;
|
|
// set the asic revision
|
|
// not implemented for the moment
|
|
// detect if it's GT and set the flag
|
|
if( ppdev->iAsic>=CI_M64_GTA )
|
|
{
|
|
pphx->b3DAvail = TRUE;
|
|
pphx->dwFIFOSize = 32;
|
|
}
|
|
else
|
|
{
|
|
pphx->b3DAvail = FALSE;
|
|
}
|
|
// linear address of the aperture
|
|
pphx->dwVideoBaseAddr=(ULONG)(ppdev->pjScreen);
|
|
// linear address of the registers
|
|
pphx->dwRegisterBaseAddr=(ULONG)(ppdev->pjMmBase);
|
|
// linear address of the offscreen memory start
|
|
pphx->dwOffScreenAddr=((ULONG)(ppdev->pjScreen) +
|
|
((ppdev->cxScreen)*(ppdev->cyScreen)*(ppdev->cBitsPerPel))/8);
|
|
// offscreen size
|
|
pphx->dwOffScreenSize=((ppdev->cyMemory)*ppdev->lDelta) -
|
|
((ppdev->cxScreen)*(ppdev->cyScreen)*(ppdev->cBitsPerPel))/8;
|
|
// RAM size
|
|
pphx->dwTotalRAM= ((ppdev->cyMemory)*ppdev->lDelta) ;
|
|
// screen info
|
|
pphx->dwScreenWidth=ppdev->cxScreen;
|
|
pphx->dwScreenHeight=ppdev->cyScreen;
|
|
pphx->dwScreenPitch=ppdev->cyScreen;
|
|
pphx->dwBpp=ppdev->cBitsPerPel;
|
|
if(pphx->dwBpp==16)
|
|
{
|
|
if(ppdev->flGreen==0x3e00)
|
|
{
|
|
pphx->dwAlphaBitMask=0x8000;
|
|
pphx->dwRedBitMask=0x7c00;
|
|
pphx->dwGreenBitMask=0x03e0;
|
|
pphx->dwBlueBitMask=0x001f;
|
|
}
|
|
else
|
|
{
|
|
pphx->dwAlphaBitMask=0;
|
|
pphx->dwRedBitMask=0xf800;
|
|
pphx->dwGreenBitMask=0x07e0;
|
|
pphx->dwBlueBitMask=0x001f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pphx->dwAlphaBitMask=0;
|
|
pphx->dwRedBitMask=0;
|
|
pphx->dwGreenBitMask=0;
|
|
pphx->dwBlueBitMask=0;
|
|
}
|
|
}
|
|
|
|
// the following functions are requested for palindrome support
|
|
ULONG GetDisplayMode(PDEV* ppdev,PVOID pvOut)
|
|
{
|
|
ULONG RetVal;
|
|
ModeInfo* pModeInfo;
|
|
|
|
pModeInfo=(ModeInfo*)pvOut;
|
|
RetVal=sizeof(ModeInfo);
|
|
|
|
#ifndef DYNAMIC_REZ_AND_COLOUR_CHANGE // palindrome support for on the fly rez and colour depth
|
|
pModeInfo->ScreenWidth= ppdev->cxScreen;
|
|
pModeInfo->ScreenHeight=ppdev->cyScreen;
|
|
#else // these values are used for dynamic resolution and colour depth support
|
|
pModeInfo->ScreenWidth=1280; //ppdev->cxScreen;
|
|
pModeInfo->ScreenHeight=1024; //ppdev->cyScreen;
|
|
#endif
|
|
|
|
//pModeInfo->ScreenColorFormat
|
|
if (ppdev->cBitsPerPel == 4)
|
|
pModeInfo->ScreenColorFormat=ATIConfig_ColorFmt_4_Packed;
|
|
else if (ppdev->cBitsPerPel == 8)
|
|
pModeInfo->ScreenColorFormat=ATIConfig_ColorFmt_8;
|
|
else if (ppdev->cBitsPerPel == 16)
|
|
pModeInfo->ScreenColorFormat=ATIConfig_ColorFmt_RGB565;
|
|
else if (ppdev->cBitsPerPel == 24)
|
|
pModeInfo->ScreenColorFormat=ATIConfig_ColorFmt_RGB888;
|
|
else if (ppdev->cBitsPerPel == 32)
|
|
pModeInfo->ScreenColorFormat=ATIConfig_ColorFmt_aRGB8888;
|
|
else
|
|
pModeInfo->ScreenColorFormat=-1;
|
|
|
|
pModeInfo->DesctopWidth=ppdev->cxScreen;
|
|
pModeInfo->DesctopHeight=ppdev->cyScreen;
|
|
pModeInfo->SystemColorFormat=pModeInfo->ScreenColorFormat;
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
ULONG AccessDevice(PDEV* ppdev,PVOID pvIn, PVOID pvOut)
|
|
{
|
|
ULONG RetVal;
|
|
ACCESSDEVICEDATA* pstrAccessDeviceData;
|
|
DWORD* pstrAccessDeviceDataOut;
|
|
|
|
RetVal=1;
|
|
pstrAccessDeviceDataOut=(DWORD*)pvOut;
|
|
pstrAccessDeviceData=(ACCESSDEVICEDATA*)pvIn;
|
|
|
|
if(pstrAccessDeviceData->dwAccessDeviceCode==ACCESSDEVICECODE_CONNECTOR)
|
|
{
|
|
switch(pstrAccessDeviceData->dwSubFunc)
|
|
{
|
|
case ACCESSDEVICEDATA_SUBFUNC_ALLOC:
|
|
if((ppdev->pal_str.lpOwnerAccessStructConnector)==NULL)
|
|
{ //the device is not allocated
|
|
(ppdev->pal_str.lpOwnerAccessStructConnector)=pstrAccessDeviceData;
|
|
(*pstrAccessDeviceDataOut) = (DWORD)pstrAccessDeviceData;
|
|
}
|
|
else
|
|
{ // the device is allocated to another owner
|
|
(*pstrAccessDeviceDataOut) = (DWORD)(ppdev->pal_str.lpOwnerAccessStructConnector);
|
|
}
|
|
break;
|
|
case ACCESSDEVICEDATA_SUBFUNC_FREE:
|
|
if((ppdev->pal_str.lpOwnerAccessStructConnector)!=NULL)
|
|
{ //the device is allocated
|
|
if((ppdev->pal_str.lpOwnerAccessStructConnector)==pstrAccessDeviceData) //if the owner wants to free the device
|
|
{
|
|
(*pstrAccessDeviceDataOut) = (DWORD)NULL;
|
|
(ppdev->pal_str.lpOwnerAccessStructConnector)=NULL; // no owner at this time
|
|
}
|
|
else
|
|
{ /*
|
|
//other process is the owner, so fail
|
|
(*pstrAccessDeviceDataOut) = (DWORD)pstrAccessDeviceData;
|
|
*/
|
|
// Due to the fact that Palindrome is inconsistent in using the same pointer to ACCESSDEVICE struct
|
|
// for QUERY, ALLOC and FREE, we have to force the dealocation anyway
|
|
(*pstrAccessDeviceDataOut) = (DWORD)NULL;
|
|
(ppdev->pal_str.lpOwnerAccessStructConnector)=NULL; // no owner at this time
|
|
|
|
}
|
|
}
|
|
else
|
|
{ // the device is not allocated , so we can free it anyway
|
|
(*pstrAccessDeviceDataOut) =(DWORD) NULL;
|
|
(ppdev->pal_str.lpOwnerAccessStructConnector)=NULL;
|
|
}
|
|
|
|
break;
|
|
case ACCESSDEVICEDATA_SUBFUNC_QUERY:
|
|
if(( ppdev->pal_str.lpOwnerAccessStructConnector)==NULL) // if the device is free
|
|
{
|
|
(*pstrAccessDeviceDataOut) = (DWORD)NULL;
|
|
}
|
|
else
|
|
{ // if the device is owned already
|
|
(*pstrAccessDeviceDataOut) = (DWORD)(ppdev->pal_str.lpOwnerAccessStructConnector);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
RetVal=0xffffffff;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pstrAccessDeviceData->dwAccessDeviceCode==ACCESSDEVICECODE_OVERLAY)
|
|
{
|
|
switch(pstrAccessDeviceData->dwSubFunc)
|
|
{
|
|
case ACCESSDEVICEDATA_SUBFUNC_ALLOC:
|
|
if((ppdev->pal_str.lpOwnerAccessStructOverlay)==NULL)
|
|
{
|
|
//the device is not allocated by an external client
|
|
// but first verify if DDraw is not using it
|
|
if(ppdev->semph_overlay==0) // = 0 resource free; = 1 in use by DDraw; = 2 in use by Palindrome;
|
|
{
|
|
(ppdev->pal_str.lpOwnerAccessStructOverlay)=pstrAccessDeviceData;
|
|
(*pstrAccessDeviceDataOut) =(DWORD) pstrAccessDeviceData;
|
|
ppdev->semph_overlay=2;
|
|
}
|
|
else
|
|
{
|
|
// the overlay is used by DDraw, so let's try to do this:
|
|
(*pstrAccessDeviceDataOut) =(DWORD)NULL;
|
|
}
|
|
|
|
}
|
|
else
|
|
{ // the device is allocated to another owner
|
|
(*pstrAccessDeviceDataOut) =(DWORD) (ppdev->pal_str.lpOwnerAccessStructOverlay);
|
|
}
|
|
break;
|
|
case ACCESSDEVICEDATA_SUBFUNC_FREE:
|
|
if((ppdev->pal_str.lpOwnerAccessStructOverlay)!=NULL)
|
|
{ //the device is allocated
|
|
if((ppdev->pal_str.lpOwnerAccessStructOverlay)==pstrAccessDeviceData) //if the owner wants to free the device
|
|
{
|
|
(*pstrAccessDeviceDataOut) = (DWORD)NULL;
|
|
(ppdev->pal_str.lpOwnerAccessStructOverlay)=NULL; // no owner at this time
|
|
ppdev->semph_overlay=0;
|
|
}
|
|
else
|
|
{ //other process is the owner, so we are supposed to fail
|
|
// (*pstrAccessDeviceDataOut) = (DWORD)pstrAccessDeviceData;
|
|
|
|
// but due to the fact that the palindrome code it's not consistently using the same pointer to the ACCESSDEVICEDATA structure
|
|
// inside a session of allocation/deallocation, we are failing the owner test so that we will free the overlay anyway if it's used by palindrome
|
|
if(ppdev->semph_overlay==2)
|
|
{
|
|
(*pstrAccessDeviceDataOut) = (DWORD)NULL;
|
|
(ppdev->pal_str.lpOwnerAccessStructOverlay)=NULL; // no owner at this time
|
|
ppdev->semph_overlay=0;
|
|
}
|
|
else // DDraw is using the overlay; very improbable at this moment
|
|
{
|
|
(*pstrAccessDeviceDataOut) = (DWORD)pstrAccessDeviceData;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( (ppdev->semph_overlay==0) || (ppdev->semph_overlay==2)) // = 0 resource free; = 1 in use by DDraw; = 2 in use by Palindrome;
|
|
{
|
|
// the device is not allocated to another process than palindrome, so we can free it anyway
|
|
(*pstrAccessDeviceDataOut) = (DWORD)NULL;
|
|
(ppdev->pal_str.lpOwnerAccessStructOverlay)=NULL;
|
|
}
|
|
else
|
|
{
|
|
// the overlay is used by DDraw, but no external app
|
|
(*pstrAccessDeviceDataOut) = (DWORD)pstrAccessDeviceData;
|
|
(ppdev->pal_str.lpOwnerAccessStructOverlay)=NULL;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case ACCESSDEVICEDATA_SUBFUNC_QUERY:
|
|
if( (ppdev->pal_str.lpOwnerAccessStructOverlay)==NULL) // if the device is free
|
|
{
|
|
//the device is not allocated by an external client
|
|
// but first verify if DDraw is not using it
|
|
if(ppdev->semph_overlay==0) // = 0 resource free; = 1 in use by DDraw; = 2 in use by Palindrome;
|
|
{
|
|
(*pstrAccessDeviceDataOut) =(DWORD) NULL;
|
|
}
|
|
else
|
|
{
|
|
// the overlay is used by DDraw, so let's try to do this (return its own access structure):
|
|
(*pstrAccessDeviceDataOut) =(DWORD)pstrAccessDeviceData;
|
|
}
|
|
|
|
}
|
|
else
|
|
{ // if the device is owned already
|
|
(*pstrAccessDeviceDataOut) = (DWORD)(ppdev->pal_str.lpOwnerAccessStructOverlay);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
RetVal=0xffffffff;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RetVal=0xffffffff;
|
|
}
|
|
}
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
ULONG GetConfiguration(PDEV* ppdev,PVOID pvOut)
|
|
{
|
|
ULONG RetVal;
|
|
ATIConfig* pATIConfig;
|
|
|
|
pATIConfig=( ATIConfig*)pvOut;
|
|
strcpy(pATIConfig->ATISig,"761295520\x0");
|
|
strcpy(pATIConfig->DriverName, "ati\x0\x0\x0\x0\x0\x0");
|
|
pATIConfig->dwMajorVersion=2;
|
|
pATIConfig->dwMinorVersion=1;
|
|
pATIConfig->dwDesktopWidth=ppdev->cxScreen;
|
|
pATIConfig->dwDesktopHeight=ppdev->cyScreen;
|
|
pATIConfig->dwEnginePitch=ppdev->lDelta;
|
|
pATIConfig->dwRealRamAvail=(ppdev->cyMemory)*(ppdev->lDelta);
|
|
pATIConfig->dwBpp=ppdev->cBitsPerPel;
|
|
pATIConfig->dwBoardBpp=ppdev->cBitsPerPel;
|
|
if (ppdev->cBitsPerPel == 4)
|
|
pATIConfig->dwColorFormat=ATIConfig_ColorFmt_4_Packed;
|
|
else if (ppdev->cBitsPerPel == 8)
|
|
pATIConfig->dwColorFormat=ATIConfig_ColorFmt_8;
|
|
else if (ppdev->cBitsPerPel == 16)
|
|
pATIConfig->dwColorFormat=ATIConfig_ColorFmt_RGB555;
|
|
else if (ppdev->cBitsPerPel == 24)
|
|
pATIConfig->dwColorFormat=ATIConfig_ColorFmt_RGB888;
|
|
else if (ppdev->cBitsPerPel == 32)
|
|
pATIConfig->dwColorFormat=ATIConfig_ColorFmt_aRGB8888;
|
|
else
|
|
pATIConfig->dwColorFormat=0xffffffff;
|
|
pATIConfig->dwAlphaBitMask=0;
|
|
pATIConfig->dwConfigBits=0;
|
|
switch(ppdev->iAsic)
|
|
{
|
|
case CI_38800_1:
|
|
pATIConfig->dwBoardType=1;
|
|
break;
|
|
case CI_68800_3:
|
|
case CI_68800_6:
|
|
case CI_68800_AX:
|
|
pATIConfig->dwBoardType=2;
|
|
break;
|
|
case CI_M64_GENERIC:
|
|
pATIConfig->dwBoardType=3;
|
|
break;
|
|
default:
|
|
pATIConfig->dwBoardType=0;
|
|
}
|
|
|
|
switch(ppdev->iAperture)
|
|
{
|
|
case ENGINE_ONLY :
|
|
pATIConfig->dwApertureType=1;
|
|
break;
|
|
case AP_LFB:
|
|
pATIConfig->dwApertureType=3;
|
|
break;
|
|
case AP_VGA_SINGLE:
|
|
case FL_VGA_SPLIT:
|
|
pATIConfig->dwApertureType=2;
|
|
break;
|
|
default:
|
|
pATIConfig->dwApertureType=0;
|
|
}
|
|
|
|
RetVal=sizeof(ATIConfig);
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
ULONG WriteRegFnct(PDEV* ppdev,PVOID pvIn)
|
|
{
|
|
ULONG RetVal;
|
|
DISPDBG( (DEBUG_ESC," reg_block: %u ",((RW_REG_STRUCT*)pvIn)->reg_block ));
|
|
DISPDBG( (DEBUG_ESC," reg_offset: 0x%X ",((RW_REG_STRUCT*)pvIn)->reg_offset ));
|
|
DISPDBG( (DEBUG_ESC," write_data: 0x%lX " ,((RW_REG_STRUCT*)pvIn)->data ));
|
|
|
|
//parameters validation for increase roboustness (limited access to certain registers and certaines fields)
|
|
if( ((((RW_REG_STRUCT*)pvIn)->reg_block)!=0)&&((((RW_REG_STRUCT*)pvIn)->reg_block)!=1) )
|
|
{
|
|
RetVal=ESC_FAILED;
|
|
DISPDBG( (DEBUG_ESC," Write failed: wrong block no."));
|
|
return (RetVal);
|
|
}
|
|
if( ((RW_REG_STRUCT*)pvIn)->reg_offset>255 )
|
|
{
|
|
RetVal=ESC_FAILED;
|
|
DISPDBG( (DEBUG_ESC," Write failed : wrong offsett value"));
|
|
return (RetVal);
|
|
}
|
|
// end of parameters validation
|
|
|
|
//what kind of write?
|
|
if((((RW_REG_STRUCT*)pvIn)->reg_block)==1) //block 1
|
|
{
|
|
if( ( (RW_REG_STRUCT*)pvIn)->reg_offset<0x30 )
|
|
{
|
|
if(ppdev->pal_str.Mode_Switch_flag==TRUE) //if a mode switch intercepts writes to the buffers and use the values stored in ppdev->pal_str
|
|
{
|
|
switch(((RW_REG_STRUCT*)pvIn)->reg_offset)
|
|
{
|
|
DWORD key_clr;
|
|
DWORD key_mask;
|
|
|
|
case 0x4:
|
|
switch(ppdev->cBitsPerPel)
|
|
{
|
|
case 8:
|
|
key_clr=0xFD;
|
|
break;
|
|
case 15:
|
|
key_clr=0x7C1F;
|
|
break;
|
|
case 16:
|
|
key_clr=0xF81F;
|
|
break;
|
|
case 24:
|
|
key_clr=0xFF00FF;
|
|
break;
|
|
case 32:
|
|
key_clr=0xFF00FF; //?
|
|
break;
|
|
}
|
|
WriteVTReg(0x4,key_clr);
|
|
break;
|
|
case 0x5:
|
|
switch(ppdev->cBitsPerPel)
|
|
{
|
|
case 8:
|
|
key_mask=0xFF;
|
|
break;
|
|
case 15:
|
|
key_mask=0xFFFF;
|
|
break;
|
|
case 16:
|
|
key_mask=0xFFFF;
|
|
break;
|
|
case 24:
|
|
key_mask=0xFFFFFF;
|
|
break;
|
|
case 32:
|
|
key_mask=0xFFFFFF; //?
|
|
break;
|
|
}
|
|
WriteVTReg(0x5,key_mask);
|
|
break;
|
|
case 0x20:
|
|
if( ppdev->iAsic>=CI_M64_GTB )
|
|
{
|
|
WriteVTReg(0x20,ppdev->pal_str.Buf0_Offset);
|
|
WriteVTReg(0x22,ppdev->pal_str.Buf0_Offset);
|
|
}
|
|
else
|
|
{
|
|
WriteVTReg(0x20,ppdev->pal_str.Buf0_Offset);
|
|
}
|
|
break;
|
|
case 0x22:
|
|
if ((ppdev->iAsic == CI_M64_VTB)||(ppdev->iAsic >= CI_M64_GTB))
|
|
{
|
|
WriteVTReg(0x22,ppdev->pal_str.Buf0_Offset);
|
|
}
|
|
break;
|
|
case 0xe:
|
|
if ((ppdev->iAsic == CI_M64_VTB)||(ppdev->iAsic >= CI_M64_GTB))
|
|
{
|
|
WriteVTReg(0xe,ppdev->pal_str.Buf0_Offset);
|
|
}
|
|
break;
|
|
case 0x26:
|
|
if ((ppdev->iAsic ==CI_M64_VTA)||(ppdev->iAsic ==CI_M64_GTA))
|
|
{
|
|
WriteVTReg(0x26,ppdev->pal_str.Buf0_Offset);
|
|
}
|
|
break;
|
|
case 0x2B:
|
|
if ((ppdev->iAsic ==CI_M64_VTA)||(ppdev->iAsic ==CI_M64_GTA))
|
|
{
|
|
WriteVTReg(0x2B,ppdev->pal_str.Buf0_Offset);
|
|
}
|
|
break;
|
|
case 0x2C:
|
|
if ((ppdev->iAsic ==CI_M64_VTA)||(ppdev->iAsic ==CI_M64_GTA))
|
|
{
|
|
WriteVTReg(0x2C,ppdev->pal_str.Buf0_Offset);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
WriteVTReg(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WriteVTReg(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
|
|
// bug in Palindrome application for VTB, GTB: the capture is set in CAPTURE_CONFIG for Continuous Even, One Shot , but without setting
|
|
// the ONESHOT_BUF_OFFSET. So I set this reg like CAP_BUF0_OFFSET.
|
|
#define CAP_BUF_BUG
|
|
#ifdef CAP_BUF_BUG
|
|
if ( (((RW_REG_STRUCT*)pvIn)->reg_offset==0x20) && (ppdev->iAsic>=CI_M64_GTB) ) //CAPTURE_BUF0_OFFSET
|
|
{
|
|
//write also the same value for ONESHOT_BUFFER
|
|
WriteVTReg(0x22,((RW_REG_STRUCT*)pvIn)->data);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
#if 1 // start debug statements for registers monitoring
|
|
if(((RW_REG_STRUCT*)pvIn)->reg_offset==0x06)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Write OVERLAY_KEY_CNTL: 0x%lX ",((RW_REG_STRUCT*)pvIn)->data));
|
|
}
|
|
if(((RW_REG_STRUCT*)pvIn)->reg_offset==0x02)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Write OVERLAY_VIDEO_KEY_CLR: 0x%lX ",((RW_REG_STRUCT*)pvIn)->data));
|
|
}
|
|
if(((RW_REG_STRUCT*)pvIn)->reg_offset==0x03)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Write OVERLAY_VIDEO_KEY_MSK: 0x%lX ",((RW_REG_STRUCT*)pvIn)->data));
|
|
}
|
|
if(((RW_REG_STRUCT*)pvIn)->reg_offset==0x04)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Write OVERLAY_GRAPHICS_KEY_CLR: 0x%lX ",((RW_REG_STRUCT*)pvIn)->data));
|
|
}
|
|
if(((RW_REG_STRUCT*)pvIn)->reg_offset==0x05)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Write OVERLAY_GRAPHICS_KEY_MSK: 0x%lX ",((RW_REG_STRUCT*)pvIn)->data));
|
|
}
|
|
|
|
// debug info for buffer offset and pitch
|
|
if(((RW_REG_STRUCT*)pvIn)->reg_offset==0x20)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Write BUFF0_OFFSET: 0x%lX ",((RW_REG_STRUCT*)pvIn)->data));
|
|
}
|
|
if(((RW_REG_STRUCT*)pvIn)->reg_offset==0x23)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Write BUFF0_PITCH: 0x%lX ",((RW_REG_STRUCT*)pvIn)->data));
|
|
}
|
|
#endif // end debug statements
|
|
|
|
}
|
|
else
|
|
{
|
|
RIP(("Protected Register in block 1"));
|
|
}
|
|
}
|
|
else //block 0
|
|
{
|
|
// #define NO_VERIFICATION
|
|
#ifndef NO_VERIFICATION
|
|
// we verify the writings
|
|
switch(((RW_REG_STRUCT*)pvIn)->reg_offset)
|
|
{
|
|
DWORD value;
|
|
case 0x1e:
|
|
MemR32(((RW_REG_STRUCT*)pvIn)->reg_offset,&value);
|
|
value=((value&0x0)|( (((RW_REG_STRUCT*)pvIn)->data)&0xffffffff ));
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset, value);
|
|
break;
|
|
case 0x34:
|
|
if ((ppdev->iAsic ==CI_M64_VTA)||(ppdev->iAsic ==CI_M64_GTA))
|
|
{
|
|
MemR32(((RW_REG_STRUCT*)pvIn)->reg_offset,&value);
|
|
value=((value&0xffffff80)|( (((RW_REG_STRUCT*)pvIn)->data)&0x3d ));
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset, value);
|
|
}
|
|
break;
|
|
case 0x31:
|
|
MemR32(((RW_REG_STRUCT*)pvIn)->reg_offset,&value);
|
|
value=((value&0x80ffbfff)|( (((RW_REG_STRUCT*)pvIn)->data)&0x3f004000 ));
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset, value);
|
|
break;
|
|
case 0x1f:
|
|
// bug in GTA hardware
|
|
if (ppdev->iAsic == CI_M64_GTA)
|
|
{
|
|
DWORD local_value;
|
|
DWORD HTotal;
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemR32(0x0,&HTotal);
|
|
MemW32(0x7,local_value);
|
|
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemW32(0x0,HTotal);
|
|
MemW32(0x7,local_value);
|
|
}
|
|
else
|
|
{
|
|
if (ppdev->iAsic ==CI_M64_VTA)
|
|
{
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
}
|
|
}
|
|
break;
|
|
case 0x28:
|
|
MemR32(((RW_REG_STRUCT*)pvIn)->reg_offset,&value);
|
|
value=((value&0xf7ffffff)|( (((RW_REG_STRUCT*)pvIn)->data)&0x08000000 ));
|
|
// the following line of code is necessary because we cannot allow user code to turn off block1
|
|
// due to the fact that this block is also used by DDraw (for this case anyway we are sharing and arbitrating resources)
|
|
// and more important by MCD OGL; so we only allow to turn on block1.
|
|
value=value | 0x08000000;
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset, value);
|
|
break;
|
|
|
|
#define NO_ACCESS
|
|
#ifdef NO_ACCESS
|
|
case 0x07: // maybe access to this register is not necessary
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
break;
|
|
case 0x24: // maybe access to this register is not necessary
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
break;
|
|
#endif // NO_ACCESS
|
|
|
|
default:
|
|
RetVal=ESC_FAILED;
|
|
RIP(("Protected Register in block 0"));
|
|
DISPDBG( (DEBUG_ESC," Write failed : this register is protected"));
|
|
break;
|
|
}
|
|
#else
|
|
// we don't verify the writings
|
|
{
|
|
// bug in hardware on GTA
|
|
if (((RW_REG_STRUCT*)pvIn)->reg_offset==0x1f)
|
|
{
|
|
DWORD local_value;
|
|
DWORD HTotal;
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemR32(0x0,&HTotal);
|
|
MemW32(0x7,local_value);
|
|
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemW32(0x0,HTotal);
|
|
MemW32(0x7,local_value);
|
|
}
|
|
else
|
|
MemW32(((RW_REG_STRUCT*)pvIn)->reg_offset,((RW_REG_STRUCT*)pvIn)->data);
|
|
|
|
}
|
|
#endif // End NO_VERIFICATION
|
|
}
|
|
RetVal=ESC_OK;
|
|
DISPDBG( (DEBUG_ESC," Write OK"));
|
|
DISPDBG( (DEBUG_ESC," "));
|
|
//DebugBreak() ;
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
ULONG ReadRegFnct(PDEV* ppdev,PVOID pvIn, PVOID pvOut)
|
|
{
|
|
ULONG RetVal;
|
|
DISPDBG( (DEBUG_ESC," reg_block: %u ",((RW_REG_STRUCT*)pvIn)->reg_block ));
|
|
DISPDBG( (DEBUG_ESC," reg_offset: 0x%X ",((RW_REG_STRUCT*)pvIn)->reg_offset ));
|
|
|
|
|
|
//parameters validation
|
|
if( ((((RW_REG_STRUCT*)pvIn)->reg_block)!=0)&&((((RW_REG_STRUCT*)pvIn)->reg_block)!=1) )
|
|
{
|
|
RetVal=ESC_FAILED;
|
|
DISPDBG( (DEBUG_ESC," Write failed: wrong block no."));
|
|
return (RetVal);
|
|
}
|
|
if( ((RW_REG_STRUCT*)pvIn)->reg_offset>255 )
|
|
{
|
|
RetVal=ESC_FAILED;
|
|
DISPDBG( (DEBUG_ESC," Write failed: wrong offset."));
|
|
return (RetVal);
|
|
}
|
|
// end of parameters validation
|
|
//what kind of read?
|
|
if((((RW_REG_STRUCT*)pvIn)->reg_block)==1)
|
|
{
|
|
ReadVTReg(((RW_REG_STRUCT*)pvIn)->reg_offset,(DWORD*)pvOut);
|
|
}
|
|
else
|
|
{
|
|
MemR32(((RW_REG_STRUCT*)pvIn)->reg_offset,(DWORD*)pvOut);
|
|
}
|
|
|
|
RetVal=ESC_OK;
|
|
DISPDBG( (DEBUG_ESC," read_data: 0x%lX " , *((DWORD*)pvOut) ));
|
|
DISPDBG( (DEBUG_ESC,"Read OK."));
|
|
DISPDBG( (DEBUG_ESC," "));
|
|
//DebugBreak() ;
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
|
|
/*^^*
|
|
* Function: I2CAccess
|
|
*
|
|
* Purpose: To complete an I2C packet.
|
|
*
|
|
* Inputs: str: LPI2CSTRUCT
|
|
*
|
|
* Outputs: void.
|
|
*^^*/
|
|
void I2CAccess_New(PDEV* ppdev,LPI2CSTRUCT_NEW str,LPI2CSTRUCT_NEW str_out)
|
|
{
|
|
unsigned char i = 0;
|
|
|
|
str_out->wError = 0;
|
|
/*
|
|
* Implement WRITE request
|
|
*/
|
|
if (str->wWriteCount) {
|
|
Start(ppdev, str->wCard);
|
|
|
|
// Write Chip Address (for WRITE)
|
|
WriteByteI2C(ppdev, str->wCard, (BYTE)(str->wChipID & 0xfe));
|
|
// Acc the previous write...
|
|
if (!Ack(ppdev, str->wCard, FALSE)) str_out->wError |= I2C_ACK_WR_ERROR;
|
|
|
|
for (i = 0;i < str->wWriteCount;i++) {
|
|
// Write the required data
|
|
WriteByteI2C(ppdev, str->wCard, str->lpWrData[i]);
|
|
// Acc the previous write...
|
|
if (!Ack(ppdev, str->wCard, FALSE)) str_out->wError |= I2C_ACK_WR_ERROR;
|
|
}
|
|
Stop(ppdev, str->wCard);
|
|
}
|
|
/*
|
|
* Implement READ request
|
|
*/
|
|
if (str->wReadCount) {
|
|
Start(ppdev, str->wCard);
|
|
|
|
// Write Chip Address (for READ)
|
|
WriteByteI2C(ppdev, str->wCard, (BYTE)(str->wChipID & 0xfe | 0x01));
|
|
|
|
//!! Can't do an Ack here with ATI hardware.
|
|
//!! SIS claims that they always do one. Don't
|
|
//!! know why there would be a difference.
|
|
if (!Ack(ppdev, str->wCard, FALSE)) str_out->wError |= I2C_ACK_RD_ERROR;
|
|
|
|
for (i = 0;i < str->wReadCount;i++) {
|
|
// Read the required data
|
|
if (i) Ack(ppdev, str->wCard, TRUE);
|
|
str_out->lpRdData[i] = ReadByteI2C(ppdev, str->wCard);
|
|
}
|
|
Stop(ppdev, str->wCard);
|
|
}
|
|
|
|
DISPDBG( (DEBUG_ESC_I2C," PAL : I2C Access"));
|
|
DISPDBG( (DEBUG_ESC_I2C," Card no: 0x%X " , str->wCard ));
|
|
DISPDBG( (DEBUG_ESC_I2C," Chip ID: 0x%X " , str->wChipID ));
|
|
DISPDBG( (DEBUG_ESC_I2C," Error: 0x%X" , str->wError ));
|
|
DISPDBG( (DEBUG_ESC_I2C," Write Count: 0x%X " , str->wWriteCount ));
|
|
DISPDBG( (DEBUG_ESC_I2C," Read Count: 0x%X " , str->wReadCount ));
|
|
for (i = 0;i < str->wWriteCount;i++)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_I2C," WriteData[%u]: 0x%X " , i, str->lpWrData[0] ));
|
|
}
|
|
for (i = 0;i < str->wReadCount;i++)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_I2C," ReadData[%u]: 0x%X " , i, str->lpRdData[0] ));
|
|
}
|
|
|
|
DISPDBG( (DEBUG_ESC_I2C," "));
|
|
//DebugBreak() ;
|
|
}
|
|
// end of I2CAccess_New
|
|
|
|
|
|
////// Functions for I2C support
|
|
|
|
/*^^*
|
|
* Function: ReadI2CData
|
|
*
|
|
* Purpose: To read a bit from the I2C data line.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write to.
|
|
*
|
|
* Outputs: BYTE, the read data bit.
|
|
*^^*/
|
|
BYTE ReadI2CData(PDEV* ppdev, WORD wCard)
|
|
{
|
|
//return (BYTE) ReadVT264Reg(ppdev, wCard,vtf_GEN_GIO2_DATA_IN);
|
|
|
|
if ((ppdev->iAsic == CI_M64_VTA)||(ppdev->iAsic == CI_M64_GTA))
|
|
return (BYTE) ReadVT264Reg(ppdev, wCard,vtf_GEN_GIO2_DATA_IN);
|
|
|
|
if ((ppdev->iAsic == CI_M64_VTB)||(ppdev->iAsic >= CI_M64_GTB))
|
|
return (BYTE) ReadVT264Reg(ppdev, wCard,vtf_GP_IO_4);
|
|
|
|
}
|
|
|
|
|
|
/*^^*
|
|
* Function: ReadAnyReg
|
|
*
|
|
* Purpose: To waste a small amount of time in order to
|
|
* ensure the I2C bus timing.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write to.
|
|
*
|
|
* Outputs: none.
|
|
*^^*/
|
|
void ReadAnyReg(PDEV* ppdev, WORD wCard)
|
|
{
|
|
ReadVT264Reg(ppdev, wCard, vtf_CFG_CHIP_FND_ID);
|
|
}
|
|
|
|
|
|
/*^^*
|
|
* Function: SetI2CDataDirection
|
|
*
|
|
* Purpose: To set the data direction of the I2C
|
|
* controller chip to allow for reads and/or
|
|
* writes to the I2C bus.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write to.
|
|
*
|
|
* Outputs: none.
|
|
*
|
|
* Note: Some chips may allow read and/or writes without
|
|
* any state change. For these chips this should be
|
|
* implemented as a NULL function.
|
|
*^^*/
|
|
void SetI2CDataDirection(PDEV* ppdev, WORD wCard, BOOL fWrite)
|
|
{
|
|
//WriteVT264Reg(ppdev, wCard, vtf_GEN_GIO2_WRITE, fWrite?1:0);
|
|
if ((ppdev->iAsic == CI_M64_VTA)||(ppdev->iAsic == CI_M64_GTA))
|
|
WriteVT264Reg(ppdev, wCard, vtf_GEN_GIO2_WRITE, fWrite?1:0);
|
|
if ((ppdev->iAsic == CI_M64_VTB)||(ppdev->iAsic >= CI_M64_GTB))
|
|
WriteVT264Reg(ppdev, wCard, vtf_GP_IO_DIR_4, fWrite?1:0);
|
|
|
|
}
|
|
|
|
|
|
/*^^*
|
|
* Function: WriteI2CClock
|
|
*
|
|
* Purpose: To set the state of the I2C clock line.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write to.
|
|
* cClock: BYTE, the new clock state.
|
|
*
|
|
* Outputs: none.
|
|
*^^*/
|
|
void WriteI2CClock(PDEV* ppdev, WORD wCard, BYTE cClock)
|
|
{
|
|
//WriteVT264Reg(ppdev, wCard, vtf_DAC_GIO_STATE_1, (DWORD)cClock);
|
|
if ((ppdev->iAsic == CI_M64_VTA)||(ppdev->iAsic == CI_M64_GTA))
|
|
WriteVT264Reg(ppdev, wCard, vtf_DAC_GIO_STATE_1, (DWORD)cClock);
|
|
if ((ppdev->iAsic == CI_M64_VTB)||(ppdev->iAsic >= CI_M64_GTB))
|
|
WriteVT264Reg(ppdev, wCard, vtf_GP_IO_B, (DWORD)cClock);
|
|
}
|
|
|
|
|
|
/*^^*
|
|
* Function: WriteI2CData
|
|
*
|
|
* Purpose: To set the state of the I2C data line.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write to.
|
|
* cDataBit: BYTE, the new data value.
|
|
*
|
|
* Outputs: none.
|
|
*^^*/
|
|
void WriteI2CData(PDEV* ppdev, WORD wCard, BYTE cDataBit)
|
|
{
|
|
//WriteVT264Reg(ppdev, wCard, vtf_GEN_GIO2_DATA_OUT, (DWORD)cDataBit);
|
|
if ((ppdev->iAsic == CI_M64_VTA)||(ppdev->iAsic == CI_M64_GTA))
|
|
WriteVT264Reg(ppdev, wCard, vtf_GEN_GIO2_DATA_OUT, (DWORD)cDataBit);
|
|
if ((ppdev->iAsic == CI_M64_VTB)||(ppdev->iAsic >= CI_M64_GTB))
|
|
WriteVT264Reg(ppdev, wCard, vtf_GP_IO_4, (DWORD)cDataBit);
|
|
|
|
}
|
|
|
|
|
|
/*^^*
|
|
* Function: ReverseByte
|
|
*
|
|
* Purpose: To reverse the bit order of a byte.
|
|
*
|
|
* Inputs: wData: BYTE, The data to be reversed.
|
|
*
|
|
* Outputs: WORD, the reversed word.
|
|
*
|
|
*^^*/
|
|
BYTE ReverseByte(BYTE wData)
|
|
{
|
|
BYTE result = 0;
|
|
BYTE x, y;
|
|
|
|
// x shifts up through all possible bits (8)
|
|
// y shifts down through all possible bits (8)
|
|
// if 'x' bit is set the set 'y' bit.
|
|
for (x=0x01, y=0x80; y; x<<=1, y>>=1) if (wData & x) result |= y;
|
|
|
|
return (result);
|
|
}
|
|
// end of ReverseByte()
|
|
|
|
|
|
/*^^*
|
|
* Function: Ack
|
|
*
|
|
* Purpose: To ask the I2C bus for an acknowledge.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write.
|
|
*
|
|
* Outputs: void.
|
|
*^^*/
|
|
WORD Ack(PDEV* ppdev, WORD wCard, BOOL fPut)
|
|
{
|
|
WORD ack = 0;
|
|
|
|
if (fPut) {
|
|
// Push Ack onto I2C bus
|
|
|
|
// Enable I2C writes
|
|
SetI2CDataDirection(ppdev, wCard, I2C_WRITE);
|
|
// Drive data line low
|
|
WriteI2CData(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive I2C clock line high
|
|
WriteI2CClock(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Write acknowledge from I2C bus
|
|
WriteI2CClock(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
// Disable I2C writes
|
|
SetI2CDataDirection(ppdev, wCard, I2C_READ);
|
|
} else {
|
|
// Receive Ack from I2C bus
|
|
|
|
// Disable I2C writes
|
|
SetI2CDataDirection(ppdev, wCard, I2C_READ);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive I2C clock line high
|
|
WriteI2CClock(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Read acknowledge from I2C bus
|
|
ack = (BYTE) ReadI2CData(ppdev, wCard);
|
|
// Drive I2C clock low
|
|
WriteI2CClock(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
}
|
|
// Clock is LOW
|
|
// Data is tristate
|
|
return (!ack);
|
|
}
|
|
// end of Ack()
|
|
|
|
|
|
/*^^*
|
|
* Function: Start
|
|
*
|
|
* Purpose: To start a transfer on the I2C bus.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write.
|
|
*
|
|
* Outputs: void.
|
|
*^^*/
|
|
void Start(PDEV* ppdev, WORD wCard)
|
|
{
|
|
// Enable I2C writes
|
|
SetI2CDataDirection(ppdev, wCard, I2C_WRITE);
|
|
// Drive data high
|
|
WriteI2CData(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive clock high
|
|
WriteI2CClock(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive data low
|
|
WriteI2CData(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive clock low
|
|
WriteI2CClock(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
|
|
// Clock is LOW
|
|
// Data is LOW
|
|
}
|
|
// end of Start
|
|
|
|
|
|
/*^^*
|
|
* Function: Stop
|
|
*
|
|
* Purpose: To stop a transfer on the I2C bus.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card number to write.
|
|
*
|
|
* Outputs: void.
|
|
*^^*/
|
|
void Stop(PDEV* ppdev, WORD wCard)
|
|
{
|
|
// Enable I2C writes
|
|
SetI2CDataDirection(ppdev, wCard, I2C_WRITE);
|
|
// Drive data low
|
|
WriteI2CData(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive clock high
|
|
WriteI2CClock(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive data high
|
|
WriteI2CData(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Disable I2C writes
|
|
SetI2CDataDirection(ppdev, wCard, I2C_READ);
|
|
|
|
// Clock is HIGH
|
|
// Data is tri-state
|
|
}
|
|
// end of Stop
|
|
|
|
|
|
/*^^*
|
|
* Function: WriteByteI2C
|
|
*
|
|
* Purpose: To write a byte of data to the I2C bus.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD, the card the I2C bus is on.
|
|
* cData: BYTE, the data to write
|
|
*
|
|
* Outputs: void.
|
|
*^^*/
|
|
void WriteByteI2C(PDEV* ppdev, WORD wCard, BYTE cData)
|
|
{
|
|
WORD x;
|
|
|
|
cData = ReverseByte(cData);
|
|
|
|
// Enable I2C writes
|
|
SetI2CDataDirection(ppdev, wCard, I2C_WRITE);
|
|
|
|
for (x=0; x<8; x++, cData>>=1) {
|
|
// Put data bit on I2C bus
|
|
WriteI2CData(ppdev, wCard, (BYTE) (cData&1));
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive I2C clock high
|
|
WriteI2CClock(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Drive I2C clock low
|
|
WriteI2CClock(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
}
|
|
|
|
// Clock is LOW
|
|
// Data is driven (LSB)
|
|
}
|
|
// end of WriteByteI2C
|
|
|
|
|
|
/*^^*
|
|
* Function: ReadByteI2C
|
|
*
|
|
* Purpose: To read a byte of data from the I2C bus.
|
|
*
|
|
* Inputs: none.
|
|
*
|
|
* Outputs: BYTE, the data that was read.
|
|
*^^*/
|
|
BYTE ReadByteI2C(PDEV* ppdev, WORD wCard)
|
|
{
|
|
BYTE cData = 0;
|
|
WORD x;
|
|
|
|
// Disable write on the I2C bus
|
|
SetI2CDataDirection(ppdev, wCard, I2C_READ);
|
|
|
|
for (x=0; x<8; x++) {
|
|
// Drive I2C clock high
|
|
WriteI2CClock(ppdev, wCard, I2C_HIGH);
|
|
I2CDelay(ppdev, wCard);
|
|
// Pull data bit from I2C bus
|
|
cData = (cData << 1) | (BYTE) ReadI2CData(ppdev, wCard);
|
|
// Drive I2C clock low
|
|
WriteI2CClock(ppdev, wCard, I2C_LOW);
|
|
I2CDelay(ppdev, wCard);
|
|
}
|
|
return (cData);
|
|
|
|
// Clock is LOW
|
|
// Data is tri-state
|
|
}
|
|
// end of ReadByteI2C
|
|
|
|
|
|
/*^^*
|
|
* Function: I2CDelay
|
|
*
|
|
* Purpose: To delay the accesses to the I2C bus long enough
|
|
* to ensure the correct timimg.
|
|
*
|
|
* Inputs: PDEV*, wCard: WORD the card to wait on.
|
|
*
|
|
* Outputs: none.
|
|
*^^*/
|
|
void I2CDelay(PDEV* ppdev, WORD wCard)
|
|
{
|
|
BYTE x;
|
|
|
|
// To ensure correct I2C bus timing, read a register a bunch of times.
|
|
for (x=0; x<I2C_TIME_DELAY; x++) ReadAnyReg(ppdev, wCard);
|
|
}
|
|
// end of I2CDelay
|
|
|
|
|
|
////// End functions for I2C support
|
|
|
|
//c code for disable overlay and scaler
|
|
BOOL DisableOvl(PDEV* ppdev)
|
|
{
|
|
HLOCAL pbuff;
|
|
// just for test:
|
|
// ULONG temp;
|
|
int i;
|
|
DWORD value;
|
|
VIDEO_CAPTURE VideoCaptureDataIn, VideoCaptureDataOut;
|
|
DWORD ReturnedDataLength ;
|
|
|
|
|
|
DISPDBG( (DEBUG_ESC_1,"Enter in DisableOverlay"));
|
|
// code for context save (all the regs in block1)
|
|
if(ppdev->pal_str.dos_flag)
|
|
{
|
|
DISPDBG( (DEBUG_ESC_1,"DOS_Flag = TRUE"));
|
|
ppdev->pal_str.dos_flag=FALSE;
|
|
pbuff = AtiAllocMem(LPTR ,FL_ZERO_MEMORY,1072); // 1072 to accomodate also 6 regs from block 0
|
|
|
|
if(pbuff!=NULL)
|
|
{
|
|
ppdev->pal_str.preg=(DWORD*)pbuff;
|
|
for(i=0;i<256;i++)
|
|
{
|
|
ReadVTReg(i,(ppdev->pal_str.preg+i));
|
|
if(i<0x31)
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
//TempFnct(ppdev);
|
|
}
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
// disable capture
|
|
WriteVTReg(TRIG_CNTL,0x0);
|
|
WriteVTReg(CAPTURE_CONFIG, 0x0);
|
|
|
|
// code for overlay and scaler disable
|
|
// fisrt the scaler
|
|
WriteVTReg(SCALER_HEIGHT_WIDTH,0x00010001);
|
|
WriteVTReg(OVERLAY_SCALE_INC, 0x10001000);
|
|
ReadVTReg(OVERLAY_SCALE_CNTL,&value);
|
|
value=value&0x7fffffff;
|
|
WriteVTReg(OVERLAY_SCALE_CNTL,value);
|
|
|
|
// the overlay
|
|
WriteVTReg(OVERLAY_Y_X,0x0);
|
|
WriteVTReg(OVERLAY_Y_X_END,0x00010001);
|
|
|
|
WriteVTReg(OVERLAY_KEY_CNTL,0x00000100);
|
|
WriteVTReg(OVERLAY_SCALE_CNTL,0x0);
|
|
// disable the settings in hardware for videocapture
|
|
VideoCaptureDataIn.dwSubFunct= 0x00000001;
|
|
VideoCaptureDataIn.dwCaptureWidth=0;
|
|
VideoCaptureDataIn.dwCaptureMode=0;
|
|
|
|
if (!AtiDeviceIoControl(ppdev->hDriver,
|
|
IOCTL_VIDEO_ATI_CAPTURE,
|
|
&VideoCaptureDataIn,
|
|
sizeof(VIDEO_CAPTURE),
|
|
&VideoCaptureDataOut,
|
|
sizeof(VIDEO_CAPTURE),
|
|
&ReturnedDataLength))
|
|
{
|
|
DISPDBG((0, "bInitializeATI - Failed IOCTL_VIDEO_ATI_CAPTURE"));
|
|
}
|
|
|
|
// save the content of the few registers used in block 0 by Palindrome
|
|
MemR32(0x1E,(ppdev->pal_str.preg+i));
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg_blk_0 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
i++;
|
|
MemR32(0x28,(ppdev->pal_str.preg+i));
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg_blk_0 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
i++;
|
|
MemR32(0x31,(ppdev->pal_str.preg+i));
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg_blk_0 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
i++;
|
|
|
|
if ((ppdev->iAsic ==CI_M64_VTA)||(ppdev->iAsic ==CI_M64_GTA))
|
|
{
|
|
MemR32(0x1F,(ppdev->pal_str.preg+i));
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg_blk_0 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
i++;
|
|
MemR32(0x34,(ppdev->pal_str.preg+i));
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg_blk_0 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
i++;
|
|
#define EXCLUDE_READ
|
|
#ifndef EXCLUDE_READ
|
|
MemR32(0x07,(ppdev->pal_str.preg+i));
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg_blk_0 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
i++;
|
|
MemR32(0x24,(ppdev->pal_str.preg+i));
|
|
DISPDBG( (DEBUG_ESC_1,"DOS switch: reg_blk_0 0x%X = 0x%Xl ",i,(DWORD)*(ppdev->pal_str.preg+i)));
|
|
#endif
|
|
}
|
|
|
|
//#define TEST_SWITCH_1
|
|
#ifndef TEST_SWITCH_1
|
|
// disable the block 1 of registers
|
|
MemR32(0x28,&value);
|
|
MemW32(0x28,value&0xf7ffffff);
|
|
return TRUE;
|
|
|
|
#else
|
|
value;
|
|
#endif
|
|
}
|
|
|
|
|
|
//code for reinitialization of overlay after a mode switch
|
|
void EnableOvl(PDEV* ppdev)
|
|
{
|
|
|
|
int i;
|
|
DWORD value;
|
|
VIDEO_CAPTURE VideoCaptureDataIn, VideoCaptureDataOut;
|
|
DWORD ReturnedDataLength ;
|
|
|
|
DISPDBG( (DEBUG_ESC_1,"Enter in EnableOverlay"));
|
|
|
|
// enable the settings in hardware for video capture
|
|
VideoCaptureDataIn.dwSubFunct= 0x00000000;
|
|
VideoCaptureDataIn.dwCaptureWidth=0;
|
|
VideoCaptureDataIn.dwCaptureMode=0;
|
|
|
|
if (!AtiDeviceIoControl(ppdev->hDriver,
|
|
IOCTL_VIDEO_ATI_CAPTURE,
|
|
&VideoCaptureDataIn,
|
|
sizeof(VIDEO_CAPTURE),
|
|
&VideoCaptureDataOut,
|
|
sizeof(VIDEO_CAPTURE),
|
|
&ReturnedDataLength))
|
|
{
|
|
DISPDBG((0, "bInitializeATI - Failed IOCTL_VIDEO_ATI_CAPTURE"));
|
|
}
|
|
|
|
//#define TEST_SWITCH
|
|
|
|
#ifndef TEST_SWITCH
|
|
//init the VT regs in block 1 (BUS_CNTL)
|
|
MemR32(0x28,&value);
|
|
value=value|0x08000000;
|
|
MemW32(0x28,value);
|
|
|
|
// initialize some overlay/scaler regs on RAGEIII
|
|
if (ppdev->iAsic>=CI_M64_GTC_UMC)
|
|
{
|
|
WriteVTReg(0x54, 0x101000); //DD_SCALER_COLOUR_CNTL
|
|
WriteVTReg(0x55, 0x2000); //DD_SCALER_H_COEFF0
|
|
WriteVTReg(0x56, 0x0D06200D); //DD_SCALER_H_COEFF1
|
|
WriteVTReg(0x57, 0x0D0A1C0D); //DD_SCALER_H_COEFF2
|
|
WriteVTReg(0x58, 0x0C0E1A0C); //DD_SCALER_H_COEFF3
|
|
WriteVTReg(0x59, 0x0C14140C); //DD_SCALER_H_COEFF4
|
|
}
|
|
|
|
//connect video (GP_IO_CNTL)
|
|
if (ppdev->iAsic == CI_M64_GTA)
|
|
{
|
|
// Hardware bug in GTA: Black screen after writing 0x1f
|
|
DWORD local_value;
|
|
DWORD HTotal;
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemR32(0x0,&HTotal);
|
|
MemW32(0x7,local_value);
|
|
|
|
MemW32(0x1F, 0x0);
|
|
|
|
// for fixing the above hardware bug
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemW32(0x0,HTotal);
|
|
MemW32(0x7,local_value);
|
|
}
|
|
else
|
|
{
|
|
if((ppdev->iAsic==CI_M64_VTA)||(ppdev->iAsic==CI_M64_VTB))
|
|
MemW32(0x1F, 0x0);
|
|
}
|
|
|
|
|
|
// Enable I2C output.
|
|
WriteVT264Reg(ppdev, 0, vtf_GEN_GIO2_EN, 1);
|
|
// Disable DAC feature connector
|
|
WriteVT264Reg(ppdev, 0, vtf_DAC_FEA_CON_EN, 0);
|
|
// Enable I2C clock output pin
|
|
WriteVT264Reg(ppdev,0, vtf_DAC_GIO_DIR_1, 1);
|
|
// Set data direction of I2C bus
|
|
SetI2CDataDirection(ppdev, 0, I2C_READ);
|
|
// Set I2C Clock High
|
|
WriteI2CClock(ppdev, 0, I2C_HIGH);
|
|
I2CDelay(ppdev, 0);
|
|
#else
|
|
i;
|
|
value;
|
|
#endif
|
|
|
|
|
|
#ifndef TEST_SWITCH
|
|
|
|
if(ppdev->pal_str.preg!=NULL)
|
|
{
|
|
for(i=0;i<256;i++)
|
|
{
|
|
if(((i<0x1a)||(i>0x1e))&&(i<0x30))
|
|
{
|
|
// some registers return a different value at read in respect with write
|
|
switch(i)
|
|
{
|
|
DWORD temp;
|
|
case 0x09: //OVERLAY_SCALE_CNTL
|
|
temp= (DWORD)(*(ppdev->pal_str.preg+i))&0xfbffffff;
|
|
WriteVTReg(i,temp);
|
|
break;
|
|
case 0x14: //CAPTURE_CONFIG
|
|
temp=(DWORD)(*(ppdev->pal_str.preg+i))&0xffffffbf;
|
|
WriteVTReg(i,temp);
|
|
break;
|
|
case 0x15: //TRIG_CNTL
|
|
temp= (DWORD)(*(ppdev->pal_str.preg+i))&0xfffffff0;
|
|
WriteVTReg(i,temp);
|
|
break;
|
|
default:
|
|
WriteVTReg(i,(DWORD)(*(ppdev->pal_str.preg+i)));
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
// now restore the content of registers in block 0
|
|
value=(DWORD)(*(ppdev->pal_str.preg+i));
|
|
MemW32(0x1E, value);
|
|
i++;
|
|
MemR32(0x28,&value);
|
|
value=((value&0xf7ffffff)|( (DWORD)(*(ppdev->pal_str.preg+i))&0x08000000 ));
|
|
MemW32(0x28, value);
|
|
i++;
|
|
MemR32(0x31,&value);
|
|
if ((ppdev->iAsic ==CI_M64_VTA)||(ppdev->iAsic ==CI_M64_GTA))
|
|
value=((value&0x80ffbfff)|( (DWORD)(*(ppdev->pal_str.preg+i))&0x3f004000 ));
|
|
else
|
|
value=((value&0xffffbfff)|( (DWORD)(*(ppdev->pal_str.preg+i))&0x00004000 ));
|
|
MemW32(0x31, value);
|
|
i++;
|
|
|
|
if ((ppdev->iAsic ==CI_M64_VTA)||(ppdev->iAsic ==CI_M64_GTA))
|
|
{
|
|
if (ppdev->iAsic == CI_M64_GTA)
|
|
{
|
|
// Hardware bug in GTA: Black screen after writing 0x1f
|
|
DWORD local_value;
|
|
DWORD HTotal;
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemR32(0x0,&HTotal);
|
|
MemW32(0x7,local_value);
|
|
|
|
MemW32(0x1F, *(ppdev->pal_str.preg+i));
|
|
|
|
// for fixing the above hardware bug
|
|
MemR32( 0x7 ,&local_value);
|
|
MemW32(0x7,(local_value&0xffbfffff));
|
|
MemW32(0x0,HTotal);
|
|
MemW32(0x7,local_value);
|
|
}
|
|
else
|
|
{
|
|
MemW32(0x1F, *(ppdev->pal_str.preg+i));
|
|
}
|
|
i++;
|
|
|
|
MemR32(0x34,&value);
|
|
value=((value&0xffffffc2)|( (DWORD)(*(ppdev->pal_str.preg+i))&0x3d ));
|
|
MemW32(0x34, value);
|
|
i++;
|
|
#define EXCLUDE_WRITE
|
|
#ifndef EXCLUDE_WRITE
|
|
MemW32(0x07, *(ppdev->pal_str.preg+i));
|
|
i++;
|
|
MemW32(0x24, *(ppdev->pal_str.preg+i));
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
AtiFreeMem((HLOCAL)ppdev->pal_str.preg) ;
|
|
}
|
|
|
|
|
|
ULONG ReallocMemory(PDEV* ppdev)
|
|
{
|
|
ULONG RetVal;
|
|
OFFSCREEN OffSize; // overlay structure
|
|
OVERLAY_LOCATION Overlay; // pointer in linear memory to the begining of the overlay (top-left)
|
|
int i,j;
|
|
DWORD key_clr;
|
|
DWORD key_mask;
|
|
|
|
RetVal=1;
|
|
j=ppdev->pal_str.alloc_cnt;
|
|
ppdev->pal_str.alloc_cnt =0;
|
|
ppdev->pal_str.no_lines_allocated=0;
|
|
|
|
//set the flag for mode switch
|
|
ppdev->pal_str.Mode_Switch_flag=TRUE;
|
|
|
|
// set the colour key and mask after a mode switch
|
|
switch(ppdev->cBitsPerPel)
|
|
{
|
|
case 8:
|
|
key_clr=0xFD;
|
|
key_mask=0xFF;
|
|
break;
|
|
case 15:
|
|
key_clr=0x7C1F;
|
|
key_mask=0xFFFF;
|
|
break;
|
|
case 16:
|
|
key_clr=0xF81F;
|
|
key_mask=0xFFFF;
|
|
break;
|
|
case 24:
|
|
key_clr=0xFF00FF;
|
|
key_mask=0xFFFFFF;
|
|
break;
|
|
case 32:
|
|
key_clr=0xFF00FF; //?
|
|
key_mask=0xFFFFFF; //?
|
|
break;
|
|
}
|
|
|
|
*(ppdev->pal_str.preg+0x4)=(DWORD)key_clr;
|
|
*(ppdev->pal_str.preg+0x5)=(DWORD)key_mask;
|
|
|
|
for (i=0;i<j; i++)
|
|
{
|
|
OffSize.cx=ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].x_bits ;
|
|
OffSize.cy=ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].y_bits ;
|
|
ppdev->pal_str.Realloc_mem_flag=TRUE;
|
|
RetVal=AllocOffscreenMem(ppdev, &OffSize, &Overlay);
|
|
if(RetVal==ESC_ALLOC_FAIL)
|
|
{
|
|
ppdev->pal_str.alloc_cnt=j;
|
|
RetVal=0;
|
|
return RetVal;
|
|
}
|
|
if(i==0) //update the buffer registers with the new values
|
|
{
|
|
// save the offset value in the ppdev->pal_str
|
|
ppdev->pal_str.Buf0_Offset =(DWORD)(Overlay.app_offset);
|
|
|
|
//set CAPTURE_BUF0_OFFSET
|
|
*(ppdev->pal_str.preg+0x20)=(DWORD)(Overlay.app_offset);
|
|
if ((ppdev->iAsic ==CI_M64_VTB)||(ppdev->iAsic >=CI_M64_GTB))
|
|
{
|
|
//set the SCALER_BUF0_OFFSET
|
|
*(ppdev->pal_str.preg+0x0e)=(DWORD)(Overlay.app_offset);
|
|
//set ONESHOT_BUFF_OFFSET
|
|
*(ppdev->pal_str.preg+0x22)=(DWORD)(Overlay.app_offset);
|
|
}
|
|
else
|
|
{ //GTA or VTA
|
|
*(ppdev->pal_str.preg+0x26)=(DWORD)(Overlay.app_offset);
|
|
*(ppdev->pal_str.preg+0x2B)=(DWORD)(Overlay.app_offset);
|
|
*(ppdev->pal_str.preg+0x2C)=(DWORD)(Overlay.app_offset);
|
|
}
|
|
}
|
|
|
|
#if 0 // for the moment we are not using double buffering at this moment
|
|
if(i==1)
|
|
{
|
|
//set the SCALER_BUF1_OFFSET
|
|
*(ppdev->pal_str.preg+0xe)=(DWORD)(Overlay.app_offset);
|
|
//set CAPTURE_BUF1_OFFSET
|
|
*(ppdev->pal_str.preg+0x21)=(DWORD)(Overlay.app_offset);
|
|
}
|
|
#endif
|
|
}
|
|
RetVal=1;
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
ULONG AllocOffscreenMem(PDEV* ppdev, PVOID pvIn, PVOID pvOut)
|
|
{
|
|
//OFFSCREEN OffSize;
|
|
OFFSCREEN* pOffSize; // pointer to the offscreen area size for overlay structure
|
|
OVERLAY_LOCATION* pOverlay; // pointer in linear memory to the begining of the overlay (top-left)
|
|
LONG x_size;
|
|
LONG y_size;
|
|
LONG x_size_orig; // for history purposes
|
|
LONG y_size_orig; // for history purposes
|
|
LONG x_bits; // for history purposes
|
|
LONG y_bits; // for history purposes
|
|
int temp_alloc_lines_cnt;
|
|
ULONG RetVal;
|
|
|
|
// If LINEAR is defined then we allocate the memory for the buffer as a contiguous zone (no as a rectangle). This will imply
|
|
// that the BUFF PITCH = width of the capture (for rectangle approach the pitch can be equal with the screen pitch)
|
|
#define LINEAR
|
|
|
|
#ifdef LINEAR
|
|
POINTL req;
|
|
#endif
|
|
|
|
DISPDBG( (DEBUG_ESC_2,"PAL : AllocOffscreenMem "));
|
|
//DebugBreak() ;
|
|
|
|
//NEW APPROACH FOR MEM MANAGEMENT
|
|
|
|
// If LINEAR is defined then we allocate the memory for the buffer as a contiguous zone (no as a rectangle). This will imply
|
|
// that the BUFF PITCH = width of the capture (for rectangle approach the pitch can be equal with the screen pitch)
|
|
#ifndef LINEAR
|
|
//allocate memory for the overlay
|
|
pOffSize=(OFFSCREEN*)pvIn;
|
|
//the size is assumed to be in bits
|
|
//we add 64 for alingment provision
|
|
if((ULONG)(pOffSize->cx)<=(ULONG)((ppdev->cxScreen)-64l))
|
|
{
|
|
x_size=(((pOffSize->cx)+63)&(0xfffffffc))/(ppdev->cBitsPerPel);
|
|
}
|
|
else
|
|
{
|
|
//since the maximum width for source is 384 pixels is very improbable that "else" case will be hit
|
|
x_size=(pOffSize->cx)/(ppdev->cBitsPerPel);
|
|
}
|
|
y_size=(pOffSize->cy);
|
|
DISPDBG( (DEBUG_ESC_2," Rectangular allocation : x=%u (RGB pels) y=%u (no of lines)", x_size, y_size));
|
|
|
|
(ppdev->pal_str.poh)=NULL;
|
|
// the following statement is for the new architecture for display driver
|
|
pohAllocate(ppdev, NULL, x_size, y_size, FLOH_MAKE_PERMANENT);
|
|
#else
|
|
// linear allocation
|
|
#if TARGET_BUILD > 351
|
|
// first thing, dealloc Heap allocated by DDraw
|
|
if(ppdev->pohDirectDraw!=NULL)
|
|
{
|
|
pohFree(ppdev, ppdev->pohDirectDraw);
|
|
ppdev->pohDirectDraw = NULL;
|
|
}
|
|
#endif
|
|
pOffSize=(OFFSCREEN*)pvIn;
|
|
//the size is assumed to be in bits of RGB pixels at the current resolution
|
|
//(the palindrome is making the conversion: RGB pixels=UYV pixels*16/ current bpp )
|
|
//x_size=(pOffSize->cx)/(ppdev->cBitsPerPel); // now we have pixels (this was introduced because in the palindrome code we have made width=width*16)
|
|
x_size=(pOffSize->cx);
|
|
y_size=(pOffSize->cy);
|
|
x_size_orig=((pOffSize->cx)*16)/(ppdev->cBitsPerPel);
|
|
y_size_orig=(pOffSize->cy);
|
|
if(ppdev->pal_str.Realloc_mem_flag==TRUE)
|
|
{
|
|
x_bits= (pOffSize->cx);
|
|
y_bits= (pOffSize->cy);
|
|
}
|
|
else
|
|
{
|
|
x_bits=(pOffSize->cx)*(ppdev->cBitsPerPel);
|
|
y_bits= (pOffSize->cy);
|
|
}
|
|
// First we will see if it's a real allocation or , if the x,y_size=0, it's a deallocation of the last surface allocated
|
|
if((x_size==0)||(y_size==0))
|
|
{
|
|
if(ppdev->pal_str.No_mem_allocated_flag==TRUE)
|
|
{
|
|
RetVal=ESC_IS_SUPPORTED;
|
|
// in build 1358 we have problems if we return ESC_ALLOC_FAIL
|
|
//RetVal=ESC_ALLOC_FAIL;
|
|
DISPDBG( (DEBUG_ESC_2,"Offscreen memory deallocation failed: ppdev->pal_str.poh==NULL "));
|
|
DISPDBG( (DEBUG_ESC_2," "));
|
|
return (RetVal);
|
|
}
|
|
if(ppdev->pal_str.poh==NULL)
|
|
{
|
|
RetVal=ESC_IS_SUPPORTED;
|
|
// in build 1358 we have problems if we return ESC_ALLOC_FAIL
|
|
//RetVal=ESC_ALLOC_FAIL;
|
|
DISPDBG( (DEBUG_ESC_2,"Offscreen memory deallocation failed: ppdev->pal_str.poh==NULL "));
|
|
DISPDBG( (DEBUG_ESC_2," "));
|
|
return (RetVal);
|
|
|
|
}
|
|
//Debug info about OH
|
|
DISPDBG( (DEBUG_ESC_2," Memory deallocation (0,0 params) for the surface starting at x=%d, y=%d; width=%d, heigth=%d", ppdev->pal_str.poh->x, \
|
|
ppdev->pal_str.poh->y, ppdev->pal_str.poh->cx, ppdev->pal_str.poh->cy));
|
|
DISPDBG( (DEBUG_ESC_2," Status of allocation:"));
|
|
switch(ppdev->pal_str.poh->ohState)
|
|
{
|
|
case 0:
|
|
DISPDBG( (DEBUG_ESC_2," OH_FREE"));
|
|
break;
|
|
case 1:
|
|
DISPDBG( (DEBUG_ESC_2," OH_DISCARDABLE"));
|
|
break;
|
|
case 2:
|
|
DISPDBG( (DEBUG_ESC_2," OH_PERMANENT"));
|
|
break;
|
|
default:
|
|
DISPDBG( (DEBUG_ESC_2," Unknown status!!"));
|
|
}
|
|
// end debug info
|
|
|
|
// deallocation of the last poh
|
|
pohFree(ppdev,(ppdev->pal_str.poh));
|
|
#ifndef ALLOC_RECT_ANYWHERE
|
|
//decrement the no. of allocated lines with the no. of lines alocated lately
|
|
ppdev->pal_str.no_lines_allocated-=ppdev->pal_str.alloc_hist[(ppdev->pal_str.alloc_cnt)-1].y_lines;
|
|
#endif
|
|
// decrement the allocation counter
|
|
ppdev->pal_str.alloc_cnt--;
|
|
// NULL the pointer to poh
|
|
ppdev->pal_str.poh=NULL;
|
|
// set the overlay_offset to 0
|
|
pOverlay=(OVERLAY_LOCATION*)pvOut;//&overlay_xy;
|
|
pOverlay->app_offset=0L;
|
|
// exit and return OK
|
|
DISPDBG( (DEBUG_ESC_2,"Offscreen memory deallocation OK "));
|
|
DISPDBG( (DEBUG_ESC_2," "));
|
|
RetVal=ESC_IS_SUPPORTED;
|
|
return (RetVal);
|
|
}
|
|
|
|
// compute the total pixels
|
|
if(ppdev->pal_str.Realloc_mem_flag==TRUE)
|
|
{
|
|
// if we are reallocating memory due to mode switch, see how much
|
|
x_size=(x_size*y_size)/(ppdev->cBitsPerPel) +1;
|
|
ppdev->pal_str.Realloc_mem_flag=FALSE;
|
|
}
|
|
else
|
|
{
|
|
x_size=x_size*y_size;
|
|
}
|
|
// how big is y if we'll use as x the total screen width (except in 800x600 in 8bpp, where cxMemory=832 and we have some problems)
|
|
#ifdef BUG_800x600_8BPP
|
|
//800x600 8bpp bug
|
|
if(ppdev->cxMemory==832)
|
|
y_size=(x_size/ppdev->cxScreen)+1;
|
|
else
|
|
#endif
|
|
y_size=(x_size/ppdev->cxMemory)+1;
|
|
|
|
DISPDBG( (DEBUG_ESC_2," Linear allocation: x=%u (total x*y in RGB pixels) y=%u (lines at current resolution)",x_size, y_size));
|
|
|
|
(ppdev->pal_str.poh)=NULL;
|
|
// we want the allocation starting here:
|
|
req.x=0;
|
|
req.y=ppdev->cyScreen + 10 + ppdev->pal_str.no_lines_allocated; //10 lines after the ending of visible screen + no. of lines already allocated before by this fnct.
|
|
DISPDBG( (DEBUG_ESC_2," Visible memory width: x=%u Visible memory height y=%u ",ppdev->cxScreen ,ppdev->cyScreen));
|
|
DISPDBG( (DEBUG_ESC_2," Total Memory width: x=%u Total Memory height y=%u Bpp= %u",ppdev->cxMemory ,ppdev->cyMemory, ppdev->cBitsPerPel));
|
|
DISPDBG( (DEBUG_ESC_2,"Parameters for poh alloc : address x=%u y=%u \n x_dim=%u y_dim=%u ",req.x,req.y,ppdev->cxMemory, y_size));
|
|
// move everything to system memory (this function is absolutely necessary)
|
|
if(!bMoveAllDfbsFromOffscreenToDibs(ppdev))
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2,"bMoveAllDfbsFromOffscreenToDibs failed "));
|
|
}
|
|
//the actual allocation fnct.
|
|
#ifdef BUG_800x600_8BPP
|
|
//800x600 8bpp bug
|
|
if(ppdev->cxMemory==832)
|
|
{
|
|
#ifndef ALLOC_RECT_ANYWHERE
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,&req,ppdev->cxScreen,y_size, FLOH_MAKE_PERMANENT);
|
|
#else
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,NULL,ppdev->cxScreen,y_size, FLOH_MAKE_PERMANENT);
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#ifndef ALLOC_RECT_ANYWHERE
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,&req,ppdev->cxMemory,y_size, FLOH_MAKE_PERMANENT);
|
|
#else
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,NULL,ppdev->cxMemory,y_size, FLOH_MAKE_PERMANENT);
|
|
#endif
|
|
}
|
|
if(ppdev->pal_str.poh==NULL)
|
|
{
|
|
#ifndef ALLOC_RECT_ANYWHERE //jump over loop
|
|
DISPDBG( (DEBUG_ESC_2," Loop for detecting free heap zone"));
|
|
// use a counter for eventually allocated lines
|
|
temp_alloc_lines_cnt=0;
|
|
do
|
|
{
|
|
#ifndef ALLOC_RECT_ANYWHERE
|
|
temp_alloc_lines_cnt++;
|
|
ppdev->pal_str.no_lines_allocated+=1;
|
|
req.y=ppdev->cyScreen + 10 + ppdev->pal_str.no_lines_allocated;
|
|
#endif
|
|
#ifdef BUG_800x600_8BPP
|
|
//800x600 8bpp bug
|
|
if(ppdev->cxMemory==832)
|
|
{
|
|
#ifndef ALLOC_RECT_ANYWHERE
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,&req,ppdev->cxScreen,y_size, FLOH_MAKE_PERMANENT);
|
|
#else
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,NULL,ppdev->cxScreen,y_size, FLOH_MAKE_PERMANENT);
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#ifndef ALLOC_RECT_ANYWHERE
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,&req,ppdev->cxMemory,y_size, FLOH_MAKE_PERMANENT);
|
|
#else
|
|
(ppdev->pal_str.poh)=pohAllocate(ppdev,NULL,ppdev->cxMemory,y_size, FLOH_MAKE_PERMANENT);
|
|
#endif
|
|
}
|
|
}
|
|
while(((ppdev->pal_str.poh)==NULL)&&(req.y<((ppdev->cyMemory)-y_size))) ;
|
|
#endif // jump over loop
|
|
if((req.y>=((ppdev->cyMemory)-y_size)))
|
|
{
|
|
ppdev->pal_str.poh=NULL;
|
|
ppdev->pal_str.no_lines_allocated=ppdev->pal_str.no_lines_allocated - temp_alloc_lines_cnt;
|
|
DISPDBG( (DEBUG_ESC_2," End loop. Not enough space in off-screen memory"));
|
|
}
|
|
else
|
|
DISPDBG( (DEBUG_ESC_2," End loop. The free zone starts at %u line",req.y));
|
|
}
|
|
|
|
#endif
|
|
DISPDBG( (DEBUG_ESC_2," allocation initialy requested (by ESC call): x=%u (in bits) y=%u (in lines)",pOffSize->cx,pOffSize->cy));
|
|
if((ppdev->pal_str.poh)==NULL)
|
|
{
|
|
RetVal=ESC_ALLOC_FAIL;
|
|
//initialize de pointer
|
|
#if 0
|
|
pOverlay=(OVERLAY_LOCATION*)pvOut;
|
|
pOverlay->app_offset= 0L;
|
|
#endif
|
|
DISPDBG( (DEBUG_ESC_2,"Offscreen memory allocation failed "));
|
|
DISPDBG( (DEBUG_ESC_2," "));
|
|
return (RetVal);
|
|
}
|
|
// save info about alloc
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].x=x_size_orig; //ppdev->cxMemory;
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].y=y_size_orig;
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].y_lines=y_size; // no of lines allocated at current memory width
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh=ppdev->pal_str.poh;
|
|
ppdev->pal_str.no_lines_allocated+=y_size; // total no of lines already allocated at this moment
|
|
// two new fields for 4.0 because the colour depth can be changed on the fly, and we need the original dimensions in bits
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].x_bits= x_bits;
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].y_bits= y_bits;
|
|
|
|
//Debug info about OH
|
|
DISPDBG( (DEBUG_ESC_2," Memory allocation for the surface starting at x=%d, y=%d; width=%d, heigth=%d", ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->x, \
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->y, ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->cx, ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->cy));
|
|
DISPDBG( (DEBUG_ESC_2," Status of allocation:"));
|
|
switch(ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->ohState)
|
|
{
|
|
case 0:
|
|
DISPDBG( (DEBUG_ESC_2," OH_FREE"));
|
|
break;
|
|
case 1:
|
|
DISPDBG( (DEBUG_ESC_2," OH_DISCARDABLE"));
|
|
break;
|
|
case 2:
|
|
DISPDBG( (DEBUG_ESC_2," OH_PERMANENT"));
|
|
break;
|
|
default:
|
|
DISPDBG( (DEBUG_ESC_2," Unknown status!!"));
|
|
}
|
|
// end debug info
|
|
// increment the alloc counter
|
|
ppdev->pal_str.alloc_cnt++;
|
|
|
|
//send back the info about where the allocated memory is
|
|
//initialize de pointer
|
|
pOverlay=(OVERLAY_LOCATION*)pvOut;//&overlay_xy;
|
|
//compute the location for the off_screen memory enforcing the alingment at 64 bits
|
|
// I abandoned this approach in the new stream code for the display driver
|
|
pOverlay->app_offset=(ULONG)((ppdev->pal_str.poh->y*ppdev->lDelta) +(ppdev->pal_str.poh->x*ppdev->cjPelSize) ) &(ULONG)(0x0fffffff8);
|
|
DISPDBG( (DEBUG_ESC_2," Memory allocation OK at 0x%lX, no. of lines totally allocated %u", pOverlay->app_offset, ppdev->pal_str.no_lines_allocated));
|
|
DISPDBG( (DEBUG_ESC_2," "));
|
|
RetVal=ESC_IS_SUPPORTED;
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
ULONG DeallocOffscreenMem(PDEV* ppdev)
|
|
{
|
|
ULONG RetVal;
|
|
int i;
|
|
// support for off-screen memory management for PALINDROME
|
|
// function for deallocation of off-screen memory used by the overlay
|
|
//Seems that we don't need to keep a record with the allocated poh because all of them will be erased in bulk
|
|
// {see ddthunk.c in the original palindrome code)
|
|
|
|
|
|
//relase all the allocated off_screen space
|
|
DISPDBG( (DEBUG_ESC_2," Memory deallocation for %u surfaces in offscreen mem", ppdev->pal_str.alloc_cnt));
|
|
DISPDBG( (DEBUG_ESC_2," "));
|
|
|
|
if(ppdev->pal_str.No_mem_allocated_flag==FALSE)
|
|
{
|
|
for(i=0;i<ppdev->pal_str.alloc_cnt; i++ )
|
|
{
|
|
//debug info
|
|
DISPDBG( (DEBUG_ESC_2," Memory deallocation for the surface starting at x=%d, y=%d; width=%d, heigth=%d", ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->x, \
|
|
ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->y, ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->cx, ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->cy));
|
|
DISPDBG( (DEBUG_ESC_2," Status of allocation:"));
|
|
switch(ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->ohState)
|
|
{
|
|
case 0:
|
|
DISPDBG( (DEBUG_ESC_2," OH_FREE"));
|
|
break;
|
|
case 1:
|
|
DISPDBG( (DEBUG_ESC_2," OH_DISCARDABLE"));
|
|
break;
|
|
case 2:
|
|
DISPDBG( (DEBUG_ESC_2," OH_PERMANENT"));
|
|
break;
|
|
default:
|
|
DISPDBG( (DEBUG_ESC_2," Unknown status!!"));
|
|
}
|
|
// end debug info
|
|
// deallocate only if the poh is valid
|
|
if((ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->x>ppdev->cxScreen) &&(ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->x<ppdev->cxMemory) \
|
|
&&(ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->y>ppdev->cyScreen)&&(ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh->y<ppdev->cyMemory) )
|
|
{
|
|
pohFree(ppdev,(ppdev->pal_str.alloc_hist[ppdev->pal_str.alloc_cnt].poh));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG( (DEBUG_ESC_2," Unvalid poh for DeAllocation"));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// reset the flag if it was TRUE
|
|
ppdev->pal_str.No_mem_allocated_flag=FALSE;
|
|
}
|
|
// reset the alloc counter
|
|
ppdev->pal_str.alloc_cnt=0;
|
|
ppdev->pal_str.no_lines_allocated=0;
|
|
ppdev->pal_str.poh=NULL;
|
|
|
|
RetVal=ESC_IS_SUPPORTED;
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
/*^^*
|
|
* Function: WriteVT264Reg
|
|
*
|
|
* Purpose: To write to a VT register.
|
|
*
|
|
* Inputs: PPDEV*, wCard: WORD, the card to write to
|
|
* bField: BYTE, the field to write to.
|
|
* dwData: DWORD, The data to write.
|
|
*
|
|
* Outputs: void.
|
|
*/
|
|
void WriteVT264Reg(PDEV* ppdev, WORD wCard, BYTE bField, DWORD dwData )
|
|
{
|
|
DWORD dwMask;
|
|
DWORD dwRegValue;
|
|
DWORD dwRegOff;
|
|
BYTE bShift;
|
|
|
|
switch(bField) {
|
|
|
|
case vtf_GP_IO_4:
|
|
bShift = 4;
|
|
dwMask = 0xffffffef;
|
|
dwRegOff = 0x1e;
|
|
break;
|
|
|
|
case vtf_GP_IO_DIR_4:
|
|
bShift = 20;
|
|
dwMask = 0xffefffff;
|
|
dwRegOff = 0x1e;
|
|
break;
|
|
|
|
case vtf_GP_IO_7:
|
|
bShift = 7;
|
|
dwMask = 0xffffff7f;
|
|
dwRegOff = 0x1e;
|
|
break;
|
|
|
|
case vtf_GP_IO_B:
|
|
bShift = 11;
|
|
dwMask = 0xfffff7ff;
|
|
dwRegOff = 0x1e;
|
|
break;
|
|
|
|
case vtf_GP_IO_DIR_B:
|
|
bShift = 27;
|
|
dwMask = 0xf7ffffff;
|
|
dwRegOff = 0x1e;
|
|
break;
|
|
|
|
case vtf_GEN_GIO2_DATA_OUT:
|
|
dwMask = 0xfffffffe;
|
|
bShift = 0;
|
|
dwRegOff = 52;
|
|
break;
|
|
|
|
case vtf_GEN_GIO2_WRITE:
|
|
bShift = 5;
|
|
dwMask = 0xffffffdf;
|
|
dwRegOff = 52;
|
|
break;
|
|
|
|
case vtf_GEN_GIO3_DATA_OUT:
|
|
bShift = 2;
|
|
dwMask = 0xfffffffb;
|
|
dwRegOff = 52;
|
|
break;
|
|
|
|
case vtf_GEN_GIO2_EN:
|
|
bShift = 4;
|
|
dwMask = 0xffffffef;
|
|
dwRegOff = 52;
|
|
break;
|
|
|
|
case vtf_DAC_GIO_STATE_1:
|
|
bShift = 24;
|
|
dwMask = 0xfeffffff;
|
|
dwRegOff = 49;
|
|
break;
|
|
|
|
case vtf_DAC_FEA_CON_EN:
|
|
bShift = 14;
|
|
dwMask = 0xffffbfff;
|
|
dwRegOff = 49;
|
|
break;
|
|
|
|
case vtf_DAC_GIO_DIR_1:
|
|
bShift = 27;
|
|
dwMask = 0xf7ffffff;
|
|
dwRegOff = 49;
|
|
break;
|
|
}
|
|
|
|
dwData = dwData << bShift;
|
|
|
|
MemR32(dwRegOff,&dwRegValue);
|
|
|
|
dwRegValue &= dwMask;
|
|
dwRegValue |= dwData;
|
|
|
|
MemW32(dwRegOff,dwRegValue);
|
|
}
|
|
|
|
// end of WriteVT264Reg
|
|
|
|
/*^^*
|
|
* Function: ReadVT264Reg
|
|
*
|
|
* Purpose: To read a register on the VT
|
|
*
|
|
* Inputs: PPDEV*, wCard: WORD, the card to read from.
|
|
* bField: BYTE, the field to read.
|
|
*
|
|
* Outputs: DWORD, the value read.
|
|
*^^*/
|
|
DWORD ReadVT264Reg(PDEV* ppdev, WORD wCard, BYTE bField )
|
|
{
|
|
DWORD dwMask;
|
|
DWORD dwRegOff;
|
|
DWORD dwRegValue;
|
|
DWORD dwFldValue;
|
|
BYTE bShift;
|
|
|
|
switch(bField) {
|
|
case vtf_GEN_GIO2_DATA_IN:
|
|
bShift = 3;
|
|
dwMask = 0x00000008;
|
|
dwRegOff = 52;
|
|
break;
|
|
|
|
case vtf_CFG_CHIP_FND_ID:
|
|
bShift = 27;
|
|
dwMask = 0x38000000;
|
|
dwRegOff = 56;
|
|
break;
|
|
|
|
case vtf_CFG_CHIP_MAJOR:
|
|
bShift = 24;
|
|
dwMask = 0x03000000;
|
|
dwRegOff = 0x38;
|
|
break;
|
|
|
|
case vtf_GP_IO_4:
|
|
bShift = 4;
|
|
dwMask = 0x00000010;
|
|
dwRegOff = 0x1e;
|
|
break;
|
|
|
|
}
|
|
MemR32(dwRegOff,&dwRegValue);
|
|
|
|
dwFldValue = dwRegValue & dwMask;
|
|
dwFldValue = dwFldValue >> bShift;
|
|
|
|
return(dwFldValue);
|
|
}
|
|
// end of ReadVT264Reg
|
|
|
|
|
|
VOID DbgExtRegsDump(PDEV* ppdev)
|
|
{
|
|
DWORD value;
|
|
int i;
|
|
|
|
for(i=0;i<256;i++)
|
|
{
|
|
ReadVTReg(i,&value);
|
|
DISPDBG( (DEBUG_DUMP,"ExtRegs: reg 0x%X = 0x%Xl ",i,value));
|
|
TempFnct(ppdev);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID TempFnct(PDEV* ppdev)
|
|
{
|
|
int i;
|
|
for (i=0;i<800;i++)
|
|
{
|
|
ReadVT264Reg(ppdev, 0, vtf_CFG_CHIP_FND_ID);
|
|
}
|
|
}
|
|
|
|
VOID DeallocDirectDraw(PDEV* ppdev)
|
|
{
|
|
#if TARGET_BUILD > 351
|
|
if(ppdev->pohDirectDraw!=NULL)
|
|
{
|
|
pohFree(ppdev, ppdev->pohDirectDraw);
|
|
ppdev->pohDirectDraw = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID ResetPalindrome(
|
|
PDEV* ppdevOld,
|
|
PDEV* ppdevNew)
|
|
{
|
|
ULONG RetVal;
|
|
|
|
// save the pal structure in the new ppdev
|
|
ppdevNew->pal_str=ppdevOld->pal_str;
|
|
|
|
if((ppdevNew->pal_str.dos_flag==TRUE)&&(ppdevNew->pal_str.Palindrome_flag==TRUE))
|
|
{
|
|
RetVal=0;
|
|
#if 1 // do not disable the following debug statements, they solve a bug
|
|
DISPDBG( (DEBUG_DUMP,"The content of the Extended Registers after DrvResetPDEV"));
|
|
DbgExtRegsDump(ppdevNew);
|
|
#endif
|
|
|
|
#ifdef DYNAMIC_REZ_AND_COLOUR_CHANGE // palindrome support for on the fly rez and colour depth
|
|
#define ALWAYS_REALLOC_MEM //always realloc memory for buffers after mode switch or exiting DOS with ALT+ENTER
|
|
#endif
|
|
|
|
#ifndef ALWAYS_REALLOC_MEM
|
|
//see if we are exiting DOS full screen with ALT+ENTER or is a mode switch
|
|
if((ppdevNew->cBitsPerPel!=ppdevOld->cBitsPerPel)||(ppdevNew->cxScreen!=ppdevOld->cxScreen)||(ppdevNew->cyScreen!=ppdevOld->cyScreen))
|
|
{
|
|
// mode switch
|
|
#if 0 //no more scaler and overlay after a mode switch
|
|
RetVal=ReallocMemory(ppdevNew);
|
|
#endif
|
|
RetVal=0;
|
|
}
|
|
else
|
|
{
|
|
// exit dos full screen mode by ALT+ENTER
|
|
bAssertModeOffscreenHeap(ppdevNew, FALSE);
|
|
DeallocDirectDraw(ppdevNew);
|
|
RetVal=ReallocMemory(ppdevNew);
|
|
}
|
|
#else
|
|
bAssertModeOffscreenHeap(ppdevNew, FALSE); //not necessary
|
|
DeallocDirectDraw(ppdevNew); // not necessary
|
|
RetVal=ReallocMemory(ppdevNew);
|
|
#endif
|
|
|
|
if(RetVal==1)
|
|
{
|
|
vM64QuietDown(ppdevNew, ppdevNew->pjMmBase);
|
|
EnableOvl(ppdevNew);
|
|
ppdevNew->pal_str.dos_flag=FALSE;
|
|
ppdevNew->pal_str.No_mem_allocated_flag=FALSE;
|
|
vM64QuietDown(ppdevNew, ppdevNew->pjMmBase);
|
|
|
|
#if 1
|
|
DISPDBG( (DEBUG_DUMP,"The content of the Extended Registers after DrvResetPDEV"));
|
|
DbgExtRegsDump(ppdevNew);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
ppdevNew->pal_str.Mode_Switch_flag=FALSE;
|
|
ppdevNew->pal_str.dos_flag=FALSE;
|
|
ppdevNew->pal_str.No_mem_allocated_flag=TRUE;
|
|
// disable mem allocation in pal structure
|
|
ppdevNew->pal_str.no_lines_allocated=0;
|
|
ppdevNew->pal_str.alloc_cnt=0;
|
|
ppdevNew->pal_str.poh=NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// end of functions for palindrome support
|
|
|
|
#endif
|