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.

372 lines
11 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: hardware.c
  3. *
  4. * Contains all the code that touches the display hardware.
  5. *
  6. * Copyright (c) 1994-1995 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. /******************************Public*Routine******************************\
  10. * BOOL bAssertModeHardware
  11. *
  12. * Sets the appropriate hardware state for graphics mode or full-screen.
  13. *
  14. \**************************************************************************/
  15. BOOL bAssertModeHardware(
  16. PDEV* ppdev,
  17. BOOL bEnable)
  18. {
  19. DWORD ReturnedDataLength;
  20. BYTE* pjBase;
  21. RECTL rcl;
  22. pjBase = ppdev->pjBase;
  23. if (bEnable)
  24. {
  25. // Reset some state:
  26. ppdev->cjVgaOffset = 0;
  27. ppdev->iVgaPage = 0;
  28. ppdev->fpScreenOffset = 0;
  29. // Set the desired mode.
  30. if (EngDeviceIoControl(ppdev->hDriver,
  31. IOCTL_VIDEO_SET_CURRENT_MODE,
  32. &ppdev->ulMode, // input buffer
  33. sizeof(VIDEO_MODE),
  34. NULL,
  35. 0,
  36. &ReturnedDataLength))
  37. {
  38. DISPDBG((0, "bAssertModeHardware - Failed VIDEO_SET_CURRENT_MODE"));
  39. goto ReturnFalse;
  40. }
  41. // Now blank the screen:
  42. rcl.left = 0;
  43. rcl.top = 0;
  44. rcl.right = ppdev->cxScreen;
  45. rcl.bottom = ppdev->cyScreen;
  46. vUpdate(ppdev, &rcl, NULL);
  47. DISPDBG((5, "Passed bAssertModeHardware"));
  48. }
  49. else
  50. {
  51. // Call the kernel driver to reset the device to a known state.
  52. // NTVDM will take things from there:
  53. if (EngDeviceIoControl(ppdev->hDriver,
  54. IOCTL_VIDEO_RESET_DEVICE,
  55. NULL,
  56. 0,
  57. NULL,
  58. 0,
  59. &ReturnedDataLength))
  60. {
  61. DISPDBG((0, "bAssertModeHardware - Failed reset IOCTL"));
  62. goto ReturnFalse;
  63. }
  64. }
  65. return(TRUE);
  66. ReturnFalse:
  67. DISPDBG((0, "Failed bAssertModeHardware"));
  68. return(FALSE);
  69. }
  70. /******************************Public*Routine******************************\
  71. * BOOL bEnableHardware
  72. *
  73. * Puts the hardware into the requested mode and initializes it.
  74. *
  75. * Note: Should be called before any access is done to the hardware from
  76. * the display driver.
  77. *
  78. \**************************************************************************/
  79. BOOL bEnableHardware(
  80. PDEV* ppdev)
  81. {
  82. VIDEO_MEMORY VideoMemory;
  83. VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
  84. VIDEO_MODE_INFORMATION VideoModeInfo;
  85. DWORD ReturnedDataLength;
  86. VIDEO_PUBLIC_ACCESS_RANGES VideoAccessRange;
  87. DWORD status;
  88. #if defined(_X86_)
  89. ppdev->pjBase = NULL;
  90. #else
  91. // Map io ports into virtual memory:
  92. VideoMemory.RequestedVirtualAddress = NULL;
  93. if (EngDeviceIoControl(ppdev->hDriver,
  94. IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
  95. NULL, // input buffer
  96. 0,
  97. &VideoAccessRange, // output buffer
  98. sizeof (VideoAccessRange),
  99. &ReturnedDataLength))
  100. {
  101. RIP("bEnableHardware - Initialization error mapping IO port base");
  102. goto ReturnFalse;
  103. }
  104. ppdev->pjBase = (UCHAR*) VideoAccessRange.VirtualAddress;
  105. #endif
  106. // Set the desired mode. (Must come before IOCTL_VIDEO_MAP_VIDEO_MEMORY;
  107. // that IOCTL returns information for the current mode, so there must be a
  108. // current mode for which to return information.)
  109. if (EngDeviceIoControl(ppdev->hDriver,
  110. IOCTL_VIDEO_SET_CURRENT_MODE,
  111. &ppdev->ulMode, // input buffer
  112. sizeof(VIDEO_MODE),
  113. NULL,
  114. 0,
  115. &ReturnedDataLength))
  116. {
  117. RIP("bEnableHardware - Set current mode");
  118. goto ReturnFalse;
  119. }
  120. // Get the linear memory address range.
  121. VideoMemory.RequestedVirtualAddress = NULL;
  122. if (EngDeviceIoControl(ppdev->hDriver,
  123. IOCTL_VIDEO_MAP_VIDEO_MEMORY,
  124. &VideoMemory, // input buffer
  125. sizeof(VIDEO_MEMORY),
  126. &VideoMemoryInfo, // output buffer
  127. sizeof(VideoMemoryInfo),
  128. &ReturnedDataLength))
  129. {
  130. DISPDBG((0, "bEnableHardware - Error mapping buffer address"));
  131. goto ReturnFalse;
  132. }
  133. DISPDBG((1, "FrameBufferBase: %lx", VideoMemoryInfo.FrameBufferBase));
  134. // Record the Frame Buffer Linear Address.
  135. ppdev->pjVga = (BYTE*) VideoMemoryInfo.FrameBufferBase;
  136. // Store the width of the screen in bytes, per-plane:
  137. ppdev->lVgaDelta = ppdev->cxScreen / 4;
  138. if (!bAssertModeHardware(ppdev, TRUE))
  139. goto ReturnFalse;
  140. DISPDBG((5, "Passed bEnableHardware"));
  141. return(TRUE);
  142. ReturnFalse:
  143. DISPDBG((0, "Failed bEnableHardware"));
  144. return(FALSE);
  145. }
  146. /******************************Public*Routine******************************\
  147. * VOID vDisableHardware
  148. *
  149. * Undoes anything done in bEnableHardware.
  150. *
  151. * Note: In an error case, we may call this before bEnableHardware is
  152. * completely done.
  153. *
  154. \**************************************************************************/
  155. VOID vDisableHardware(
  156. PDEV* ppdev)
  157. {
  158. DWORD ReturnedDataLength;
  159. VIDEO_MEMORY VideoMemory;
  160. VideoMemory.RequestedVirtualAddress = ppdev->pjVga;
  161. if (EngDeviceIoControl(ppdev->hDriver,
  162. IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
  163. &VideoMemory,
  164. sizeof(VIDEO_MEMORY),
  165. NULL,
  166. 0,
  167. &ReturnedDataLength))
  168. {
  169. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_UNMAP_VIDEO"));
  170. }
  171. #if !defined(_X86_)
  172. VideoMemory.RequestedVirtualAddress = ppdev->pjBase;
  173. if (EngDeviceIoControl(ppdev->hDriver,
  174. IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES,
  175. &VideoMemory,
  176. sizeof(VIDEO_MEMORY),
  177. NULL,
  178. 0,
  179. &ReturnedDataLength))
  180. {
  181. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_FREE_PUBLIC_ACCESS"));
  182. }
  183. #endif
  184. }
  185. /******************************Public*Routine******************************\
  186. * VOID vUpdate(ppdev, prcl, pco)
  187. *
  188. * Updates the screen from the DIB surface for the given rectangle.
  189. * Increases the rectangle size if necessary for easy alignment.
  190. *
  191. * NOTE: Life is made complicated by the fact that we are faking DirectDraw
  192. * 'flip' surfaces. When we're asked by GDI to draw, it should be
  193. * copied from the shadow buffer to the physical screen only if
  194. * DirectDraw is currently 'flipped' to the primary surface.
  195. *
  196. \**************************************************************************/
  197. VOID vUpdate(PDEV* ppdev, RECTL* prcl, CLIPOBJ* pco)
  198. {
  199. BYTE* pjBase;
  200. RECTL rcl;
  201. SURFOBJ* pso;
  202. LONG lSrcDelta;
  203. BYTE* pjSrcStart;
  204. BYTE* pjSrc;
  205. LONG lDstDelta;
  206. BYTE* pjDstStart;
  207. BYTE* pjDst;
  208. ULONG cy;
  209. ULONG cDwordsPerPlane;
  210. ULONG iPage;
  211. ULONG i;
  212. ULONG ul;
  213. pjBase = ppdev->pjBase;
  214. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  215. {
  216. // We have to clip to the screen dimensions because we may have
  217. // been a bit loose when we guessed the bounds of the drawing:
  218. rcl.left = max(0, prcl->left);
  219. rcl.top = max(0, prcl->top);
  220. rcl.right = min(ppdev->cxScreen, prcl->right);
  221. rcl.bottom = min(ppdev->cyScreen, prcl->bottom);
  222. }
  223. else
  224. {
  225. // We may as well save ourselves some blting by clipping to
  226. // the clip object's maximum extent. The clip object's bounds
  227. // are guaranteed to be contained within the dimensions of the
  228. // screen:
  229. rcl.left = max(pco->rclBounds.left, prcl->left);
  230. rcl.top = max(pco->rclBounds.top, prcl->top);
  231. rcl.right = min(pco->rclBounds.right, prcl->right);
  232. rcl.bottom = min(pco->rclBounds.bottom, prcl->bottom);
  233. }
  234. // Be paranoid:
  235. if ((rcl.left >= rcl.right) || (rcl.top >= rcl.bottom))
  236. return;
  237. // Align to dwords to keep things simple.
  238. rcl.left = (rcl.left) & ~15;
  239. rcl.right = (rcl.right + 15) & ~15;
  240. lSrcDelta = ppdev->lScreenDelta;
  241. pjSrcStart = ppdev->pjScreen + ppdev->fpScreenOffset
  242. + (rcl.top * lSrcDelta)
  243. + rcl.left;
  244. lDstDelta = ppdev->lVgaDelta;
  245. pjDstStart = ppdev->pjVga + ppdev->cjVgaOffset
  246. + (rcl.top * lDstDelta)
  247. + (rcl.left >> 2);
  248. cy = (rcl.bottom - rcl.top);
  249. cDwordsPerPlane = (rcl.right - rcl.left) >> 4;
  250. lSrcDelta -= 4; // Account for per-plane increment
  251. WRITE_PORT_UCHAR(pjBase + VGA_BASE + SEQ_ADDR, SEQ_MAP_MASK);
  252. do {
  253. for (iPage = 0; iPage < 4; iPage++, pjSrcStart++)
  254. {
  255. WRITE_PORT_UCHAR(pjBase + VGA_BASE + SEQ_DATA, 1 << iPage);
  256. pjSrc = pjSrcStart;
  257. pjDst = pjDstStart;
  258. #if defined(_X86_)
  259. _asm {
  260. mov esi,pjSrcStart
  261. mov edi,pjDstStart
  262. mov ecx,cDwordsPerPlane
  263. PixelLoop:
  264. mov al,[esi+8]
  265. mov ah,[esi+12]
  266. shl eax,16
  267. mov al,[esi]
  268. mov ah,[esi+4]
  269. mov [edi],eax
  270. add edi,4
  271. add esi,16
  272. dec ecx
  273. jnz PixelLoop
  274. }
  275. #else
  276. for (i = cDwordsPerPlane; i != 0; i--)
  277. {
  278. ul = (*(pjSrc))
  279. | (*(pjSrc + 4) << 8)
  280. | (*(pjSrc + 8) << 16)
  281. | (*(pjSrc + 12) << 24);
  282. WRITE_REGISTER_ULONG((ULONG*) pjDst, ul);
  283. pjDst += 4;
  284. pjSrc += 16;
  285. }
  286. #endif
  287. }
  288. pjSrcStart += lSrcDelta;
  289. pjDstStart += lDstDelta;
  290. } while (--cy != 0);
  291. }