|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: S3Sup.c
3: *
4: * S3 support routines.
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: *
8: \**************************************************************************/
9:
10: #include "driver.h"
11:
12: #define TOP_CLIP 0x1
13: #define LEFT_CLIP 0x2
14: #define RIGHT_CLIP 0x4
15: #define BOTTOM_CLIP 0x8
16:
17: #if CATCHIT
18:
19: ULONG nOutpAccesses,
20: nOutpwAccesses,
21: nInpAccesses,
22: nInpwAccesses;
23:
24: #define CHIP_STATE_TEST \
25: byte = inp(0x3d4); \
26: outp(0x3d4, 0x39); \
27: if ((inp(0x3d5) & 0xA0) != 0xA0) \
28: RIP("S3.DLL! Invalid Reg 39\n"); \
29: outp(0x3d4, 0x40); \
30: if (!(inp(0x3d5) & 0x1)) \
31: RIP("S3.DLL! Invalid Reg 40 bit 0\n"); \
32: outp(0x3d4, byte);
33:
34: #else
35:
36: #if LOG_OUTS
37:
38: #define MAX_LOG 256
39:
40: typedef struct _logentry {
41: WORD port,
42: val ;
43: } LOGENTRY;
44:
45: LOGENTRY aLogEntries[MAX_LOG];
46: INT iCurrentLogEntry = 0;
47:
48:
49: #define LOG_OUTPUT \
50: aLogEntries[iCurrentLogEntry].port = (WORD) port; \
51: aLogEntries[iCurrentLogEntry].val = (WORD) val; \
52: iCurrentLogEntry = ++iCurrentLogEntry % MAX_LOG;
53:
54:
55: #endif
56: #endif
57:
58:
59: BYTE Rop2ToS3Rop[] = {
60: LOGICAL_0, /* 0 1 */
61: NOT_SCREEN_AND_NOT_NEW, /* DPon 2 */
62: SCREEN_AND_NOT_NEW, /* DPna 3 */
63: NOT_NEW, /* Pn 4 */
64: NOT_SCREEN_AND_NEW, /* PDna 5 */
65: NOT_SCREEN, /* Dn 6 */
66: SCREEN_XOR_NEW, /* DPx 7 */
67: NOT_SCREEN_OR_NOT_NEW, /* DPan 8 */
68: SCREEN_AND_NEW, /* DPa 9 */
69: NOT_SCREEN_XOR_NEW, /* DPxn 10 */
70: LEAVE_ALONE, /* D 11 */
71: SCREEN_OR_NOT_NEW, /* DPno 12 */
72: OVERPAINT, /* P 13 */
73: NOT_SCREEN_OR_NEW, /* PDno 14 */
74: SCREEN_OR_NEW, /* DPo 15 */
75: LOGICAL_1 /* 1 16 */
76: };
77:
78: #if defined(i386)
79:
80: /****************************************************************************\
81: * vDataPortInB
82: \****************************************************************************/
83: VOID vDataPortInB(PPDEV ppdev, PBYTE pb, UINT count)
84: {
85: ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);
86:
87: _asm {
88: cld
89:
90: mov ecx, count
91: mov edi, pb
92: mov edx, pixtrans
93:
94: rep insb
95: }
96: }
97:
98: /*****************************************************************************
99: * vDataPortIn
100: ****************************************************************************/
101: VOID vDataPortIn(PPDEV ppdev, PWORD pw, UINT count)
102: {
103: ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);
104:
105:
106: _asm {
107: cld
108:
109: mov ecx, count
110: mov edi, pw
111: mov edx, pixtrans
112:
113: rep insw
114: }
115: }
116:
117:
118: /*****************************************************************************
119: * vDataPortOutB
120: ****************************************************************************/
121: VOID vDataPortOutB(PPDEV ppdev, PBYTE pb, UINT count)
122: {
123: ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);
124:
125: _asm {
126: cld
127:
128: mov ecx, count
129: mov esi, pb
130: mov edx, pixtrans
131:
132: rep outsb
133: }
134: }
135:
136: /*****************************************************************************
137: * vDataPortOut
138: ****************************************************************************/
139: VOID vDataPortOut(PPDEV ppdev, PWORD pw, UINT count)
140: {
141: ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);
142:
143: _asm {
144: cld
145:
146: mov ecx, count
147: mov esi, pw
148: mov edx, pixtrans
149:
150: rep outsw
151: }
152: }
153:
154: #else
155:
156: /****************************************************************************\
157: * vDataPortInB
158: \****************************************************************************/
159: VOID vDataPortInB(PPDEV ppdev, PBYTE pb, UINT count)
160: {
161: while (count-- > 0) {
162: *((PUCHAR)pb)++ = READ_PORT_UCHAR (gpucCsrBase + PIXEL_TRANSFER);
163: }
164: }
165:
166: /*****************************************************************************
167: * vDataPortIn
168: ****************************************************************************/
169: VOID vDataPortIn(PPDEV ppdev, PWORD pw, UINT count)
170: {
171: while (count-- > 0) {
172: *((USHORT UNALIGNED *)pw)++ = READ_PORT_USHORT ((PUSHORT)(gpucCsrBase + PIXEL_TRANSFER));
173: }
174: }
175:
176:
177: /*****************************************************************************
178: * vDataPortOutB
179: ****************************************************************************/
180: VOID vDataPortOutB(PPDEV ppdev, PBYTE pb, UINT count)
181: {
182: while (count-- > 0) {
183: WRITE_PORT_UCHAR (gpucCsrBase + PIXEL_TRANSFER, *((PUCHAR)pb)++);
184: }
185: }
186:
187: /*****************************************************************************
188: * vDataPortOut
189: ****************************************************************************/
190: VOID vDataPortOut(PPDEV ppdev, PWORD pw, UINT count)
191: {
192: while (count-- > 0) {
193: WRITE_PORT_USHORT ((PUSHORT)(gpucCsrBase + PIXEL_TRANSFER), *((USHORT UNALIGNED *)pw)++);
194: }
195:
196: }
197:
198: #endif //i386
199:
200: /*****************************************************************************
201: * bIntersectTest -
202: ****************************************************************************/
203: BOOL bIntersectTest(PRECTL prcl1, PRECTL prcl2)
204: {
205:
206: if ( (prcl1->left > prcl2->right) ||
207: (prcl1->right < prcl2->left) ||
208: (prcl1->top > prcl2->bottom) ||
209: (prcl1->bottom < prcl2->top) )
210: return(FALSE);
211:
212: return(TRUE);
213: }
214:
215:
216: /*****************************************************************************
217: * bTrivialAccept - Test for a trivial accept rect 1 being inside or
218: * coincident with rect 2.
219: ****************************************************************************/
220: BOOL bTrivialAcceptTest(PRECTL prcl1, PRECTL prcl2)
221: {
222:
223: if ( (prcl1->left < prcl2->left) ||
224: (prcl1->right > prcl2->right) ||
225: (prcl1->top < prcl2->top) ||
226: (prcl1->bottom > prcl2->bottom) )
227: return(FALSE);
228:
229: return(TRUE);
230: }
231:
232:
233: /*****************************************************************************
234: * vResetS3Clipping
235: *****************************************************************************/
236: VOID vResetS3Clipping(PPDEV ppdev)
237: {
238: RECTL rcl;
239:
240: rcl.top = 0;
241: rcl.left = 0;
242: rcl.right = S3_MAX_RAM_WIDTH;
243: rcl.bottom = S3_MAX_RAM_HEIGHT;
244:
245: vSetS3ClipRect(ppdev, &rcl);
246: }
247:
248: /*****************************************************************************
249: * vSetS3ClipRect
250: *
251: * Important note: GDI is inclusive/exclusive,
252: * the chip is inclusive/inclusive,
253: * and this routine does the mapping.
254: *****************************************************************************/
255: VOID vSetS3ClipRect(PPDEV ppdev, PRECTL prclClip)
256: {
257: ULONG fl;
258: WORD clipcount;
259:
260: fl = 0;
261: clipcount = 0;
262:
263: if (ppdev->ClipTop != prclClip->top) {
264: fl |= TOP_CLIP;
265: ppdev->ClipTop = prclClip->top;
266: clipcount++;
267: }
268:
269: if (ppdev->ClipLeft != prclClip->left) {
270: fl |= LEFT_CLIP;
271: ppdev->ClipLeft = prclClip->left;
272: clipcount++;
273: }
274:
275: if (ppdev->ClipRight != prclClip->right) {
276: fl |= RIGHT_CLIP;
277: ppdev->ClipRight = prclClip->right;
278: clipcount++;
279: }
280:
281: if (ppdev->ClipBottom != prclClip->bottom) {
282: fl |= BOTTOM_CLIP;
283: ppdev->ClipBottom = prclClip->bottom;
284: clipcount++;
285: }
286:
287: if (fl == 0)
288: return;
289: #if 1
290:
291: if (ppdev->cxScreen == ppdev->cxMaxRam)
292: {
293: if (ppdev->ClipRight > ( (LONG)(ppdev->cxScreen)))
294: {
295: RIP("S3.DLL!vSetS3ClipRect - (ppdev->ClipRight > ppdev->cxScreen)\n");
296: }
297: }
298:
299: DISPDBG((1, "S3.DLL!vSetS3ClipRect - New Clipping %d, %d %d, %d\n",
300: ppdev->ClipTop, ppdev->ClipLeft,
301: ppdev->ClipRight, ppdev->ClipBottom));
302:
303: #endif
304:
305: //
306: // Wait for the minium amount of queue entries needed
307: //
308:
309: clipcount = (FIFO_1_EMPTY << 1) >> clipcount;
310:
311: FIFOWAIT(clipcount);
312:
313: if (fl & TOP_CLIP)
314: OUTPW (MULTIFUNC_CNTL, (CLIP_TOP | ppdev->ClipTop));
315:
316: if (fl & LEFT_CLIP)
317: OUTPW (MULTIFUNC_CNTL, (CLIP_LEFT | ppdev->ClipLeft));
318:
319: if (fl & RIGHT_CLIP)
320: OUTPW (MULTIFUNC_CNTL, (CLIP_RIGHT | (ppdev->ClipRight - 1)));
321:
322: if (fl & BOTTOM_CLIP)
323: OUTPW (MULTIFUNC_CNTL, (CLIP_BOTTOM | (ppdev->ClipBottom - 1)));
324: }
325:
326:
327: #if CATCHIT
328:
329: VOID outpw_test(unsigned port , unsigned val)
330: {
331: BYTE byte;
332:
333: CHIP_STATE_TEST;
334:
335: LOGDBG((9, "Ow %lx: %lx\n", port, val));
336:
337: nOutpwAccesses++;
338:
339: outpw(port, val);
340: return;
341: }
342:
343:
344: VOID outp_test(unsigned port, int val)
345: {
346: BYTE byte;
347:
348: CHIP_STATE_TEST;
349:
350: LOGDBG((9, "Ob %lx: %lx\n", port, val));
351:
352: nOutpAccesses++;
353:
354: outp(port, val);
355: return;
356: }
357:
358:
359: BYTE inp_test(WORD port)
360: {
361: BYTE byte;
362:
363: CHIP_STATE_TEST;
364:
365: nInpAccesses++;
366:
367: return(inp(port));
368: }
369:
370:
371: WORD inpw_test(WORD port)
372: {
373: BYTE byte;
374:
375: CHIP_STATE_TEST;
376:
377: nInpwAccesses++;
378:
379: return(inpw(port));
380: }
381:
382: VOID vCheckDataReady(PPDEV ppdev)
383: {
384: ASSERTS3((INPW(GP_STAT) & HARDWARE_BUSY),
385: "S3.DLL - S3 not ready for data transfer\n");
386: }
387:
388: VOID vCheckDataComplete(PPDEV ppdev)
389: {
390: LONG i;
391:
392: // We loop because it may take a while for the hardware to finish
393: // digesting all the data we transferred:
394:
395: for (i = 1000; i > 0; i--)
396: {
397: if (!(INPW(GP_STAT) & HARDWARE_BUSY))
398: return;
399: }
400:
401: RIP("S3.DLL - S3 data transfer not complete\n");
402: }
403:
404: #endif
405:
406: #if LOG_OUTS
407:
408: VOID outpw_log(unsigned port , unsigned val)
409: {
410: BYTE byte;
411:
412: LOG_OUTPUT;
413:
414: LOGDBG((9, "Ow %lx: %lx\n", port, val));
415:
416: return (outpw(port, val));
417: }
418:
419:
420: VOID outp_log(unsigned port, int val)
421: {
422: BYTE byte;
423:
424: LOG_OUTPUT;
425:
426: LOGDBG((9, "Ob %lx: %lx\n", port, val));
427:
428: return (outp(port, val));
429: }
430:
431:
432: #endif
433:
434:
435:
436:
437: #if !defined(_X86_) && !defined(i386)
438:
439: /******************************************************************************
440: * vPuntGetBits - Get the bits from the device surface onto the "punt" bitmap.
441: *****************************************************************************/
442: VOID vPuntGetBits(PPDEV ppdev, SURFOBJ *psoTrg, RECTL *prclTrg)
443: {
444: UINT i, j ;
445:
446: LONG lDestDelta,
447: xTrg, yTrg,
448: cxTrg, cyTrg ;
449:
450: PBYTE pbScan0,
451: pbDestRect ;
452:
453: PWORD pw ;
454:
455: WORD s3Cmd ;
456:
457: RECTL rclClip ;
458:
459:
460: // Default the clipping to the entire screen to get the data.
461: // we can over write portions of the host dest bitmap
462: // because we never display it, we only use this dest bitmap
463: // as work surface for the engine.
464:
465: rclClip.left = 0 ;
466: rclClip.top = 0 ;
467: rclClip.right = S3BM_WIDTH;
468: rclClip.bottom = S3BM_HEIGHT;
469:
470: vSetS3ClipRect(ppdev, &rclClip) ;
471:
472: // Calculate the size of the target rectangle, and pick up
473: // some convienent locals.
474:
475: pbScan0 = (PBYTE) ppdev->psoTemp->pvScan0 ;
476:
477: // The source rectangle passed into DrvCopyBits/DrvBitBlt might
478: // not be clipped to the visible surface (because the clip object
479: // would take care of that), so we have to be careful that we don't
480: // overwrite anything outside the visible surface:
481:
482: xTrg = max(prclTrg->left, 0) ;
483: yTrg = max(prclTrg->top, 0) ;
484:
485: cxTrg = min(prclTrg->right, (LONG) ppdev->cxScreen) - xTrg ;
486: cyTrg = min(prclTrg->bottom, (LONG) ppdev->cyScreen) - yTrg ;
487:
488: lDestDelta = ppdev->psoTemp->lDelta ;
489:
490: // Copy the target rectangle from the real screen to the
491: // bitmap we are telling the engine is the screen.
492:
493: // Calculate the location of the dest rect.
494:
495: pbDestRect = pbScan0 + (yTrg * lDestDelta) + xTrg ;
496:
497: // Set the S3 chip up for the copy.
498:
499: s3Cmd = RECTANGLE_FILL | BYTE_SWAP | BUS_SIZE_16 |
500: DRAWING_DIR_TBLRXM | DIR_TYPE_XY | WAIT |
501: DRAW | LAST_PIXEL_ON | READ ;
502:
503: FIFOWAIT(FIFO_6_EMPTY) ;
504:
505: outpw (MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)) ;
506: outpw (CUR_X, xTrg) ;
507: outpw (CUR_Y, yTrg) ;
508: outpw (RECT_WIDTH, cxTrg - 1) ;
509: outpw (MULTIFUNC_CNTL, (RECT_HEIGHT | (cyTrg - 1))) ;
510: outpw (CMD, s3Cmd) ;
511:
512: // Wait for the Data Available.
513:
514: while (!(inpw(GP_STAT) & READ_DATA_AVAILABLE)) ;
515:
516: // Now transfer the data from the screen to the host memory bitmap.
517:
518: pw = (PWORD) pbDestRect ;
519: j = (cxTrg + 1) / 2 ;
520:
521: for (i = 0 ; i < (UINT) cyTrg ; i++)
522: {
523: vDataPortIn(ppdev, pw, j) ;
524: ((PBYTE) pw) += lDestDelta ;
525: }
526:
527: }
528:
529: /******************************************************************************
530: * vPuntPutBits - Put the bits from the "punt" bitmap to the device surface.
531: *****************************************************************************/
532: VOID vPuntPutBits(PPDEV ppdev, SURFOBJ *psoTrg, RECTL *prclTrg)
533: {
534: UINT i, j ;
535:
536: LONG lDestDelta,
537: xTrg, yTrg,
538: cxTrg, cyTrg ;
539:
540: PBYTE pbScan0,
541: pbDestRect ;
542:
543: PWORD pw ;
544:
545: WORD s3Cmd ;
546:
547: // Set the clipping to exactly what we need on the destination.
548:
549: vSetS3ClipRect(ppdev, prclTrg) ;
550:
551: // Recalculate the target position(s) and extent(s)
552:
553: // The target rectangle passed into DrvCopyBits/DrvBitBlt might
554: // not be clipped to the visible surface (because the clip object
555: // would take care of that), so we have to be careful that we don't
556: // overwrite anything outside the visible surface:
557:
558: xTrg = max(prclTrg->left, 0) ;
559: yTrg = max(prclTrg->top, 0) ;
560:
561: cxTrg = min(prclTrg->right, (LONG) ppdev->cxScreen) - xTrg ;
562: cyTrg = min(prclTrg->bottom, (LONG) ppdev->cyScreen) - yTrg ;
563:
564: pbScan0 = (PBYTE) (ppdev->psoTemp->pvScan0) ;
565: lDestDelta = ppdev->psoTemp->lDelta ;
566: pbDestRect = pbScan0 + (yTrg * lDestDelta) + xTrg ;
567:
568: // Put the bits back on the screen.
569:
570: s3Cmd = RECTANGLE_FILL | BUS_SIZE_16 | BYTE_SWAP | WAIT |
571: DRAW | DRAWING_DIR_TBLRXM | DIR_TYPE_XY |
572: LAST_PIXEL_ON | SINGLE_PIXEL | WRITE ;
573:
574: FIFOWAIT(FIFO_7_EMPTY) ;
575:
576: outpw(FRGD_MIX, (SRC_CPU_DATA | OVERPAINT)) ;
577: outpw(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)) ;
578: outpw (CUR_X, xTrg) ;
579: outpw (CUR_Y, yTrg) ;
580: outpw (RECT_WIDTH, cxTrg - 1) ;
581: outpw (MULTIFUNC_CNTL, (RECT_HEIGHT | (cyTrg - 1))) ;
582: outpw(CMD, s3Cmd) ;
583:
584: // Now transfer the data, from the host memory bitmap to the screen.
585:
586: pw = (PWORD) pbDestRect ;
587: j = (cxTrg + 1) / 2 ;
588:
589: for (i = 0 ; i < (UINT) cyTrg ; i++)
590: {
591: vDataPortOut(ppdev, pw, j) ;
592: ((PBYTE) pw) += lDestDelta ;
593: }
594:
595: return ;
596: }
597:
598: #endif // !defined(_X86_) && !defined(i386)
599:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.