Source code of Windows XP (NT5)
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.

783 lines
26 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: misc.c
  3. *
  4. * Miscellaneous common routines.
  5. *
  6. * Copyright (c) 1992-1995 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. /******************************Public*Table********************************\
  11. * ULONG gaul32HwMixFromRop2[]
  12. *
  13. * Table to convert from a Source and Destination Rop2 to the Mach32's
  14. * hardware mix.
  15. \**************************************************************************/
  16. ULONG gaul32HwMixFromRop2[] = {
  17. LOGICAL_0, // 00 -- 0 BLACKNESS
  18. NOT_SCREEN_AND_NOT_NEW, // 11 -- DSon NOTSRCERASE
  19. SCREEN_AND_NOT_NEW, // 22 -- DSna
  20. NOT_NEW, // 33 -- Sn NOSRCCOPY
  21. NOT_SCREEN_AND_NEW, // 44 -- SDna SRCERASE
  22. NOT_SCREEN, // 55 -- Dn DSTINVERT
  23. SCREEN_XOR_NEW, // 66 -- DSx SRCINVERT
  24. NOT_SCREEN_OR_NOT_NEW, // 77 -- DSan
  25. SCREEN_AND_NEW, // 88 -- DSa SRCAND
  26. NOT_SCREEN_XOR_NEW, // 99 -- DSxn
  27. LEAVE_ALONE, // AA -- D
  28. SCREEN_OR_NOT_NEW, // BB -- DSno MERGEPAINT
  29. OVERPAINT, // CC -- S SRCCOPY
  30. NOT_SCREEN_OR_NEW, // DD -- SDno
  31. SCREEN_OR_NEW, // EE -- DSo SRCPAINT
  32. LOGICAL_1 // FF -- 1 WHITENESS
  33. };
  34. /******************************Public*Table********************************\
  35. * ULONG gaul32HwMixFromMix[]
  36. *
  37. * Table to convert from a GDI mix value to the Mach32's hardware mix.
  38. *
  39. * Ordered so that the mix may be calculated from gaul32HwMixFromMix[mix & 0xf]
  40. * or gaul32HwMixFromMix[mix & 0xff].
  41. \**************************************************************************/
  42. ULONG gaul32HwMixFromMix[] = {
  43. LOGICAL_1, // 0 -- 1
  44. LOGICAL_0, // 1 -- 0
  45. NOT_SCREEN_AND_NOT_NEW, // 2 -- DPon
  46. SCREEN_AND_NOT_NEW, // 3 -- DPna
  47. NOT_NEW, // 4 -- Pn
  48. NOT_SCREEN_AND_NEW, // 5 -- PDna
  49. NOT_SCREEN, // 6 -- Dn
  50. SCREEN_XOR_NEW, // 7 -- DPx
  51. NOT_SCREEN_OR_NOT_NEW, // 8 -- DPan
  52. SCREEN_AND_NEW, // 9 -- DPa
  53. NOT_SCREEN_XOR_NEW, // 10 -- DPxn
  54. LEAVE_ALONE, // 11 -- D
  55. SCREEN_OR_NOT_NEW, // 12 -- DPno
  56. OVERPAINT, // 13 -- P
  57. NOT_SCREEN_OR_NEW, // 14 -- PDno
  58. SCREEN_OR_NEW, // 15 -- DPo
  59. LOGICAL_1 // 16 -- 1
  60. };
  61. /******************************Public*Table********************************\
  62. * ULONG gaul64HwMixFromRop2[]
  63. *
  64. * Table to convert from a Source and Destination Rop2 to the Mach64's
  65. * foreground hardware mix.
  66. \**************************************************************************/
  67. ULONG gaul64HwMixFromRop2[] = {
  68. LOGICAL_0 << 16, // 00 -- 0 BLACKNESS
  69. NOT_SCREEN_AND_NOT_NEW << 16, // 11 -- DSon NOTSRCERASE
  70. SCREEN_AND_NOT_NEW << 16, // 22 -- DSna
  71. NOT_NEW << 16, // 33 -- Sn NOSRCCOPY
  72. NOT_SCREEN_AND_NEW << 16, // 44 -- SDna SRCERASE
  73. NOT_SCREEN << 16, // 55 -- Dn DSTINVERT
  74. SCREEN_XOR_NEW << 16, // 66 -- DSx SRCINVERT
  75. NOT_SCREEN_OR_NOT_NEW << 16, // 77 -- DSan
  76. SCREEN_AND_NEW << 16, // 88 -- DSa SRCAND
  77. NOT_SCREEN_XOR_NEW << 16, // 99 -- DSxn
  78. LEAVE_ALONE << 16, // AA -- D
  79. SCREEN_OR_NOT_NEW << 16, // BB -- DSno MERGEPAINT
  80. OVERPAINT << 16, // CC -- S SRCCOPY
  81. NOT_SCREEN_OR_NEW << 16, // DD -- SDno
  82. SCREEN_OR_NEW << 16, // EE -- DSo SRCPAINT
  83. LOGICAL_1 << 16 // FF -- 1 WHITENESS
  84. };
  85. /******************************Public*Table********************************\
  86. * ULONG gaul64HwMixFromMix[]
  87. *
  88. * Table to convert from a GDI mix value to the Mach64's foreground hardware
  89. * mix.
  90. *
  91. * Ordered so that the mix may be calculated from gaul64HwMixFromMix[mix & 0xf]
  92. * or gaul64HwMixFromMix[mix & 0xff].
  93. \**************************************************************************/
  94. ULONG gaul64HwMixFromMix[] = {
  95. LOGICAL_1 << 16, // 0 -- 1
  96. LOGICAL_0 << 16, // 1 -- 0
  97. NOT_SCREEN_AND_NOT_NEW << 16, // 2 -- DPon
  98. SCREEN_AND_NOT_NEW << 16, // 3 -- DPna
  99. NOT_NEW << 16, // 4 -- Pn
  100. NOT_SCREEN_AND_NEW << 16, // 5 -- PDna
  101. NOT_SCREEN << 16, // 6 -- Dn
  102. SCREEN_XOR_NEW << 16, // 7 -- DPx
  103. NOT_SCREEN_OR_NOT_NEW << 16, // 8 -- DPan
  104. SCREEN_AND_NEW << 16, // 9 -- DPa
  105. NOT_SCREEN_XOR_NEW << 16, // 10 -- DPxn
  106. LEAVE_ALONE << 16, // 11 -- D
  107. SCREEN_OR_NOT_NEW << 16, // 12 -- DPno
  108. OVERPAINT << 16, // 13 -- P
  109. NOT_SCREEN_OR_NEW << 16, // 14 -- PDno
  110. SCREEN_OR_NEW << 16, // 15 -- DPo
  111. LOGICAL_1 << 16 // 16 -- 1
  112. };
  113. /******************************Public*Data*********************************\
  114. * MIX translation table
  115. *
  116. * Translates a mix 1-16, into an old style Rop 0-255.
  117. *
  118. \**************************************************************************/
  119. BYTE gaRop3FromMix[] =
  120. {
  121. 0xFF, // R2_WHITE - Allow rop = gaRop3FromMix[mix & 0x0F]
  122. 0x00, // R2_BLACK
  123. 0x05, // R2_NOTMERGEPEN
  124. 0x0A, // R2_MASKNOTPEN
  125. 0x0F, // R2_NOTCOPYPEN
  126. 0x50, // R2_MASKPENNOT
  127. 0x55, // R2_NOT
  128. 0x5A, // R2_XORPEN
  129. 0x5F, // R2_NOTMASKPEN
  130. 0xA0, // R2_MASKPEN
  131. 0xA5, // R2_NOTXORPEN
  132. 0xAA, // R2_NOP
  133. 0xAF, // R2_MERGENOTPEN
  134. 0xF0, // R2_COPYPEN
  135. 0xF5, // R2_MERGEPENNOT
  136. 0xFA, // R2_MERGEPEN
  137. 0xFF // R2_WHITE - Allow rop = gaRop3FromMix[mix & 0xFF]
  138. };
  139. /******************************Public*Routine******************************\
  140. * BOOL bIntersect
  141. *
  142. * If 'prcl1' and 'prcl2' intersect, has a return value of TRUE and returns
  143. * the intersection in 'prclResult'. If they don't intersect, has a return
  144. * value of FALSE, and 'prclResult' is undefined.
  145. *
  146. \**************************************************************************/
  147. BOOL bIntersect(
  148. RECTL* prcl1,
  149. RECTL* prcl2,
  150. RECTL* prclResult)
  151. {
  152. prclResult->left = max(prcl1->left, prcl2->left);
  153. prclResult->right = min(prcl1->right, prcl2->right);
  154. if (prclResult->left < prclResult->right)
  155. {
  156. prclResult->top = max(prcl1->top, prcl2->top);
  157. prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
  158. if (prclResult->top < prclResult->bottom)
  159. {
  160. return(TRUE);
  161. }
  162. }
  163. return(FALSE);
  164. }
  165. /******************************Public*Routine******************************\
  166. * LONG cIntersect
  167. *
  168. * This routine takes a list of rectangles from 'prclIn' and clips them
  169. * in-place to the rectangle 'prclClip'. The input rectangles don't
  170. * have to intersect 'prclClip'; the return value will reflect the
  171. * number of input rectangles that did intersect, and the intersecting
  172. * rectangles will be densely packed.
  173. *
  174. \**************************************************************************/
  175. LONG cIntersect(
  176. RECTL* prclClip,
  177. RECTL* prclIn, // List of rectangles
  178. LONG c) // Can be zero
  179. {
  180. LONG cIntersections;
  181. RECTL* prclOut;
  182. cIntersections = 0;
  183. prclOut = prclIn;
  184. for (; c != 0; prclIn++, c--)
  185. {
  186. prclOut->left = max(prclIn->left, prclClip->left);
  187. prclOut->right = min(prclIn->right, prclClip->right);
  188. if (prclOut->left < prclOut->right)
  189. {
  190. prclOut->top = max(prclIn->top, prclClip->top);
  191. prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
  192. if (prclOut->top < prclOut->bottom)
  193. {
  194. prclOut++;
  195. cIntersections++;
  196. }
  197. }
  198. }
  199. return(cIntersections);
  200. }
  201. /******************************Public*Routine******************************\
  202. * VOID vResetClipping
  203. \**************************************************************************/
  204. VOID vResetClipping(
  205. PDEV* ppdev)
  206. {
  207. BYTE* pjMmBase;
  208. BYTE* pjIoBase;
  209. if (ppdev->iMachType == MACH_MM_64)
  210. {
  211. pjMmBase = ppdev->pjMmBase;
  212. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 2);
  213. M64_OD(pjMmBase, SC_LEFT_RIGHT, PACKPAIR(0, M64_MAX_SCISSOR_R));
  214. M64_OD(pjMmBase, SC_TOP_BOTTOM, PACKPAIR(0, ppdev->cyMemory));
  215. }
  216. else if (ppdev->iMachType == MACH_MM_32)
  217. {
  218. pjMmBase = ppdev->pjMmBase;
  219. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  220. M32_OW(pjMmBase, EXT_SCISSOR_L, 0);
  221. M32_OW(pjMmBase, EXT_SCISSOR_R, M32_MAX_SCISSOR);
  222. M32_OW(pjMmBase, EXT_SCISSOR_T, 0);
  223. M32_OW(pjMmBase, EXT_SCISSOR_B, M32_MAX_SCISSOR);
  224. }
  225. else
  226. {
  227. pjIoBase = ppdev->pjIoBase;
  228. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 4);
  229. I32_OW(pjIoBase, EXT_SCISSOR_L, 0);
  230. I32_OW(pjIoBase, EXT_SCISSOR_R, M32_MAX_SCISSOR);
  231. I32_OW(pjIoBase, EXT_SCISSOR_T, 0);
  232. I32_OW(pjIoBase, EXT_SCISSOR_B, M32_MAX_SCISSOR);
  233. }
  234. }
  235. /******************************Public*Routine******************************\
  236. * VOID vSetClipping
  237. \**************************************************************************/
  238. VOID vSetClipping(
  239. PDEV* ppdev,
  240. RECTL* prclClip) // In relative coordinates
  241. {
  242. LONG xOffset;
  243. LONG yOffset;
  244. BYTE* pjMmBase;
  245. BYTE* pjIoBase;
  246. xOffset = ppdev->xOffset;
  247. yOffset = ppdev->yOffset;
  248. if (ppdev->iMachType == MACH_MM_64)
  249. {
  250. pjMmBase = ppdev->pjMmBase;
  251. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 2);
  252. if (ppdev->iBitmapFormat != BMF_24BPP)
  253. {
  254. M64_OD(pjMmBase, SC_LEFT_RIGHT, PACKPAIR(xOffset + prclClip->left,
  255. xOffset + prclClip->right - 1));
  256. }
  257. else
  258. {
  259. M64_OD(pjMmBase, SC_LEFT_RIGHT, PACKPAIR((xOffset + prclClip->left) * 3,
  260. (xOffset + prclClip->right) * 3 - 1));
  261. }
  262. M64_OD(pjMmBase, SC_TOP_BOTTOM, PACKPAIR(yOffset + prclClip->top,
  263. yOffset + prclClip->bottom - 1));
  264. }
  265. else if (ppdev->iMachType == MACH_MM_32)
  266. {
  267. pjMmBase = ppdev->pjMmBase;
  268. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  269. M32_OW(pjMmBase, EXT_SCISSOR_L, xOffset + prclClip->left);
  270. M32_OW(pjMmBase, EXT_SCISSOR_R, xOffset + prclClip->right - 1);
  271. M32_OW(pjMmBase, EXT_SCISSOR_T, yOffset + prclClip->top);
  272. M32_OW(pjMmBase, EXT_SCISSOR_B, yOffset + prclClip->bottom - 1);
  273. }
  274. else
  275. {
  276. pjIoBase = ppdev->pjIoBase;
  277. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 4);
  278. I32_OW(pjIoBase, EXT_SCISSOR_L, xOffset + prclClip->left);
  279. I32_OW(pjIoBase, EXT_SCISSOR_R, xOffset + prclClip->right - 1);
  280. I32_OW(pjIoBase, EXT_SCISSOR_T, yOffset + prclClip->top);
  281. I32_OW(pjIoBase, EXT_SCISSOR_B, yOffset + prclClip->bottom - 1);
  282. }
  283. }
  284. ////////////////////////////////////////////////////////////////////////////////
  285. // For mach8 cards only...
  286. //
  287. VOID vI32DataPortIn(PDEV *ppdev, WORD *pw, UINT count)
  288. {
  289. BYTE *pjIoBase = ppdev->pjIoBase;
  290. UINT i;
  291. for (i=0; i < count; i++)
  292. {
  293. *((USHORT UNALIGNED *)pw)++ = I32_IW(pjIoBase, PIX_TRANS);
  294. }
  295. }
  296. VOID vI32GetBits( PDEV *ppdev,
  297. SURFOBJ *psoDst,
  298. RECTL *prclDst,
  299. POINTL *pptlSrc
  300. )
  301. {
  302. LONG xPunt, yPunt,
  303. cxPunt, cyPunt, nwords;
  304. LONG lDeltaDst = psoDst->lDelta;
  305. PBYTE pjPunt, pjIoBase = ppdev->pjIoBase;
  306. PWORD pw;
  307. WORD Cmd;
  308. // pptlSrc gives the starting point on the screen.
  309. xPunt = pptlSrc->x;
  310. yPunt = pptlSrc->y;
  311. // prclDst gives the region size.
  312. cxPunt = prclDst->right - prclDst->left;
  313. cyPunt = prclDst->bottom - prclDst->top;
  314. // Do not optimize for word alignment if prclDst points to beginning of scan.
  315. if ((prclDst->left) && (xPunt & 0x1))
  316. {
  317. xPunt--;
  318. cxPunt++;
  319. pjPunt = (PBYTE) psoDst->pvScan0 + (prclDst->top * lDeltaDst) + prclDst->left - 1;
  320. }
  321. else
  322. pjPunt = (PBYTE) psoDst->pvScan0 + (prclDst->top * lDeltaDst) + prclDst->left;
  323. // Make sure the cx is an even number of words.
  324. if (cxPunt & 0x1)
  325. {
  326. cxPunt++;
  327. }
  328. // Set the engine up for the copy.
  329. Cmd = READ | FG_COLOR_SRC_HOST | DATA_WIDTH | DATA_ORDER | DRAW;
  330. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 7);
  331. I32_OW(pjIoBase, DP_CONFIG, Cmd );
  332. I32_OW(pjIoBase, WRT_MASK, 0xffff );
  333. I32_OW(pjIoBase, CUR_X, (SHORT) xPunt );
  334. I32_OW(pjIoBase, CUR_Y, (SHORT) yPunt );
  335. I32_OW(pjIoBase, DEST_X_START, (SHORT) xPunt );
  336. I32_OW(pjIoBase, DEST_X_END, (SHORT) (xPunt + cxPunt) );
  337. I32_OW(pjIoBase, DEST_Y_END, (SHORT) (yPunt + cyPunt) );
  338. // Wait for the Data Available.
  339. while (!(I32_IW(pjIoBase, GE_STAT) & 0x100));
  340. // Now transfer the data from the screen to the host memory bitmap.
  341. pw = (PWORD) pjPunt;
  342. nwords = (cxPunt + 1)/2;
  343. while (cyPunt-- > 0)
  344. {
  345. vI32DataPortIn(ppdev, pw, nwords);
  346. ((PBYTE) pw) += lDeltaDst;
  347. }
  348. }
  349. VOID vI32DataPortOut(PDEV *ppdev, WORD *pw, UINT count)
  350. {
  351. BYTE *pjIoBase = ppdev->pjIoBase;
  352. UINT i;
  353. for (i=0; i < count; i++)
  354. {
  355. if (i % 8 == 0)
  356. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 10);
  357. I32_OW(pjIoBase, PIX_TRANS, *((USHORT UNALIGNED *)pw)++);
  358. }
  359. }
  360. VOID vI32PutBits( PDEV *ppdev,
  361. SURFOBJ *psoSrc,
  362. RECTL *prclDst,
  363. POINTL *pptlSrc
  364. )
  365. {
  366. BOOL leftScissor = FALSE, rightScissor = FALSE;
  367. LONG xPunt, yPunt,
  368. cxPunt, cyPunt, nwords;
  369. LONG lDeltaSrc = psoSrc->lDelta;
  370. PBYTE pjPunt, pjIoBase = ppdev->pjIoBase;
  371. PWORD pw;
  372. WORD Cmd;
  373. // prclDst gives the starting point on the screen.
  374. xPunt = prclDst->left;
  375. yPunt = prclDst->top;
  376. // prclDst gives the region size.
  377. cxPunt = min( prclDst->right, (LONG) ppdev->cxMemory ) - xPunt;
  378. cyPunt = prclDst->bottom - yPunt;
  379. // Do not optimize for word alignment if pptlSrc points to beginning of scan.
  380. if ((pptlSrc->x) && (xPunt & 0x1))
  381. {
  382. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
  383. I32_OW(pjIoBase, EXT_SCISSOR_L, (SHORT) xPunt );
  384. xPunt--;
  385. cxPunt++;
  386. leftScissor = TRUE;
  387. pjPunt = (PBYTE) psoSrc->pvScan0 + (pptlSrc->y * lDeltaSrc) + pptlSrc->x - 1;
  388. }
  389. else
  390. pjPunt = (PBYTE) psoSrc->pvScan0 + (pptlSrc->y * lDeltaSrc) + pptlSrc->x;
  391. // Make sure the cx is an even number of words.
  392. if (cxPunt & 0x1)
  393. {
  394. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
  395. I32_OW(pjIoBase, EXT_SCISSOR_R, (SHORT) (xPunt + cxPunt - 1) );
  396. cxPunt++;
  397. rightScissor = TRUE;
  398. }
  399. // Set the engine up for the copy.
  400. Cmd = FG_COLOR_SRC_HOST | DATA_ORDER | DATA_WIDTH | DRAW | WRITE;
  401. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 9);
  402. I32_OW(pjIoBase, DP_CONFIG, Cmd );
  403. I32_OW(pjIoBase, WRT_MASK, 0xffff );
  404. I32_OW(pjIoBase, ALU_FG_FN, OVERPAINT );
  405. I32_OW(pjIoBase, ALU_BG_FN, OVERPAINT );
  406. I32_OW(pjIoBase, CUR_X, (SHORT) xPunt );
  407. I32_OW(pjIoBase, CUR_Y, (SHORT) yPunt );
  408. I32_OW(pjIoBase, DEST_X_START, (SHORT) xPunt );
  409. I32_OW(pjIoBase, DEST_X_END, (SHORT) (xPunt + cxPunt) );
  410. I32_OW(pjIoBase, DEST_Y_END, (SHORT) (yPunt + cyPunt) );
  411. // Now transfer the data, from the host memory bitmap to the screen.
  412. pw = (PWORD) pjPunt;
  413. nwords = (cxPunt + 1)/2;
  414. while (cyPunt-- > 0)
  415. {
  416. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
  417. vI32DataPortOut(ppdev, pw, nwords);
  418. ((PBYTE) pw) += lDeltaSrc;
  419. }
  420. if (leftScissor)
  421. {
  422. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
  423. I32_OW(pjIoBase, EXT_SCISSOR_L, 0 );
  424. }
  425. if (rightScissor)
  426. {
  427. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
  428. I32_OW(pjIoBase, EXT_SCISSOR_R, (SHORT) M32_MAX_SCISSOR );
  429. }
  430. }
  431. ////////////////////////////////////////////////////////////////////////////////
  432. // Context Stuff
  433. //
  434. #define _bit(x) (1 << (x))
  435. #define CONTEXT_ADDR(ppdev,p) (ppdev->pjContextBase - (((p)+1) * 0x100))
  436. #define cxtCONTEXT_MASK 0
  437. #define cxtDST_OFF_PITCH 2
  438. #define cxtDST_Y_X 3
  439. #define cxtDST_HEIGHT_WIDTH 4
  440. #define cxtDST_BRES_ERR 5
  441. #define cxtDST_BRES_INC 6
  442. #define cxtDST_BRES_DEC 7
  443. #define cxtSRC_OFF_PITCH 8
  444. #define cxtSRC_Y_X 9
  445. #define cxtSRC_HEIGHT1_WIDTH1 10
  446. #define cxtSRC_Y_X_START 11
  447. #define cxtSRC_HEIGHT2_WIDTH2 12
  448. #define cxtPAT_REG0 13
  449. #define cxtPAT_REG1 14
  450. #define cxtSC_LEFT_RIGHT 15
  451. #define cxtSC_TOP_BOTTOM 16
  452. #define cxtDP_BKGD_CLR 17
  453. #define cxtDP_FRGD_CLR 18
  454. #define cxtDP_WRITE_MASK 19
  455. #define cxtDP_CHAIN_MASK 20
  456. #define cxtDP_PIX_WIDTH 21
  457. #define cxtDP_MIX 22
  458. #define cxtDP_SRC 23
  459. #define cxtCLR_CMP_CLR 24
  460. #define cxtCLR_CMP_MASK 25
  461. #define cxtCLR_CMP_CNTL 26
  462. #define cxtGUI_TRAJ_CNTL 27
  463. #define cxtCONTEXT_LOAD_CNTL 28
  464. BYTE *ContextBaseAddress(PDEV *ppdev)
  465. {
  466. ULONG context_addr = 0;
  467. DWORD mem_cntl;
  468. mem_cntl = M64_ID(ppdev->pjMmBase, M64_MEM_CNTL);
  469. switch (mem_cntl & 7)
  470. {
  471. case 0:
  472. context_addr = 0x80000; // 512 K
  473. break;
  474. case 1:
  475. context_addr = 0x100000; // 1 M
  476. break;
  477. case 2:
  478. context_addr = 0x200000;
  479. break;
  480. case 3:
  481. context_addr = 0x400000;
  482. break;
  483. case 4:
  484. context_addr = 0x600000;
  485. break;
  486. case 5:
  487. context_addr = 0x800000;
  488. break;
  489. }
  490. return (BYTE *) context_addr;
  491. }
  492. VOID SetContextWorkspace( PDEV *ppdev, DWORD *context_regs,
  493. DWORD context_mask, DWORD context_load_cntl )
  494. {
  495. BYTE* pjMmBase = ppdev->pjMmBase;
  496. INT i;
  497. for (i = 0; i < 64; i++)
  498. context_regs[i] = 0;
  499. context_regs[ 0] = context_mask;
  500. if (context_mask & 0x00000004)
  501. *(context_regs+ 2) = M64_ID(pjMmBase, DST_OFF_PITCH);
  502. if (context_mask & 0x00000008)
  503. *(context_regs+ 3) = M64_ID(pjMmBase, DST_Y_X);
  504. if (context_mask & 0x00000010)
  505. *(context_regs+ 4) = M64_ID(pjMmBase, DST_HEIGHT_WIDTH);
  506. if (context_mask & 0x00000020)
  507. *(context_regs+ 5) = M64_ID(pjMmBase, DST_BRES_ERR);
  508. if (context_mask & 0x00000040)
  509. *(context_regs+ 6) = M64_ID(pjMmBase, DST_BRES_INC);
  510. if (context_mask & 0x00000080)
  511. *(context_regs+ 7) = M64_ID(pjMmBase, DST_BRES_DEC);
  512. if (context_mask & 0x00000100)
  513. *(context_regs+ 8) = M64_ID(pjMmBase, SRC_OFF_PITCH);
  514. if (context_mask & 0x00000200)
  515. *(context_regs+ 9) = M64_ID(pjMmBase, SRC_Y_X);
  516. if (context_mask & 0x00000400)
  517. *(context_regs+10) = M64_ID(pjMmBase, SRC_HEIGHT1_WIDTH1);
  518. if (context_mask & 0x00000800)
  519. *(context_regs+11) = M64_ID(pjMmBase, SRC_Y_X_START);
  520. if (context_mask & 0x00001000)
  521. *(context_regs+12) = M64_ID(pjMmBase, SRC_HEIGHT2_WIDTH2);
  522. if (context_mask & 0x00002000)
  523. *(context_regs+13) = M64_ID(pjMmBase, PAT_REG0);
  524. if (context_mask & 0x00004000)
  525. *(context_regs+14) = M64_ID(pjMmBase, PAT_REG1);
  526. if (context_mask & 0x00008000)
  527. *(context_regs+15) = M64_ID(pjMmBase, SC_LEFT_RIGHT);
  528. if (context_mask & 0x00010000)
  529. *(context_regs+16) = M64_ID(pjMmBase, SC_TOP_BOTTOM);
  530. if (context_mask & 0x00020000)
  531. *(context_regs+17) = M64_ID(pjMmBase, DP_BKGD_CLR);
  532. if (context_mask & 0x00040000)
  533. *(context_regs+18) = M64_ID(pjMmBase, DP_FRGD_CLR);
  534. if (context_mask & 0x00080000)
  535. *(context_regs+19) = M64_ID(pjMmBase, DP_WRITE_MASK);
  536. if (context_mask & 0x00100000)
  537. *(context_regs+20) = M64_ID(pjMmBase, DP_CHAIN_MASK);
  538. if (context_mask & 0x00200000)
  539. *(context_regs+21) = M64_ID(pjMmBase, DP_PIX_WIDTH);
  540. if (context_mask & 0x00400000)
  541. *(context_regs+22) = M64_ID(pjMmBase, DP_MIX);
  542. if (context_mask & 0x00800000)
  543. *(context_regs+23) = M64_ID(pjMmBase, DP_SRC);
  544. if (context_mask & 0x01000000)
  545. *(context_regs+24) = M64_ID(pjMmBase, CLR_CMP_CLR);
  546. if (context_mask & 0x02000000)
  547. *(context_regs+25) = M64_ID(pjMmBase, CLR_CMP_MSK);
  548. if (context_mask & 0x04000000)
  549. *(context_regs+26) = M64_ID(pjMmBase, CLR_CMP_CNTL);
  550. if (context_mask & 0x08000000)
  551. *(context_regs+27) = M64_ID(pjMmBase, GUI_TRAJ_CNTL);
  552. context_regs[28] = context_load_cntl;
  553. }
  554. VOID UploadContext( PDEV *ppdev, DWORD *context_regs, BYTE *context_addr )
  555. {
  556. BYTE* pjMmBase = ppdev->pjMmBase;
  557. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
  558. M64_OD(pjMmBase, CLR_CMP_CNTL, 0 );
  559. M64_OD(pjMmBase, SC_LEFT_RIGHT, (255) << 16 );
  560. M64_OD(pjMmBase, SC_TOP_BOTTOM, 0 );
  561. M64_OD(pjMmBase, DP_SRC, DP_SRC_Host << 8 );
  562. M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir );
  563. M64_OD(pjMmBase, DP_MIX, OVERPAINT << 16 );
  564. M64_OD(pjMmBase, DP_PIX_WIDTH, DP_PIX_WIDTH_8bpp | (DP_PIX_WIDTH_8bpp << 16) );
  565. M64_OD(pjMmBase, DST_OFF_PITCH,
  566. (ULONG)((ULONG_PTR) context_addr/8 | (256 << 19) ));
  567. M64_OD(pjMmBase, DST_Y_X, 0 );
  568. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, 0x01000001 ); // 256x1
  569. vM64DataPortOutB(ppdev, (BYTE *)context_regs, 256);
  570. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  571. M64_OD(pjMmBase, DST_OFF_PITCH, ppdev->ulScreenOffsetAndPitch );
  572. M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth );
  573. M64_OD(pjMmBase, SC_LEFT_RIGHT, M64_MAX_SCISSOR_R << 16 );
  574. M64_OD(pjMmBase, SC_TOP_BOTTOM, ppdev->cyMemory << 16 );
  575. }
  576. VOID vSetDefaultContext(PDEV * ppdev)
  577. {
  578. DWORD work_context [64];
  579. SetContextWorkspace( ppdev, work_context,
  580. _bit(cxtCONTEXT_MASK) |
  581. _bit(cxtDP_WRITE_MASK) |
  582. _bit(cxtCLR_CMP_CNTL) |
  583. _bit(cxtGUI_TRAJ_CNTL),
  584. 0);
  585. // Fix vanishing text and fills, as well as other color problems:
  586. work_context[cxtDP_WRITE_MASK] = 0xFFFFFFFF;
  587. work_context[cxtCLR_CMP_CNTL] = 0;
  588. // Fix frizzy text and RGB ordering problems:
  589. work_context[cxtGUI_TRAJ_CNTL] = DST_CNTL_XDir | DST_CNTL_YDir;
  590. UploadContext( ppdev, work_context, CONTEXT_ADDR(ppdev,ppdev->iDefContext) );
  591. }
  592. VOID vEnableContexts(PDEV * ppdev)
  593. {
  594. ppdev->pjContextBase = ContextBaseAddress(ppdev);
  595. if (ppdev->cjBank == (LONG)((ULONG_PTR)ppdev->pjContextBase))
  596. ppdev->ulContextCeiling =(ULONG)((ULONG_PTR)ppdev->pjContextBase - 1024);
  597. else
  598. ppdev->ulContextCeiling = (ULONG)((ULONG_PTR) ppdev->pjContextBase);
  599. // Compute ALL context pointers needed in the driver.
  600. ppdev->iDefContext = (ULONG)((ULONG_PTR)ppdev->pjContextBase
  601. - (ULONG_PTR)ppdev->ulContextCeiling)/256;
  602. ppdev->ulContextCeiling -= 256;
  603. // In general, you need to check whether a context allocation will decrease
  604. // cyMemory. Here, we only have the one and FIRST allocation, so decrement cyMemory.
  605. ppdev->cyMemory--;
  606. }
  607. ////////////////////////////////////////////////////////////////////////////////
  608. // DataPortOutB routine for the mach64
  609. //
  610. VOID vM64DataPortOutB(PDEV *ppdev, PBYTE pb, UINT count)
  611. {
  612. PBYTE pjMmBase = ppdev->pjMmBase;
  613. UINT i, DWLeft, LastBytes;
  614. DWORD UNALIGNED *pdw;
  615. PBYTE Byte_in_Dword;
  616. DWORD Buffer;
  617. #define THRESH 14
  618. pdw = (DWORD*)pb;
  619. DWLeft = (count + 3)/4;
  620. LastBytes = count % 4;
  621. while ( DWLeft > 0 )
  622. {
  623. if (DWLeft < THRESH || (DWLeft == THRESH && LastBytes != 0))
  624. {
  625. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, DWLeft);
  626. if (LastBytes > 0)
  627. {
  628. for (i=0; i< DWLeft-1 ; i++)
  629. M64_OD(pjMmBase, HOST_DATA0, *(pdw+i));
  630. Byte_in_Dword = (PBYTE) (pdw+i);
  631. Buffer = 0;
  632. for (i=0; i < LastBytes; i++)
  633. {
  634. Buffer |= (*Byte_in_Dword) << (i*8);
  635. Byte_in_Dword++;
  636. }
  637. M64_OD(pjMmBase, HOST_DATA0, Buffer);
  638. }
  639. else
  640. {
  641. for (i=0; i< DWLeft ; i++)
  642. M64_OD(pjMmBase, HOST_DATA0, *(pdw+i));
  643. }
  644. pdw += DWLeft;
  645. DWLeft = 0;
  646. }
  647. else
  648. {
  649. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  650. /* Inline coded for greater performance */
  651. M64_OD(pjMmBase, HOST_DATA0, *(pdw)); // 1 Word
  652. M64_OD(pjMmBase, HOST_DATA0, *(pdw+1)); // 2 Words
  653. M64_OD(pjMmBase, HOST_DATA0, *(pdw+2)); // 3 Words
  654. M64_OD(pjMmBase, HOST_DATA0, *(pdw+3)); // 4 Words
  655. M64_OD(pjMmBase, HOST_DATA0, *(pdw+4)); // 5 Words
  656. M64_OD(pjMmBase, HOST_DATA0, *(pdw+5)); // 6 Words
  657. M64_OD(pjMmBase, HOST_DATA0, *(pdw+6)); // 7 Words
  658. M64_OD(pjMmBase, HOST_DATA0, *(pdw+7)); // 8 Words
  659. M64_OD(pjMmBase, HOST_DATA0, *(pdw+8)); // 9 Words
  660. M64_OD(pjMmBase, HOST_DATA0, *(pdw+9)); // 10 Words
  661. M64_OD(pjMmBase, HOST_DATA0, *(pdw+10)); // 11 Words
  662. M64_OD(pjMmBase, HOST_DATA0, *(pdw+11)); // 12 Words
  663. M64_OD(pjMmBase, HOST_DATA0, *(pdw+12)); // 13 Words
  664. M64_OD(pjMmBase, HOST_DATA0, *(pdw+13)); // 14 Words
  665. pdw += 14;
  666. DWLeft -= THRESH;
  667. } /*if*/
  668. } /* while */
  669. #undef THRESH
  670. }