|
|
1.1 root 1: /******************************************************************************
2: *
3: * S3 Bank Manager
4: *
5: * Copyright (c) 1992 Microsoft Corporation
6: *****************************************************************************/
7:
8: #include "driver.h"
9:
10: // Bank select forward prototype.
11:
12: VOID vSetS3Bank(PPDEV ppdev, UINT iBank);
13:
14: /******************************************************************************
15: * bBankInit - Initialize the bank manager.
16: *
17: * Setup the ppdev->arclBanks Array. Since this driver is chip specific,
18: * we can take a number of short cuts. We know there will always
19: * be 1 meg of memory on the board, and there will only be 1 64K R/W
20: * bank.
21: *
22: *****************************************************************************/
23: BOOL bBankInit(
24: PPDEV ppdev,
25: BOOL fFirstTime)
26: {
27: INT i;
28: BYTE jMemCfg;
29:
30: DISPDBG((3, "S3.DLL: bBankInit - Entry\n"));
31:
32: if (fFirstTime)
33: {
34: ppdev->BankSize = MEMORY_APERTURE_SIZE;
35: ppdev->ScansPerBank = ppdev->BankSize / ppdev->cxMaxRam;
36: ppdev->MaxBanks = ppdev->cyMaxRam / ppdev->ScansPerBank;
37:
38: ppdev->prclBanks = LocalAlloc(LPTR, ppdev->MaxBanks * sizeof (RECT));
39: if (ppdev->prclBanks == NULL)
40: {
41: DISPDBG((0, "S3.DLL!bBankInit - LocalAlloc (prclBanks) failed \n"));
42: EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
43: return (FALSE);
44: }
45:
46: ppdev->pBanks = LocalAlloc(LPTR, ppdev->MaxBanks * sizeof (BANK));
47: if (ppdev->pBanks == NULL)
48: {
49: DISPDBG((0, "S3.DLL!bBankInit - LocalAlloc (pBanks) failed \n"));
50: EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
51: return (FALSE);
52: }
53:
54: // Note: We only care about scans for the S3 chip. So don't
55: // bother initializing the left and right sides of the rectangle.
56:
57: for (i = 0; i < ppdev->MaxBanks; i++) {
58: ppdev->prclBanks[i].top = i * ppdev->ScansPerBank;
59: ppdev->prclBanks[i].bottom = ppdev->prclBanks[i].top + ppdev->ScansPerBank;
60: }
61: }
62:
63: // Unlock some of the S3 registers.
64:
65: OUTPW (CRTC_INDEX, ((REG_UNLOCK_1 << 8) | S3R8));
66:
67: // Enable the Memory Aperture.
68:
69: OUTP(CRTC_INDEX, S3R1);
70: jMemCfg = INP(CRTC_DATA);
71: jMemCfg |= CPUA_BASE;
72: OUTP(CRTC_DATA, jMemCfg);
73:
74: // Get the initial value of S3R5 and save it away.
75: // This will prevent reading the Aperature control register
76: // each time we want to set the bank.
77:
78: OUTP(CRTC_INDEX, S3R5);
79: ppdev->jS3R5 = INP(CRTC_DATA);
80: ppdev->jS3R5 &= 0xF0; // Just mask for the bits we want.
81:
82: return(TRUE);
83: }
84:
85: /******************************************************************************
86: * bBankEnumStart - Start the bank enumeration.
87: *
88: * Save the original values for pvScan0 and rclBounds (The start of the
89: * engine managed bitmap and the clipping bounding rectangle.)
90: *
91: * Setup all the banks to enumerate in the ppdev->pBanks array.
92: * Setup the first bank to enumerate.
93: *
94: * Entry: prclScan->bottom - Ptr to the top (first) scan to render (inclusive)
95: * prclScan->top - Ptr to the bottom (last) scan to render (inclusive)
96: * pso - The surface object.
97: * pco - The clipping object.
98: *
99: * Exit: TRUE - if any rendering needs to be done.
100: * FALSE - if there is nothing to render, (i.e. the object
101: * is completely clipped out.)
102: * prclScan->bottom - The Top Scan to render into.
103: * prclScan->top - The Bottom Scan to render into.
104: *
105: *****************************************************************************/
106: BOOL bBankEnumStart(
107: PPDEV ppdev,
108: PRECTL prclScans,
109: SURFOBJ *pso,
110: CLIPOBJ *pco)
111: {
112: LONG TopScan, BottomScan, BankBottom;
113: PBYTE pbScan0;
114: INT i, iFirstBank, iLastBank;
115:
116: DISPDBG((3, "S3.DLL: bBankEnumStart - Entry\n"));
117:
118: // Save the original pvScan0 and the ClipObj's rclBounds.
119:
120: ppdev->pvOrgScan0 = pso->pvScan0;
121: ppdev->rclOrgBounds = pco->rclBounds;
122: ppdev->iOrgDComplexity = pco->iDComplexity;
123: ppdev->fjOptions = pco->fjOptions;
124:
125: // Set the flag in the clip object to tell the engine to forcible
126: // clip to the rclBounds of the clip object.
127:
128: pco->fjOptions |= OC_BANK_CLIP;
129:
130: // If the clipping is not trivial, do an intersection of the
131: // top & bottom scans with the clipping bounds.
132:
133: if (pco->iDComplexity != DC_TRIVIAL)
134: {
135: TopScan = max (pco->rclBounds.top, prclScans->top);
136: BottomScan = min (pco->rclBounds.bottom, prclScans->bottom);
137: }
138: else
139: {
140: TopScan = prclScans->top;
141: BottomScan = prclScans->bottom;
142: }
143:
144: // Init the variables used to set up the banks.
145:
146: iLastBank = -1;
147: ppdev->cBanks = 0;
148: ppdev->iBank = 0;
149: pbScan0 = (PBYTE) pso->pvScan0;
150:
151: // Find the bank that contains the top scan (the first bank).
152:
153: for (i = 0; i < ppdev->MaxBanks; i++)
154: {
155: BankBottom = ppdev->prclBanks[i].bottom;
156: if (BankBottom > TopScan)
157: {
158: // The Top scan is within this bank,
159:
160: iFirstBank = i;
161:
162: // Set up the bank entry.
163:
164: ppdev->pBanks[ppdev->iBank].pvScan0 = pbScan0 - (i * ppdev->BankSize);
165: ppdev->pBanks[ppdev->iBank].Bank = i;
166: ppdev->pBanks[ppdev->iBank].rclClip.top = TopScan;
167:
168: if (BankBottom < BottomScan)
169: {
170: ppdev->pBanks[ppdev->iBank].rclClip.bottom = BankBottom;
171: }
172: else
173: {
174: ppdev->pBanks[ppdev->iBank].rclClip.bottom = BottomScan;
175: iLastBank = iFirstBank;
176: }
177:
178: // Set the left and right bounds of the bank clip rect.
179:
180: ppdev->pBanks[ppdev->iBank].rclClip.left = pco->rclBounds.left;
181: ppdev->pBanks[ppdev->iBank].rclClip.right = pco->rclBounds.right;
182:
183: // Bump bank array index to next entry and the bank
184: // count.
185:
186: ppdev->iBank++;
187: ppdev->cBanks++;
188:
189: // Since we found the first bank, bail out of this loop.
190:
191: break;
192:
193: }
194: }
195:
196: if (i == ppdev->MaxBanks) {
197:
198: RIP("S3.DLL: bBankEnumStart - error \n");
199: return FALSE;
200: }
201:
202: if (iLastBank != iFirstBank)
203: {
204: // Set the last bank to the first bank in case there are no
205: // middle banks.
206:
207: iLastBank = iFirstBank;
208:
209: // Take care of all the middle banks.
210:
211: for (i = iFirstBank+1; i < ppdev->MaxBanks; i++)
212: {
213: if (ppdev->prclBanks[i].bottom < BottomScan)
214: {
215: // This bank is completely within the rendering rectangle.
216:
217: ppdev->pBanks[ppdev->iBank].pvScan0 = pbScan0 - (i * ppdev->BankSize);
218: ppdev->pBanks[ppdev->iBank].Bank = i;
219: ppdev->pBanks[ppdev->iBank].rclClip.top = ppdev->prclBanks[i].top;
220: ppdev->pBanks[ppdev->iBank].rclClip.bottom = ppdev->prclBanks[i].bottom;
221:
222: // Set the left and right bounds of the bank clip rect.
223:
224: ppdev->pBanks[ppdev->iBank].rclClip.left = pco->rclBounds.left;
225: ppdev->pBanks[ppdev->iBank].rclClip.right = pco->rclBounds.right;
226:
227: // Bump bank array index to next entry and the bank
228: // count.
229:
230: ppdev->iBank++;
231: ppdev->cBanks++;
232:
233: iLastBank = i;
234: }
235: else
236: {
237: // The bottom of the bank we're currently "looking" at is
238: // below (greater in value) than the bottom of the rectangle
239: // were rendering, so there we're done looking at the middle
240: // banks.
241:
242: break;
243: }
244: }
245:
246: // Now take care of the last bank.
247:
248: iLastBank++;
249:
250: if (ppdev->prclBanks[iLastBank].top < BottomScan)
251: {
252: ppdev->pBanks[ppdev->iBank].pvScan0 = pbScan0 - (iLastBank * ppdev->BankSize);
253: ppdev->pBanks[ppdev->iBank].Bank = iLastBank;
254:
255: ppdev->pBanks[ppdev->iBank].rclClip.top = ppdev->prclBanks[iLastBank].top;
256: ppdev->pBanks[ppdev->iBank].rclClip.bottom = BottomScan;
257:
258: ppdev->pBanks[ppdev->iBank].rclClip.left = pco->rclBounds.left;
259: ppdev->pBanks[ppdev->iBank].rclClip.right = pco->rclBounds.right;
260:
261: ppdev->cBanks++;
262:
263: }
264: }
265:
266: // We need to make sure the clipping level is at least DC_RECT.
267: // Some code in the engine (like EngCopybits) will ignore the
268: // clip rectangle entirely if the level is DC_TRIVIAL.
269:
270: if (pco->iDComplexity == DC_TRIVIAL)
271: pco->iDComplexity = DC_RECT;
272:
273: // Now take care of setting the first bank
274:
275: ppdev->iBank = 1; // set the next bank index
276: ppdev->cBanks--; // set # of remaining banks
277:
278: // Set the top and bottom scans for the caller
279:
280: prclScans->top = ppdev->pBanks[0].rclClip.top; // set top scan.
281: prclScans->bottom = ppdev->pBanks[0].rclClip.bottom; // set bottom scan.
282:
283: // Set the S3 chip.
284:
285: vSetS3Bank(ppdev, ppdev->pBanks[0].Bank);
286:
287: // Set the clip rectangle for the engine.
288:
289: pco->rclBounds = ppdev->pBanks[0].rclClip;
290:
291: // Set pvScan0 for the engine.
292:
293: pso->pvScan0 = ppdev->pBanks[0].pvScan0;
294:
295: ENABLE_DIRECT_ACCESS;
296:
297: return (TRUE);
298: }
299:
300: /******************************************************************************
301: * bSrcBankEnumStart - Start the bank enumeration when the screen is the
302: * source
303: *
304: * Save the original values for pvScan0 and rclBounds (The start of the
305: * engine managed bitmap and the clipping bounding rectangle.)
306: *
307: * Setup all the banks to enumerate in the ppdev->pBanks array.
308: * Setup the first bank to enumerate.
309: *
310: * Entry: prclScan->bottom - Ptr to the top (first) scan to render (inclusive)
311: * prclScan->top - Ptr to the bottom (last) scan to render (inclusive)
312: * pso - The surface object.
313: * pco - The clipping object.
314: *
315: * Exit: TRUE - if any rendering needs to be done.
316: * FALSE - if there is nothing to render, (i.e. the object
317: * is completely clipped out.)
318: * prclScan->bottom - The Top Scan to render into.
319: * prclScan->top - The Bottom Scan to render into.
320: *
321: * NOTE: This routine is a little trickier than bBankEnumStart. We make GDI
322: * read only the current bank by altering the CLIPOBJ before passing the
323: * call back to GDI. The problem here is that the CLIPOBJ applies only to the
324: * destination, but for this case it's the screen that is the source. So we
325: * have to adjust for this accordingly.
326: *
327: *****************************************************************************/
328: BOOL bSrcBankEnumStart(
329: PPDEV ppdev,
330: PRECTL prclScans,
331: SURFOBJ *pso,
332: CLIPOBJ *pco,
333: PRECTL prclDest)
334: {
335: LONG TopScan, BottomScan, BankBottom;
336: PBYTE pbScan0;
337: INT i, iFirstBank, iLastBank, cyFirstBank, cyMiddleBanks;
338: RECTL rclBounds;
339:
340: DISPDBG((3, "S3.DLL: bSrcBankEnumStart - Entry\n"));
341:
342: // Save the original pvScan0 and the ClipObj's rclBounds.
343:
344: ppdev->pvOrgScan0 = pso->pvScan0;
345: ppdev->rclOrgBounds = pco->rclBounds;
346: ppdev->iOrgDComplexity = pco->iDComplexity;
347: ppdev->fjOptions = pco->fjOptions;
348:
349: // If the clipping is not trivial, do an intersection of the
350: // Set the flag in the clip object to tell the engine to forcible
351: // clip to the rclBounds of the clip object.
352:
353: pco->fjOptions |= OC_BANK_CLIP;
354:
355: // top & bottom scans with the clipping bounds.
356:
357: // NOTE: Since the Scans rectangle and the clipping rectangle
358: // refer to two different surfaces, we will always use the
359: // the Scans rectangle to determine the bank(s) we need to
360: // enumerate.
361:
362: // rclBounds keeps track of the y-extents of the destination, and is
363: // calculated from the intersection of the destination rectangle
364: // and the CLIPOBJ's bounds:
365:
366: if (pco->iDComplexity != DC_TRIVIAL)
367: {
368: rclBounds.top = max(prclDest->top, pco->rclBounds.top);
369: rclBounds.bottom = min(prclDest->bottom, pco->rclBounds.bottom);
370: }
371: else
372: {
373: rclBounds.top = prclDest->top;
374: rclBounds.bottom = prclDest->bottom;
375: }
376:
377: // TopScan and BottomScan keep track of the corresponding y-extents of
378: // the source:
379:
380: TopScan = prclScans->top + (rclBounds.top - prclDest->top);
381: BottomScan = prclScans->bottom + (rclBounds.bottom - prclDest->bottom);
382:
383: // Init the variables used to set up the banks.
384:
385: iLastBank = -1;
386: ppdev->cBanks = 0;
387: ppdev->iBank = 0;
388: pbScan0 = (PBYTE) pso->pvScan0;
389:
390: // Find the bank that contains the top scan (the first bank).
391:
392: for (i = 0; i < ppdev->MaxBanks; i++)
393: {
394: BankBottom = ppdev->prclBanks[i].bottom;
395: if (BankBottom > TopScan)
396: {
397: // The Top scan is within this bank,
398:
399: iFirstBank = i;
400:
401: // Set up the bank entry.
402:
403: ppdev->pBanks[ppdev->iBank].pvScan0 = pbScan0 - (i * ppdev->BankSize);
404: ppdev->pBanks[ppdev->iBank].Bank = i;
405: ppdev->pBanks[ppdev->iBank].rclClip.top = rclBounds.top;
406:
407: // Take care of the case where the entire operation
408: // fits within one bank.
409:
410: if (BankBottom < BottomScan)
411: {
412: // The operation spans more than this one bank.
413:
414: cyFirstBank = BankBottom - TopScan;
415: ppdev->pBanks[ppdev->iBank].rclClip.bottom = rclBounds.top + cyFirstBank;
416: }
417: else
418: {
419: // The operation is completel contained with in this
420: // single bank.
421:
422: ppdev->pBanks[ppdev->iBank].rclClip.bottom = rclBounds.bottom;
423: iLastBank = iFirstBank;
424: }
425:
426: // Set the left and right bounds of the bank clip rect.
427:
428: ppdev->pBanks[ppdev->iBank].rclClip.left = pco->rclBounds.left;
429: ppdev->pBanks[ppdev->iBank].rclClip.right = pco->rclBounds.right;
430:
431: // Bump bank array index to next entry and the bank
432: // count.
433:
434: ppdev->iBank++;
435: ppdev->cBanks++;
436:
437: // Since we found the first bank, bail out of this loop.
438:
439: break;
440:
441: }
442: }
443:
444: if (i == ppdev->MaxBanks) {
445:
446: RIP("S3.DLL: bSrcBankEnumStart - error \n");
447: return FALSE;
448: }
449:
450: if (iLastBank != iFirstBank)
451: {
452: // Set the last bank to the first bank in case there are no
453: // middle banks.
454:
455: iLastBank = iFirstBank;
456:
457: // Take care of all the middle banks.
458: // Update rclBounds for this bank.
459:
460: rclBounds.top += cyFirstBank;
461:
462: cyMiddleBanks = ppdev->ScansPerBank;
463: rclBounds.bottom = rclBounds.top + cyMiddleBanks;
464:
465: for (i = iFirstBank+1; i < ppdev->MaxBanks; i++)
466: {
467: if (ppdev->prclBanks[i].bottom < BottomScan)
468: {
469: // This bank is completely within the rendering rectangle.
470:
471: ppdev->pBanks[ppdev->iBank].pvScan0 = pbScan0 - (i * ppdev->BankSize);
472: ppdev->pBanks[ppdev->iBank].Bank = i;
473:
474: ppdev->pBanks[ppdev->iBank].rclClip.top = rclBounds.top;
475: ppdev->pBanks[ppdev->iBank].rclClip.bottom = rclBounds.bottom;
476:
477: // Set the left and right bounds of the bank clip rect.
478:
479: ppdev->pBanks[ppdev->iBank].rclClip.left = pco->rclBounds.left;
480: ppdev->pBanks[ppdev->iBank].rclClip.right = pco->rclBounds.right;
481:
482: // Update for the next bank bounds.
483:
484: rclBounds.top += cyMiddleBanks;
485:
486: rclBounds.bottom = rclBounds.top + cyMiddleBanks;
487:
488: // Bump bank array index to next entry and the bank
489: // count.
490:
491: ppdev->iBank++;
492: ppdev->cBanks++;
493:
494: iLastBank = i;
495:
496: }
497: }
498:
499: // Now take care of the last bank.
500:
501: iLastBank++;
502:
503: if (ppdev->prclBanks[iLastBank].top < BottomScan)
504: {
505: ppdev->pBanks[ppdev->iBank].pvScan0 = pbScan0 - (iLastBank * ppdev->BankSize);
506: ppdev->pBanks[ppdev->iBank].Bank = iLastBank;
507:
508: ppdev->pBanks[ppdev->iBank].rclClip.top = rclBounds.top;
509: ppdev->pBanks[ppdev->iBank].rclClip.bottom = rclBounds.bottom;
510:
511: ppdev->pBanks[ppdev->iBank].rclClip.left = pco->rclBounds.left;
512: ppdev->pBanks[ppdev->iBank].rclClip.right = pco->rclBounds.right;
513:
514: ppdev->cBanks++;
515:
516: }
517: }
518:
519: // We need to make sure the clipping level is at least DC_RECT.
520: // Some code in the engine (like EngCopybits) will ignore the
521: // clip rectangle entirely if the level is DC_TRIVIAL.
522:
523: if (pco->iDComplexity == DC_TRIVIAL)
524: pco->iDComplexity = DC_RECT;
525:
526: // Now take care of setting the first bank
527:
528: ppdev->iBank = 1; // set the next bank index
529: ppdev->cBanks--; // set # of remaining banks
530:
531: // Set the top and bottom scans for the caller
532:
533: prclScans->top = ppdev->pBanks[0].rclClip.top; // set top scan.
534: prclScans->bottom = ppdev->pBanks[0].rclClip.bottom; // set bottom scan.
535:
536: // Set the S3 chip.
537:
538: vSetS3Bank(ppdev, ppdev->pBanks[0].Bank);
539:
540: // Set the clip rectangle for the engine.
541:
542: pco->rclBounds = ppdev->pBanks[0].rclClip;
543:
544: // Set pvScan0 for the engine.
545:
546: pso->pvScan0 = ppdev->pBanks[0].pvScan0;
547:
548: ENABLE_DIRECT_ACCESS;
549:
550: return (TRUE);
551: }
552:
553: /******************************************************************************
554: * bBankEnum - Enumerate the next bank.
555: *
556: * Just enumerate the next bank. pvScan0, the clipping Rect, and the
557: * chip are all set up for this bank.
558: *
559: * Entry: none
560: *
561: * Exit: TRUE - if this bank needs any rendering.
562: * FALSE - if there is nothing to render.
563: *
564: * prclScans - The Scans to render into.
565: *
566: ******************************************************************************/
567: BOOL bBankEnum(
568: PPDEV ppdev,
569: PRECTL prclScans,
570: SURFOBJ *pso,
571: CLIPOBJ *pco)
572: {
573: DISPDBG((3, "S3.DLL: bBankEnum - Entry\n"));
574:
575: if (ppdev->cBanks == 0)
576: return (FALSE);
577:
578: // Set the top and bottom scans for the caller
579:
580: prclScans->top = ppdev->pBanks[ppdev->iBank].rclClip.top; // set top scan.
581: prclScans->bottom = ppdev->pBanks[ppdev->iBank].rclClip.bottom; // set bottom scan.
582:
583: // Set the S3 chip.
584:
585: vSetS3Bank(ppdev, ppdev->pBanks[ppdev->iBank].Bank);
586:
587: // Set the clip rectangle for the engine.
588:
589: pco->rclBounds = ppdev->pBanks[ppdev->iBank].rclClip;
590:
591: // Set pvScan0 for the engine.
592:
593: pso->pvScan0 = ppdev->pBanks[ppdev->iBank].pvScan0;
594:
595: // Update the bank index and bank count.
596:
597: ppdev->cBanks--;
598: ppdev->iBank++;
599:
600: return (TRUE);
601: }
602:
603: /******************************************************************************
604: * bBankEnumEnd - Finish the bank enumeration.
605: *
606: * Cleanup from the enumeration. This restores the original pvScan0 and
607: * ClipRectangle.
608: *
609: ******************************************************************************/
610: BOOL bBankEnumEnd(
611: PPDEV ppdev,
612: SURFOBJ *pso,
613: CLIPOBJ *pco)
614: {
615: DISPDBG((3, "S3.DLL: bBankEnumEnd - Entry\n"));
616:
617: pso->pvScan0 = ppdev->pvOrgScan0;
618: pco->rclBounds = ppdev->rclOrgBounds;
619: pco->iDComplexity = ppdev->iOrgDComplexity;
620: pco->fjOptions = ppdev->fjOptions;
621:
622: ENABLE_S3_ENGINE;
623:
624: return (TRUE);
625: }
626:
627:
628:
629:
630: /******************************************************************************
631: * vSetS3Bank - Set the bank on the S3 chip.
632: ******************************************************************************/
633: VOID vSetS3Bank(
634: PPDEV ppdev,
635: UINT iBank)
636: {
637:
638: TEST_928("S3.DLL!vSetS3Bank - pre bank switch 928 failure\n");
639:
640: // Set the bank
641:
642: OUTPW1 (CRTC_INDEX, (((ppdev->jS3R5 | (0x0F & iBank)) << 8) | S3R5));
643:
644: if (ppdev->bNewBankControl == TRUE)
645: {
646: OUTP1 (CRTC_INDEX, EX_SCTL_2);
647: OUTP1 (CRTC_DATA, ppdev->ExtSysCtl2 | ((0x30 & iBank) >> 2));
648: }
649:
650: // CHIPBUG.
651: // Anil said I should read this back.
652:
653: INP1(CRTC_DATA);
654:
655: TEST_928("S3.DLL!vSetS3Bank - post bank switch 928 failure\n");
656:
657: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.