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.
 
 
 
 
 
 

534 lines
18 KiB

/******************************Module*Header***********************************\
*
* *******************
* * GDI SAMPLE CODE *
* *******************
*
* Module Name: hwinit.c
*
* This module contains the functions that enable and disable the hardware
*
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
\******************************************************************************/
#include "precomp.h"
#include "gdi.h"
#include "p2ctxt.h"
#include "tvp4020.h"
#include "p2rd.h"
#define ALLOC_TAG ALLOC_TAG_WH2P
//-----------------------------------------------------------------------------
//
// vInitCoreRegisters
//
// set all core Permedia registers to a known state
//
//-----------------------------------------------------------------------------
VOID
vInitCoreRegisters(PPDev ppdev)
{
PERMEDIA_DECL;
PERMEDIA_DEFS(ppdev);
// tracks FBWindowBase for off-screen bitmaps
permediaInfo->PixelOffset = 0;
permediaInfo->TextureAddressMode = __PERMEDIA_ENABLE;
permediaInfo->TextureReadMode = __PERMEDIA_DISABLE;
/*__FX_TEXREADMODE_2048HIGH |
__FX_TEXREADMODE_2048WIDE |
__FX_TEXREADMODE_TWRAP_REPEAT |
__FX_TEXREADMODE_SWRAP_REPEAT |
__PERMEDIA_ENABLE;*/
RESERVEDMAPTR( 41);
SEND_PERMEDIA_DATA(DeltaMode, 0);
SEND_PERMEDIA_DATA(ColorDDAMode, 0);
SEND_PERMEDIA_DATA(ScissorMode, 0);
SEND_PERMEDIA_DATA(TextureColorMode, 0);
SEND_PERMEDIA_DATA(FogMode, 0);
SEND_PERMEDIA_DATA(Window, 0);
SEND_PERMEDIA_DATA(StencilMode, 0);
SEND_PERMEDIA_DATA(DepthMode, 0);
SEND_PERMEDIA_DATA(AlphaBlendMode, 0);
SEND_PERMEDIA_DATA(DitherMode, 0);
SEND_PERMEDIA_DATA(LBReadMode, 0);
SEND_PERMEDIA_DATA(LBWriteMode, 0);
SEND_PERMEDIA_DATA(RasterizerMode, 0);
SEND_PERMEDIA_DATA(WindowOrigin, 0);
SEND_PERMEDIA_DATA(StatisticMode, 0);
SEND_PERMEDIA_DATA(FBSoftwareWriteMask, -1);
SEND_PERMEDIA_DATA(FBHardwareWriteMask, -1);
SEND_PERMEDIA_DATA(FilterMode, 0);
SEND_PERMEDIA_DATA(FBWindowBase, 0);
SEND_PERMEDIA_DATA(FBPixelOffset, 0);
SEND_PERMEDIA_DATA(LogicalOpMode, 0);
SEND_PERMEDIA_DATA(FBReadMode, 0);
SEND_PERMEDIA_DATA(dXDom, 0);
SEND_PERMEDIA_DATA(dXSub, 0);
SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
SEND_PERMEDIA_DATA(TextureAddressMode, 0);
SEND_PERMEDIA_DATA(TextureReadMode, 0);
SEND_PERMEDIA_DATA(TexelLUTMode, 0);
SEND_PERMEDIA_DATA(Texel0, 0);
SEND_PERMEDIA_DATA(YUVMode, 0);
SEND_PERMEDIA_DATA(FBReadPixel, __PERMEDIA_32BITPIXEL); // 32 bit pixels
SEND_PERMEDIA_DATA(SStart, 0);
SEND_PERMEDIA_DATA(dSdx, 1 << 20);
SEND_PERMEDIA_DATA(dSdyDom, 0);
SEND_PERMEDIA_DATA(TStart, 0);
SEND_PERMEDIA_DATA(dTdx, 0);
SEND_PERMEDIA_DATA(dTdyDom, 0);
SEND_PERMEDIA_DATA(TextureDataFormat, __FX_TEXTUREDATAFORMAT_32BIT_RGBA |
__P2_TEXTURE_DATAFORMAT_FLIP);
SEND_PERMEDIA_DATA(TextureColorMode,
(_P2_TEXTURE_COPY << PM_TEXCOLORMODE_APPLICATION)
| __PERMEDIA_ENABLE); // ignored by texture glyph rendering
SEND_PERMEDIA_DATA(TextureAddressMode, permediaInfo->TextureAddressMode);
SEND_PERMEDIA_DATA(TextureReadMode, permediaInfo->TextureReadMode);
COMMITDMAPTR();
FLUSHDMA();
}
//-----------------------------------------------------------------------------
//
// bInitializeHW
//
// Called to load the initial values into the chip. We assume the hardware
// has been mapped. All the relevant stuff should be hanging off ppdev. We
// also sort out all the hardware capabilities etc.
//
//-----------------------------------------------------------------------------
BOOL
bInitializeHW(PPDev ppdev)
{
HwDataPtr permediaInfo;
Surf* psurf;
LONG i, j;
ULONG width;
ULONG ulValue;
BOOL bExists;
ULONG ulLength;
ULONG dmaBufferSize;
PERMEDIA_DEFS(ppdev);
DBG_GDI((7, "bInitializeHW: fbsize: 0x%x", ppdev->FrameBufferLength));
// allocate and initialize ppdev->permediaInfo. We store hardware specific
// stuff in this structure.
//
permediaInfo = (HwDataPtr)
ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(HwDataRec), ALLOC_TAG);
if ( permediaInfo == NULL )
{
DBG_GDI((0, "cannot allocate memory for permediaInfo struct"));
return (FALSE);
}
ppdev->permediaInfo = permediaInfo;
permediaInfo->pGDICtxt = NULL;
permediaInfo->pCurrentCtxt = NULL;
// retrieve the PCI configuration information and local buffer size
ulLength = sizeof(Hw_Device_Info);
if ( EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_QUERY_DEVICE_INFO,
NULL,
0,
(PVOID)&(permediaInfo->deviceInfo),
ulLength,
&ulLength) )
{
DBG_GDI((1, "QUERY_DEVICE_INFO failed."));
return (FALSE);
}
ulLength = sizeof(PINTERRUPT_CONTROL_BLOCK);
if ( EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_MAP_INTERRUPT_CMD_BUF,
NULL,
0,
(PVOID)&pP2dma,
ulLength,
&ulLength) )
{
DBG_GDI((1, "MAP_INTERRUPT_CMD_BUF failed."));
return FALSE;
}
//
// On NT4.0 the above IOCTL_VIDEO_MAP_INTERRUPT_CMD_BUF will fail and
// pP2dma will be NULL. Hence we allocate it via ENGALLOCMEM.
//
if(g_bOnNT40)
{
ASSERTDD(pP2dma == 0, "bInitializeHW: pP2dma != 0");
pP2dma = (P2DMA*) ENGALLOCMEM(FL_ZERO_MEMORY, sizeof(_P2DMA), ALLOC_TAG);
}
// Even if IOCtrl call succeeded,
// the allocation can still fail.
if (pP2dma==NULL)
{
DBG_GDI((0,"allocation of memory for P2DMA from miniport failed"));
return FALSE;
}
// store away shared memory area for later use in ppdev
ppdev->pP2dma=pP2dma;
//@@BEGIN_DDKSPLIT
#if MULTITHREADED && DBG
pP2dma->ppdev = ppdev;
#endif
//@@END_DDKSPLIT
DBG_GDI((7, "deviceInfo: VendorId: 0x%x, DevId %d, DeltaId 0x%x,"
"RevId %d, SubId %d, SubVId %d, lbuf len 0x%x, lbuf width %d",
permediaInfo->deviceInfo.VendorId,
permediaInfo->deviceInfo.DeviceId,
permediaInfo->deviceInfo.DeltaRevId,
permediaInfo->deviceInfo.RevisionId,
permediaInfo->deviceInfo.SubsystemId,
permediaInfo->deviceInfo.SubsystemVendorId,
permediaInfo->deviceInfo.LocalbufferLength,
permediaInfo->deviceInfo.LocalbufferWidth));
// collect flags as we initialize so zero it here
permediaInfo->flags = 0;
// set up default pointers to our low level rendering functions
//
ppdev->pgfnAlphaBlend = vAlphaBlend;
ppdev->pgfnConstantAlphaBlend = vConstantAlphaBlend;
ppdev->pgfnCopyBlt = vCopyBlt;
ppdev->pgfnGradientFillRect = vGradientFillRect;
ppdev->pgfnPatFill = vPatFill;
ppdev->pgfnMonoPatFill = vMonoPatFill;
ppdev->pgfnMonoOffset = vMonoOffset;
ppdev->pgfnPatRealize = vPatRealize;
ppdev->pgfnSolidFill = vSolidFill;
ppdev->pgfnSolidFillWithRop = vSolidFillWithRop;
ppdev->pgfnTransparentBlt = vTransparentBlt;
ppdev->pgfnInvert = vInvert;
ppdev->pulRamdacBase = (ULONG*) ppdev->pulCtrlBase[0]
+ P2_EXTERNALVIDEO / sizeof(ULONG);
// safe pointers to Permedia 2 registers for later use
//
ppdev->pCtrlBase = ((ULONG *)ppdev->pulCtrlBase[0])+CTRLBASE/sizeof(ULONG);
ppdev->pGPFifo = ((ULONG *)ppdev->pulCtrlBase[0])+GPFIFO/sizeof(ULONG);
ppdev->pCoreBase = ((ULONG *)ppdev->pulCtrlBase[0])+COREBASE/sizeof(ULONG);
DBG_GDI((5, "Initialize: pCtrlBase=0x%p", ppdev->pCtrlBase));
DBG_GDI((5, "Initialize: pGPFifo=0x%p", ppdev->pGPFifo));
DBG_GDI((5, "Initialize: pCoreBase=0x%p", ppdev->pCoreBase));
if (!bInitializeP2DMA( pP2dma,
ppdev->hDriver,
(ULONG *)ppdev->pulCtrlBase[0],
ppdev->dwAccelLevel,
TRUE
))
{
DBG_GDI((0, "P2DMA initialization failed."));
return FALSE;
}
// keep a copy of Permedia 2 ChipConfig, so we know
// if we are running on a AGP card or not
ppdev->dwChipConfig = P2_READ_CTRL_REG(PREG_CHIPCONFIG);
//
// If we have a gamma ramp saved in the registry then use that. Otherwise,
// initialize the LUT with a gamma of 1.0
//
if ( !bRegistryRetrieveGammaLUT(ppdev, &permediaInfo->gammaLUT) ||
!bInstallGammaLUT(ppdev, &permediaInfo->gammaLUT) )
{
vSetNewGammaValue(ppdev, 0x10000);
}
//
// fill in the permediaInfo capability flags and block fill size.
//
permediaInfo->flags |= GLICAP_NT_CONFORMANT_LINES;
//
// reset all core registers
//
vInitCoreRegisters(ppdev);
//
// now initialize the non-zero core registers
//
RESERVEDMAPTR(20); // reserve a reasonable amount until the all is setup
// Rasterizer Mode
// Fraction and Bias are used by the line drawing code. MirrorBitMask
// is set as all the bits we download are interpreted from bit 31 to bit 0
permediaInfo->RasterizerMode = __PERMEDIA_START_BIAS_ZERO << 4 |
__PERMEDIA_FRACTION_ADJUST_ALMOST_HALF << 2 |
__PERMEDIA_ENABLE << 0 | // mirror bit mask
__PERMEDIA_ENABLE << 18; // limits enabled
SEND_PERMEDIA_DATA(RasterizerMode, permediaInfo->RasterizerMode);
//@@BEGIN_DDKSPLIT
// TODO: we should not enable limit checking
//@@END_DDKSPLIT
SEND_PERMEDIA_DATA(YLimits, 2047 << 16);
SEND_PERMEDIA_DATA(XLimits, 2047 << 16);
// Disable screen scissor
SEND_PERMEDIA_DATA(ScissorMode, __PERMEDIA_DISABLE);
SEND_PERMEDIA_DATA(ScreenSize, ppdev->cyScreen << 16 | ppdev->cxScreen);
ULONG ulPackedPP;
DBG_GDI((7, "assuming screen stride is %d pixels\n", ppdev->cxMemory));
vCalcPackedPP( ppdev->cxMemory, NULL, &ulPackedPP);
// initialize FBReadMode for our default stride
SEND_PERMEDIA_DATA(FBReadMode, ulPackedPP);
// FB Write Mode
permediaInfo->FBWriteMode = 1 | ((32/*permediaInfo->fastFillBlockSz*/ >> 4) << 1);
SEND_PERMEDIA_DATA(FBWriteMode, permediaInfo->FBWriteMode);
DBG_GDI((7, "setting FBWriteMode to 0x%x", (DWORD)permediaInfo->FBWriteMode));
SEND_PERMEDIA_DATA(FBReadPixel, ppdev->cPelSize);
//
// do a probe to see if we support hardware writemasks. use the bottom
// 8 bits only so the same code works for all depths. We also query a
// registry variable which, if set, forces the use of software masking.
//
bExists = bRegistryQueryUlong( ppdev,
REG_USE_SOFTWARE_WRITEMASK,
&ulValue);
if ( !bExists || (ulValue == 0) )
{
// this code works as everything is little endian. i.e. the byte we
// test is always at the lowest address regardless of the pixel depth.
//
WRITE_SCREEN_ULONG(ppdev->pjScreen, 0); // quickest way to clear a pixel!!
SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_CONSTANT_FB_WRITE);
SEND_PERMEDIA_DATA(FBWriteData, 0xff);
SEND_PERMEDIA_DATA(StartXDom, 0);
SEND_PERMEDIA_DATA(StartY, 0);
SEND_PERMEDIA_DATA(FBHardwareWriteMask, 0xa5);
SEND_PERMEDIA_DATA(Render, __RENDER_POINT_PRIMITIVE);
COMMITDMAPTR();
SYNC_WITH_PERMEDIA;
ulValue = READ_SCREEN_ULONG(ppdev->pjScreen);
if ( (ulValue & 0xff) == 0xa5 )
permediaInfo->flags |= GLICAP_HW_WRITE_MASK;
RESERVEDMAPTR(3);
}
DBG_GDI((7, "mode registers initialized"));
SEND_PERMEDIA_DATA(FBHardwareWriteMask, -1);
SEND_PERMEDIA_DATA(TextureAddressMode, __PERMEDIA_DISABLE);
SEND_PERMEDIA_DATA(TextureColorMode, __PERMEDIA_DISABLE);
COMMITDMAPTR();
FLUSHDMA();
// Initialize out InFifo cached information
dmaBufferSize = INPUT_BUFFER_SIZE;
#if defined(_X86_) || defined(_IA64_)
if(!g_bOnNT40 && !pP2dma->bDMAEmulation)
{
AllocateDMABuffer(ppdev->hDriver,
(LONG *) &dmaBufferSize,
&ppdev->dmaBufferVirtualAddress,
&ppdev->dmaBufferPhysicalAddress);
if(ppdev->dmaBufferVirtualAddress != NULL
&& dmaBufferSize < INPUT_BUFFER_SIZE)
{
FreeDMABuffer(ppdev->hDriver, ppdev->dmaBufferVirtualAddress);
ppdev->dmaBufferVirtualAddress = NULL;
}
}
else
{
ppdev->dmaBufferVirtualAddress = NULL;
}
#else
ppdev->dmaBufferVirtualAddress = NULL;
#endif
if(ppdev->dmaBufferVirtualAddress != NULL)
{
ppdev->pulInFifoStart = ppdev->dmaBufferVirtualAddress;
ppdev->pulInFifoEnd = ppdev->dmaBufferVirtualAddress
+ (INPUT_BUFFER_SIZE>>3);
ppdev->dmaCurrentBufferOffset = 0;
}
else
{
ppdev->pulInFifoStart = (ULONG*) ENGALLOCMEM(0, INPUT_BUFFER_SIZE>>1, ALLOC_TAG);
if(ppdev->pulInFifoStart == NULL)
{
DBG_GDI((0, "bInitializeHW: unable to allocate scratch buffer"));
pP2dma->bEnabled = FALSE;
goto errExit;
}
ppdev->pulInFifoEnd = ppdev->pulInFifoStart + (INPUT_BUFFER_SIZE>>3);
}
ppdev->pulInFifoPtr = ppdev->pulInFifoStart;
#if DBG
ppdev->ulReserved = 0;
#endif
//
// We are done setting up the GDI context state.
//
//
// Allocate a hardware context for this PDEV saving the current context.
//
DBG_GDI((7, "allocating new context"));
permediaInfo->pGDICtxt = P2AllocateNewContext(ppdev,
NULL,
0,
P2CtxtWriteOnly
);
if ( permediaInfo->pGDICtxt == NULL )
{
DBG_GDI((1, "failed to allocate Permedia context for display driver/GDI"));
pP2dma->bEnabled = FALSE;
return (FALSE);
}
DBG_GDI((7, "got context id 0x%x for GDI context", permediaInfo->pGDICtxt));
P2SwitchContext(ppdev, permediaInfo->pGDICtxt);
return (TRUE);
errExit:
return FALSE;
}// bInitializeHW()
//-----------------------------------------------------------------------------
//
// vDisableHW
//
// do whatever needs to be done to disable the hardware and free resources
// allocated in bInitializeHW
//
//-----------------------------------------------------------------------------
VOID
vDisableHW(PPDev ppdev)
{
Surf* psurf;
PERMEDIA_DECL;
if ( !permediaInfo )
{
return;
}
if(ppdev->dmaBufferVirtualAddress != NULL)
FreeDMABuffer( ppdev->hDriver, ppdev->dmaBufferVirtualAddress);
else if(ppdev->pulInFifoStart) // No DMA case..we allocated via ENGALLOCMEM
ENGFREEMEM(ppdev->pulInFifoStart);
//
// Free up any contexts we allocated
//
if ( permediaInfo->pGDICtxt != NULL )
{
P2FreeContext(ppdev, permediaInfo->pGDICtxt);
permediaInfo->pGDICtxt = NULL;
}
if ( permediaInfo->ContextTable )
{
ENGFREEMEM(permediaInfo->ContextTable);
}
permediaInfo->ContextTable=NULL;
vFree(ppdev->pP2dma);
ppdev->pP2dma = NULL;
ENGFREEMEM(permediaInfo);
}// vDisableHW()
//-----------------------------------------------------------------------------
//
// VOID vAssertModeHW
//
// We're about to switch to/from full screen mode so do whatever we need to
// to save context etc.
//
//-----------------------------------------------------------------------------
VOID
vAssertModeHW(PPDev ppdev, BOOL bEnable)
{
PERMEDIA_DECL;
if (!permediaInfo)
return;
if (!bEnable)
{
if(ppdev->permediaInfo->pCurrentCtxt != NULL)
P2SwitchContext(ppdev, NULL);
//
// Disable DMA
//
ASSERTDD(ppdev->pP2dma->bEnabled,
"vAssertModeHW: expected dma to be enabled");
vSyncWithPermedia(ppdev->pP2dma);
ppdev->pP2dma->bEnabled = FALSE;
}
else
{
//
// Enable DMA
//
if (!bInitializeP2DMA( ppdev->pP2dma,
ppdev->hDriver,
(ULONG *)ppdev->pulCtrlBase[0],
ppdev->dwAccelLevel,
FALSE
))
{
RIP("vAssertModeHW: Cannot restore DMA");
}
ASSERTDD(ppdev->permediaInfo->pCurrentCtxt == NULL,
"vAssertModeHW: expected no active context");
//
// Restore the current gamma LUT.
//
bInstallGammaLUT(ppdev, &permediaInfo->gammaLUT);
}
}