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

  1. /******************************Module*Header***********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: hwinit.c
  8. *
  9. * This module contains the functions that enable and disable the hardware
  10. *
  11. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  13. \******************************************************************************/
  14. #include "precomp.h"
  15. #include "gdi.h"
  16. #include "p2ctxt.h"
  17. #include "tvp4020.h"
  18. #include "p2rd.h"
  19. #define ALLOC_TAG ALLOC_TAG_WH2P
  20. //-----------------------------------------------------------------------------
  21. //
  22. // vInitCoreRegisters
  23. //
  24. // set all core Permedia registers to a known state
  25. //
  26. //-----------------------------------------------------------------------------
  27. VOID
  28. vInitCoreRegisters(PPDev ppdev)
  29. {
  30. PERMEDIA_DECL;
  31. PERMEDIA_DEFS(ppdev);
  32. // tracks FBWindowBase for off-screen bitmaps
  33. permediaInfo->PixelOffset = 0;
  34. permediaInfo->TextureAddressMode = __PERMEDIA_ENABLE;
  35. permediaInfo->TextureReadMode = __PERMEDIA_DISABLE;
  36. /*__FX_TEXREADMODE_2048HIGH |
  37. __FX_TEXREADMODE_2048WIDE |
  38. __FX_TEXREADMODE_TWRAP_REPEAT |
  39. __FX_TEXREADMODE_SWRAP_REPEAT |
  40. __PERMEDIA_ENABLE;*/
  41. RESERVEDMAPTR( 41);
  42. SEND_PERMEDIA_DATA(DeltaMode, 0);
  43. SEND_PERMEDIA_DATA(ColorDDAMode, 0);
  44. SEND_PERMEDIA_DATA(ScissorMode, 0);
  45. SEND_PERMEDIA_DATA(TextureColorMode, 0);
  46. SEND_PERMEDIA_DATA(FogMode, 0);
  47. SEND_PERMEDIA_DATA(Window, 0);
  48. SEND_PERMEDIA_DATA(StencilMode, 0);
  49. SEND_PERMEDIA_DATA(DepthMode, 0);
  50. SEND_PERMEDIA_DATA(AlphaBlendMode, 0);
  51. SEND_PERMEDIA_DATA(DitherMode, 0);
  52. SEND_PERMEDIA_DATA(LBReadMode, 0);
  53. SEND_PERMEDIA_DATA(LBWriteMode, 0);
  54. SEND_PERMEDIA_DATA(RasterizerMode, 0);
  55. SEND_PERMEDIA_DATA(WindowOrigin, 0);
  56. SEND_PERMEDIA_DATA(StatisticMode, 0);
  57. SEND_PERMEDIA_DATA(FBSoftwareWriteMask, -1);
  58. SEND_PERMEDIA_DATA(FBHardwareWriteMask, -1);
  59. SEND_PERMEDIA_DATA(FilterMode, 0);
  60. SEND_PERMEDIA_DATA(FBWindowBase, 0);
  61. SEND_PERMEDIA_DATA(FBPixelOffset, 0);
  62. SEND_PERMEDIA_DATA(LogicalOpMode, 0);
  63. SEND_PERMEDIA_DATA(FBReadMode, 0);
  64. SEND_PERMEDIA_DATA(dXDom, 0);
  65. SEND_PERMEDIA_DATA(dXSub, 0);
  66. SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
  67. SEND_PERMEDIA_DATA(TextureAddressMode, 0);
  68. SEND_PERMEDIA_DATA(TextureReadMode, 0);
  69. SEND_PERMEDIA_DATA(TexelLUTMode, 0);
  70. SEND_PERMEDIA_DATA(Texel0, 0);
  71. SEND_PERMEDIA_DATA(YUVMode, 0);
  72. SEND_PERMEDIA_DATA(FBReadPixel, __PERMEDIA_32BITPIXEL); // 32 bit pixels
  73. SEND_PERMEDIA_DATA(SStart, 0);
  74. SEND_PERMEDIA_DATA(dSdx, 1 << 20);
  75. SEND_PERMEDIA_DATA(dSdyDom, 0);
  76. SEND_PERMEDIA_DATA(TStart, 0);
  77. SEND_PERMEDIA_DATA(dTdx, 0);
  78. SEND_PERMEDIA_DATA(dTdyDom, 0);
  79. SEND_PERMEDIA_DATA(TextureDataFormat, __FX_TEXTUREDATAFORMAT_32BIT_RGBA |
  80. __P2_TEXTURE_DATAFORMAT_FLIP);
  81. SEND_PERMEDIA_DATA(TextureColorMode,
  82. (_P2_TEXTURE_COPY << PM_TEXCOLORMODE_APPLICATION)
  83. | __PERMEDIA_ENABLE); // ignored by texture glyph rendering
  84. SEND_PERMEDIA_DATA(TextureAddressMode, permediaInfo->TextureAddressMode);
  85. SEND_PERMEDIA_DATA(TextureReadMode, permediaInfo->TextureReadMode);
  86. COMMITDMAPTR();
  87. FLUSHDMA();
  88. }
  89. //-----------------------------------------------------------------------------
  90. //
  91. // bInitializeHW
  92. //
  93. // Called to load the initial values into the chip. We assume the hardware
  94. // has been mapped. All the relevant stuff should be hanging off ppdev. We
  95. // also sort out all the hardware capabilities etc.
  96. //
  97. //-----------------------------------------------------------------------------
  98. BOOL
  99. bInitializeHW(PPDev ppdev)
  100. {
  101. HwDataPtr permediaInfo;
  102. Surf* psurf;
  103. LONG i, j;
  104. ULONG width;
  105. ULONG ulValue;
  106. BOOL bExists;
  107. ULONG ulLength;
  108. ULONG dmaBufferSize;
  109. PERMEDIA_DEFS(ppdev);
  110. DBG_GDI((7, "bInitializeHW: fbsize: 0x%x", ppdev->FrameBufferLength));
  111. // allocate and initialize ppdev->permediaInfo. We store hardware specific
  112. // stuff in this structure.
  113. //
  114. permediaInfo = (HwDataPtr)
  115. ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(HwDataRec), ALLOC_TAG);
  116. if ( permediaInfo == NULL )
  117. {
  118. DBG_GDI((0, "cannot allocate memory for permediaInfo struct"));
  119. return (FALSE);
  120. }
  121. ppdev->permediaInfo = permediaInfo;
  122. permediaInfo->pGDICtxt = NULL;
  123. permediaInfo->pCurrentCtxt = NULL;
  124. // retrieve the PCI configuration information and local buffer size
  125. ulLength = sizeof(Hw_Device_Info);
  126. if ( EngDeviceIoControl(ppdev->hDriver,
  127. IOCTL_VIDEO_QUERY_DEVICE_INFO,
  128. NULL,
  129. 0,
  130. (PVOID)&(permediaInfo->deviceInfo),
  131. ulLength,
  132. &ulLength) )
  133. {
  134. DBG_GDI((1, "QUERY_DEVICE_INFO failed."));
  135. return (FALSE);
  136. }
  137. ulLength = sizeof(PINTERRUPT_CONTROL_BLOCK);
  138. if ( EngDeviceIoControl(ppdev->hDriver,
  139. IOCTL_VIDEO_MAP_INTERRUPT_CMD_BUF,
  140. NULL,
  141. 0,
  142. (PVOID)&pP2dma,
  143. ulLength,
  144. &ulLength) )
  145. {
  146. DBG_GDI((1, "MAP_INTERRUPT_CMD_BUF failed."));
  147. return FALSE;
  148. }
  149. //
  150. // On NT4.0 the above IOCTL_VIDEO_MAP_INTERRUPT_CMD_BUF will fail and
  151. // pP2dma will be NULL. Hence we allocate it via ENGALLOCMEM.
  152. //
  153. if(g_bOnNT40)
  154. {
  155. ASSERTDD(pP2dma == 0, "bInitializeHW: pP2dma != 0");
  156. pP2dma = (P2DMA*) ENGALLOCMEM(FL_ZERO_MEMORY, sizeof(_P2DMA), ALLOC_TAG);
  157. }
  158. // Even if IOCtrl call succeeded,
  159. // the allocation can still fail.
  160. if (pP2dma==NULL)
  161. {
  162. DBG_GDI((0,"allocation of memory for P2DMA from miniport failed"));
  163. return FALSE;
  164. }
  165. // store away shared memory area for later use in ppdev
  166. ppdev->pP2dma=pP2dma;
  167. //@@BEGIN_DDKSPLIT
  168. #if MULTITHREADED && DBG
  169. pP2dma->ppdev = ppdev;
  170. #endif
  171. //@@END_DDKSPLIT
  172. DBG_GDI((7, "deviceInfo: VendorId: 0x%x, DevId %d, DeltaId 0x%x,"
  173. "RevId %d, SubId %d, SubVId %d, lbuf len 0x%x, lbuf width %d",
  174. permediaInfo->deviceInfo.VendorId,
  175. permediaInfo->deviceInfo.DeviceId,
  176. permediaInfo->deviceInfo.DeltaRevId,
  177. permediaInfo->deviceInfo.RevisionId,
  178. permediaInfo->deviceInfo.SubsystemId,
  179. permediaInfo->deviceInfo.SubsystemVendorId,
  180. permediaInfo->deviceInfo.LocalbufferLength,
  181. permediaInfo->deviceInfo.LocalbufferWidth));
  182. // collect flags as we initialize so zero it here
  183. permediaInfo->flags = 0;
  184. // set up default pointers to our low level rendering functions
  185. //
  186. ppdev->pgfnAlphaBlend = vAlphaBlend;
  187. ppdev->pgfnConstantAlphaBlend = vConstantAlphaBlend;
  188. ppdev->pgfnCopyBlt = vCopyBlt;
  189. ppdev->pgfnGradientFillRect = vGradientFillRect;
  190. ppdev->pgfnPatFill = vPatFill;
  191. ppdev->pgfnMonoPatFill = vMonoPatFill;
  192. ppdev->pgfnMonoOffset = vMonoOffset;
  193. ppdev->pgfnPatRealize = vPatRealize;
  194. ppdev->pgfnSolidFill = vSolidFill;
  195. ppdev->pgfnSolidFillWithRop = vSolidFillWithRop;
  196. ppdev->pgfnTransparentBlt = vTransparentBlt;
  197. ppdev->pgfnInvert = vInvert;
  198. ppdev->pulRamdacBase = (ULONG*) ppdev->pulCtrlBase[0]
  199. + P2_EXTERNALVIDEO / sizeof(ULONG);
  200. // safe pointers to Permedia 2 registers for later use
  201. //
  202. ppdev->pCtrlBase = ((ULONG *)ppdev->pulCtrlBase[0])+CTRLBASE/sizeof(ULONG);
  203. ppdev->pGPFifo = ((ULONG *)ppdev->pulCtrlBase[0])+GPFIFO/sizeof(ULONG);
  204. ppdev->pCoreBase = ((ULONG *)ppdev->pulCtrlBase[0])+COREBASE/sizeof(ULONG);
  205. DBG_GDI((5, "Initialize: pCtrlBase=0x%p", ppdev->pCtrlBase));
  206. DBG_GDI((5, "Initialize: pGPFifo=0x%p", ppdev->pGPFifo));
  207. DBG_GDI((5, "Initialize: pCoreBase=0x%p", ppdev->pCoreBase));
  208. if (!bInitializeP2DMA( pP2dma,
  209. ppdev->hDriver,
  210. (ULONG *)ppdev->pulCtrlBase[0],
  211. ppdev->dwAccelLevel,
  212. TRUE
  213. ))
  214. {
  215. DBG_GDI((0, "P2DMA initialization failed."));
  216. return FALSE;
  217. }
  218. // keep a copy of Permedia 2 ChipConfig, so we know
  219. // if we are running on a AGP card or not
  220. ppdev->dwChipConfig = P2_READ_CTRL_REG(PREG_CHIPCONFIG);
  221. //
  222. // If we have a gamma ramp saved in the registry then use that. Otherwise,
  223. // initialize the LUT with a gamma of 1.0
  224. //
  225. if ( !bRegistryRetrieveGammaLUT(ppdev, &permediaInfo->gammaLUT) ||
  226. !bInstallGammaLUT(ppdev, &permediaInfo->gammaLUT) )
  227. {
  228. vSetNewGammaValue(ppdev, 0x10000);
  229. }
  230. //
  231. // fill in the permediaInfo capability flags and block fill size.
  232. //
  233. permediaInfo->flags |= GLICAP_NT_CONFORMANT_LINES;
  234. //
  235. // reset all core registers
  236. //
  237. vInitCoreRegisters(ppdev);
  238. //
  239. // now initialize the non-zero core registers
  240. //
  241. RESERVEDMAPTR(20); // reserve a reasonable amount until the all is setup
  242. // Rasterizer Mode
  243. // Fraction and Bias are used by the line drawing code. MirrorBitMask
  244. // is set as all the bits we download are interpreted from bit 31 to bit 0
  245. permediaInfo->RasterizerMode = __PERMEDIA_START_BIAS_ZERO << 4 |
  246. __PERMEDIA_FRACTION_ADJUST_ALMOST_HALF << 2 |
  247. __PERMEDIA_ENABLE << 0 | // mirror bit mask
  248. __PERMEDIA_ENABLE << 18; // limits enabled
  249. SEND_PERMEDIA_DATA(RasterizerMode, permediaInfo->RasterizerMode);
  250. //@@BEGIN_DDKSPLIT
  251. // TODO: we should not enable limit checking
  252. //@@END_DDKSPLIT
  253. SEND_PERMEDIA_DATA(YLimits, 2047 << 16);
  254. SEND_PERMEDIA_DATA(XLimits, 2047 << 16);
  255. // Disable screen scissor
  256. SEND_PERMEDIA_DATA(ScissorMode, __PERMEDIA_DISABLE);
  257. SEND_PERMEDIA_DATA(ScreenSize, ppdev->cyScreen << 16 | ppdev->cxScreen);
  258. ULONG ulPackedPP;
  259. DBG_GDI((7, "assuming screen stride is %d pixels\n", ppdev->cxMemory));
  260. vCalcPackedPP( ppdev->cxMemory, NULL, &ulPackedPP);
  261. // initialize FBReadMode for our default stride
  262. SEND_PERMEDIA_DATA(FBReadMode, ulPackedPP);
  263. // FB Write Mode
  264. permediaInfo->FBWriteMode = 1 | ((32/*permediaInfo->fastFillBlockSz*/ >> 4) << 1);
  265. SEND_PERMEDIA_DATA(FBWriteMode, permediaInfo->FBWriteMode);
  266. DBG_GDI((7, "setting FBWriteMode to 0x%x", (DWORD)permediaInfo->FBWriteMode));
  267. SEND_PERMEDIA_DATA(FBReadPixel, ppdev->cPelSize);
  268. //
  269. // do a probe to see if we support hardware writemasks. use the bottom
  270. // 8 bits only so the same code works for all depths. We also query a
  271. // registry variable which, if set, forces the use of software masking.
  272. //
  273. bExists = bRegistryQueryUlong( ppdev,
  274. REG_USE_SOFTWARE_WRITEMASK,
  275. &ulValue);
  276. if ( !bExists || (ulValue == 0) )
  277. {
  278. // this code works as everything is little endian. i.e. the byte we
  279. // test is always at the lowest address regardless of the pixel depth.
  280. //
  281. WRITE_SCREEN_ULONG(ppdev->pjScreen, 0); // quickest way to clear a pixel!!
  282. SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_CONSTANT_FB_WRITE);
  283. SEND_PERMEDIA_DATA(FBWriteData, 0xff);
  284. SEND_PERMEDIA_DATA(StartXDom, 0);
  285. SEND_PERMEDIA_DATA(StartY, 0);
  286. SEND_PERMEDIA_DATA(FBHardwareWriteMask, 0xa5);
  287. SEND_PERMEDIA_DATA(Render, __RENDER_POINT_PRIMITIVE);
  288. COMMITDMAPTR();
  289. SYNC_WITH_PERMEDIA;
  290. ulValue = READ_SCREEN_ULONG(ppdev->pjScreen);
  291. if ( (ulValue & 0xff) == 0xa5 )
  292. permediaInfo->flags |= GLICAP_HW_WRITE_MASK;
  293. RESERVEDMAPTR(3);
  294. }
  295. DBG_GDI((7, "mode registers initialized"));
  296. SEND_PERMEDIA_DATA(FBHardwareWriteMask, -1);
  297. SEND_PERMEDIA_DATA(TextureAddressMode, __PERMEDIA_DISABLE);
  298. SEND_PERMEDIA_DATA(TextureColorMode, __PERMEDIA_DISABLE);
  299. COMMITDMAPTR();
  300. FLUSHDMA();
  301. // Initialize out InFifo cached information
  302. dmaBufferSize = INPUT_BUFFER_SIZE;
  303. #if defined(_X86_) || defined(_IA64_)
  304. if(!g_bOnNT40 && !pP2dma->bDMAEmulation)
  305. {
  306. AllocateDMABuffer(ppdev->hDriver,
  307. (LONG *) &dmaBufferSize,
  308. &ppdev->dmaBufferVirtualAddress,
  309. &ppdev->dmaBufferPhysicalAddress);
  310. if(ppdev->dmaBufferVirtualAddress != NULL
  311. && dmaBufferSize < INPUT_BUFFER_SIZE)
  312. {
  313. FreeDMABuffer(ppdev->hDriver, ppdev->dmaBufferVirtualAddress);
  314. ppdev->dmaBufferVirtualAddress = NULL;
  315. }
  316. }
  317. else
  318. {
  319. ppdev->dmaBufferVirtualAddress = NULL;
  320. }
  321. #else
  322. ppdev->dmaBufferVirtualAddress = NULL;
  323. #endif
  324. if(ppdev->dmaBufferVirtualAddress != NULL)
  325. {
  326. ppdev->pulInFifoStart = ppdev->dmaBufferVirtualAddress;
  327. ppdev->pulInFifoEnd = ppdev->dmaBufferVirtualAddress
  328. + (INPUT_BUFFER_SIZE>>3);
  329. ppdev->dmaCurrentBufferOffset = 0;
  330. }
  331. else
  332. {
  333. ppdev->pulInFifoStart = (ULONG*) ENGALLOCMEM(0, INPUT_BUFFER_SIZE>>1, ALLOC_TAG);
  334. if(ppdev->pulInFifoStart == NULL)
  335. {
  336. DBG_GDI((0, "bInitializeHW: unable to allocate scratch buffer"));
  337. pP2dma->bEnabled = FALSE;
  338. goto errExit;
  339. }
  340. ppdev->pulInFifoEnd = ppdev->pulInFifoStart + (INPUT_BUFFER_SIZE>>3);
  341. }
  342. ppdev->pulInFifoPtr = ppdev->pulInFifoStart;
  343. #if DBG
  344. ppdev->ulReserved = 0;
  345. #endif
  346. //
  347. // We are done setting up the GDI context state.
  348. //
  349. //
  350. // Allocate a hardware context for this PDEV saving the current context.
  351. //
  352. DBG_GDI((7, "allocating new context"));
  353. permediaInfo->pGDICtxt = P2AllocateNewContext(ppdev,
  354. NULL,
  355. 0,
  356. P2CtxtWriteOnly
  357. );
  358. if ( permediaInfo->pGDICtxt == NULL )
  359. {
  360. DBG_GDI((1, "failed to allocate Permedia context for display driver/GDI"));
  361. pP2dma->bEnabled = FALSE;
  362. return (FALSE);
  363. }
  364. DBG_GDI((7, "got context id 0x%x for GDI context", permediaInfo->pGDICtxt));
  365. P2SwitchContext(ppdev, permediaInfo->pGDICtxt);
  366. return (TRUE);
  367. errExit:
  368. return FALSE;
  369. }// bInitializeHW()
  370. //-----------------------------------------------------------------------------
  371. //
  372. // vDisableHW
  373. //
  374. // do whatever needs to be done to disable the hardware and free resources
  375. // allocated in bInitializeHW
  376. //
  377. //-----------------------------------------------------------------------------
  378. VOID
  379. vDisableHW(PPDev ppdev)
  380. {
  381. Surf* psurf;
  382. PERMEDIA_DECL;
  383. if ( !permediaInfo )
  384. {
  385. return;
  386. }
  387. if(ppdev->dmaBufferVirtualAddress != NULL)
  388. FreeDMABuffer( ppdev->hDriver, ppdev->dmaBufferVirtualAddress);
  389. else if(ppdev->pulInFifoStart) // No DMA case..we allocated via ENGALLOCMEM
  390. ENGFREEMEM(ppdev->pulInFifoStart);
  391. //
  392. // Free up any contexts we allocated
  393. //
  394. if ( permediaInfo->pGDICtxt != NULL )
  395. {
  396. P2FreeContext(ppdev, permediaInfo->pGDICtxt);
  397. permediaInfo->pGDICtxt = NULL;
  398. }
  399. if ( permediaInfo->ContextTable )
  400. {
  401. ENGFREEMEM(permediaInfo->ContextTable);
  402. }
  403. permediaInfo->ContextTable=NULL;
  404. vFree(ppdev->pP2dma);
  405. ppdev->pP2dma = NULL;
  406. ENGFREEMEM(permediaInfo);
  407. }// vDisableHW()
  408. //-----------------------------------------------------------------------------
  409. //
  410. // VOID vAssertModeHW
  411. //
  412. // We're about to switch to/from full screen mode so do whatever we need to
  413. // to save context etc.
  414. //
  415. //-----------------------------------------------------------------------------
  416. VOID
  417. vAssertModeHW(PPDev ppdev, BOOL bEnable)
  418. {
  419. PERMEDIA_DECL;
  420. if (!permediaInfo)
  421. return;
  422. if (!bEnable)
  423. {
  424. if(ppdev->permediaInfo->pCurrentCtxt != NULL)
  425. P2SwitchContext(ppdev, NULL);
  426. //
  427. // Disable DMA
  428. //
  429. ASSERTDD(ppdev->pP2dma->bEnabled,
  430. "vAssertModeHW: expected dma to be enabled");
  431. vSyncWithPermedia(ppdev->pP2dma);
  432. ppdev->pP2dma->bEnabled = FALSE;
  433. }
  434. else
  435. {
  436. //
  437. // Enable DMA
  438. //
  439. if (!bInitializeP2DMA( ppdev->pP2dma,
  440. ppdev->hDriver,
  441. (ULONG *)ppdev->pulCtrlBase[0],
  442. ppdev->dwAccelLevel,
  443. FALSE
  444. ))
  445. {
  446. RIP("vAssertModeHW: Cannot restore DMA");
  447. }
  448. ASSERTDD(ppdev->permediaInfo->pCurrentCtxt == NULL,
  449. "vAssertModeHW: expected no active context");
  450. //
  451. // Restore the current gamma LUT.
  452. //
  453. bInstallGammaLUT(ppdev, &permediaInfo->gammaLUT);
  454. }
  455. }