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.

1515 lines
52 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: bank.c
  3. *
  4. * Functions to control 256 colour VGA banking.
  5. *
  6. * Copyright (c) 1992 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "driver.h"
  9. #include "limits.h"
  10. VOID vBankErrorTrap(PPDEV, ULONG, BANK_JUST);
  11. VOID vBank2Window(PPDEV, ULONG, BANK_JUST, ULONG);
  12. VOID vBank2Window2RW(PPDEV, ULONG, BANK_JUST, ULONG);
  13. VOID vBank2Window1RW(PPDEV, ULONG, BANK_JUST, ULONG);
  14. VOID vBank1Window2RW(PPDEV, ULONG, BANK_JUST);
  15. VOID vBank1Window(PPDEV, ULONG, BANK_JUST);
  16. VOID vPlanar2Window(PPDEV, ULONG, BANK_JUST, ULONG);
  17. VOID vPlanar2Window2RW(PPDEV, ULONG, BANK_JUST, ULONG);
  18. VOID vPlanar2Window1RW(PPDEV, ULONG, BANK_JUST, ULONG);
  19. VOID vPlanar1Window2RW(PPDEV, ULONG, BANK_JUST);
  20. VOID vPlanar1Window(PPDEV, ULONG, BANK_JUST);
  21. /******************************Public*Routine******************************\
  22. * bInitializeNonPlanar(ppdev, pBankInfo)
  23. *
  24. * Initialize for non-planar mode banking.
  25. *
  26. * NOTE: Allocates ppdev->pbiBankInfo and ppdev->pjJustifyTopBank buffers!
  27. \**************************************************************************/
  28. BOOL bInitializeNonPlanar(PPDEV ppdev, VIDEO_BANK_SELECT* pBankInfo)
  29. {
  30. LONG lTotalScans;
  31. LONG lTotalBanks;
  32. ULONG cjBankSize;
  33. ULONG cjGranularity = pBankInfo->Granularity;
  34. LONG lDelta = pBankInfo->BitmapWidthInBytes;
  35. ULONG cjBitmapSize = pBankInfo->BitmapSize;
  36. ASSERTVGA(cjBitmapSize >= ppdev->cyScreen * lDelta, "Not enough vram");
  37. // Set up for non-planar banking:
  38. ppdev->lNextScan = lDelta;
  39. ppdev->vbtBankingType = pBankInfo->BankingType;
  40. ppdev->pfnBankSwitchCode =
  41. (PFN) (((BYTE*)pBankInfo) + pBankInfo->CodeOffset);
  42. // Set all clip rects to invalid; they'll be updated when the first
  43. // bank is mapped in
  44. ppdev->rcl1WindowClip.bottom = -1;
  45. ppdev->rcl2WindowClip[0].bottom = -1;
  46. ppdev->rcl2WindowClip[1].bottom = -1;
  47. // Set up to call the appropriate banking control routines
  48. switch(pBankInfo->BankingType)
  49. {
  50. case VideoBanked1RW:
  51. ppdev->pfnBankControl = vBank1Window;
  52. ppdev->pfnBankControl2Window = vBank2Window1RW;
  53. break;
  54. case VideoBanked1R1W:
  55. ppdev->pfnBankControl = vBank1Window;
  56. ppdev->pfnBankControl2Window = vBank2Window;
  57. break;
  58. case VideoBanked2RW:
  59. ppdev->pfnBankControl = vBank1Window2RW;
  60. ppdev->pfnBankControl2Window = vBank2Window2RW;
  61. // Offset from one bank index to next to make two 32k banks
  62. // appear to be one seamless 64k bank:
  63. ppdev->ulBank2RWSkip = BANK_SIZE_2RW_WINDOW / cjGranularity;
  64. break;
  65. default:
  66. RIP("Bad BankingType");
  67. return(FALSE);
  68. }
  69. // Set up the bank control tables with clip rects for banks
  70. // Note: lTotalBanks is generally an overestimate when granularity
  71. // is less than window size, because we ignore any banks after the
  72. // first one that includes the last scan line of the bitmap. A bit
  73. // of memory could be saved by sizing lTotalBanks exactly. Note too,
  74. // though, that the 2 RW window case may require more entries then,
  75. // because its windows are shorter, so you'd have to make sure there
  76. // were enough entries for the 2 RW window case, or recalculate
  77. // lTotalBanks for the 2 RW case
  78. lTotalBanks = (cjBitmapSize + cjGranularity - 1) / cjGranularity;
  79. lTotalScans = cjBitmapSize / lDelta;
  80. ppdev->cTotalScans = lTotalScans;
  81. ppdev->pbiBankInfo = (PBANK_INFO) EngAllocMem(FL_ZERO_MEMORY,
  82. lTotalBanks * sizeof(BANK_INFO), ALLOC_TAG);
  83. if (ppdev->pbiBankInfo == NULL)
  84. {
  85. DISPDBG((0, "VGA256: Couldn't get memory for bank info"));
  86. return(FALSE);
  87. }
  88. ppdev->pjJustifyTopBank = (BYTE*) EngAllocMem(0, lTotalScans, ALLOC_TAG);
  89. if (ppdev->pjJustifyTopBank == NULL)
  90. {
  91. DISPDBG((0, "VGA256: Couldn't get memory for JustifyTopBank table"));
  92. return(FALSE);
  93. }
  94. // For 2 RW windows, windows are assumed to be 32k in size, otherwise
  95. // assumed to be 64k:
  96. if (pBankInfo->BankingType == VideoBanked2RW)
  97. cjBankSize = BANK_SIZE_2RW_WINDOW;
  98. else
  99. cjBankSize = BANK_SIZE_1_WINDOW;
  100. if ((cjGranularity + lDelta) >= cjBankSize &&
  101. (cjGranularity % lDelta) != 0)
  102. {
  103. // Oh no, we've got broken rasters (where a scan line crosses
  104. // a bank boundary):
  105. RIP("Oops, broken rasters not yet handled");
  106. return(FALSE);
  107. }
  108. else
  109. {
  110. // We now fill in the scan-to-bank look-up and bank tables:
  111. LONG iScan = 0;
  112. ULONG iBank = 0;
  113. ULONG cjScan = 0;
  114. ULONG cjNextBank = cjGranularity;
  115. ULONG cjEndOfBank = cjBankSize;
  116. PBANK_INFO pbiWorking = ppdev->pbiBankInfo;
  117. while (TRUE)
  118. {
  119. pbiWorking->ulBankOffset = cjNextBank - cjGranularity;
  120. // There are no broken rasters, so don't worry about left and right
  121. // edges:
  122. pbiWorking->rclBankBounds.left = LONG_MIN + 1; // +1 to avoid
  123. // compiler warn
  124. pbiWorking->rclBankBounds.right = LONG_MAX;
  125. pbiWorking->rclBankBounds.top = iScan;
  126. pbiWorking->rclBankBounds.bottom = iScan +
  127. (cjEndOfBank - cjScan) / lDelta;
  128. // We don't need any more banks if we can see to the end
  129. // of the bitmap with the current bank:
  130. if (cjScan + cjBankSize >= cjBitmapSize)
  131. break;
  132. while (cjScan < cjNextBank)
  133. {
  134. ppdev->pjJustifyTopBank[iScan++] = (BYTE) iBank;
  135. cjScan += lDelta;
  136. }
  137. // Get ready for next bank:
  138. cjNextBank += cjGranularity;
  139. cjEndOfBank += cjGranularity;
  140. pbiWorking++;
  141. iBank++;
  142. }
  143. // Clean up the last scans:
  144. ppdev->iLastBank = iBank;
  145. pbiWorking->rclBankBounds.bottom = lTotalScans;
  146. while (iScan < lTotalScans)
  147. {
  148. ppdev->pjJustifyTopBank[iScan++] = (BYTE) iBank;
  149. }
  150. // We've just computed the precise table for JustifyTop; we now
  151. // compute the scan offset for determining JustifyBottom:
  152. ASSERTVGA(cjBankSize >= cjGranularity,
  153. "Device says granularity more than bank size?");
  154. ppdev->ulJustifyBottomOffset = (cjBankSize - cjGranularity) / lDelta;
  155. // ulJustifyBottomOffset must be less than the number of scans
  156. // that fit entirely in any bank less the granularity size; if
  157. // our width doesn't divide evenly into the granularity, we'll
  158. // have to adjust the value to account for the first scan not
  159. // starting at offset 0 in any bank:
  160. if ((cjGranularity % lDelta) != 0 && ppdev->ulJustifyBottomOffset > 0)
  161. ppdev->ulJustifyBottomOffset--;
  162. }
  163. return(TRUE);
  164. }
  165. /******************************Public*Routine******************************\
  166. * bInitializePlanar(ppdev, pBankInfo)
  167. *
  168. * Initialize for non-planar mode banking.
  169. *
  170. * NOTE: Allocates ppdev->pbiPlanarInfo and ppdev->pjJustifyTopPlanar buffers!
  171. \**************************************************************************/
  172. BOOL bInitializePlanar(PPDEV ppdev, VIDEO_BANK_SELECT* pBankInfo)
  173. {
  174. LONG lTotalScans;
  175. LONG lTotalBanks;
  176. ULONG cjBankSize;
  177. ULONG cjGranularity = pBankInfo->PlanarHCGranularity;
  178. // Since we're in planar mode, every byte we see actually represents
  179. // four bytes of video memory:
  180. LONG lDelta = pBankInfo->BitmapWidthInBytes / 4;
  181. ULONG cjBitmapSize = pBankInfo->BitmapSize / 4;
  182. ppdev->fl |= DRIVER_PLANAR_CAPABLE;
  183. // Set all clip rects to invalid; they'll be updated when the first
  184. // bank is mapped in
  185. ppdev->rcl1PlanarClip.bottom = -1;
  186. ppdev->rcl2PlanarClip[0].bottom = -1;
  187. ppdev->rcl2PlanarClip[1].bottom = -1;
  188. // Set up for planar banking:
  189. ppdev->pfnPlanarSwitchCode =
  190. (PFN) (((BYTE*)pBankInfo) + pBankInfo->PlanarHCBankCodeOffset);
  191. ppdev->pfnPlanarEnable =
  192. (PFN) (((BYTE*)pBankInfo) + pBankInfo->PlanarHCEnableCodeOffset);
  193. ppdev->pfnPlanarDisable =
  194. (PFN) (((BYTE*)pBankInfo) + pBankInfo->PlanarHCDisableCodeOffset);
  195. ppdev->lPlanarNextScan = lDelta;
  196. ppdev->vbtPlanarType = pBankInfo->PlanarHCBankingType;
  197. // Set up to call the appropriate banking control routines
  198. switch(ppdev->vbtPlanarType)
  199. {
  200. case VideoBanked1RW:
  201. ppdev->pfnPlanarControl = vPlanar1Window;
  202. ppdev->pfnPlanarControl2 = vPlanar2Window1RW;
  203. break;
  204. case VideoBanked1R1W:
  205. ppdev->pfnPlanarControl = vPlanar1Window;
  206. ppdev->pfnPlanarControl2 = vPlanar2Window;
  207. break;
  208. case VideoBanked2RW:
  209. ppdev->pfnPlanarControl = vPlanar1Window2RW;
  210. ppdev->pfnPlanarControl2 = vPlanar2Window2RW;
  211. // Offset from one bank index to next to make two 32k banks
  212. // appear to be one seamless 64k bank:
  213. ppdev->ulPlanar2RWSkip = BANK_SIZE_2RW_WINDOW / cjGranularity;
  214. break;
  215. default:
  216. RIP("Bad BankingType");
  217. return(FALSE);
  218. }
  219. lTotalBanks = (cjBitmapSize + cjGranularity - 1) / cjGranularity;
  220. lTotalScans = cjBitmapSize / lDelta;
  221. ppdev->pbiPlanarInfo = (PBANK_INFO) EngAllocMem(FL_ZERO_MEMORY,
  222. lTotalBanks * sizeof(BANK_INFO), ALLOC_TAG);
  223. if (ppdev->pbiPlanarInfo == NULL)
  224. {
  225. DISPDBG((0, "VGA256: Couldn't get memory for bank info"));
  226. return(FALSE);
  227. }
  228. ppdev->pjJustifyTopPlanar = (BYTE*) EngAllocMem(0, lTotalScans, ALLOC_TAG);
  229. if (ppdev->pjJustifyTopPlanar == NULL)
  230. {
  231. DISPDBG((0, "VGA256: Couldn't get memory for JustifyTopBank table"));
  232. return(FALSE);
  233. }
  234. // For 2 RW windows, windows are assumed to be 32k in size, otherwise
  235. // assumed to be 64k:
  236. if (pBankInfo->BankingType == VideoBanked2RW)
  237. cjBankSize = BANK_SIZE_2RW_WINDOW;
  238. else
  239. cjBankSize = BANK_SIZE_1_WINDOW;
  240. if ((cjGranularity + lDelta) >= cjBankSize &&
  241. (cjGranularity % lDelta) != 0)
  242. {
  243. // Oh no, we've got broken rasters (where a scan line crosses
  244. // a bank boundary):
  245. DISPDBG((0, "Can't handle broken planar rasters"));
  246. ppdev->fl &= ~DRIVER_PLANAR_CAPABLE;// !!! Temporary, until we handle
  247. return(TRUE); // broken rasters in planar copy
  248. }
  249. else
  250. {
  251. // We now fill in the scan-to-bank look-up and bank tables:
  252. LONG iScan = 0;
  253. ULONG iBank = 0;
  254. ULONG cjScan = 0;
  255. ULONG cjNextBank = cjGranularity;
  256. ULONG cjEndOfBank = cjBankSize;
  257. PBANK_INFO pbiWorking = ppdev->pbiPlanarInfo;
  258. while (TRUE)
  259. {
  260. pbiWorking->ulBankOffset = cjNextBank - cjGranularity;
  261. // There are no broken rasters, so don't worry about left and right
  262. // edges:
  263. pbiWorking->rclBankBounds.left = LONG_MIN + 1; // +1 to avoid
  264. // compiler warn
  265. pbiWorking->rclBankBounds.right = LONG_MAX;
  266. pbiWorking->rclBankBounds.top = iScan;
  267. pbiWorking->rclBankBounds.bottom = iScan +
  268. (cjEndOfBank - cjScan) / lDelta;
  269. // We don't need any more banks if we can see to the end
  270. // of the bitmap with the current bank:
  271. if (cjScan + cjBankSize >= cjBitmapSize)
  272. break;
  273. while (cjScan < cjNextBank)
  274. {
  275. ppdev->pjJustifyTopPlanar[iScan++] = (BYTE) iBank;
  276. cjScan += lDelta;
  277. }
  278. // Get ready for next bank:
  279. cjNextBank += cjGranularity;
  280. cjEndOfBank += cjGranularity;
  281. pbiWorking++;
  282. iBank++;
  283. }
  284. // Clean up the last scans:
  285. ppdev->iLastPlanar = iBank;
  286. pbiWorking->rclBankBounds.bottom = lTotalScans;
  287. while (iScan < lTotalScans)
  288. {
  289. ppdev->pjJustifyTopPlanar[iScan++] = (BYTE) iBank;
  290. }
  291. // We've just computed the precise table for JustifyTop; we now
  292. // compute the scan offset for determining JustifyBottom:
  293. ASSERTVGA(cjBankSize >= cjGranularity,
  294. "Device says granularity more than bank size?");
  295. ppdev->ulPlanarBottomOffset = (cjBankSize - cjGranularity) / lDelta;
  296. // ulPlanarBottomOffset must be less than the number of scans
  297. // that fit entirely in any bank less the granularity size; if
  298. // our width doesn't divide evenly into the granularity, we'll
  299. // have to adjust the value to account for the first scan not
  300. // starting at offset 0 in any bank:
  301. if ((cjGranularity % lDelta) != 0 && ppdev->ulPlanarBottomOffset > 0)
  302. ppdev->ulPlanarBottomOffset--;
  303. }
  304. return(TRUE);
  305. }
  306. /******************************Public*Routine******************************\
  307. * bEnableBanking(ppdev)
  308. *
  309. * Set up banking for the current mode
  310. * pdsurf and ppdev are the pointers to the current surface and device
  311. * Relevant fields in the surface are set up for banking
  312. \**************************************************************************/
  313. BOOL bEnableBanking(PPDEV ppdev)
  314. {
  315. PVIDEO_BANK_SELECT pBankInfo;
  316. UINT ReturnedDataLength;
  317. VIDEO_BANK_SELECT TempBankInfo;
  318. DWORD status;
  319. // Make sure we've set to NULL any pointers to buffers that we allocate,
  320. // so that we can free them in our error path:
  321. ppdev->pBankInfo = NULL;
  322. ppdev->pjJustifyTopBank = NULL;
  323. ppdev->pbiBankInfo = NULL;
  324. ppdev->pjJustifyTopPlanar = NULL;
  325. ppdev->pbiPlanarInfo = NULL;
  326. // Query the miniport for banking info for this mode.
  327. //
  328. // First, figure out how big a buffer we need for the banking info
  329. // (returned in TempBankInfo->Size).
  330. if (status = EngDeviceIoControl(ppdev->hDriver,
  331. IOCTL_VIDEO_GET_BANK_SELECT_CODE,
  332. NULL, // input buffer
  333. 0,
  334. (LPVOID) &TempBankInfo, // output buffer
  335. sizeof(VIDEO_BANK_SELECT),
  336. &ReturnedDataLength))
  337. {
  338. // We expect this call to fail, because we didn't allow any room
  339. // for the code; we just want to get the required output buffer
  340. // size.
  341. }
  342. // Now, allocate a buffer of the required size and get the banking info.
  343. pBankInfo = (PVIDEO_BANK_SELECT) EngAllocMem(FL_ZERO_MEMORY,
  344. TempBankInfo.Size, ALLOC_TAG);
  345. if (pBankInfo == NULL)
  346. {
  347. DISPDBG((0, "VGA256: Initialization error-couldn't get memory for bank info"));
  348. goto error;
  349. }
  350. // Remember it so we can free it later:
  351. ppdev->pBankInfo = pBankInfo;
  352. if (EngDeviceIoControl(ppdev->hDriver,
  353. IOCTL_VIDEO_GET_BANK_SELECT_CODE,
  354. NULL,
  355. 0,
  356. (LPVOID) pBankInfo,
  357. TempBankInfo.Size,
  358. &ReturnedDataLength))
  359. {
  360. RIP("Initialization error-GetBankSelectCode, second call");
  361. goto error;
  362. }
  363. // Set up for banking:
  364. ppdev->ulBitmapSize = pBankInfo->BitmapSize;
  365. if (!bInitializeNonPlanar(ppdev, pBankInfo))
  366. goto error;
  367. if (pBankInfo->BankingFlags & PLANAR_HC)
  368. {
  369. ppdev->fl |= DRIVER_PLANAR_CAPABLE;
  370. if (!bInitializePlanar(ppdev, pBankInfo))
  371. goto error;
  372. }
  373. // Map in scan line 0 for read & write, to put things in a known state:
  374. ppdev->pfnBankControl(ppdev, 0, JustifyTop);
  375. return(TRUE);
  376. // Error path:
  377. error:
  378. vDisableBanking(ppdev);
  379. return(FALSE);
  380. }
  381. /******************************Public*Routine******************************\
  382. * vDisableBanking(ppdev)
  383. *
  384. * Disable banking for the current mode
  385. \**************************************************************************/
  386. VOID vDisableBanking(PPDEV ppdev)
  387. {
  388. EngFreeMem((LPVOID) ppdev->pBankInfo);
  389. EngFreeMem((LPVOID) ppdev->pjJustifyTopBank);
  390. EngFreeMem((LPVOID) ppdev->pbiBankInfo);
  391. EngFreeMem((LPVOID) ppdev->pjJustifyTopPlanar);
  392. EngFreeMem((LPVOID) ppdev->pbiPlanarInfo);
  393. }
  394. /******************************Private*Routine******************************\
  395. * vBankErrorTrap
  396. *
  397. * Traps calls to bank control functions in non-banked modes
  398. *
  399. \**************************************************************************/
  400. VOID vBankErrorTrap(PPDEV ppdev, ULONG lScan, BANK_JUST ulJustification)
  401. {
  402. DISPDBG((0,"Call to bank manager in unbanked mode"));
  403. }
  404. /******************************Private*Routine******************************\
  405. * vBank1Window
  406. *
  407. * Maps in a single R/W window that allows access to lScan. Applies to both
  408. * 1 RW window and 1R1W window banking schemes.
  409. *
  410. \**************************************************************************/
  411. VOID vBank1Window(PPDEV ppdev, ULONG lScan, BANK_JUST ulJustification)
  412. {
  413. ULONG ulBank;
  414. PBANK_INFO pbiWorking;
  415. volatile ULONG ulBank0;
  416. volatile PFN pBankFn;
  417. BANK_POSITION BankPosition;
  418. ULONG ulReturn;
  419. // ASM routines that call this may have STD in effect, but the C compiler
  420. // assumes CLD
  421. _asm pushfd
  422. _asm cld
  423. // Set the clip rect for this bank; if it's set to -1, that indicates that
  424. // a double-window set-up is currently active, so invalidate double-window
  425. // clip rects and display memory pointers (when double-window is active,
  426. // single-window is inactive, and vice-versa; a full bank set-up has to be
  427. // performed to switch between the two)
  428. if (ppdev->rcl1WindowClip.bottom == -1)
  429. {
  430. if (ppdev->flBank & BANK_PLANAR)
  431. {
  432. ppdev->flBank &= ~BANK_PLANAR;
  433. ppdev->pfnPlanarDisable();
  434. }
  435. ppdev->rcl2WindowClip[0].bottom = -1;
  436. ppdev->rcl2WindowClip[1].bottom = -1;
  437. ppdev->rcl1PlanarClip.bottom = -1;
  438. ppdev->rcl2PlanarClip[0].bottom = -1;
  439. ppdev->rcl2PlanarClip[1].bottom = -1;
  440. }
  441. ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode");
  442. // Find the bank containing the scan line with the desired justification:
  443. {
  444. register LONG lSearchScan = (LONG)lScan;
  445. if (ulJustification == JustifyBottom)
  446. {
  447. lSearchScan -= ppdev->ulJustifyBottomOffset;
  448. if (lSearchScan <= 0)
  449. lSearchScan = 0;
  450. }
  451. ulBank = (ULONG) ppdev->pjJustifyTopBank[lSearchScan];
  452. pbiWorking = &ppdev->pbiBankInfo[ulBank];
  453. }
  454. ASSERTVGA(pbiWorking->rclBankBounds.top <= (LONG)lScan &&
  455. pbiWorking->rclBankBounds.bottom > (LONG)lScan,
  456. "Oops, scan not in bank");
  457. ppdev->rcl1WindowClip = pbiWorking->rclBankBounds;
  458. // Shift the bitmap start address so that the desired bank aligns with
  459. // the banking window. The source and destination are set only so 1 R/W
  460. // aligned blits will work without having to be specifically aware of
  461. // the adapter type (some of the same code works with 1R/1W adapters too).
  462. ppdev->pvBitmapStart = (PVOID) (ppdev->pjScreen - pbiWorking->ulBankOffset);
  463. ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart;
  464. ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart;
  465. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  466. // Map in the desired bank for both read and write
  467. // This is so convoluted to avoid problems with wiping out registers C
  468. // thinks it's still using; the values are tranferred to volatiles, and
  469. // then to registers
  470. ulBank0 = ulBank;
  471. if (ppdev->BankIoctlSupported) {
  472. static ulBankOld = -1;
  473. if (ulBank0 != ulBankOld) {
  474. ulBankOld = ulBank0;
  475. BankPosition.ReadBankPosition = ulBank0;
  476. BankPosition.WriteBankPosition = ulBank0;
  477. EngDeviceIoControl(ppdev->hDriver,
  478. IOCTL_VIDEO_SET_BANK_POSITION,
  479. &BankPosition,
  480. sizeof(BANK_POSITION),
  481. NULL,
  482. 0,
  483. &ulReturn);
  484. }
  485. } else {
  486. pBankFn = ppdev->pfnBankSwitchCode;
  487. _asm mov eax,ulBank0;
  488. _asm mov edx,eax;
  489. _asm call pBankFn; // actually switch the banks
  490. }
  491. _asm popfd
  492. }
  493. /******************************Private*Routine******************************\
  494. * vBank1Window2RW
  495. *
  496. * Maps in two 32K RW windows so that they form a single 64K R/W window that
  497. * allows access to lScan. Applies only to 2 RW window schemes.
  498. *
  499. \**************************************************************************/
  500. VOID vBank1Window2RW(PPDEV ppdev, ULONG lScan, BANK_JUST ulJustification)
  501. {
  502. ULONG ulBank0;
  503. ULONG ulBank1;
  504. volatile PFN pBankFn;
  505. // ASM routines that call this may have STD in effect, but the C compiler
  506. // assumes CLD
  507. _asm pushfd
  508. _asm cld
  509. // Set the clip rect for this bank; if it's set to -1, that indicates that
  510. // a double-window set-up is currently active, so invalidate double-window
  511. // clip rects and display memory pointers (when double-window is active,
  512. // single-window is inactive, and vice-versa; a full bank set-up has to be
  513. // performed to switch between the two)
  514. if (ppdev->rcl1WindowClip.bottom == -1)
  515. {
  516. if (ppdev->flBank & BANK_PLANAR)
  517. {
  518. ppdev->flBank &= ~BANK_PLANAR;
  519. ppdev->pfnPlanarDisable();
  520. }
  521. ppdev->rcl2WindowClip[0].bottom = -1;
  522. ppdev->rcl2WindowClip[1].bottom = -1;
  523. ppdev->rcl1PlanarClip.bottom = -1;
  524. ppdev->rcl2PlanarClip[0].bottom = -1;
  525. ppdev->rcl2PlanarClip[1].bottom = -1;
  526. }
  527. ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode");
  528. // Find the bank containing the scan line with the desired justification:
  529. if (ulJustification == JustifyTop)
  530. {
  531. ulBank0 = ppdev->pjJustifyTopBank[lScan];
  532. ulBank1 = ulBank0 + ppdev->ulBank2RWSkip;
  533. if (ulBank1 >= ppdev->iLastBank)
  534. {
  535. ulBank1 = ppdev->iLastBank;
  536. ulBank0 = ulBank1 - ppdev->ulBank2RWSkip;
  537. }
  538. }
  539. else
  540. {
  541. lScan -= ppdev->ulJustifyBottomOffset;
  542. if ((LONG)lScan <= 0)
  543. lScan = 0;
  544. ulBank1 = ppdev->pjJustifyTopBank[lScan];
  545. ulBank0 = ulBank1 - ppdev->ulBank2RWSkip;
  546. if ((LONG) ulBank0 < 0)
  547. {
  548. ulBank0 = 0;
  549. ulBank1 = ppdev->ulBank2RWSkip;
  550. }
  551. }
  552. ppdev->rcl1WindowClip.left = ppdev->pbiBankInfo[ulBank0].rclBankBounds.left;
  553. ppdev->rcl1WindowClip.top = ppdev->pbiBankInfo[ulBank0].rclBankBounds.top;
  554. ppdev->rcl1WindowClip.bottom = ppdev->pbiBankInfo[ulBank1].rclBankBounds.bottom;
  555. ppdev->rcl1WindowClip.right = ppdev->pbiBankInfo[ulBank1].rclBankBounds.right;
  556. // Shift the bitmap start address so that the desired bank aligns with
  557. // the banking window. The source and destination are set only so 1 R/W
  558. // aligned blits will work without having to be specifically aware of
  559. // the adapter type (some of the same code works with 1R/1W adapters too).
  560. ppdev->pvBitmapStart = (PVOID) ((BYTE*)ppdev->pjScreen
  561. - ppdev->pbiBankInfo[ulBank0].ulBankOffset);
  562. ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart;
  563. ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart;
  564. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  565. // Map in the desired bank for both read and write; this is accomplished
  566. // by mapping in the desired 32K bank, followed by the next 32K bank.
  567. // This is so convoluted to avoid problems with wiping out registers C
  568. // thinks it's still using; the values are tranferred to volatiles, and
  569. // then to registers
  570. pBankFn = ppdev->pfnBankSwitchCode;
  571. _asm mov eax,ulBank0;
  572. _asm mov edx,ulBank1;
  573. _asm call pBankFn; // actually switch the banks
  574. _asm popfd;
  575. }
  576. /******************************Private*Routine******************************\
  577. * vBank2Window
  578. *
  579. * Maps in one of two windows, either the source window (window 0) or the dest
  580. * window (window 1), to allows access to lScan. Applies to 1R1W window
  581. * banking scheme; should never be called for 1 RW window schemes, because
  582. * there's only one window in that case.
  583. *
  584. \**************************************************************************/
  585. VOID vBank2Window(
  586. PPDEV ppdev,
  587. ULONG lScan,
  588. BANK_JUST ulJustification,
  589. ULONG ulWindowToMap)
  590. {
  591. ULONG ulBank;
  592. PBANK_INFO pbiWorking;
  593. volatile ULONG ulBank0;
  594. volatile ULONG ulBank1;
  595. volatile PFN pBankFn;
  596. // ASM routines that call this may have STD in effect, but the C compiler
  597. // assumes CLD
  598. _asm pushfd
  599. _asm cld
  600. // Find the bank containing the scan line with the desired justification:
  601. if (ulJustification == JustifyBottom)
  602. {
  603. lScan -= ppdev->ulJustifyBottomOffset;
  604. if ((LONG)lScan <= 0)
  605. lScan = 0;
  606. }
  607. ulBank = (ULONG) ppdev->pjJustifyTopBank[lScan];
  608. pbiWorking = &ppdev->pbiBankInfo[ulBank];
  609. // Set the clip rect for this bank; if it's set to -1, that indicates that
  610. // a single-window set-up is currently active, so invalidate single-window
  611. // clip rects and display memory pointers (when double-window is active,
  612. // single-window is inactive, and vice-versa; a full bank set-up has to be
  613. // performed to switch between the two)
  614. if (ppdev->rcl2WindowClip[ulWindowToMap].bottom == -1)
  615. {
  616. ULONG ulOtherWindow = ulWindowToMap ^ 1;
  617. if (ppdev->flBank & BANK_PLANAR)
  618. {
  619. ppdev->flBank &= ~BANK_PLANAR;
  620. ppdev->pfnPlanarDisable();
  621. }
  622. ppdev->rcl1WindowClip.bottom = -1;
  623. ppdev->rcl1PlanarClip.bottom = -1;
  624. ppdev->rcl2PlanarClip[0].bottom = -1;
  625. ppdev->rcl2PlanarClip[1].bottom = -1;
  626. // Neither of the 2 window windows was active, so we have to set up the
  627. // variables for the other bank (the one other than the one we were
  628. // called to set) as well, to make it valid. The other bank is set to
  629. // the same state as the bank we were called to set
  630. ppdev->rcl2WindowClip[ulOtherWindow] = pbiWorking->rclBankBounds;
  631. ppdev->ulWindowBank[ulOtherWindow] = ulBank;
  632. ppdev->pvBitmapStart2Window[ulOtherWindow] =
  633. (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset);
  634. }
  635. ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode");
  636. ppdev->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds;
  637. // Shift the bitmap start address so that the desired bank aligns with the
  638. // banking window
  639. ppdev->pvBitmapStart2Window[ulWindowToMap] =
  640. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset);
  641. // Map in the desired bank; also map in the other bank to whatever its
  642. // current state is
  643. ppdev->ulWindowBank[ulWindowToMap] = ulBank;
  644. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  645. // Set both banks at once, because we may have just initialized the other
  646. // bank, and because this way the bank switch code doesn't have to do a
  647. // read before write to obtain the state of the other bank.
  648. // This is so convoluted to avoid problems with wiping out registers C
  649. // thinks it's still using; the values are tranferred to volatiles, and
  650. // then to registers
  651. ulBank0 = ppdev->ulWindowBank[0];
  652. ulBank1 = ppdev->ulWindowBank[1];
  653. pBankFn = ppdev->pfnBankSwitchCode;
  654. _asm mov eax,ulBank0;
  655. _asm mov edx,ulBank1;
  656. _asm call pBankFn; // actually switch the banks
  657. _asm popfd;
  658. }
  659. /******************************Private*Routine******************************\
  660. * vBank2Window1RW
  661. *
  662. * Maps in the one window in 1R/W case. Does exactly the same thing as the
  663. * one window case, because there's only one window, but has to be a separate
  664. * entry point because of the extra parameter (because we're using STDCALL).
  665. \**************************************************************************/
  666. VOID vBank2Window1RW(PPDEV ppdev, ULONG lScan,
  667. BANK_JUST ulJustification, ULONG ulWindowToMap)
  668. {
  669. vBank1Window(ppdev, lScan, ulJustification);
  670. }
  671. /******************************Private*Routine******************************\
  672. * vBank2Window2RW
  673. *
  674. * Maps in one of two windows, either the source window (window 0) or the dest
  675. * window (window 1), to allows access to lScan. Applies to 2RW window
  676. * banking scheme; should never be called for 1 RW window schemes, because
  677. * there's only one window in that case.
  678. \**************************************************************************/
  679. VOID vBank2Window2RW(
  680. PPDEV ppdev,
  681. ULONG lScan,
  682. BANK_JUST ulJustification,
  683. ULONG ulWindowToMap)
  684. {
  685. ULONG ulBank;
  686. PBANK_INFO pbiWorking;
  687. volatile ULONG ulBank0;
  688. volatile ULONG ulBank1;
  689. volatile PFN pBankFn;
  690. // ASM routines that call this may have STD in effect, but the C compiler
  691. // assumes CLD
  692. _asm pushfd
  693. _asm cld
  694. // Find the bank containing the scan line with the desired justification:
  695. if (ulJustification == JustifyBottom)
  696. {
  697. lScan -= ppdev->ulJustifyBottomOffset;
  698. if ((LONG)lScan <= 0)
  699. lScan = 0;
  700. }
  701. ulBank = (ULONG) ppdev->pjJustifyTopBank[lScan];
  702. pbiWorking = &ppdev->pbiBankInfo[ulBank];
  703. // Set the clip rect for this bank; if it's set to -1, that indicates that
  704. // a single-window set-up is currently active, so invalidate single-window
  705. // clip rects and display memory pointers (when double-window is active,
  706. // single-window is inactive, and vice-versa; a full bank set-up has to be
  707. // performed to switch between the two)
  708. if (ppdev->rcl2WindowClip[ulWindowToMap].bottom == -1)
  709. {
  710. if (ppdev->flBank & BANK_PLANAR)
  711. {
  712. ppdev->flBank &= ~BANK_PLANAR;
  713. ppdev->pfnPlanarDisable();
  714. }
  715. ppdev->rcl1WindowClip.bottom = -1;
  716. ppdev->rcl1PlanarClip.bottom = -1;
  717. ppdev->rcl2PlanarClip[0].bottom = -1;
  718. ppdev->rcl2PlanarClip[1].bottom = -1;
  719. // Neither of the 2 window windows was active, so we have to set up the
  720. // variables for the other bank (the one other than the one we were
  721. // called to set) as well, to make it valid. The other bank is set to
  722. // the same state as the bank we were called to set
  723. ppdev->rcl2WindowClip[ulWindowToMap^1] = pbiWorking->rclBankBounds;
  724. if (ulWindowToMap == 1)
  725. {
  726. ppdev->pvBitmapStart2Window[0] =
  727. (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset);
  728. }
  729. else
  730. {
  731. ppdev->pvBitmapStart2Window[1] =
  732. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset +
  733. BANK_SIZE_2RW_WINDOW);
  734. }
  735. ppdev->ulWindowBank[ulWindowToMap^1] = ulBank;
  736. }
  737. ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode");
  738. ppdev->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds;
  739. // Shift the bitmap start address so that the desired bank aligns with the
  740. // banking window
  741. if (ulWindowToMap == 0)
  742. {
  743. ppdev->pvBitmapStart2Window[0] =
  744. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset);
  745. }
  746. else
  747. {
  748. ppdev->pvBitmapStart2Window[1] =
  749. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset +
  750. BANK_SIZE_2RW_WINDOW);
  751. }
  752. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  753. // Map in the desired bank; also map in the other bank to whatever its
  754. // current state is
  755. ppdev->ulWindowBank[ulWindowToMap] = ulBank;
  756. // Set both banks at once, because we may have just initialized the other
  757. // bank, and because this way the bank switch code doesn't have to do a
  758. // read before write to obtain the state of the other bank.
  759. // This is so convoluted to avoid problems with wiping out registers C
  760. // thinks it's still using; the values are tranferred to volatiles, and
  761. // then to registers
  762. ulBank0 = ppdev->ulWindowBank[0];
  763. ulBank1 = ppdev->ulWindowBank[1];
  764. pBankFn = ppdev->pfnBankSwitchCode;
  765. _asm mov eax,ulBank0;
  766. _asm mov edx,ulBank1;
  767. _asm call pBankFn; // actually switch the banks
  768. _asm popfd;
  769. }
  770. /******************************Private*Routine******************************\
  771. * vPlanar1Window
  772. *
  773. * Maps in a single R/W window that allows access to lScan. Applies to both
  774. * 1 RW window and 1R1W window banking schemes.
  775. \**************************************************************************/
  776. VOID vPlanar1Window(PPDEV ppdev, ULONG lScan, BANK_JUST ulJustification)
  777. {
  778. ULONG ulBank;
  779. PBANK_INFO pbiWorking;
  780. volatile ULONG ulBank0;
  781. volatile PFN pBankFn;
  782. // ASM routines that call this may have STD in effect, but the C compiler
  783. // assumes CLD
  784. _asm pushfd
  785. _asm cld
  786. // Set the clip rect for this bank; if it's set to -1, that indicates that
  787. // a double-window set-up is currently active, so invalidate double-window
  788. // clip rects and display memory pointers (when double-window is active,
  789. // single-window is inactive, and vice-versa; a full bank set-up has to be
  790. // performed to switch between the two)
  791. if (ppdev->rcl1PlanarClip.bottom == -1)
  792. {
  793. if (!(ppdev->flBank & BANK_PLANAR))
  794. {
  795. ppdev->flBank |= BANK_PLANAR;
  796. ppdev->pfnPlanarEnable();
  797. }
  798. ppdev->rcl1WindowClip.bottom = -1;
  799. ppdev->rcl2WindowClip[0].bottom = -1;
  800. ppdev->rcl2WindowClip[1].bottom = -1;
  801. ppdev->rcl2PlanarClip[0].bottom = -1;
  802. ppdev->rcl2PlanarClip[1].bottom = -1;
  803. }
  804. ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode");
  805. // Find the bank containing the scan line with the desired justification:
  806. if (ulJustification == JustifyBottom)
  807. {
  808. lScan -= ppdev->ulPlanarBottomOffset;
  809. if ((LONG)lScan <= 0)
  810. lScan = 0;
  811. }
  812. ulBank = (ULONG) ppdev->pjJustifyTopPlanar[lScan];
  813. pbiWorking = &ppdev->pbiPlanarInfo[ulBank];
  814. ppdev->rcl1PlanarClip = pbiWorking->rclBankBounds;
  815. // Shift the bitmap start address so that the desired bank aligns with
  816. // the banking window. The source and destination are set only so 1 R/W
  817. // aligned blits will work without having to be specifically aware of
  818. // the adapter type (some of the same code works with 1R/1W adapters too).
  819. ppdev->pvBitmapStart = (PVOID) (ppdev->pjScreen - pbiWorking->ulBankOffset);
  820. ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart;
  821. ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart;
  822. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  823. // Map in the desired bank for both read and write
  824. // This is so convoluted to avoid problems with wiping out registers C
  825. // thinks it's still using; the values are tranferred to volatiles, and
  826. // then to registers
  827. ulBank0 = ulBank;
  828. pBankFn = ppdev->pfnPlanarSwitchCode;
  829. _asm mov eax,ulBank0;
  830. _asm mov edx,eax;
  831. _asm call pBankFn; // actually switch the banks
  832. _asm popfd
  833. }
  834. /******************************Private*Routine******************************\
  835. * vPlanar1Window2RW
  836. *
  837. * Maps in two 32K RW windows so that they form a single 64K R/W window that
  838. * allows access to lScan. Applies only to 2 RW window schemes.
  839. *
  840. \**************************************************************************/
  841. VOID vPlanar1Window2RW(PPDEV ppdev, ULONG lScan, BANK_JUST ulJustification)
  842. {
  843. ULONG ulBank0;
  844. ULONG ulBank1;
  845. volatile PFN pBankFn;
  846. // ASM routines that call this may have STD in effect, but the C compiler
  847. // assumes CLD
  848. _asm pushfd
  849. _asm cld
  850. // Set the clip rect for this bank; if it's set to -1, that indicates that
  851. // a double-window set-up is currently active, so invalidate double-window
  852. // clip rects and display memory pointers (when double-window is active,
  853. // single-window is inactive, and vice-versa; a full bank set-up has to be
  854. // performed to switch between the two)
  855. if (ppdev->rcl1PlanarClip.bottom == -1)
  856. {
  857. if (!(ppdev->flBank & BANK_PLANAR))
  858. {
  859. ppdev->flBank |= BANK_PLANAR;
  860. ppdev->pfnPlanarEnable();
  861. }
  862. ppdev->rcl1WindowClip.bottom = -1;
  863. ppdev->rcl2WindowClip[0].bottom = -1;
  864. ppdev->rcl2WindowClip[1].bottom = -1;
  865. ppdev->rcl2PlanarClip[0].bottom = -1;
  866. ppdev->rcl2PlanarClip[1].bottom = -1;
  867. }
  868. ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode");
  869. // Find the bank containing the scan line with the desired justification:
  870. if (ulJustification == JustifyTop)
  871. {
  872. ulBank0 = ppdev->pjJustifyTopPlanar[lScan];
  873. ulBank1 = ulBank0 + ppdev->ulPlanar2RWSkip;
  874. if (ulBank1 >= ppdev->iLastPlanar)
  875. ulBank1 = ppdev->iLastPlanar;
  876. }
  877. else
  878. {
  879. lScan -= ppdev->ulPlanarBottomOffset;
  880. if ((LONG)lScan <= 0)
  881. lScan = 0;
  882. ulBank1 = ppdev->pjJustifyTopPlanar[lScan];
  883. ulBank0 = ulBank1 - ppdev->ulPlanar2RWSkip;
  884. if ((LONG) ulBank0 < 0)
  885. ulBank0 = 0;
  886. }
  887. ppdev->rcl1PlanarClip.left = ppdev->pbiPlanarInfo[ulBank0].rclBankBounds.left;
  888. ppdev->rcl1PlanarClip.top = ppdev->pbiPlanarInfo[ulBank0].rclBankBounds.top;
  889. ppdev->rcl1PlanarClip.bottom = ppdev->pbiPlanarInfo[ulBank1].rclBankBounds.bottom;
  890. ppdev->rcl1PlanarClip.right = ppdev->pbiPlanarInfo[ulBank1].rclBankBounds.right;
  891. // Shift the bitmap start address so that the desired bank aligns with
  892. // the banking window. The source and destination are set only so 1 R/W
  893. // aligned blits will work without having to be specifically aware of
  894. // the adapter type (some of the same code works with 1R/1W adapters too).
  895. ppdev->pvBitmapStart = (PVOID) ((BYTE*)ppdev->pjScreen
  896. - ppdev->pbiPlanarInfo[ulBank0].ulBankOffset);
  897. ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart;
  898. ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart;
  899. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  900. // Map in the desired bank for both read and write; this is accomplished
  901. // by mapping in the desired 32K bank, followed by the next 32K bank.
  902. // This is so convoluted to avoid problems with wiping out registers C
  903. // thinks it's still using; the values are tranferred to volatiles, and
  904. // then to registers
  905. pBankFn = ppdev->pfnPlanarSwitchCode;
  906. _asm mov eax,ulBank0;
  907. _asm mov edx,ulBank1;
  908. _asm call pBankFn; // actually switch the banks
  909. _asm popfd;
  910. }
  911. /******************************Private*Routine******************************\
  912. * vPlanar2Window
  913. *
  914. * Maps in one of two windows, either the source window (window 0) or the dest
  915. * window (window 1), to allows access to lScan. Applies to 1R1W window
  916. * banking scheme; should never be called for 1 RW window schemes, because
  917. * there's only one window in that case.
  918. *
  919. \**************************************************************************/
  920. VOID vPlanar2Window(
  921. PPDEV ppdev,
  922. ULONG lScan,
  923. BANK_JUST ulJustification,
  924. ULONG ulWindowToMap)
  925. {
  926. ULONG ulBank;
  927. PBANK_INFO pbiWorking;
  928. volatile ULONG ulBank0;
  929. volatile ULONG ulBank1;
  930. volatile PFN pBankFn;
  931. // ASM routines that call this may have STD in effect, but the C compiler
  932. // assumes CLD
  933. _asm pushfd
  934. _asm cld
  935. // Find the bank containing the scan line with the desired justification:
  936. if (ulJustification == JustifyBottom)
  937. {
  938. lScan -= ppdev->ulPlanarBottomOffset;
  939. if ((LONG)lScan <= 0)
  940. lScan = 0;
  941. }
  942. ulBank = (ULONG) ppdev->pjJustifyTopPlanar[lScan];
  943. pbiWorking = &ppdev->pbiPlanarInfo[ulBank];
  944. // Set the clip rect for this bank; if it's set to -1, that indicates that
  945. // a single-window set-up is currently active, so invalidate single-window
  946. // clip rects and display memory pointers (when double-window is active,
  947. // single-window is inactive, and vice-versa; a full bank set-up has to be
  948. // performed to switch between the two)
  949. if (ppdev->rcl2PlanarClip[ulWindowToMap].bottom == -1)
  950. {
  951. ULONG ulOtherWindow = ulWindowToMap ^ 1;
  952. if (!(ppdev->flBank & BANK_PLANAR))
  953. {
  954. ppdev->flBank |= BANK_PLANAR;
  955. ppdev->pfnPlanarEnable();
  956. }
  957. ppdev->rcl1WindowClip.bottom = -1;
  958. ppdev->rcl2WindowClip[0].bottom = -1;
  959. ppdev->rcl2WindowClip[1].bottom = -1;
  960. ppdev->rcl1PlanarClip.bottom = -1;
  961. // Neither of the 2 window windows was active, so we have to set up the
  962. // variables for the other bank (the one other than the one we were
  963. // called to set) as well, to make it valid. The other bank is set to
  964. // the same state as the bank we were called to set
  965. ppdev->rcl2PlanarClip[ulOtherWindow] = pbiWorking->rclBankBounds;
  966. ppdev->ulWindowBank[ulOtherWindow] = ulBank;
  967. ppdev->pvBitmapStart2Window[ulOtherWindow] =
  968. (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset);
  969. }
  970. ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode");
  971. ppdev->rcl2PlanarClip[ulWindowToMap] = pbiWorking->rclBankBounds;
  972. // Shift the bitmap start address so that the desired bank aligns with the
  973. // banking window
  974. ppdev->pvBitmapStart2Window[ulWindowToMap] =
  975. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset);
  976. // Map in the desired bank; also map in the other bank to whatever its
  977. // current state is
  978. ppdev->ulWindowBank[ulWindowToMap] = ulBank;
  979. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  980. // Set both banks at once, because we may have just initialized the other
  981. // bank, and because this way the bank switch code doesn't have to do a
  982. // read before write to obtain the state of the other bank.
  983. // This is so convoluted to avoid problems with wiping out registers C
  984. // thinks it's still using; the values are tranferred to volatiles, and
  985. // then to registers
  986. ulBank0 = ppdev->ulWindowBank[0];
  987. ulBank1 = ppdev->ulWindowBank[1];
  988. pBankFn = ppdev->pfnPlanarSwitchCode;
  989. _asm mov eax,ulBank0;
  990. _asm mov edx,ulBank1;
  991. _asm call pBankFn; // actually switch the banks
  992. _asm popfd;
  993. }
  994. /******************************Private*Routine******************************\
  995. * vPlanar2Window1RW
  996. *
  997. * Maps in the one window in 1R/W case. Does exactly the same thing as the
  998. * one window case, because there's only one window, but has to be a separate
  999. * entry point because of the extra parameter (because we're using STDCALL).
  1000. \**************************************************************************/
  1001. VOID vPlanar2Window1RW(PPDEV ppdev, ULONG lScan,
  1002. BANK_JUST ulJustification, ULONG ulWindowToMap)
  1003. {
  1004. vPlanar1Window(ppdev, lScan, ulJustification);
  1005. }
  1006. /******************************Private*Routine******************************\
  1007. * vPlanar2Window2RW
  1008. *
  1009. * Maps in one of two windows, either the source window (window 0) or the dest
  1010. * window (window 1), to allows access to lScan. Applies to 2RW window
  1011. * banking scheme; should never be called for 1 RW window schemes, because
  1012. * there's only one window in that case.
  1013. \**************************************************************************/
  1014. VOID vPlanar2Window2RW(
  1015. PPDEV ppdev,
  1016. ULONG lScan,
  1017. BANK_JUST ulJustification,
  1018. ULONG ulWindowToMap)
  1019. {
  1020. ULONG ulBank;
  1021. PBANK_INFO pbiWorking;
  1022. volatile ULONG ulBank0;
  1023. volatile ULONG ulBank1;
  1024. volatile PFN pBankFn;
  1025. // ASM routines that call this may have STD in effect, but the C compiler
  1026. // assumes CLD
  1027. _asm pushfd
  1028. _asm cld
  1029. // Find the bank containing the scan line with the desired justification:
  1030. if (ulJustification == JustifyBottom)
  1031. {
  1032. lScan -= ppdev->ulPlanarBottomOffset;
  1033. if ((LONG)lScan <= 0)
  1034. lScan = 0;
  1035. }
  1036. ulBank = (ULONG) ppdev->pjJustifyTopPlanar[lScan];
  1037. pbiWorking = &ppdev->pbiPlanarInfo[ulBank];
  1038. // Set the clip rect for this bank; if it's set to -1, that indicates that
  1039. // a single-window set-up is currently active, so invalidate single-window
  1040. // clip rects and display memory pointers (when double-window is active,
  1041. // single-window is inactive, and vice-versa; a full bank set-up has to be
  1042. // performed to switch between the two)
  1043. if (ppdev->rcl2PlanarClip[ulWindowToMap].bottom == -1)
  1044. {
  1045. if (!(ppdev->flBank & BANK_PLANAR))
  1046. {
  1047. ppdev->flBank |= BANK_PLANAR;
  1048. ppdev->pfnPlanarEnable();
  1049. }
  1050. ppdev->rcl1WindowClip.bottom = -1;
  1051. ppdev->rcl2WindowClip[0].bottom = -1;
  1052. ppdev->rcl2WindowClip[1].bottom = -1;
  1053. ppdev->rcl1PlanarClip.bottom = -1;
  1054. // Neither of the 2 window windows was active, so we have to set up the
  1055. // variables for the other bank (the one other than the one we were
  1056. // called to set) as well, to make it valid. The other bank is set to
  1057. // the same state as the bank we were called to set
  1058. ppdev->rcl2PlanarClip[ulWindowToMap^1] = pbiWorking->rclBankBounds;
  1059. if (ulWindowToMap == 1)
  1060. {
  1061. ppdev->pvBitmapStart2Window[0] =
  1062. (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset);
  1063. }
  1064. else
  1065. {
  1066. ppdev->pvBitmapStart2Window[1] =
  1067. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset +
  1068. BANK_SIZE_2RW_WINDOW);
  1069. }
  1070. ppdev->ulWindowBank[ulWindowToMap^1] = ulBank;
  1071. }
  1072. ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode");
  1073. ppdev->rcl2PlanarClip[ulWindowToMap] = pbiWorking->rclBankBounds;
  1074. // Shift the bitmap start address so that the desired bank aligns with the
  1075. // banking window
  1076. if (ulWindowToMap == 0)
  1077. {
  1078. ppdev->pvBitmapStart2Window[0] =
  1079. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset);
  1080. }
  1081. else
  1082. {
  1083. ppdev->pvBitmapStart2Window[1] =
  1084. (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset +
  1085. BANK_SIZE_2RW_WINDOW);
  1086. }
  1087. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  1088. // Map in the desired bank; also map in the other bank to whatever its
  1089. // current state is
  1090. ppdev->ulWindowBank[ulWindowToMap] = ulBank;
  1091. // Set both banks at once, because we may have just initialized the other
  1092. // bank, and because this way the bank switch code doesn't have to do a
  1093. // read before write to obtain the state of the other bank.
  1094. // This is so convoluted to avoid problems with wiping out registers C
  1095. // thinks it's still using; the values are tranferred to volatiles, and
  1096. // then to registers
  1097. ulBank0 = ppdev->ulWindowBank[0];
  1098. ulBank1 = ppdev->ulWindowBank[1];
  1099. pBankFn = ppdev->pfnPlanarSwitchCode;
  1100. _asm mov eax,ulBank0;
  1101. _asm mov edx,ulBank1;
  1102. _asm call pBankFn; // actually switch the banks
  1103. _asm popfd;
  1104. }
  1105. /******************************Private*Routine******************************\
  1106. * vPlanarDouble
  1107. *
  1108. * Maps in two windows simultaneously, both the source window (window 0)
  1109. * and the dest window (window 1), to allows access to the scans.
  1110. * Applies to 1R1W and 2R/w window banking schemes; should never be called
  1111. * for 1 RW window schemes, because there's only one window in that case.
  1112. *
  1113. \**************************************************************************/
  1114. VOID vPlanarDouble(
  1115. PPDEV ppdev,
  1116. LONG lScan0, // Source bank
  1117. BANK_JUST ulJustification0,// Source justification
  1118. LONG lScan1, // Destination bank
  1119. BANK_JUST ulJustification1)// Destination justification
  1120. {
  1121. PBANK_INFO pbi0;
  1122. PBANK_INFO pbi1;
  1123. ULONG ulBank0;
  1124. ULONG ulBank1;
  1125. volatile ULONG ulBank0_vol;
  1126. volatile ULONG ulBank1_vol;
  1127. volatile PFN pBankFn;
  1128. // ASM routines that call this may have STD in effect, but the C compiler
  1129. // assumes CLD
  1130. _asm pushfd
  1131. _asm cld
  1132. // Find the banks containing the scan lines with the desired justification:
  1133. if (ulJustification0 == JustifyBottom)
  1134. {
  1135. lScan0 -= ppdev->ulPlanarBottomOffset;
  1136. if (lScan0 <= 0)
  1137. lScan0 = 0;
  1138. }
  1139. if (ulJustification1 == JustifyBottom)
  1140. {
  1141. lScan1 -= ppdev->ulPlanarBottomOffset;
  1142. if (lScan1 <= 0)
  1143. lScan1 = 0;
  1144. }
  1145. ulBank0 = (ULONG) ppdev->pjJustifyTopPlanar[lScan0];
  1146. ulBank1 = (ULONG) ppdev->pjJustifyTopPlanar[lScan1];
  1147. pbi0 = &ppdev->pbiPlanarInfo[ulBank0];
  1148. pbi1 = &ppdev->pbiPlanarInfo[ulBank1];
  1149. // Set the clip rect for this bank; if it's set to -1, that indicates that
  1150. // a single-window set-up is currently active, so invalidate single-window
  1151. // clip rects and display memory pointers (when double-window is active,
  1152. // single-window is inactive, and vice-versa; a full bank set-up has to be
  1153. // performed to switch between the two)
  1154. if (ppdev->rcl2PlanarClip[0].bottom == -1)
  1155. {
  1156. if (!(ppdev->flBank & BANK_PLANAR))
  1157. {
  1158. ppdev->flBank |= BANK_PLANAR;
  1159. ppdev->pfnPlanarEnable();
  1160. }
  1161. ppdev->rcl1WindowClip.bottom = -1;
  1162. ppdev->rcl2WindowClip[0].bottom = -1;
  1163. ppdev->rcl2WindowClip[1].bottom = -1;
  1164. ppdev->rcl1PlanarClip.bottom = -1;
  1165. }
  1166. ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode");
  1167. ppdev->rcl2PlanarClip[0] = pbi0->rclBankBounds;
  1168. ppdev->rcl2PlanarClip[1] = pbi1->rclBankBounds;
  1169. // Shift the bitmap start address so that the desired bank aligns with the
  1170. // banking window
  1171. ppdev->pvBitmapStart2Window[0] =
  1172. (PVOID) ((UCHAR *)ppdev->pjScreen - pbi0->ulBankOffset);
  1173. ppdev->pvBitmapStart2Window[1] =
  1174. (PVOID) ((UCHAR *)ppdev->pjScreen - pbi1->ulBankOffset);
  1175. if (ppdev->vbtPlanarType == VideoBanked2RW)
  1176. {
  1177. ppdev->pvBitmapStart2Window[1] = (PVOID) ((BYTE*)
  1178. ppdev->pvBitmapStart2Window[1] + BANK_SIZE_2RW_WINDOW);
  1179. }
  1180. // Map in the desired banks.
  1181. ppdev->ulWindowBank[0] = ulBank0;
  1182. ppdev->ulWindowBank[1] = ulBank1;
  1183. ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters
  1184. // Set both banks at once.
  1185. // This is so convoluted to avoid problems with wiping out registers C
  1186. // thinks it's still using; the values are tranferred to volatiles, and
  1187. // then to registers
  1188. ulBank0_vol = ulBank0;
  1189. ulBank1_vol = ulBank1;
  1190. pBankFn = ppdev->pfnPlanarSwitchCode;
  1191. _asm mov eax,ulBank0_vol;
  1192. _asm mov edx,ulBank1_vol;
  1193. _asm call pBankFn; // actually switch the banks
  1194. _asm popfd;
  1195. }