|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: bank.c
3: *
4: * Functions to control VGA banking
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: \**************************************************************************/
8:
9:
10: #include "driver.h" // private driver defines
11:
12: void BankErrorTrap(PDEVSURF, LONG, BANK_JUST);
13: void Bank2Window(PDEVSURF, LONG, BANK_JUST, ULONG);
14: void Bank2Window2RW(PDEVSURF, LONG, BANK_JUST, ULONG);
15: void Bank2Window1RW(PDEVSURF, LONG, BANK_JUST, ULONG);
16: void Bank1Window2RW(PDEVSURF, LONG, BANK_JUST);
17: void Bank1Window(PDEVSURF, LONG, BANK_JUST);
18:
19: LPBYTE pPtrWork;
20: LPBYTE pPtrSave;
21:
22: // BUGBUG all routines should get the scan width out of the surface
23: ULONG ulNextScan_global;
24:
25: /******************************Public*Routine******************************\
26: * SetUpBanking
27: *
28: * Set up banking for the current mode
29: * pdsurf and ppdev are the pointers to the current surface and device
30: * Relevant fields in the surface are set up for banking
31: \**************************************************************************/
32:
33: BOOL SetUpBanking(PDEVSURF pdsurf, PPDEV ppdev)
34: {
35: INT i;
36: LONG lTemp;
37: LONG lScansPerBank, lScan, lTotalScans, lTotalBanks;
38: LONG lScansBetweenBanks;
39: ULONG ulOffset;
40: PVIDEO_BANK_SELECT BankInfo;
41: UINT ReturnedDataLength;
42: VIDEO_BANK_SELECT TempBankInfo;
43: PBANK_INFO pbiWorking;
44:
45: //
46: // Query the miniport for banking info for this mode.
47: //
48: // First, figure out how big a buffer we need for the banking info
49: // (returned in TempBankInfo->Size).
50: //
51:
52: //
53: // BUGBUG The error paths should point to the end of the function where
54: // we can deallocate all the buffers that were allocated.
55: //
56:
57: if (!DeviceIoControl(ppdev->hDriver,
58: IOCTL_VIDEO_GET_BANK_SELECT_CODE,
59: NULL, // input buffer
60: 0,
61: &TempBankInfo, // output buffer
62: sizeof(VIDEO_BANK_SELECT),
63: &ReturnedDataLength,
64: NULL)) {
65:
66: //
67: // We expect this call to fail, because we didn't allow any room
68: // for the code; we just want to get the required output buffer
69: // size. Make sure we got the expected error, ERROR_MORE_DATA.
70: //
71:
72: if (GetLastError() != ERROR_MORE_DATA) {
73:
74: //
75: // Should post error and return FALSE
76: //
77:
78: RIP("VGA.DLL: Initialization error-GetBankSelectCode, first call");
79:
80: return FALSE;
81: }
82:
83: }
84:
85:
86: //
87: // Now, allocate a buffer of the required size and get the banking info.
88: //
89:
90: if ((BankInfo = (PVIDEO_BANK_SELECT) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
91: TempBankInfo.Size)) == NULL) {
92:
93: //
94: // Should post error and return FALSE
95: //
96:
97: RIP("VGA.DLL: Initialization error-couldn't get memory for bank info");
98: return FALSE;
99:
100:
101: }
102:
103: if (!DeviceIoControl(ppdev->hDriver,
104: IOCTL_VIDEO_GET_BANK_SELECT_CODE,
105: NULL,
106: 0,
107: BankInfo,
108: TempBankInfo.Size,
109: &ReturnedDataLength,
110: NULL)) {
111:
112: //
113: // Should post error and return FALSE
114: //
115:
116: RIP("VGA.DLL: Initialization error-GetBankSelectCode, second call");
117: return FALSE;
118:
119: }
120:
121:
122: //
123: // Set up for banking.
124: //
125:
126: // Set up variables that are the same whether the adapter is banked or not
127:
128: pdsurf->pBankSelectInfo = BankInfo;
129: pdsurf->pfnBankSwitchCode =
130: (PFN) (((UCHAR *)BankInfo) + BankInfo->CodeOffset);
131: pdsurf->vbtBankingType = BankInfo->BankingType;
132: pdsurf->ulBitmapSize = BankInfo->BitmapSize;
133: pdsurf->lNextScan = BankInfo->BitmapWidthInBytes;
134:
135: // BUGBUG this should not be static
136: ulNextScan_global = BankInfo->BitmapWidthInBytes;
137:
138: // Set up the pointer off-screen work areas at the very end of display
139: // memory (values are relative to bitmap start)
140: // BUGBUG should be in PDEV
141: pPtrWork = (LPBYTE) pdsurf->ulBitmapSize - POINTER_WORK_AREA_SIZE;
142: pPtrSave = pPtrWork - POINTER_SAVE_AREA_SIZE;
143:
144: // Set up info that depends on whether or not the adapter is banked
145:
146: if (BankInfo->BankingType == VideoNotBanked) {
147:
148: lTotalScans = BankInfo->BitmapSize / BankInfo->BitmapWidthInBytes;
149:
150: // Unbanked; set all clip rects for the full bitmap, so the bank never
151: // needs to be changed, and set the banking vectors to error traps,
152: // since they should never be called
153:
154: pdsurf->rcl1WindowClip.left = pdsurf->rcl2WindowClip[0].left =
155: pdsurf->rcl2WindowClip[1].left = pdsurf->rcl1WindowClip.top =
156: pdsurf->rcl2WindowClip[0].top = pdsurf->rcl2WindowClip[1].top = 0;
157:
158: pdsurf->rcl1WindowClip.right = pdsurf->rcl2WindowClip[0].right =
159: pdsurf->rcl2WindowClip[1].right =
160: BankInfo->BitmapWidthInBytes << 8;
161:
162: pdsurf->rcl1WindowClip.bottom = pdsurf->rcl2WindowClip[0].bottom =
163: pdsurf->rcl2WindowClip[1].bottom = lTotalScans;
164:
165: pdsurf->pfnBankControl = BankErrorTrap;
166: pdsurf->pfnBankControl2Window = BankErrorTrap;
167:
168: pdsurf->ulWindowBank[0] = pdsurf->ulWindowBank[1] = (ULONG)0;
169: pdsurf->pvBitmapStart = pdsurf->pvBitmapStart2Window[0] =
170: pdsurf->pvBitmapStart2Window[1] = pdsurf->pvStart;
171:
172: // Scan line to be used with JustifyBottom to map in the bank
173: // containing the pointer work and save areas, which are guaranteed not
174: // to span banks. Is only used to determine that the bank never needs
175: // to be changed to map in the pointer in unbanked case
176: pdsurf->ulPtrBankScan = 0;
177:
178: // Mark that the bank info pointers are unused, so we don't try to
179: // deallocate the memory they point to
180: pdsurf->pbiBankInfo = pdsurf->pbiBankInfo2RW = NULL;
181:
182: // Allocate space for the temp buffer.
183:
184: if ((pdsurf->pvBankBufferPlane0 =
185: (PVOID) LocalAlloc(LMEM_FIXED |
186: LMEM_ZEROINIT, BANK_BUFFER_SIZE_UNBANKED)) == NULL) {
187:
188: //
189: // Should post error and return FALSE
190: //
191:
192: RIP("VGA.DLL: Couldn't get memory for temp buffer");
193: return FALSE;
194:
195: }
196:
197: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_UNBANKED;
198:
199: // These should never be used
200: pdsurf->pvBankBufferPlane1 =
201: pdsurf->pvBankBufferPlane2 =
202: pdsurf->pvBankBufferPlane3 = (PVOID) NULL;
203:
204: } else {
205:
206: // Banked, so set up all banking variables and initialize the bank
207: // control routines and their data tables
208:
209: // Reject if there are broken rasters (a broken raster is a scan line
210: // that crosses a bank boundary); that's not handled in this driver
211:
212: if (BankInfo->BankingType != VideoBanked2RW) {
213:
214: // For the 1 RW window and 1R1W window cases, windows are
215: // assumed to be BANK_SIZE_1_WINDOW in size (generally 64K)
216: lTemp = BANK_SIZE_1_WINDOW;
217:
218: } else {
219:
220: // For the 2 RW window case, windows are assumed to be
221: // BANK_SIZE_2RW_WINDOW in size (generally 32K)
222: lTemp = BANK_SIZE_2RW_WINDOW;
223:
224: }
225:
226: if ((lTemp % BankInfo->BitmapWidthInBytes) != 0) {
227:
228: //
229: // Should post error and return FALSE
230: //
231:
232: RIP("VGA.DLL: Broken rasters not supported");
233: return FALSE;
234:
235: }
236:
237: // These will be set properly on first call to bank controller, below,
238: // or something's wrong
239: pdsurf->ulWindowBank[0] = (ULONG)-1;
240: pdsurf->ulWindowBank[1] = (ULONG)-1;
241: pdsurf->pvBitmapStart = pdsurf->pvBitmapStart2Window[0] =
242: pdsurf->pvBitmapStart2Window[1] = (PVOID) 0;
243:
244: // Set all clip rects to invalid; they'll be updated when the first
245: // bank is mapped in
246:
247: pdsurf->rcl1WindowClip.left = pdsurf->rcl2WindowClip[0].left =
248: pdsurf->rcl2WindowClip[1].left = pdsurf->rcl1WindowClip.top =
249: pdsurf->rcl2WindowClip[0].top = pdsurf->rcl2WindowClip[1].top =
250: pdsurf->rcl1WindowClip.right = pdsurf->rcl2WindowClip[0].right =
251: pdsurf->rcl2WindowClip[1].right = pdsurf->rcl1WindowClip.bottom =
252: pdsurf->rcl2WindowClip[0].bottom =
253: pdsurf->rcl2WindowClip[1].bottom = -1;
254:
255: // Set up to call the appropriate banking control routines
256:
257: switch(BankInfo->BankingType) {
258:
259: case VideoBanked1RW:
260:
261: pdsurf->pfnBankControl = Bank1Window;
262: pdsurf->pfnBankControl2Window = Bank2Window1RW;
263:
264: if ((pdsurf->pvBankBufferPlane0 =
265: (PVOID) LocalAlloc(LMEM_FIXED |
266: LMEM_ZEROINIT, BANK_BUFFER_SIZE_1RW)) == NULL) {
267:
268: //
269: // Should post error and return FALSE
270: //
271:
272: RIP("VGA.DLL: Couldn't get memory for temp buffer");
273: return FALSE;
274:
275: }
276:
277: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_1RW;
278:
279: pdsurf->pvBankBufferPlane1 =
280: ((LPBYTE)pdsurf->pvBankBufferPlane0) +
281: BANK_BUFFER_PLANE_SIZE;
282: pdsurf->pvBankBufferPlane2 =
283: ((LPBYTE)pdsurf->pvBankBufferPlane1) +
284: BANK_BUFFER_PLANE_SIZE;
285: pdsurf->pvBankBufferPlane3 =
286: ((LPBYTE)pdsurf->pvBankBufferPlane2) +
287: BANK_BUFFER_PLANE_SIZE;
288:
289: break;
290:
291:
292: case VideoBanked1R1W:
293:
294: pdsurf->pfnBankControl = Bank1Window;
295: pdsurf->pfnBankControl2Window = Bank2Window;
296:
297: if ((pdsurf->pvBankBufferPlane0 =
298: (PVOID) LocalAlloc(LMEM_FIXED |
299: LMEM_ZEROINIT, BANK_BUFFER_SIZE_1R1W)) == NULL) {
300:
301: //
302: // Should post error and return FALSE
303: //
304:
305: RIP("VGA.DLL: Couldn't get memory for temp buffer");
306: return FALSE;
307:
308: }
309:
310: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_1R1W;
311:
312: // These should never be used
313: pdsurf->pvBankBufferPlane1 =
314: pdsurf->pvBankBufferPlane2 =
315: pdsurf->pvBankBufferPlane3 = (PVOID) NULL;
316:
317: break;
318:
319:
320: case VideoBanked2RW:
321:
322: pdsurf->pfnBankControl = Bank1Window2RW;
323: pdsurf->pfnBankControl2Window = Bank2Window2RW;
324:
325: if ((pdsurf->pvBankBufferPlane0 =
326: (PVOID) LocalAlloc(LMEM_FIXED |
327: LMEM_ZEROINIT, BANK_BUFFER_SIZE_2RW)) == NULL) {
328:
329: //
330: // Should post error and return FALSE
331: //
332:
333: RIP("VGA.DLL: Couldn't get memory for temp buffer");
334: return FALSE;
335:
336: }
337:
338: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_2RW;
339:
340: // These should never be used
341: pdsurf->pvBankBufferPlane1 =
342: pdsurf->pvBankBufferPlane2 =
343: pdsurf->pvBankBufferPlane3 = (PVOID) NULL;
344:
345: break;
346:
347: default:
348:
349: //
350: // Should post error and return FALSE
351: //
352:
353: RIP("VGA.DLL: bad BankingType");
354: return FALSE;
355:
356: }
357:
358: // Set up the bank control tables with clip rects for banks
359: // Note: lTotalBanks is generally an overestimate when granularity
360: // is less than window size, because we ignore any banks after the
361: // first one that includes the last scan line of the bitmap. A bit
362: // of memory could be saved by sizing lTotalBanks exactly. Note too,
363: // though, that the 2 RW window case may require more entries then,
364: // because its windows are shorter, so you'd have to make sure there
365: // were enough entries for the 2 RW window case, or recalculate
366: // lTotalBanks for the 2 RW case
367:
368: lTotalBanks = BankInfo->BitmapSize / BankInfo->Granularity;
369: lTotalScans = BankInfo->BitmapSize / BankInfo->BitmapWidthInBytes;
370: lScansBetweenBanks =
371: BankInfo->Granularity / BankInfo->BitmapWidthInBytes;
372:
373: // Allocate memory for bank control info
374:
375: if ((pdsurf->pbiBankInfo = (PBANK_INFO) LocalAlloc(LMEM_FIXED |
376: LMEM_ZEROINIT, lTotalBanks * sizeof(BANK_INFO))) == NULL) {
377:
378: //
379: // Should post error and return FALSE
380: //
381:
382: RIP("VGA.DLL: Couldn't get memory for bank info #2");
383: return FALSE;
384:
385: }
386:
387: // Build the list of bank rects & offsets assuming standard window
388: // size
389:
390: lScansPerBank = BANK_SIZE_1_WINDOW / BankInfo->BitmapWidthInBytes;
391: ulOffset = 0;
392: lScan = -lScansBetweenBanks; // precompensate for 1st time in loop
393: i = 0;
394: pbiWorking = pdsurf->pbiBankInfo;
395:
396: do {
397:
398: lScan += lScansBetweenBanks;
399: pbiWorking->rclBankBounds.left = 0;
400: pbiWorking->rclBankBounds.right = pdsurf->sizlSurf.cx;
401: pbiWorking->rclBankBounds.top = lScan;
402: pbiWorking->rclBankBounds.bottom = lScan + lScansPerBank;
403: pbiWorking->ulBankOffset = ulOffset;
404: ulOffset += BankInfo->Granularity;
405: i++;
406: pbiWorking++;
407:
408: } while ((lScan + lScansPerBank) < lTotalScans);
409:
410: pdsurf->ulBankInfoLength = i;
411:
412: // If this is a 2RW bank adapter, build a table for that too, with
413: // 32K windows
414:
415: if (BankInfo->BankingType == VideoBanked2RW) {
416:
417: // Offset from one bank index to next to make two 32K banks
418: // appear to be one seamless 64K bank
419: pdsurf->ulBank2RWSkip =
420: (BANK_SIZE_2RW_WINDOW / BankInfo->Granularity);
421:
422: // Allocate memory for 2RW case bank control info
423: if ((pdsurf->pbiBankInfo2RW =
424: (PBANK_INFO) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
425: lTotalBanks * sizeof(BANK_INFO))) == NULL) {
426:
427: //
428: // Should post error and return FALSE
429: //
430:
431: RIP("VGA.DLL: Couldn't get memory for bank info #3");
432: return FALSE;
433:
434: }
435:
436: // Build the list of bank rects & offsets for 2RW case
437: lScansPerBank =
438: BANK_SIZE_2RW_WINDOW / BankInfo->BitmapWidthInBytes;
439: lScan = -lScansBetweenBanks; // precompensate for 1st time
440: ulOffset = 0;
441: i = 0;
442: pbiWorking = pdsurf->pbiBankInfo2RW;
443:
444: do {
445:
446: lScan += lScansBetweenBanks;
447: pbiWorking->rclBankBounds.left = 0;
448: pbiWorking->rclBankBounds.right = pdsurf->sizlSurf.cx;
449: pbiWorking->rclBankBounds.top = lScan;
450: pbiWorking->rclBankBounds.bottom = lScan + lScansPerBank;
451: pbiWorking->ulBankOffset = ulOffset;
452: ulOffset += BankInfo->Granularity;
453: i++;
454: pbiWorking++;
455:
456: } while ((lScan + lScansPerBank) < lTotalScans);
457:
458: pdsurf->ulBankInfo2RWLength = i;
459:
460: } else {
461:
462: // Not a 2RW bank adapter, just use standard table for 2-window
463: // cases
464:
465: pdsurf->pbiBankInfo2RW = pdsurf->pbiBankInfo;
466: pdsurf->ulBankInfo2RWLength = pdsurf->ulBankInfoLength;
467:
468: }
469:
470: // Map in scan line 0 for read & write, to put things in a known state
471:
472: pdsurf->pfnBankControl(pdsurf, 0, JustifyTop);
473:
474: // Scan line to be used with JustifyBottom to map in the bank
475: // containing the pointer work and save areas, which are guaranteed not
476: // to span banks
477: pdsurf->ulPtrBankScan = (pdsurf->ulBitmapSize/pdsurf->lNextScan) - 1;
478:
479: }
480:
481:
482: return TRUE;
483: }
484:
485: /******************************Private*Routine******************************\
486: * BankErrorTrap
487: *
488: * Traps calls to bank control functions in non-banked modes
489: *
490: \**************************************************************************/
491:
492: void BankErrorTrap(PDEVSURF pdsurf, LONG lScan,
493: BANK_JUST ulJustification)
494: {
495: DISPDBG((0, "VGA.DLL: Call to bank manager in unbanked mode\n"));
496: }
497:
498:
499: /******************************Private*Routine******************************\
500: * Bank1Window
501: *
502: * Maps in a single R/W window that allows access to lScan. Applies to both
503: * 1 RW window and 1R1W window banking schemes.
504: *
505: * Note: in the 1 R/W adapter case, this may be called with a fourth parameter
506: * (the source/dest selector), which is ignored. This is so that we can use the
507: * same routine as the destination for 1 R/W 2-window calls; those calls don't
508: * map in separate banks, of course, but they let us get away with common code
509: * for 1 R/W and 1R/1W in some cases (such as aligned blits).
510: *
511: \**************************************************************************/
512:
513: void Bank1Window(PDEVSURF pdsurf, LONG lScan,
514: BANK_JUST ulJustification)
515: {
516: ULONG ulBank;
517: PBANK_INFO pbiWorking;
518: volatile ULONG ulBank0;
519: volatile PFN pBankFn;
520:
521: // ASM routines that call this may have STD in effect, but the C compiler
522: // assumes CLD
523:
524: _asm pushfd
525: _asm cld
526:
527: // Find the bank containing the scan line with the desired justification
528: if (ulJustification == JustifyTop) {
529:
530: // Map scan line in as near as possible to the top of the window
531: ulBank = pdsurf->ulBankInfoLength-1;
532: pbiWorking = pdsurf->pbiBankInfo + ulBank;
533: while (pbiWorking->rclBankBounds.top > lScan) {
534: ulBank--;
535: pbiWorking--;
536: }
537:
538: } else {
539:
540: // Map scan line in as near as possible to the bottom of the window
541: ulBank = 0;
542: pbiWorking = pdsurf->pbiBankInfo;
543: while (pbiWorking->rclBankBounds.bottom <= lScan) {
544: ulBank++;
545: pbiWorking++;
546: }
547:
548: }
549:
550: // Set the clip rect for this bank; if it's set to -1, that indicates that
551: // a double-window set-up is currently active, so invalidate double-window
552: // clip rects and display memory pointers (when double-window is active,
553: // single-window is inactive, and vice-versa; a full bank set-up has to be
554: // performed to switch between the two)
555:
556: if (pdsurf->rcl1WindowClip.top == -1) {
557:
558: pdsurf->rcl2WindowClip[0].top =
559: pdsurf->rcl2WindowClip[0].bottom =
560: pdsurf->rcl2WindowClip[0].right =
561: pdsurf->rcl2WindowClip[0].left =
562: pdsurf->rcl2WindowClip[1].top =
563: pdsurf->rcl2WindowClip[1].bottom =
564: pdsurf->rcl2WindowClip[1].right =
565: pdsurf->rcl2WindowClip[1].left = -1;
566: pdsurf->pvBitmapStart2Window[0] = (PDEVSURF) 0;
567: pdsurf->pvBitmapStart2Window[1] = (PDEVSURF) 0;
568:
569: } else {
570: // ASSERT(pdsurf->rcl2WindowClip[0].top == -1,
571: // "BANK.C: 2 bank src not mapped out");
572: // ASSERT(pdsurf->rcl2WindowClip[1].top == -1,
573: // "BANK.C: 2 bank src not mapped out");
574: }
575:
576:
577: pdsurf->rcl1WindowClip = pbiWorking->rclBankBounds;
578:
579: // Shift the bitmap start address so that the desired bank aligns with
580: // the banking window. The source and destination are set only so 1 R/W
581: // aligned blits will work without having to be specifically aware of
582: // the adapter type (some of the same code works with 1R/1W adapters too).
583:
584: pdsurf->pvBitmapStart =
585: pdsurf->pvBitmapStart2Window[0] =
586: pdsurf->pvBitmapStart2Window[1] =
587: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset);
588:
589: // Map in the desired bank for both read and write
590: // This is so convoluted to avoid problems with wiping out registers C
591: // thinks it's still using; the values are tranferred to volatiles, and
592: // then to registers
593:
594: ulBank0 = ulBank;
595: pBankFn = pdsurf->pfnBankSwitchCode;
596: _asm mov eax,ulBank0;
597: _asm mov edx,eax;
598: pBankFn(); // actually switch the banks
599:
600: _asm popfd
601: }
602:
603:
604: /******************************Private*Routine******************************\
605: * Bank1Window2RW
606: *
607: * Maps in two 32K RW windows so that they form a single 64K R/W window that
608: * allows access to lScan. Applies only to 2 RW window schemes.
609: *
610: \**************************************************************************/
611:
612: void Bank1Window2RW(PDEVSURF pdsurf, LONG lScan,
613: BANK_JUST ulJustification)
614: {
615: ULONG ulBank;
616: PBANK_INFO pbiWorking;
617: volatile ULONG ulBank0;
618: volatile ULONG ulBank1;
619: volatile PFN pBankFn;
620:
621: // ASM routines that call this may have STD in effect, but the C compiler
622: // assumes CLD
623:
624: _asm pushfd
625: _asm cld
626:
627: // Find the bank containing the scan line with the desired justification
628: if (ulJustification == JustifyTop) {
629:
630: // Map scan line in as near as possible to the top of the window
631: ulBank = pdsurf->ulBankInfoLength-1;
632: pbiWorking = pdsurf->pbiBankInfo + ulBank;
633: while (pbiWorking->rclBankBounds.top > lScan) {
634: ulBank--;
635: pbiWorking--;
636: }
637:
638: } else {
639:
640: // Map scan line in as near as possible to the bottom of the window
641: ulBank = 0;
642: pbiWorking = pdsurf->pbiBankInfo;
643: while (pbiWorking->rclBankBounds.bottom <= lScan) {
644: ulBank++;
645: pbiWorking++;
646: }
647:
648: }
649:
650: // Set the clip rect for this bank; if it's set to -1, that indicates that
651: // a double-window set-up is currently active, so invalidate double-window
652: // clip rects and display memory pointers (when double-window is active,
653: // single-window is inactive, and vice-versa; a full bank set-up has to be
654: // performed to switch between the two)
655:
656: if (pdsurf->rcl1WindowClip.top == -1) {
657:
658: pdsurf->rcl2WindowClip[0].top =
659: pdsurf->rcl2WindowClip[0].bottom =
660: pdsurf->rcl2WindowClip[0].right =
661: pdsurf->rcl2WindowClip[0].left =
662: pdsurf->rcl2WindowClip[1].top =
663: pdsurf->rcl2WindowClip[1].bottom =
664: pdsurf->rcl2WindowClip[1].right =
665: pdsurf->rcl2WindowClip[1].left = -1;
666: pdsurf->pvBitmapStart2Window[0] = (PDEVSURF) 0;
667: pdsurf->pvBitmapStart2Window[1] = (PDEVSURF) 0;
668:
669: } else {
670: // ASSERT(pdsurf->rcl2WindowClip[0].top == -1,
671: // "BANK.C: 2 bank src not mapped out");
672: // ASSERT(pdsurf->rcl2WindowClip[1].top == -1,
673: // "BANK.C: 2 bank src not mapped out");
674: }
675:
676:
677: pdsurf->rcl1WindowClip = pbiWorking->rclBankBounds;
678:
679: // Shift the bitmap start address so that the desired bank aligns with
680: // the banking window. The source and destination are set only so 1 R/W
681: // aligned blits will work without having to be specifically aware of
682: // the adapter type (some of the same code works with 1R/1W adapters too).
683:
684: pdsurf->pvBitmapStart =
685: pdsurf->pvBitmapStart2Window[0] =
686: pdsurf->pvBitmapStart2Window[1] =
687: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset);
688:
689: // Map in the desired bank for both read and write; this is accomplished
690: // by mapping in the desired 32K bank, followed by the next 32K bank.
691: // This is so convoluted to avoid problems with wiping out registers C
692: // thinks it's still using; the values are tranferred to volatiles, and
693: // then to registers
694:
695: ulBank0 = ulBank;
696: ulBank1 = ulBank0 + pdsurf->ulBank2RWSkip;
697: pBankFn = pdsurf->pfnBankSwitchCode;
698: _asm mov eax,ulBank0;
699: _asm mov edx,ulBank1;
700: pBankFn(); // actually switch the banks
701:
702: _asm popfd
703: }
704:
705:
706: /******************************Private*Routine******************************\
707: * Bank2Window
708: *
709: * Maps in one of two windows, either the source window (window 0) or the dest
710: * window (window 1), to allows access to lScan. Applies to 1R1W window
711: * banking scheme; should never be called for 1 RW window schemes, because
712: * there's only one window in that case.
713: *
714: \**************************************************************************/
715:
716: void Bank2Window(PDEVSURF pdsurf, LONG lScan,
717: BANK_JUST ulJustification, ULONG ulWindowToMap)
718: {
719: ULONG ulBank;
720: PBANK_INFO pbiWorking;
721: volatile ULONG ulBank0, ulBank1;
722: volatile PFN pBankFn;
723:
724: // ASM routines that call this may have STD in effect, but the C compiler
725: // assumes CLD
726:
727: _asm pushfd
728: _asm cld
729:
730: // Find the bank containing the scan line with the desired justification
731: if (ulJustification == JustifyTop) {
732:
733: // Map scan line in as near as possible to the top of the window
734: ulBank = pdsurf->ulBankInfoLength-1;
735: pbiWorking = pdsurf->pbiBankInfo + ulBank;
736: while (pbiWorking->rclBankBounds.top > lScan) {
737: ulBank--;
738: pbiWorking--;
739: }
740:
741: } else {
742:
743: // Map scan line in as near as possible to the bottom of the window
744: ulBank = 0;
745: pbiWorking = pdsurf->pbiBankInfo;
746: while (pbiWorking->rclBankBounds.bottom <= lScan) {
747: ulBank++;
748: pbiWorking++;
749: }
750:
751: }
752:
753: // Set the clip rect for this bank; if it's set to -1, that indicates that
754: // a single-window set-up is currently active, so invalidate single-window
755: // clip rects and display memory pointers (when double-window is active,
756: // single-window is inactive, and vice-versa; a full bank set-up has to be
757: // performed to switch between the two)
758:
759: if (pdsurf->rcl2WindowClip[ulWindowToMap].top == -1) {
760:
761: pdsurf->rcl1WindowClip.top =
762: pdsurf->rcl1WindowClip.bottom =
763: pdsurf->rcl1WindowClip.right =
764: pdsurf->rcl1WindowClip.left = -1;
765: pdsurf->pvBitmapStart = (PDEVSURF) 0;
766:
767: // Neither of the 2 window windows was active, so we have to set up the
768: // variables for the other bank (the one other than the one we were
769: // called to set) as well, to make it valid. The other bank is set to
770: // the same state as the bank we were called to set
771: pdsurf->rcl2WindowClip[ulWindowToMap^1] = pbiWorking->rclBankBounds;
772: pdsurf->pvBitmapStart2Window[ulWindowToMap^1] =
773: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset);
774: pdsurf->ulWindowBank[ulWindowToMap^1] = ulBank;
775: } else {
776: // ASSERT(pdsurf->rcl1WindowClip.top == -1,
777: // "BANK.C: 1 bank not mapped out");
778: }
779:
780: pdsurf->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds;
781:
782: // Shift the bitmap start address so that the desired bank aligns with the
783: // banking window
784:
785: pdsurf->pvBitmapStart2Window[ulWindowToMap] =
786: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset);
787:
788: // Map in the desired bank; also map in the other bank to whatever its
789: // current state is
790:
791: pdsurf->ulWindowBank[ulWindowToMap] = ulBank;
792:
793: // Set both banks at once, because we may have just initialized the other
794: // bank, and because this way the bank switch code doesn't have to do a
795: // read before write to obtain the state of the other bank.
796: // This is so convoluted to avoid problems with wiping out registers C
797: // thinks it's still using; the values are tranferred to volatiles, and
798: // then to registers
799:
800: ulBank0 = pdsurf->ulWindowBank[0];
801: ulBank1 = pdsurf->ulWindowBank[1];
802: pBankFn = pdsurf->pfnBankSwitchCode;
803: _asm mov eax,ulBank0;
804: _asm mov edx,ulBank1;
805: pBankFn(); // actually switch the banks
806:
807: _asm popfd
808: }
809:
810:
811: /******************************Private*Routine******************************\
812: * Bank2Window1RW
813: *
814: * Maps in the one window in 1R/W case. Does exactly the same thing as the
815: * one window case, because there's only one window, but has to be a separate
816: * entry point because of the extra parameter (because we're using STDCALL).
817: \**************************************************************************/
818:
819: void Bank2Window1RW(PDEVSURF pdsurf, LONG lScan,
820: BANK_JUST ulJustification, ULONG ulWindowToMap)
821: {
822: Bank1Window(pdsurf, lScan, ulJustification);
823: }
824:
825:
826: /******************************Private*Routine******************************\
827: * Bank2Window2RW
828: *
829: * Maps in one of two windows, either the source window (window 0) or the dest
830: * window (window 1), to allows access to lScan. Applies to 2RW window
831: * banking scheme; should never be called for 1 RW window schemes, because
832: * there's only one window in that case.
833: \**************************************************************************/
834:
835: void Bank2Window2RW(PDEVSURF pdsurf, LONG lScan,
836: BANK_JUST ulJustification, ULONG ulWindowToMap)
837: {
838: ULONG ulBank;
839: PBANK_INFO pbiWorking;
840: volatile ULONG ulBank0, ulBank1;
841: volatile PFN pBankFn;
842:
843: // ASM routines that call this may have STD in effect, but the C compiler
844: // assumes CLD
845:
846: _asm pushfd
847: _asm cld
848:
849: // Find the bank containing the scan line with the desired justification
850: if (ulJustification == JustifyTop) {
851:
852: // Map scan line in as near as possible to the top of the window
853: ulBank = pdsurf->ulBankInfo2RWLength-1;
854: pbiWorking = pdsurf->pbiBankInfo2RW + ulBank;
855: while (pbiWorking->rclBankBounds.top > lScan) {
856: ulBank--;
857: pbiWorking--;
858: }
859:
860: } else {
861:
862: // Map scan line in as near as possible to the bottom of the window
863: ulBank = 0;
864: pbiWorking = pdsurf->pbiBankInfo2RW;
865: while (pbiWorking->rclBankBounds.bottom <= lScan) {
866: ulBank++;
867: pbiWorking++;
868: }
869:
870: }
871:
872: // Set the clip rect for this bank; if it's set to -1, that indicates that
873: // a single-window set-up is currently active, so invalidate single-window
874: // clip rects and display memory pointers (when double-window is active,
875: // single-window is inactive, and vice-versa; a full bank set-up has to be
876: // performed to switch between the two)
877:
878: if (pdsurf->rcl2WindowClip[ulWindowToMap].top == -1) {
879:
880: pdsurf->rcl1WindowClip.top =
881: pdsurf->rcl1WindowClip.bottom =
882: pdsurf->rcl1WindowClip.right =
883: pdsurf->rcl1WindowClip.left = -1;
884: pdsurf->pvBitmapStart = (PDEVSURF) 0;
885:
886: // Neither of the 2 window windows was active, so we have to set up the
887: // variables for the other bank (the one other than the one we were
888: // called to set) as well, to make it valid. The other bank is set to
889: // the same state as the bank we were called to set
890: pdsurf->rcl2WindowClip[ulWindowToMap^1] = pbiWorking->rclBankBounds;
891: if (ulWindowToMap == 1) {
892: pdsurf->pvBitmapStart2Window[0] =
893: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset);
894: } else {
895: pdsurf->pvBitmapStart2Window[1] =
896: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset +
897: BANK_SIZE_2RW_WINDOW);
898: }
899: pdsurf->ulWindowBank[ulWindowToMap^1] = ulBank;
900: } else {
901: // ASSERT(pdsurf->rcl1WindowClip.top == -1,
902: // "BANK.C: 1 bank not mapped out");
903: }
904:
905: pdsurf->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds;
906:
907: // Shift the bitmap start address so that the desired bank aligns with the
908: // banking window
909:
910: if (ulWindowToMap == 0) {
911: pdsurf->pvBitmapStart2Window[0] =
912: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset);
913: } else {
914: pdsurf->pvBitmapStart2Window[1] =
915: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset +
916: BANK_SIZE_2RW_WINDOW);
917: }
918:
919: // Map in the desired bank; also map in the other bank to whatever its
920: // current state is
921:
922: pdsurf->ulWindowBank[ulWindowToMap] = ulBank;
923:
924: // Set both banks at once, because we may have just initialized the other
925: // bank, and because this way the bank switch code doesn't have to do a
926: // read before write to obtain the state of the other bank.
927: // This is so convoluted to avoid problems with wiping out registers C
928: // thinks it's still using; the values are tranferred to volatiles, and
929: // then to registers
930:
931: ulBank0 = pdsurf->ulWindowBank[0];
932: ulBank1 = pdsurf->ulWindowBank[1];
933: pBankFn = pdsurf->pfnBankSwitchCode;
934: _asm mov eax,ulBank0;
935: _asm mov edx,ulBank1;
936: pBankFn(); // actually switch the banks
937:
938: _asm popfd
939: }
940:
941:
942: /************************************************************************\
943: * DrvIntersectRect
944: *
945: * Calculates the intersection between *prcSrc1 and *prcSrc2,
946: * returning the resulting rect in *prcDst. Returns TRUE if
947: * *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no
948: * intersection, an empty rect is returned in *prcDst
949: \************************************************************************/
950: static const RECTL rclEmpty = { 0, 0, 0, 0 };
951:
952: BOOL DrvIntersectRect(
953: PRECTL prcDst,
954: PRECTL prcSrc1,
955: PRECTL prcSrc2)
956:
957: {
958: prcDst->left = max(prcSrc1->left, prcSrc2->left);
959: prcDst->right = min(prcSrc1->right, prcSrc2->right);
960:
961: /*
962: * check for empty rect
963: */
964: if (prcDst->left < prcDst->right) {
965:
966: prcDst->top = max(prcSrc1->top, prcSrc2->top);
967: prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
968:
969: /*
970: * check for empty rect
971: */
972: if (prcDst->top < prcDst->bottom) {
973: return TRUE; // not empty
974: }
975: }
976:
977: /*
978: * empty rect
979: */
980: *prcDst = rclEmpty;
981:
982: return FALSE;
983: }
984:
985: /************************************************************************\
986: * vForceBank0
987: *
988: * Forces the VGA to map in bank 0 if there's banking. Intended for use
989: * when returning from fullscreen, so a known bank is mapped.
990: \************************************************************************/
991: VOID vForceBank0(
992: PPDEV ppdev)
993: {
994: PDEVSURF pdsurf = ppdev->pdsurf;
995:
996: if (pdsurf->vbtBankingType != VideoNotBanked) {
997:
998: // Set all clip rects to invalid; they'll be updated when we map in
999: // bank 0
1000: pdsurf->rcl1WindowClip.left = pdsurf->rcl2WindowClip[0].left =
1001: pdsurf->rcl2WindowClip[1].left = pdsurf->rcl1WindowClip.top =
1002: pdsurf->rcl2WindowClip[0].top = pdsurf->rcl2WindowClip[1].top =
1003: pdsurf->rcl1WindowClip.right = pdsurf->rcl2WindowClip[0].right =
1004: pdsurf->rcl2WindowClip[1].right = pdsurf->rcl1WindowClip.bottom =
1005: pdsurf->rcl2WindowClip[0].bottom =
1006: pdsurf->rcl2WindowClip[1].bottom = -1;
1007:
1008: // Map in scan line 0 for read & write, to put things in a known state
1009: pdsurf->pfnBankControl(pdsurf, 0, JustifyTop);
1010: }
1011: }
1012:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.