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