#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; xpal_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;ipal_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;ipal_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->xcxMemory) \ &&(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->ycyMemory) ) { 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