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.

1522 lines
53 KiB

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