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.

344 lines
11 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *************************
  4. * * GDI/DDRAW SAMPLE CODE *
  5. * *************************
  6. *
  7. * Module Name: ddraw.c
  8. *
  9. * Content: Provides interfaces back from the DDRAW .lib file into the main NT driver
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "glint.h"
  16. #if WNT_DDRAW
  17. // The code inside this WNT_DDRAW ifdef is code that interfaces between the DirectDraw
  18. // core (as ported from Win 95) and the Win NT display driver.
  19. /*
  20. * vNTSyncWith2DDriver ()
  21. * --------------------------
  22. *
  23. * Sync DirectDraw with every other subsystem: 2D driver . We
  24. * put it in a function to get at the correct data structures.
  25. */
  26. VOID vNTSyncWith2DDriver(PPDEV ppdev)
  27. {
  28. GLINT_DECL;
  29. SYNC_WITH_GLINT;
  30. }
  31. // if we're expecting to use the vblank interrupt but the adapter hasn't been allocated an
  32. // interrupt, we'll need to provide temporary storage for values that would otherwise have been
  33. // stored within the interrupt block
  34. ULONG gulOverlayEnabled;
  35. ULONG gulVBLANKUpdateOverlay;
  36. ULONG gulVBLANKUpdateOverlayWidth;
  37. ULONG gulVBLANKUpdateOverlayHeight;
  38. /*
  39. * bSetupOffscreenForDDraw ()
  40. * --------------------------
  41. *
  42. * This function enables and disables the Display Driver's off-screen video memory.
  43. * This allows DirectDraw to take control of the off-screen memory and to
  44. * create it's linear heap in the memory.
  45. *
  46. * Note: only implemented for Permedia.
  47. */
  48. BOOL bSetupOffscreenForDDraw(
  49. BOOL enableFlag,
  50. PPDEV ppdev,
  51. volatile DWORD **VBlankAddress,
  52. volatile DWORD **bOverlayEnabled,
  53. volatile DWORD **VBLANKUpdateOverlay,
  54. volatile DWORD **VBLANKUpdateOverlayWidth,
  55. volatile DWORD **VBLANKUpdateOverlayHeight)
  56. {
  57. BOOL retVal = TRUE;
  58. PINTERRUPT_CONTROL_BLOCK pBlock;
  59. GLINT_DECL;
  60. DISPDBG((DBGLVL, "bSetupOffscreenForDDraw: in addr 0x%x", VBlankAddress));
  61. if (enableFlag)
  62. {
  63. if((ppdev->flStatus & STAT_LINEAR_HEAP) == 0)
  64. {
  65. // disabling DDraw, reenabling 2D offscreeen
  66. vEnable2DOffscreenMemory(ppdev);
  67. }
  68. // Get pointer to interrupt command block
  69. pBlock = glintInfo->pInterruptCommandBlock;
  70. // Reset the interrupt flags
  71. if (INTERRUPTS_ENABLED && (pBlock->Control & DIRECTDRAW_VBLANK_ENABLED))
  72. {
  73. // Clear the flag to stop the interrupt routine setting the
  74. // flag in the shared structure
  75. pBlock->Control &= ~DIRECTDRAW_VBLANK_ENABLED;
  76. // clear VBLANK flag or we'll get an immediate interrupt
  77. WRITE_GLINT_CTRL_REG(IntFlags, INTR_CLEAR_VBLANK);
  78. // Re-instate the original flags
  79. WRITE_GLINT_CTRL_REG(IntEnable, ppdev->oldIntEnableFlags);
  80. }
  81. }
  82. else
  83. {
  84. // enabling DDraw, disabling 2D offscreen
  85. // We zap off-screen memory chunks on Permedia, only if there
  86. // aren't any OGL apps running.
  87. {
  88. // There aren't any OGL apps running, so grab all the
  89. // memory for DDraw
  90. if(ppdev->flStatus & ENABLE_LINEAR_HEAP)
  91. {
  92. // DX managed linear heap - we don't need to do anything
  93. // NB. check against whether we have the capability to use the linear heap, rather than
  94. // whether it's currently enabled as it's only enabled much later, in DrvNotify
  95. retVal = TRUE;
  96. }
  97. else
  98. retVal = bDisable2DOffscreenMemory(ppdev);
  99. if (retVal == TRUE)
  100. {
  101. // We return a pointer to a 'long' which DirectDraw can
  102. // poll to see if it is zero or not.
  103. if (VBlankAddress != NULL)
  104. {
  105. DWORD enableFlags;
  106. *VBlankAddress = NULL;
  107. if (INTERRUPTS_ENABLED)
  108. {
  109. // Get pointer to interrupt command block
  110. pBlock = glintInfo->pInterruptCommandBlock;
  111. // Indicate that we require the miniport to
  112. // set a flag for us
  113. pBlock->Control |= DIRECTDRAW_VBLANK_ENABLED;
  114. // clear VBLANK flag or we'll get an immediate interrupt
  115. WRITE_GLINT_CTRL_REG(IntFlags, INTR_CLEAR_VBLANK);
  116. // enable the VBLANK interrupt
  117. READ_GLINT_CTRL_REG (IntEnable, enableFlags);
  118. WRITE_GLINT_CTRL_REG(IntEnable, enableFlags | INTR_ENABLE_VBLANK);
  119. // Save the old interrupt flags so that we can restore them
  120. ppdev->oldIntEnableFlags = enableFlags;
  121. // Set up pointers into the shared memory
  122. *VBlankAddress = &pBlock->DDRAW_VBLANK;
  123. *bOverlayEnabled = &pBlock->bOverlayEnabled;
  124. *VBLANKUpdateOverlay = &pBlock->bVBLANKUpdateOverlay;
  125. *VBLANKUpdateOverlayWidth = &pBlock->VBLANKUpdateOverlayWidth;
  126. *VBLANKUpdateOverlayHeight = &pBlock->VBLANKUpdateOverlayHeight;
  127. }
  128. else
  129. {
  130. *bOverlayEnabled = &gulOverlayEnabled;
  131. *VBLANKUpdateOverlay = &gulVBLANKUpdateOverlay;
  132. *VBLANKUpdateOverlayWidth = &gulVBLANKUpdateOverlayWidth;
  133. *VBLANKUpdateOverlayHeight = &gulVBLANKUpdateOverlayHeight;
  134. }
  135. DISPDBG((DBGLVL, "bSetupOffscreenForDDraw: configured ptr 0x%x", *VBlankAddress));
  136. }
  137. }
  138. }
  139. }
  140. DISPDBG((DBGLVL, "bSetupOffscreenForDDraw: exit %d", retVal));
  141. return (retVal);
  142. }
  143. /*
  144. * GetChipInfoForDDraw ()
  145. * ----------------------
  146. *
  147. * A simple helper function to return chip information to DirectDraw
  148. */
  149. VOID GetChipInfoForDDraw(
  150. PPDEV ppdev,
  151. DWORD* pdwChipID,
  152. DWORD* pdwChipRev,
  153. DWORD* pdwChipFamily,
  154. DWORD* pdwGammaRev)
  155. {
  156. GLINT_DECL;
  157. DISPDBG((DBGLVL,"*** In GetChipInfoForDDraw"));
  158. DISPDBG((DBGLVL," Chip is PXRX Family"));
  159. *pdwChipFamily = PERMEDIA3_ID;
  160. *pdwChipID = glintInfo->deviceInfo.DeviceId;
  161. *pdwChipRev = glintInfo->deviceInfo.RevisionId;
  162. *pdwGammaRev = glintInfo->deviceInfo.GammaRevId;
  163. }
  164. /*
  165. * GetFBLBInfoForDDraw ()
  166. * ----------------------
  167. *
  168. * Return some basic framnebuffer/localbuffer info to DirectDraw.
  169. */
  170. VOID GetFBLBInfoForDDraw(
  171. PPDEV ppdev,
  172. void **fbPtr, // Framebuffer pointer
  173. void **lbPtr, // Localbuffer pointer
  174. DWORD *fbSizeInBytes, // Size of framebuffer
  175. DWORD *lbSizeInBytes, // Size of localbuffer
  176. DWORD *fbOffsetInBytes, // Offset to 1st 'free' byte in framebuffer
  177. BOOL *bSDRAM) // TRUE if SDRAM (i.e. no h/w write mask)
  178. {
  179. GLINT_DECL;
  180. *fbPtr = ppdev->pjScreen;
  181. *lbPtr = NULL; // We don't know this one
  182. *fbSizeInBytes = ppdev->FrameBufferLength;
  183. *lbSizeInBytes = TEXTURE_MEMORY_SIZE;
  184. *fbOffsetInBytes = ppdev->heap.DDrawOffscreenStart * ppdev->cjPelSize;
  185. *bSDRAM = (GLINT_HW_WRITE_MASK == FALSE);
  186. DISPDBG((DBGLVL, "GetFBLBInfoForDDraw: offstart 0x%x, buf[1] 0x%lx, pelsz %d",
  187. ppdev->heap.DDrawOffscreenStart,
  188. GLINT_BUFFER_OFFSET(1),
  189. ppdev->cjPelSize));
  190. }
  191. // DDSendDMAData
  192. // Uses DMA to transfer one complete buffer of DDRAW data
  193. // under NT5.
  194. // Before initiating DMA transfer, a check is made to ensure
  195. // that any previous DMA transfer has completed.
  196. // Then the DMA is initiated and the routine returns, so that
  197. // the DMA transfer proceeds in parallel with the processor's
  198. // proceeding execution.
  199. LONG DDSendDMAData(
  200. PDEV* ppdev,
  201. ULONG PhysAddr,
  202. ULONG_PTR VirtAddr,
  203. LONG nDataEntries)
  204. {
  205. ULONG frontIndex, nextIndex;
  206. volatile ULONG ulValue;
  207. GLINT_DECL ;
  208. // PhysAddr += DataOffset;
  209. // VirtAddr += DataOffset;
  210. DISPDBG((DBGLVL, "DMASendData: DMA at 0x%x for %d", PhysAddr, nDataEntries));
  211. ppdev->g_GlintBoardStatus &= ~GLINT_DMA_COMPLETE;
  212. if (ppdev->g_GlintBoardStatus & GLINT_INTR_CONTEXT)
  213. {
  214. PINTERRUPT_CONTROL_BLOCK pBlock = glintInfo->pInterruptCommandBlock;
  215. DISPDBG((DBGLVL, "Processing buffer at 0x%x for %d", PhysAddr, nDataEntries));
  216. DISPDBG((DBGLVL, "Adding buffer to Q"));
  217. frontIndex = pBlock->frontIndex;
  218. if ((nextIndex = frontIndex+1) == pBlock->endIndex)
  219. nextIndex = 0;
  220. // wait for a free queue entry. We should really do a backoff here.
  221. while (nextIndex == pBlock->backIndex);
  222. DISPDBG((DBGLVL, "Add to DMA Q backindex %d frontindex %d",frontIndex, pBlock->backIndex));
  223. // add the DMA address and count to the new entry.
  224. pBlock->dmaQueue[frontIndex].address = PhysAddr;
  225. pBlock->dmaQueue[frontIndex].count = nDataEntries;
  226. pBlock->frontIndex = nextIndex;
  227. // wakeup the interrupt handler using an error interrupt. To save on
  228. // interrupt processing, only do this if a DMA interrupt is not
  229. // pending.
  230. //
  231. //if (!pBlock->InterruptPending)
  232. {
  233. DISPDBG((DBGLVL, "Generating error interrupt"));
  234. WRITE_GLINT_CTRL_REG(ErrorFlags, 0x7); // clear error flags
  235. READ_OUTPUT_FIFO(ulValue); // generate interrupt
  236. }
  237. }
  238. else
  239. {
  240. WAIT_IMMEDIATE_DMA_COMPLETE;
  241. SET_DMA_ADDRESS(PhysAddr, VirtAddr) ;
  242. SET_DMA_COUNT(nDataEntries);
  243. }
  244. DISPDBG((DBGLVL,"DMA count=%d\n", nDataEntries )) ;
  245. return 1 ;
  246. }
  247. // Wrapper function used for requesting a DMA memory buffer
  248. // from NT for use by D3D. NT 5 only.
  249. LONG DDGetFreeDMABuffer(
  250. DWORD *physAddr,
  251. ULONG_PTR *virtAddr,
  252. DWORD *bufferSize)
  253. {
  254. LONG BuffNum;
  255. QUERY_DMA_BUFFERS dmaBuffer;
  256. BuffNum = GetFreeDMABuffer(&dmaBuffer);
  257. if (BuffNum >= 0)
  258. {
  259. *physAddr = (DWORD)dmaBuffer.physAddr.LowPart;
  260. *virtAddr = (ULONG_PTR)dmaBuffer.virtAddr;
  261. *bufferSize = (DWORD)dmaBuffer.size;
  262. }
  263. else
  264. {
  265. // Failed to get a free DMA buffer
  266. *physAddr = 0;
  267. *virtAddr = 0;
  268. *bufferSize = 0;
  269. }
  270. return BuffNum;
  271. }
  272. // Frees the given DMA buffer.
  273. VOID DDFreeDMABuffer(void* pPhysAddress)
  274. {
  275. FreeDMABuffer(pPhysAddress);
  276. return;
  277. }
  278. LONG DDWaitDMAComplete(PDEV *ppdev)
  279. {
  280. GLINT_DECL ;
  281. WAIT_DMA_COMPLETE;
  282. return 0;
  283. }
  284. #endif WNT_DDRAW