/******************************Module*Header**********************************\ * * ******************* * * GDI SAMPLE CODE * * ******************* * * Module Name: sync.c * * Content: DrvSynchronize * * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved. \*****************************************************************************/ #include "precomp.h" #include "pxrx.h" /******************************Public*Routine******************************\ * VOID DrvSynchronize * * Synchronize with the GLINT. * * Before letting GDI draw onto our screen DIBs we must synchronize with GLINT. * We do this by hooking HOOK_SYNCHRONIZE when we create a DIV that points to * the screen (or off-screen). GDI then calls DrvSynchronize() before trying * to render to any of these screen DIBs. The advantage is that we can forget * about doing SYNC_WITH_GLINT in the code and have GDI call DrvSynchronize * at the appropriate moment. * \**************************************************************************/ VOID DrvSynchronize( DHPDEV dhpdev, RECTL *prcl) { PDEV* ppdev = (PDEV*) dhpdev; GLINT_DECL; DISPDBG((DBGLVL, "DrvSynchronize called")); // These chips use cached syncs SYNC_IF_CORE_BUSY; } //@@BEGIN_DDKSPLIT #if 0 #if USE_LD_GLINT_FIFO_FUNCTION void loadGlintFIFOrelease( GlintDataPtr glintInfo, ULONG tag, ULONG data ) { /**/ TEMP_MACRO_VARS; LD_GLINT_FIFO_FREE( tag, data ); /*/ static ULONG fifoSpace = 0; ULONG *dst; TEMP_MACRO_VARS; if( fifoSpace < 2 ) { GET_INPUT_FIFO_SPACE( fifoSpace ); if ( GLINT_GAMMA_PRESENT ) { if( space > MAX_GAMMA_FIFO_ENTRIES ) space = MAX_GAMMA_FIFO_ENTRIES; } else { if( space > MAX_P3_FIFO_ENTRIES ) space = MAX_P3_FIFO_ENTRIES; } } dst = (ULONG *) glintInfo->regs.InFIFOInterface; MEMORY_BARRIER(); WRITE_FAST_ULONG( dst, tag ); dst++; MEMORY_BARRIER(); WRITE_FAST_ULONG( dst, data ); /**/ } void loadGlintFIFOdebug( GlintDataPtr glintInfo, ULONG tag, ULONG data ) { TEMP_MACRO_VARS; LD_GLINT_FIFO_DBG( tag, data ) } #if DBG LoadGlintFIFO loadGlintFIFO = loadGlintFIFOdebug; #else LoadGlintFIFO loadGlintFIFO = loadGlintFIFOrelease; #endif // DBG #endif // USE_LD_GLINT_FIFO_FUNCTION #endif // 0 //@@END_DDKSPLIT #if USE_SYNC_FUNCTION void syncWithGlint( PPDEV ppdev, GlintDataPtr glintInfo ) { DWORD gsync; ULONG bmask; TEMP_MACRO_VARS; WAIT_DMA_COMPLETE; // Setting the pxrxDMA->bFlushRequired flag below to false ensures that // the interrupt routine will not try to write to the chip. Without // this check, the Vblank interrupt can attempt to flush outstanding 2D // rendering by writing ContinueNewSub tag and data to the chip. // The problem with this is that the interrupt can occur between the // writes of the tag and data in the code below, and if this happens, // the tag and data becomes out of step and typically results in a hang. // // Note that we have to set a MUTEX otherwise we still get hangs on a // multi-processor system when an interrupt routine can be running // simultaneously on another processor. The MUTEX avoids race conditions. GET_INTR_CMD_BLOCK_MUTEX(&glintInfo->pInterruptCommandBlock->General); glintInfo->pxrxDMA->bFlushRequired = FALSE ; WAIT_GLINT_FIFO(4); LD_GLINT_FIFO(__GlintTagFilterMode, 0x400); LD_GLINT_FIFO(__GlintTagSync, 0); LD_GLINT_FIFO(__GlintTagFilterMode, 0x0); do { WAIT_OUTPUT_FIFO_READY; READ_OUTPUT_FIFO(gsync); DISPDBG((DBGLVL, "SYNC: got 0x%x from output FIFO", gsync)); } while (gsync != __GlintTagSync); glintInfo->bGlintCoreBusy = FALSE; RELEASE_INTR_CMD_BLOCK_MUTEX(&glintInfo->pInterruptCommandBlock->General); } void waitDMAcomplete( PPDEV ppdev, GlintDataPtr glintInfo ) { TEMP_MACRO_VARS; if (ppdev->currentCtxt == glintInfo->ddCtxtId) { SEND_PXRX_DMA_FORCE; } if (!(ppdev->g_GlintBoardStatus & GLINT_DMA_COMPLETE)) { if (ppdev->g_GlintBoardStatus & GLINT_INTR_CONTEXT) { // do any VBLANK wait, wait Q to empty and last DMA to complete PINTERRUPT_CONTROL_BLOCK pBlock = glintInfo->pInterruptCommandBlock; while (pBlock->Control & SUSPEND_DMA_TILL_VBLANK) { NULL; } while (pBlock->frontIndex != pBlock->backIndex) { NULL; } } if ((GET_DMA_COUNT(_temp_volatile_i)) > 0) { do { while (--_temp_volatile_i > 0) { NULL; } } while ((GET_DMA_COUNT(_temp_volatile_i)) > 0); } ppdev->g_GlintBoardStatus |= GLINT_DMA_COMPLETE; } } #endif // USE_SYNC_FUNCTION