Leaked source code of windows server 2003
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.
 
 
 
 
 
 

599 lines
27 KiB

/******************************Module*Header*******************************\
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !! !!
* !! WARNING: NOT DDK SAMPLE CODE !!
* !! !!
* !! This source code is provided for completeness only and should not be !!
* !! used as sample code for display driver development. Only those sources !!
* !! marked as sample code for a given driver component should be used for !!
* !! development purposes. !!
* !! !!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* Module Name: dma.h
*
* Content: DMA transport definitons and macros
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#ifndef __DMA_H
#define __DMA_H
//-----------------------------------------------------------------------------
//
// DMA/Fifo utility function declarations
//
//-----------------------------------------------------------------------------
// Enables a driver to switch between FIFO/DMA operations
void HWC_SwitchToFIFO( P3_THUNKEDDATA* pThisDisplay, LPGLINTINFO pGLInfo );
void HWC_SwitchToDMA( P3_THUNKEDDATA* pThisDisplay, LPGLINTINFO pGLInfo );
void HWC_AllocDMABuffer(P3_THUNKEDDATA* pThisDisplay);
DWORD WINAPI HWC_StartDMA(P3_THUNKEDDATA* pThisDisplay,
DWORD dwContext,
DWORD dwSize,
DWORD dwPhys,
ULONG_PTR dwVirt,
DWORD dwEvent);
void HWC_GetDXBuffer( P3_THUNKEDDATA*, char*, int );
void HWC_SetDXBuffer( P3_THUNKEDDATA*, char*, int );
void HWC_FlushDXBuffer( P3_THUNKEDDATA* );
//-----------------------------------------------------------------------------
//
// DMA & Fifo common definitions & macros
//
//-----------------------------------------------------------------------------
// Compute the depth of the FIFO depending on if we are a simple
// Permedia3 or if we are going through the Gamma chip of the GVX1
#define FIFO_DEPTH ((ULONG)((TLCHIP_GAMMA) ? 32 : 120))
// Always check the FIFO. Remember that the DMA just loads the FIFO, and even
// if the DMA is empty, there can be tons left in the FIFO.
#define DRAW_ENGINE_BUSY(pThisDisplay) \
( pThisDisplay->pGlint->InFIFOSpace < FIFO_DEPTH )
// We track the fifo space so that we never wait for entries that we don't
// need to. We wait for nEntries + 1 instead of nEntries because of an issue
// in the Gamma chip
#define __WAIT_GLINT_FIFO_SPACE(nEntries) \
{ \
DWORD dwEntries; \
do \
{ \
dwEntries = *inFIFOptr; \
if (dwEntries > 120) dwEntries = 120; \
} while (dwEntries < nEntries + 1); \
}
// Local variables needed on all DX functions that try to use DMA/FIFO
#define P3_DMA_DEFS() \
ULONG * volatile dmaPtr; \
ULONG * volatile inFIFOptr = \
(ULONG *)(&pThisDisplay->pGlint->InFIFOSpace)
// Debug & free versions to get / commit / flush a buffer
#if DBG
#define P3_DMA_GET_BUFFER() \
{ \
HWC_GetDXBuffer( pThisDisplay, __FILE__, __LINE__ ); \
dmaPtr = pThisDisplay->pGLInfo->CurrentBuffer; \
}
#define P3_DMA_COMMIT_BUFFER() \
{ \
pThisDisplay->pGLInfo->CurrentBuffer = dmaPtr; \
HWC_SetDXBuffer( pThisDisplay, __FILE__, __LINE__ ); \
}
#else
#define P3_DMA_GET_BUFFER() \
dmaPtr = pThisDisplay->pGLInfo->CurrentBuffer;
#define P3_DMA_COMMIT_BUFFER() \
{ \
pThisDisplay->pGLInfo->CurrentBuffer = dmaPtr; \
}
#endif // DBG
#define P3_DMA_FLUSH_BUFFER() \
{ \
P3_DMA_COMMIT_BUFFER(); \
HWC_FlushDXBuffer( pThisDisplay ); \
dmaPtr = pThisDisplay->pGLInfo->CurrentBuffer; \
}
#if DBG
#define __SET_FIFO_ENTRIES_LEFT(a) \
do { \
g_pThisTemp = pThisDisplay; \
pThisDisplay->EntriesLeft = (a); \
} while (0)
#define __SET_DMA_ENTRIES_LEFT(a) \
do { \
g_pThisTemp = pThisDisplay; \
pThisDisplay->DMAEntriesLeft = (a); \
} while (0)
#define __RESET_FIFO_ERROR_CHECK g_bDetectedFIFOError = FALSE
#else
#define __SET_FIFO_ENTRIES_LEFT(a)
#define __SET_DMA_ENTRIES_LEFT(a)
#define __RESET_FIFO_ERROR_CHECK
#endif // DBG
#if DBG
// Note the DMAEntriesLeft+=2 compensates for the fact that this macro
// doesn't load a DMA Buffer - it writes to the FIFO directly. That
// means it does need to wait for FIFO space
#define LOAD_GLINT_REG(r, v) \
{ \
DISPDBG(( DBGLVL, "LoadGlintReg: %s 0x%x", #r, v )); \
__SET_DMA_ENTRIES_LEFT(pThisDisplay->DMAEntriesLeft + 2); \
CHECK_FIFO(2); \
MEMORY_BARRIER(); \
pThisDisplay->pGlint->r = v; \
MEMORY_BARRIER(); \
}
// Control registers do not require fifo entries
#define LOAD_GLINT_CTRL_REG(r, v) \
{ \
MEMORY_BARRIER(); \
pThisDisplay->pGlint->r = v; \
MEMORY_BARRIER(); \
}
#else
#define LOAD_GLINT_REG(r, v) \
{ \
MEMORY_BARRIER(); \
pThisDisplay->pGlint->r = v; \
MEMORY_BARRIER(); \
}
#define LOAD_GLINT_CTRL_REG(r, v) \
{ \
MEMORY_BARRIER(); \
pThisDisplay->pGlint->r = v; \
MEMORY_BARRIER(); \
}
#endif
#define READ_GLINT_CTRL_REG(r) (pThisDisplay->pGlint->r)
// We wait for nEntries + 1 instead of nEntries because of a bug in Gamma chip
#define WAIT_GLINT_FIFO(nEntries) \
while((READ_GLINT_CTRL_REG (InFIFOSpace)) < nEntries + 1);
#define READ_OUTPUT_FIFO(d) d = READ_GLINT_CTRL_REG(GPFifo[0])
#define GET_DMA_COUNT(c) c = READ_GLINT_CTRL_REG(DMACount)
#if DBG
#define SET_MAX_ERROR_CHECK_FIFO_SPACE pThisDisplay->EntriesLeft = 120;
#define SET_ERROR_CHECK_FIFO_SPACES(a) pThisDisplay->EntriesLeft = (a);
#else
#define SET_MAX_ERROR_CHECK_FIFO_SPACE
#define SET_ERROR_CHECK_FIFO_SPACES(a)
#endif
//-----------------------------------------------------------------------------
//
// DMA EXCLUSIVE definitions & macros
//
// Below macros are used if we have defined that we want a DMA capable build
//-----------------------------------------------------------------------------
#ifdef WANT_DMA
#define WAIT_FIFO(a) \
do { if(pThisDisplay->pGLInfo->InterfaceType != GLINT_DMA) \
__WAIT_GLINT_FIFO_SPACE(a); \
__SET_FIFO_ENTRIES_LEFT(a); \
__RESET_FIFO_ERROR_CHECK; \
} while (0)
#define __ENSURE_DMA_SPACE(entries) \
{ \
if (pThisDisplay->pGLInfo->InterfaceType != GLINT_NON_DMA) \
{ \
if(((ULONG_PTR)dmaPtr + entries) >= \
(ULONG_PTR)(pThisDisplay->pGLInfo->DMAPartition[pThisDisplay->pGLInfo->CurrentPartition].MaxAddress)) \
{ \
P3_DMA_FLUSH_BUFFER(); \
} \
} \
else \
{ \
pThisDisplay->pGLInfo->CurrentBuffer = (ULONG*)&pThisDisplay->pGlint->GPFifo; \
dmaPtr = pThisDisplay->pGLInfo->CurrentBuffer; \
} \
__SET_DMA_ENTRIES_LEFT(entries); \
__RESET_FIFO_ERROR_CHECK; \
}
#define P3_ENSURE_DX_SPACE(entries) \
{ \
__ENSURE_DMA_SPACE(entries) \
__SET_DMA_ENTRIES_LEFT(entries); \
__RESET_FIFO_ERROR_CHECK; \
}
#if WNT_DDRAW
#define WAIT_DMA_COMPLETE DDWaitDMAComplete(pThisDisplay->ppdev);
#else
extern void Wait_2D_DMA_Complete(P3_THUNKEDDATA* pThisDisplay);
#define PATIENTLY_WAIT_DMA() \
{ \
volatile DWORD count; \
while (GET_DMA_COUNT(count) > 0) \
{ \
if (count < 32) \
count = 1; \
else \
count <<= 1; \
while (--count > 0) NULL; \
} \
}
#define WAIT_DMA_COMPLETE \
{ \
CHECK_ERROR(); \
if (!(pThisDisplay->pGLInfo->GlintBoardStatus & GLINT_DMA_COMPLETE)) { \
if (pThisDisplay->pGLInfo->GlintBoardStatus & GLINT_INTR_CONTEXT) { \
static int retry = 0; \
while (!(pThisDisplay->pGLInfo->GlintBoardStatus & GLINT_DMA_COMPLETE)) \
{ \
LOCKUP(); \
} \
} else { \
if (pThisDisplay->pGLInfo->dwCurrentContext == CONTEXT_DISPLAY_HANDLE) {\
Wait_2D_DMA_Complete(pThisDisplay); \
} \
else { \
PATIENTLY_WAIT_DMA(); \
pThisDisplay->pGLInfo->GlintBoardStatus |= GLINT_DMA_COMPLETE; \
} \
} \
ASSERTDD( READ_GLINT_CTRL_REG(DMACount) == 0, "DMACount not zero after WAIT_DMA_COMPLETE" );\
ASSERTDD((READ_GLINT_CTRL_REG(ByDMAControl) & 3 ) == 0, "Bypass DMA not complete after WAIT_DMA_COMPLETE" );\
} \
else { \
ASSERTDD( READ_GLINT_CTRL_REG(DMACount) == 0, "DMACount not zero despite GLINT_DMA_COMPLETE" );\
ASSERTDD((READ_GLINT_CTRL_REG(ByDMAControl) & 3 ) == 0, "Bypass DMA not complete despite GLINT_DMA_COMPLETE" );\
} \
CHECK_ERROR(); \
}
#endif // WNT_DDRAW
#if WNT_DDRAW
#define SYNC_WITH_GLINT \
vNTSyncWith2DDriver(pThisDisplay->ppdev); \
SET_MAX_ERROR_CHECK_FIFO_SPACE
#else
#define SYNC_WITH_GLINT \
DISPDBG(( DBGLVL, "SYNC_WITH_GLINT" )); \
WAIT_DMA_COMPLETE \
while( pThisDisplay->pGlint->InFIFOSpace < 6 ) /* void */ ; \
SET_ERROR_CHECK_FIFO_SPACES(6); \
LOAD_GLINT_REG(FilterMode, 0x400); \
LOAD_GLINT_REG(Sync, 0); \
LOAD_GLINT_REG(FilterMode, 0x0); \
do { \
while (pThisDisplay->pGlint->OutFIFOWords == 0) /* void */ ; \
} while (pThisDisplay->pGlint->GPFifo[0] != 0x188); \
DISPDBG((DBGLVL,"Sync at line %d in %s", __LINE__, __FILE__)); \
SET_MAX_ERROR_CHECK_FIFO_SPACE
#endif // WNT_DDRAW
//-----------------------------------------------------------------------------
//
// FIFO EXCLUSIVE definitions & macros
//
//-----------------------------------------------------------------------------
#else //!WANT_DMA
#define WAIT_FIFO(a) \
do { \
__WAIT_GLINT_FIFO_SPACE(a); \
__SET_FIFO_ENTRIES_LEFT(a); \
__RESET_FIFO_ERROR_CHECK; \
} while(0)
#define P3_ENSURE_DX_SPACE(entries) \
{ \
dmaPtr = (unsigned long *) (DWORD)pThisDisplay->pGlint->GPFifo; \
P3_DMA_COMMIT_BUFFER(); \
__SET_DMA_ENTRIES_LEFT(entries); \
__RESET_FIFO_ERROR_CHECK; \
}
#define P3_DMA_FLUSH_BUFFER() \
{ \
dmaPtr = (unsigned long *) pThisDisplay->pGlint->GPFifo; \
P3_DMA_COMMIT_BUFFER(); \
}
#define WAIT_DMA_COMPLETE
#define SYNC_WITH_GLINT \
vNTSyncWith2DDriver(pThisDisplay->ppdev); \
SET_MAX_ERROR_CHECK_FIFO_SPACE
#endif // !WANT_DMA
//-----------------------------------------------------------------------------
//
// Win9x specific definitons & macros
//
//-----------------------------------------------------------------------------
#if W95_DDRAW
// wait for DMA to complete (DMACount becomes zero). So as not to kill the
// PCI bus bandwidth for the DMA put in a backoff based on the amount of data
// still left to DMA. Also set the timer going if at any time, the count we
// read is the same as the previous count.
//
#if DBG
#define LOCKUP() \
if(( ++retry & 0xfffff ) == 0 ) \
{ \
DISPDBG(( WRNLVL, "Locked up in WAIT_DMA_COMPLETE" \
" - %d retries", retry )); \
}
#else
#define LOCKUP()
#endif
#endif // W95_DDRAW
//-----------------------------------------------------------------------------
//
// Macros used to send data to the Permedia 3 hardware
//
//-----------------------------------------------------------------------------
#define SEND_P3_DATA(tag,data) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = tag##_Tag; \
MEMORY_BARRIER(); \
dmaPtr[1] = data; \
MEMORY_BARRIER(); \
dmaPtr+=2; \
CHECK_FIFO(2); \
}
#define SEND_P3_DATA_OFFSET(tag,data, i) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = (tag##_Tag + i); \
MEMORY_BARRIER(); \
dmaPtr[1] = data; \
MEMORY_BARRIER(); \
dmaPtr += 2; CHECK_FIFO(2); \
}
#define COPY_P3_DATA(tag,data) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = tag##_Tag; \
MEMORY_BARRIER(); \
dmaPtr[1] = *((unsigned long*) &(data)); \
MEMORY_BARRIER(); \
dmaPtr += 2; \
CHECK_FIFO(2); \
}
#define COPY_P3_DATA_OFFSET(tag,data,i) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = tag##_Tag + i; \
MEMORY_BARRIER(); \
dmaPtr[1] = *((unsigned long*) &(data)); \
MEMORY_BARRIER(); \
dmaPtr += 2; \
CHECK_FIFO(2); \
}
#define P3RX_HOLD_CMD(tag, count) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = ( tag##_Tag | ((count-1) << 16)); \
dmaPtr++; \
CHECK_FIFO(1); \
}
#define P3_DMA_GET_BUFFER_ENTRIES( fifo_count ) \
{ \
P3_DMA_GET_BUFFER(); \
WAIT_FIFO( fifo_count ); \
P3_ENSURE_DX_SPACE((fifo_count)); \
}
#define ADD_FUNNY_DWORD(a) \
{ \
MEMORY_BARRIER(); \
*dmaPtr++ = a; \
MEMORY_BARRIER(); \
CHECK_FIFO(1); \
}
//-----------------------------------------------------------------------------
//
// Setup/Clear discconnect signals
//
// Setting the FIFODiscon register to 1 forces host write retries until
// the data is accepted (might affect other time-critical processes though)
//
//-----------------------------------------------------------------------------
#if DBG
#define NO_FIFO_CHECK pThisDisplay->EntriesLeft = -20000;
#define END_NO_FIFO_CHECK pThisDisplay->EntriesLeft = 0;
#else
#define NO_FIFO_CHECK
#define END_NO_FIFO_CHECK
#endif
#define SET_DISCONNECT_CONTROL(val) \
if(pThisDisplay->pGLInfo->InterfaceType == GLINT_NON_DMA) \
{ \
WAIT_FIFO(1); \
if(pThisDisplay->pGLInfo->dwFlags & GMVF_DELTA) \
{ \
LOAD_GLINT_REG(DeltaDisconnectControl,val); \
} \
else \
{ \
LOAD_GLINT_REG(FIFODiscon,val); \
} \
}
#define TURN_ON_DISCONNECT \
SET_DISCONNECT_CONTROL(0x1) \
NO_FIFO_CHECK
#define TURN_OFF_DISCONNECT \
SET_DISCONNECT_CONTROL(0x0) \
END_NO_FIFO_CHECK
#define SET_D3D_DISCONNECT_CONTROL(val) \
if(pThisDisplay->pGLInfo->InterfaceType == GLINT_NON_DMA) \
{ \
WAIT_FIFO(1); \
if(pThisDisplay->pGLInfo->dwFlags & GMVF_DELTA) \
{ \
LOAD_GLINT_REG(DeltaDisconnectControl,val); \
} \
else \
{ \
LOAD_GLINT_REG(FIFODiscon,val); \
} \
}
#define TURN_ON_D3D_DISCONNECT \
SET_D3D_DISCONNECT_CONTROL(0x1) \
NO_FIFO_CHECK
#define TURN_OFF_D3D_DISCONNECT \
SET_D3D_DISCONNECT_CONTROL(0x0) \
END_NO_FIFO_CHECK
//-----------------------------------------------------------------------------
//
// Macros used to switch the chips hardware context between DDRAW/D3D ops
//
//-----------------------------------------------------------------------------
#define DDRAW_OPERATION(pContext, pThisDisplay) \
{ \
ASSERTDD(pThisDisplay, "Error: pThisDisplay invalid in DDRAW_OPERATION!");\
if (!IS_DXCONTEXT_CURRENT(pThisDisplay)) \
{ \
DXCONTEXT_IMMEDIATE(pThisDisplay); \
if (pThisDisplay->b2D_FIFOS == TRUE) \
{ \
HWC_SwitchToFIFO(pThisDisplay, pThisDisplay->pGLInfo); \
} \
else \
{ \
HWC_SwitchToDMA(pThisDisplay, pThisDisplay->pGLInfo); \
} \
HWC_SwitchToDDRAW(pThisDisplay, TRUE); \
pThisDisplay->pGLInfo->dwDirectXState = DIRECTX_LASTOP_2D; \
} \
else \
{ \
if (pThisDisplay->pGLInfo->dwDirectXState != DIRECTX_LASTOP_2D) \
{ \
if (pThisDisplay->b2D_FIFOS == TRUE) \
{ \
HWC_SwitchToFIFO(pThisDisplay, pThisDisplay->pGLInfo); \
} \
else \
{ \
HWC_SwitchToDMA(pThisDisplay, pThisDisplay->pGLInfo); \
} \
HWC_SwitchToDDRAW(pThisDisplay, FALSE); \
pThisDisplay->pGLInfo->dwDirectXState = DIRECTX_LASTOP_2D; \
} \
} \
}
#define D3D_OPERATION(pContext, pThisDisplay) \
{ \
ASSERTDD(pThisDisplay, "Error: pThisDisplay invalid in D3D_OPERATION!"); \
ASSERTDD(pContext, "Error: pContext invalid in D3D_OPERATION!"); \
if (!IS_DXCONTEXT_CURRENT(pThisDisplay)) \
{ \
DXCONTEXT_IMMEDIATE(pThisDisplay); \
if (pContext->b3D_FIFOS == TRUE) \
{ \
HWC_SwitchToFIFO(pThisDisplay, pThisDisplay->pGLInfo); \
} \
else \
{ \
HWC_SwitchToDMA(pThisDisplay, pThisDisplay->pGLInfo); \
} \
HWC_SwitchToD3D(pContext, pThisDisplay, TRUE); \
pThisDisplay->pGLInfo->dwDirectXState = (ULONG_PTR)pContext; \
} \
else \
{ \
if ((pThisDisplay->pGLInfo->dwDirectXState != (ULONG_PTR)pContext) || \
(pContext->dwDirtyFlags & CONTEXT_DIRTY_RENDER_OFFSETS)) \
{ \
if (pContext->b3D_FIFOS == TRUE) \
{ \
HWC_SwitchToFIFO(pThisDisplay, pThisDisplay->pGLInfo); \
} \
else \
{ \
HWC_SwitchToDMA(pThisDisplay, pThisDisplay->pGLInfo); \
} \
HWC_SwitchToD3D(pContext, pThisDisplay, FALSE); \
pThisDisplay->pGLInfo->dwDirectXState = (ULONG_PTR)pContext; \
} \
} \
}
// Function to update the DDDRAW & D3D Software copy
void HWC_SwitchToDDRAW( P3_THUNKEDDATA* pThisDisplay, BOOL bDXEntry );
void HWC_SwitchToD3D(struct _p3_d3dcontext* pContext,
struct tagThunkedData* pThisDisplay, BOOL bDXEntry);
#endif __DMA_H