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.

600 lines
19 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. // Values for the internal, EGA-compatible palette.
  10. static WORD gPaletteBuffer[] = {
  11. 16, // 16 entries
  12. 0, // start with first palette register
  13. // On the VGA, the palette contains indices into the array of color DACs.
  14. // Since we can program the DACs as we please, we'll just put all the indices
  15. // down at the beginning of the DAC array (that is, pass pixel values through
  16. // the internal palette unchanged).
  17. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
  18. };
  19. // These are the values for the first 16 DAC registers, the only ones we'll
  20. // work with. These correspond to the RGB colors (6 bits for each primary, with
  21. // the fourth entry unused) for pixel values 0-15.
  22. static BYTE gColorBuffer[] = {
  23. 16, // 16 entries
  24. 0,
  25. 0,
  26. 0, // start with first palette register
  27. 0x00, 0x00, 0x00, 0x00, // black
  28. 0x2A, 0x00, 0x15, 0x00, // red
  29. 0x00, 0x2A, 0x15, 0x00, // green
  30. 0x2A, 0x2A, 0x15, 0x00, // mustard/brown
  31. 0x00, 0x00, 0x2A, 0x00, // blue
  32. 0x2A, 0x15, 0x2A, 0x00, // magenta
  33. 0x15, 0x2A, 0x2A, 0x00, // cyan
  34. 0x21, 0x22, 0x23, 0x00, // dark gray 2A
  35. 0x30, 0x31, 0x32, 0x00, // light gray 39
  36. 0x3F, 0x00, 0x00, 0x00, // bright red
  37. 0x00, 0x3F, 0x00, 0x00, // bright green
  38. 0x3F, 0x3F, 0x00, 0x00, // bright yellow
  39. 0x00, 0x00, 0x3F, 0x00, // bright blue
  40. 0x3F, 0x00, 0x3F, 0x00, // bright magenta
  41. 0x00, 0x3F, 0x3F, 0x00, // bright cyan
  42. 0x3F, 0x3F, 0x3F, 0x00 // bright white
  43. };
  44. /******************************Public*Routine******************************\
  45. * BOOL bAssertModeHardware
  46. *
  47. * Sets the appropriate hardware state for graphics mode or full-screen.
  48. *
  49. \**************************************************************************/
  50. BOOL bAssertModeHardware(
  51. PDEV* ppdev,
  52. BOOL bEnable)
  53. {
  54. DWORD ReturnedDataLength;
  55. BYTE* pjBase;
  56. pjBase = ppdev->pjBase;
  57. if (bEnable)
  58. {
  59. // Set the desired mode.
  60. if (EngDeviceIoControl(ppdev->hDriver,
  61. IOCTL_VIDEO_SET_CURRENT_MODE,
  62. &ppdev->ulMode, // input buffer
  63. sizeof(VIDEO_MODE),
  64. NULL,
  65. 0,
  66. &ReturnedDataLength))
  67. {
  68. DISPDBG((0, "bAssertModeHardware - Failed VIDEO_SET_CURRENT_MODE"));
  69. goto ReturnFalse;
  70. }
  71. // Set up the internal palette.
  72. if (EngDeviceIoControl(ppdev->hDriver,
  73. IOCTL_VIDEO_SET_PALETTE_REGISTERS,
  74. (PVOID) gPaletteBuffer, // input buffer
  75. sizeof(gPaletteBuffer),
  76. NULL, // output buffer
  77. 0,
  78. &ReturnedDataLength))
  79. {
  80. DISPDBG((0, "bAssertModeHardware - Failed VIDEO_SET_PALETTE_REGISTERS"));
  81. return(FALSE);
  82. }
  83. // Set up the DAC.
  84. if (EngDeviceIoControl(ppdev->hDriver,
  85. IOCTL_VIDEO_SET_COLOR_REGISTERS,
  86. (PVOID) gColorBuffer, // input buffer
  87. sizeof(gColorBuffer),
  88. NULL, // output buffer
  89. 0,
  90. &ReturnedDataLength))
  91. {
  92. DISPDBG((0, "bAssertModeHardware - Failed VIDEO_SET_COLOR_REGISTERS"));
  93. return(FALSE);
  94. }
  95. // Initialize sequencer to its defaults (all planes enabled, index
  96. // pointing to Map Mask).
  97. OUT_WORD(pjBase, VGA_BASE + SEQ_ADDR, (MM_ALL << 8) + SEQ_MAP_MASK);
  98. // Initialize graphics controller to its defaults (set/reset disabled for
  99. // all planes, no rotation & ALU function == replace, write mode 0 & read
  100. // mode 0, color compare ignoring all planes (read mode 1 reads always
  101. // return 0ffh, handy for ANDing), and the bit mask == 0ffh, gating all
  102. // bytes from the CPU.
  103. OUT_WORD(pjBase, VGA_BASE + GRAF_ADDR, GRAF_ENAB_SR);
  104. OUT_WORD(pjBase, VGA_BASE + GRAF_ADDR, (DR_SET << 8) + GRAF_DATA_ROT);
  105. OUT_WORD(pjBase, VGA_BASE + GRAF_ADDR, ((M_PROC_WRITE | M_DATA_READ) << 8)
  106. + GRAF_MODE);
  107. OUT_WORD(pjBase, VGA_BASE + GRAF_ADDR, GRAF_CDC);
  108. OUT_WORD(pjBase, VGA_BASE + GRAF_ADDR, (0xffL << 8) + GRAF_BIT_MASK);
  109. DISPDBG((5, "Passed bAssertModeHardware"));
  110. }
  111. else
  112. {
  113. // Call the kernel driver to reset the device to a known state.
  114. // NTVDM will take things from there:
  115. if (EngDeviceIoControl(ppdev->hDriver,
  116. IOCTL_VIDEO_RESET_DEVICE,
  117. NULL,
  118. 0,
  119. NULL,
  120. 0,
  121. &ReturnedDataLength))
  122. {
  123. DISPDBG((0, "bAssertModeHardware - Failed reset IOCTL"));
  124. goto ReturnFalse;
  125. }
  126. }
  127. return(TRUE);
  128. ReturnFalse:
  129. DISPDBG((0, "Failed bAssertModeHardware"));
  130. return(FALSE);
  131. }
  132. /******************************Public*Routine******************************\
  133. * BOOL bEnableHardware
  134. *
  135. * Puts the hardware into the requested mode and initializes it.
  136. *
  137. * Note: Should be called before any access is done to the hardware from
  138. * the display driver.
  139. *
  140. \**************************************************************************/
  141. BOOL bEnableHardware(
  142. PDEV* ppdev)
  143. {
  144. VIDEO_MEMORY VideoMemory;
  145. VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
  146. VIDEO_MODE_INFORMATION VideoModeInfo;
  147. DWORD ReturnedDataLength;
  148. VIDEO_PUBLIC_ACCESS_RANGES VideoAccessRange;
  149. DWORD status;
  150. // Map io ports into virtual memory:
  151. VideoMemory.RequestedVirtualAddress = NULL;
  152. if (EngDeviceIoControl(ppdev->hDriver,
  153. IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
  154. NULL, // input buffer
  155. 0,
  156. &VideoAccessRange, // output buffer
  157. sizeof (VideoAccessRange),
  158. &ReturnedDataLength))
  159. {
  160. DISPDBG((0, "bEnableHardware - Initialization error mapping IO port base"));
  161. goto ReturnFalse;
  162. }
  163. ppdev->pjBase = (UCHAR*) VideoAccessRange.VirtualAddress;
  164. // Set the desired mode. (Must come before IOCTL_VIDEO_MAP_VIDEO_MEMORY;
  165. // that IOCTL returns information for the current mode, so there must be a
  166. // current mode for which to return information.)
  167. if (EngDeviceIoControl(ppdev->hDriver,
  168. IOCTL_VIDEO_SET_CURRENT_MODE,
  169. &ppdev->ulMode, // input buffer
  170. sizeof(VIDEO_MODE),
  171. NULL,
  172. 0,
  173. &ReturnedDataLength))
  174. {
  175. DISPDBG((0, "bEnableHardware - Set current mode"));
  176. goto ReturnFalse;
  177. }
  178. // Get the linear memory address range.
  179. VideoMemory.RequestedVirtualAddress = NULL;
  180. if (EngDeviceIoControl(ppdev->hDriver,
  181. IOCTL_VIDEO_MAP_VIDEO_MEMORY,
  182. &VideoMemory, // input buffer
  183. sizeof(VIDEO_MEMORY),
  184. &VideoMemoryInfo, // output buffer
  185. sizeof(VideoMemoryInfo),
  186. &ReturnedDataLength))
  187. {
  188. DISPDBG((0, "bEnableHardware - Error mapping buffer address"));
  189. goto ReturnFalse;
  190. }
  191. DISPDBG((1, "FrameBufferBase: %lx", VideoMemoryInfo.FrameBufferBase));
  192. // Record the Frame Buffer Linear Address.
  193. ppdev->pjScreen = (BYTE*) VideoMemoryInfo.FrameBufferBase;
  194. if (EngDeviceIoControl(ppdev->hDriver,
  195. IOCTL_VIDEO_QUERY_CURRENT_MODE,
  196. NULL,
  197. 0,
  198. &VideoModeInfo,
  199. sizeof(VideoModeInfo),
  200. &ReturnedDataLength))
  201. {
  202. DISPDBG((0, "bEnableHardware - failed VIDEO_QUERY_CURRENT_MODE"));
  203. goto ReturnFalse;
  204. }
  205. // Store the width of the screen in bytes
  206. ppdev->lDelta = VideoModeInfo.ScreenStride;
  207. if (!bAssertModeHardware(ppdev, TRUE))
  208. goto ReturnFalse;
  209. DISPDBG((5, "Passed bEnableHardware"));
  210. return(TRUE);
  211. ReturnFalse:
  212. DISPDBG((0, "Failed bEnableHardware"));
  213. return(FALSE);
  214. }
  215. /******************************Public*Routine******************************\
  216. * VOID vDisableHardware
  217. *
  218. * Undoes anything done in bEnableHardware.
  219. *
  220. * Note: In an error case, we may call this before bEnableHardware is
  221. * completely done.
  222. *
  223. \**************************************************************************/
  224. VOID vDisableHardware(
  225. PDEV* ppdev)
  226. {
  227. DWORD ReturnedDataLength;
  228. VIDEO_MEMORY VideoMemory;
  229. if ((VideoMemory.RequestedVirtualAddress = ppdev->pjScreen) != NULL) {
  230. if (EngDeviceIoControl(ppdev->hDriver,
  231. IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
  232. &VideoMemory,
  233. sizeof(VIDEO_MEMORY),
  234. NULL,
  235. 0,
  236. &ReturnedDataLength))
  237. {
  238. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_UNMAP_VIDEO"));
  239. }
  240. }
  241. if((VideoMemory.RequestedVirtualAddress = ppdev->pjBase) != INVALID_BASE_ADDRESS)
  242. {
  243. if (EngDeviceIoControl(ppdev->hDriver,
  244. IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES,
  245. &VideoMemory,
  246. sizeof(VIDEO_MEMORY),
  247. NULL,
  248. 0,
  249. &ReturnedDataLength))
  250. {
  251. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_FREE_PUBLIC_ACCESS"));
  252. }
  253. ppdev->pjBase = INVALID_BASE_ADDRESS;
  254. }
  255. }
  256. /******************************Public*Routine******************************\
  257. * VOID vUpdate(ppdev, prcl, pco)
  258. *
  259. * Updates the screen from the DIB surface for the given rectangle.
  260. * Increases the rectangle size if necessary for easy alignment.
  261. *
  262. \**************************************************************************/
  263. #define STRIP_SIZE 32
  264. // This little macro returns the 'PositionInNibble' bit of the
  265. // 'NibbleNumber' nibble of the given 'Dword', and aligns it so that
  266. // it's in the 'PositionInResult' bit of the result. Numbering is done
  267. // in the order '7 6 5 4 3 2 1 0'.
  268. //
  269. // Given constants for everything but 'Dword', this will amount to an
  270. // AND and a SHIFT.
  271. #define BITPOS(Dword, PositionInNibble, NibbleNumber, PositionInResult) \
  272. (WORD) (((((PositionInNibble) + (NibbleNumber) * 4) > (PositionInResult)) ? \
  273. (((Dword) & (1 << ((PositionInNibble) + (NibbleNumber) * 4))) \
  274. >> ((PositionInNibble) + (NibbleNumber) * 4 - (PositionInResult))) : \
  275. (((Dword) & (1 << ((PositionInNibble) + (NibbleNumber) * 4))) \
  276. << ((PositionInResult) - (PositionInNibble) - (NibbleNumber) * 4))))
  277. VOID vUpdate(PDEV* ppdev, RECTL* prcl, CLIPOBJ* pco)
  278. {
  279. BYTE* pjBase;
  280. RECTL rcl;
  281. SURFOBJ* pso;
  282. LONG cy;
  283. LONG cyThis;
  284. LONG cw;
  285. ULONG* pulSrcStart;
  286. ULONG* pulSrc;
  287. WORD* pwDstStart;
  288. WORD* pwDst;
  289. LONG i;
  290. LONG j;
  291. ULONG ul;
  292. WORD w;
  293. LONG lSrcDelta;
  294. LONG lDstDelta;
  295. LONG lSrcSkip;
  296. LONG lDstSkip;
  297. pjBase = ppdev->pjBase;
  298. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  299. {
  300. // We have to clip to the screen dimensions because we may have
  301. // been a bit loose when we guessed the bounds of the drawing:
  302. rcl.left = max(0, prcl->left);
  303. rcl.top = max(0, prcl->top);
  304. rcl.right = min(ppdev->cxScreen, prcl->right);
  305. rcl.bottom = min(ppdev->cyScreen, prcl->bottom);
  306. }
  307. else
  308. {
  309. // We may as well save ourselves some blting by clipping to
  310. // the clip object's maximum extent. The clip object's bounds
  311. // are guaranteed to be contained within the dimensions of the
  312. // screen:
  313. rcl.left = max(pco->rclBounds.left, prcl->left);
  314. rcl.top = max(pco->rclBounds.top, prcl->top);
  315. rcl.right = min(pco->rclBounds.right, prcl->right);
  316. rcl.bottom = min(pco->rclBounds.bottom, prcl->bottom);
  317. }
  318. // Be paranoid:
  319. if ((rcl.left >= rcl.right) || (rcl.top >= rcl.bottom))
  320. return;
  321. // Align to words so that we don't have to do any read-modify-write
  322. // operations.
  323. rcl.left = (rcl.left) & ~15;
  324. rcl.right = (rcl.right + 15) & ~15;
  325. pso = ppdev->pso;
  326. lSrcDelta = pso->lDelta;
  327. pulSrcStart = (ULONG*) ((BYTE*) pso->pvScan0 + (rcl.top * lSrcDelta)
  328. + (rcl.left >> 1));
  329. lDstDelta = ppdev->lDelta;
  330. pwDstStart = (WORD*) (ppdev->pjScreen + (rcl.top * lDstDelta)
  331. + (rcl.left >> 3));
  332. cy = (rcl.bottom - rcl.top);
  333. cw = (rcl.right - rcl.left) >> 4;
  334. lSrcSkip = lSrcDelta - (8 * cw);
  335. lDstSkip = lDstDelta - (2 * cw);
  336. do {
  337. cyThis = STRIP_SIZE;
  338. cy -= STRIP_SIZE;
  339. if (cy < 0)
  340. cyThis += cy;
  341. // Map in plane 0:
  342. OUT_BYTE(pjBase, VGA_BASE + SEQ_DATA, MM_C0);
  343. pwDst = pwDstStart;
  344. pulSrc = pulSrcStart;
  345. for (j = cyThis; j != 0; j--)
  346. {
  347. for (i = cw; i != 0; i--)
  348. {
  349. ul = *(pulSrc);
  350. w = BITPOS(ul, 0, 6, 0) |
  351. BITPOS(ul, 0, 7, 1) |
  352. BITPOS(ul, 0, 4, 2) |
  353. BITPOS(ul, 0, 5, 3) |
  354. BITPOS(ul, 0, 2, 4) |
  355. BITPOS(ul, 0, 3, 5) |
  356. BITPOS(ul, 0, 0, 6) |
  357. BITPOS(ul, 0, 1, 7);
  358. ul = *(pulSrc + 1);
  359. w |= BITPOS(ul, 0, 6, 8) |
  360. BITPOS(ul, 0, 7, 9) |
  361. BITPOS(ul, 0, 4, 10) |
  362. BITPOS(ul, 0, 5, 11) |
  363. BITPOS(ul, 0, 2, 12) |
  364. BITPOS(ul, 0, 3, 13) |
  365. BITPOS(ul, 0, 0, 14) |
  366. BITPOS(ul, 0, 1, 15);
  367. WRITE_WORD(pwDst, w);
  368. pwDst += 1;
  369. pulSrc += 2;
  370. }
  371. pwDst = (WORD*) ((BYTE*) pwDst + lDstSkip);
  372. pulSrc = (ULONG*) ((BYTE*) pulSrc + lSrcSkip);
  373. }
  374. // Map in plane 1:
  375. OUT_BYTE(pjBase, VGA_BASE + SEQ_DATA, MM_C1);
  376. pwDst = pwDstStart;
  377. pulSrc = pulSrcStart;
  378. for (j = cyThis; j != 0; j--)
  379. {
  380. for (i = cw; i != 0; i--)
  381. {
  382. ul = *(pulSrc);
  383. w = BITPOS(ul, 1, 6, 0) |
  384. BITPOS(ul, 1, 7, 1) |
  385. BITPOS(ul, 1, 4, 2) |
  386. BITPOS(ul, 1, 5, 3) |
  387. BITPOS(ul, 1, 2, 4) |
  388. BITPOS(ul, 1, 3, 5) |
  389. BITPOS(ul, 1, 0, 6) |
  390. BITPOS(ul, 1, 1, 7);
  391. ul = *(pulSrc + 1);
  392. w |= BITPOS(ul, 1, 6, 8) |
  393. BITPOS(ul, 1, 7, 9) |
  394. BITPOS(ul, 1, 4, 10) |
  395. BITPOS(ul, 1, 5, 11) |
  396. BITPOS(ul, 1, 2, 12) |
  397. BITPOS(ul, 1, 3, 13) |
  398. BITPOS(ul, 1, 0, 14) |
  399. BITPOS(ul, 1, 1, 15);
  400. WRITE_WORD(pwDst, w);
  401. pwDst += 1;
  402. pulSrc += 2;
  403. }
  404. pwDst = (WORD*) ((BYTE*) pwDst + lDstSkip);
  405. pulSrc = (ULONG*) ((BYTE*) pulSrc + lSrcSkip);
  406. }
  407. // Map in plane 2:
  408. OUT_BYTE(pjBase, VGA_BASE + SEQ_DATA, MM_C2);
  409. pwDst = pwDstStart;
  410. pulSrc = pulSrcStart;
  411. for (j = cyThis; j != 0; j--)
  412. {
  413. for (i = cw; i != 0; i--)
  414. {
  415. ul = *(pulSrc);
  416. w = BITPOS(ul, 2, 6, 0) |
  417. BITPOS(ul, 2, 7, 1) |
  418. BITPOS(ul, 2, 4, 2) |
  419. BITPOS(ul, 2, 5, 3) |
  420. BITPOS(ul, 2, 2, 4) |
  421. BITPOS(ul, 2, 3, 5) |
  422. BITPOS(ul, 2, 0, 6) |
  423. BITPOS(ul, 2, 1, 7);
  424. ul = *(pulSrc + 1);
  425. w |= BITPOS(ul, 2, 6, 8) |
  426. BITPOS(ul, 2, 7, 9) |
  427. BITPOS(ul, 2, 4, 10) |
  428. BITPOS(ul, 2, 5, 11) |
  429. BITPOS(ul, 2, 2, 12) |
  430. BITPOS(ul, 2, 3, 13) |
  431. BITPOS(ul, 2, 0, 14) |
  432. BITPOS(ul, 2, 1, 15);
  433. WRITE_WORD(pwDst, w);
  434. pwDst += 1;
  435. pulSrc += 2;
  436. }
  437. pwDst = (WORD*) ((BYTE*) pwDst + lDstSkip);
  438. pulSrc = (ULONG*) ((BYTE*) pulSrc + lSrcSkip);
  439. }
  440. // Map in plane 3:
  441. OUT_BYTE(pjBase, VGA_BASE + SEQ_DATA, MM_C3);
  442. pwDst = pwDstStart;
  443. pulSrc = pulSrcStart;
  444. for (j = cyThis; j != 0; j--)
  445. {
  446. for (i = cw; i != 0; i--)
  447. {
  448. ul = *(pulSrc);
  449. w = BITPOS(ul, 3, 6, 0) |
  450. BITPOS(ul, 3, 7, 1) |
  451. BITPOS(ul, 3, 4, 2) |
  452. BITPOS(ul, 3, 5, 3) |
  453. BITPOS(ul, 3, 2, 4) |
  454. BITPOS(ul, 3, 3, 5) |
  455. BITPOS(ul, 3, 0, 6) |
  456. BITPOS(ul, 3, 1, 7);
  457. ul = *(pulSrc + 1);
  458. w |= BITPOS(ul, 3, 6, 8) |
  459. BITPOS(ul, 3, 7, 9) |
  460. BITPOS(ul, 3, 4, 10) |
  461. BITPOS(ul, 3, 5, 11) |
  462. BITPOS(ul, 3, 2, 12) |
  463. BITPOS(ul, 3, 3, 13) |
  464. BITPOS(ul, 3, 0, 14) |
  465. BITPOS(ul, 3, 1, 15);
  466. WRITE_WORD(pwDst, w);
  467. pwDst += 1;
  468. pulSrc += 2;
  469. }
  470. pwDst = (WORD*) ((BYTE*) pwDst + lDstSkip);
  471. pulSrc = (ULONG*) ((BYTE*) pulSrc + lSrcSkip);
  472. }
  473. // Get ready for next strip:
  474. pulSrcStart = (ULONG*) ((BYTE*) pulSrcStart + (cyThis * lSrcDelta));
  475. pwDstStart = (WORD*) ((BYTE*) pwDstStart + (cyThis * lDstDelta));
  476. } while (cy > 0);
  477. }