1 /*
2 * $XFree86: mit/server/ddx/x386/vga256/drivers/cirrus/cir_im.c,v 2.2 1993/10/02 16:09:18 dawes Exp $
3 *
4 * Copyright 1993 by Bill Reynolds, Santa Fe, New Mexico
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Bill Reynolds not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Bill Reynolds makes no representations
13 * about the suitability of this software for any purpose. It is provided
14 * "as is" without express or implied warranty.
15 *
16 * BILL REYNOLDS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL BILL REYNOLDS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Author: Bill Reynolds, bill@goshawk.lanl.gov
25 *
26 * Reworked by: Simon P. Cooper, <scooper@vizlab.rutgers.edu>
27 *
28 * Id: cir_im.c,v 0.7 1993/09/16 01:07:25 scooper Exp
29 */
30
31 #include "misc.h"
32 #include "x386.h"
33 #include "X.h"
34 #include "Xos.h"
35 #include "Xmd.h"
36 #include "Xproto.h"
37 #include "gcstruct.h"
38 #include "windowstr.h"
39 #include "scrnintstr.h"
40 #include "pixmapstr.h"
41 #include "regionstr.h"
42 #include "cfb.h"
43 #include "cfbmskbits.h"
44 #include "cfb8bit.h"
45
46 #include "mergerop.h"
47 #include "vgaBank.h"
48 #include "compiler.h"
49 #include "os.h" /* For FatalError */
50
51 #include "cir_driver.h"
52
53 extern pointer vgaBase;
54
55 #define BLITADDRESS (vgaBase+4)
56
57 extern void vgaImageWrite ();
58 extern void vgaImageRead ();
59 extern void SpeedUpBitBlt ();
60
CirrusBltLine(dstAddr,srcAddr,dstPitch,srcPitch,w,h,dir)61 CirrusBltLine (dstAddr, srcAddr, dstPitch, srcPitch, w, h, dir)
62 unsigned int dstAddr, srcAddr;
63 unsigned int dstPitch, srcPitch;
64 unsigned int w, h;
65 int dir; /* >0, increase adrresses, <0, decrease */
66 {
67 volatile unsigned char tmpreg;
68
69 /* Set the SrcAddress */
70
71 outw (0x3CE, ((srcAddr & 0x000000FF) << 8) | 0x2C);
72 outw (0x3CE, ((srcAddr & 0x0000FF00)) | 0x2D);
73 outw (0x3CE, ((srcAddr & 0x001F0000) >> 8) | 0x2E);
74
75 /* Set the Src Pitch */
76
77 outw (0x3CE, ((srcPitch & 0x000000FF) << 8) | 0x26);
78 outw (0x3CE, ((srcPitch & 0x00000F00)) | 0x27);
79
80 /* Set the DstAddress */
81
82 outw (0x3CE, ((dstAddr & 0x000000FF) << 8) | 0x28);
83 outw (0x3CE, ((dstAddr & 0x0000FF00)) | 0x29);
84 outw (0x3CE, ((dstAddr & 0x001F0000) >> 8) | 0x2A);
85
86 /* Set the Dest Pitch */
87
88 outw (0x3CE, ((dstPitch & 0x000000FF) << 8) | 0x24);
89 outw (0x3CE, ((dstPitch & 0x00000F00)) | 0x25);
90
91 /* Set the Width */
92
93 w--;
94 outw (0x3CE, ((w & 0x000000FF) << 8) | 0x20);
95 outw (0x3CE, ((w & 0x00000700)) | 0x21);
96
97 /* Set the Height */
98
99 h--;
100 outw (0x3CE, ((h & 0x000000FF) << 8) | 0x22);
101 outw (0x3CE, ((h & 0x00000300)) | 0x23);
102
103 /* Set the direction */
104 if (dir > 0)
105 {
106 outw (0x3CE, (0x00 << 8) | 0x30);
107 }
108 else
109 {
110 outw (0x3CE, (0x01 << 8) | 0x30);
111 }
112
113 /* Set the ROP: Copy = 0x0D */
114 outw (0x3CE, (CROP_SRC << 8) | 0x32);
115
116 /* Ok, we're all loaded up, let's do it */
117 outw (0x3CE, (0x02 << 8) | 0x31);
118
119 do
120 {
121 outb (0x3CE, 0x31);
122 tmpreg = inb (0x3CF);
123 }
124 while (tmpreg & 0x01);
125
126 }
127
128 void
CirrusBitBlt(pdstBase,psrcBase,widthSrc,widthDst,x,y,x1,y1,w,h,xdir,ydir,alu,planemask)129 CirrusBitBlt (pdstBase, psrcBase, widthSrc, widthDst, x, y,
130 x1, y1, w, h, xdir, ydir, alu, planemask)
131 pointer pdstBase, psrcBase; /* start of src bitmap */
132 int widthSrc, widthDst;
133 int x, y, x1, y1, w, h; /* Src x,y; Dst x1,y1; Dst (w)idth,(h)eight */
134 int xdir, ydir;
135 int alu;
136 unsigned long planemask;
137 {
138 unsigned int psrc, pdst, ppdst;
139 int i;
140
141 if (widthSrc < 0)
142 widthSrc *= -1;
143 if (widthDst < 0)
144 widthDst *= -1;
145
146 if (alu == GXcopy && (planemask & 0xFF) == 0xFF)
147 {
148 if (xdir == 1) /* left to right */
149 {
150 if (ydir == 1) /* top to bottom */
151 {
152 psrc = (y * widthSrc) + x;
153 pdst = (y1 * widthDst) + x1;
154 }
155 else
156 /* bottom to top */
157 {
158 psrc = ((y + h - 1) * widthSrc) + x;
159 pdst = ((y1 + h - 1) * widthDst) + x1;
160 }
161 }
162 else
163 /* right to left */
164 {
165 if (ydir == 1) /* top to bottom */
166 {
167 psrc = (y * widthSrc) + x + w - 1;
168 pdst = (y1 * widthDst) + x1 + w - 1;
169 }
170 else
171 /* bottom to top */
172 {
173 psrc = ((y + h - 1) * widthSrc) + x + w - 1;
174 pdst = ((y1 + h - 1) * widthDst) + x1 + w - 1;
175 }
176 }
177
178 /* I could probably do the line by line */
179 /* blits a little faster by breaking the */
180 /* blit regions into rectangles */
181 /* and blitting those, making sure I don't */
182 /* overwrite stuff. However, the */
183 /* difference between the line by line */
184 /* and block blits isn't noticable to */
185 /* me, so I think I'll blow it off. */
186
187 if (xdir == 1)
188 {
189 if (ydir == 1)
190 { /* Nothing special, straight blit */
191 CirrusBltLine (pdst, psrc, widthDst, widthSrc, w, h, 1);
192 }
193 else
194 /* Line by line, going up. */
195 {
196 for (i = 0; i < h; i++)
197 {
198 CirrusBltLine (pdst, psrc, widthDst, widthSrc, w, 1, 1);
199 psrc -= widthSrc;
200 pdst -= widthDst;
201 }
202 }
203 }
204 else
205 {
206
207 if (ydir == 1) /* Line by line, going down and to the left */
208 {
209 for (i = 0; i < h; i++)
210 {
211 CirrusBltLine (pdst, psrc, widthDst, widthSrc, w, 1, -1);
212 psrc += widthSrc;
213 pdst += widthDst;
214 }
215 }
216 else
217 /* Another stock blit, albeit backwards */
218 {
219 CirrusBltLine (pdst, psrc, widthDst, widthSrc, w, h, -1);
220 }
221 }
222 }
223 }
224
225 void
CirrusImageWrite(pdstBase,psrcBase,widthSrc,widthDst,x,y,x1,y1,w,h,xdir,ydir,alu,planemask)226 CirrusImageWrite (pdstBase, psrcBase, widthSrc, widthDst, x, y,
227 x1, y1, w, h, xdir, ydir, alu, planemask)
228 pointer pdstBase, psrcBase; /* start of src bitmap */
229 int widthSrc, widthDst;
230 int x, y, x1, y1, w, h; /* Src x,y; Dst x1,y1; Dst (w)idth,(h)eight */
231 int xdir, ydir;
232 int alu;
233 unsigned long planemask;
234 {
235 unsigned long *plSrc;
236 volatile unsigned char status;
237 volatile unsigned long *pDst;
238 pointer psrc;
239 unsigned int dstAddr;
240 unsigned int word_count, word_rem;
241 int i, j;
242
243 if (alu == GXcopy && (planemask & 0xFF) == 0xFF)
244 {
245 int width, height;
246
247 psrc = psrcBase + (y * widthSrc) + x;
248 dstAddr = (y1 * widthDst) + x1;
249
250 /* Set the DstAddress */
251
252 outw (0x3CE, ((dstAddr & 0x000000FF) << 8) | 0x28);
253 outw (0x3CE, ((dstAddr & 0x0000FF00)) | 0x29);
254 outw (0x3CE, ((dstAddr & 0x001F0000) >> 8) | 0x2A);
255
256 /* Set the Dest Pitch */
257
258 outw (0x3CE, ((widthDst & 0x000000FF) << 8) | 0x24);
259 outw (0x3CE, ((widthDst & 0x00000F00)) | 0x25);
260
261 /* Set the Width */
262
263 width = w - 1;
264 outw (0x3CE, ((width & 0x000000FF) << 8) | 0x20);
265 outw (0x3CE, ((width & 0x00000700)) | 0x21);
266
267 /* Set the Height */
268
269 height = h - 1;
270 outw (0x3CE, ((height & 0x000000FF) << 8) | 0x22);
271 outw (0x3CE, ((height & 0x00000300)) | 0x23);
272
273 /* Set the direction and source (System Memory) */
274
275 outw (0x3CE, (0x04 << 8) | 0x30);
276
277 /* Set the ROP: Copy = 0x0D */
278 outw (0x3CE, (0x0D << 8) | 0x32);
279
280 /* Lets play DMA controller ... */
281 outw (0x3CE, (0x02 << 8) | 0x31);
282
283 /*
284 * We must transfer 4 bytes per blit line. This is cautious code and I
285 * do not read from outside of the pixmap... The 386/486 allows
286 * unaligned memory acceses, and has little endian word ordering. This
287 * is used to our advantage when dealing with the 3 byte remainder.
288 * Don't try this on your Sparc :-)
289 */
290
291 pDst = (unsigned long *) BLITADDRESS;
292
293 word_count = w >> 2;
294 word_rem = w & 0x3;
295
296 switch (word_rem)
297 {
298
299 case 0:
300 for (i = 0; i < h; i++)
301 {
302 plSrc = (unsigned long *) psrc;
303 for (j = 0; j < word_count; j++)
304 *pDst = *plSrc++;
305 psrc += widthSrc;
306 }
307 break;
308
309 case 1: /* One byte extra */
310 for (i = 0; i < h; i++)
311 {
312 plSrc = (unsigned long *) psrc;
313 for (j = 0; j < word_count; j++)
314 *pDst = *plSrc++;
315
316 *pDst = (unsigned long) (*(unsigned char *) plSrc);
317
318 psrc += widthSrc;
319 }
320 break;
321
322 case 2: /* Two bytes extra */
323 for (i = 0; i < h; i++)
324 {
325 plSrc = (unsigned long *) psrc;
326 for (j = 0; j < word_count; j++)
327 *pDst = *plSrc++;
328
329 *pDst = (unsigned long) (*(unsigned short *) plSrc);
330
331 psrc += widthSrc;
332 }
333 break;
334
335 case 3:
336
337 for (i = 0; i < h; i++)
338 {
339 plSrc = (unsigned long *) psrc;
340 for (j = 0; j < word_count; j++)
341 *pDst = *plSrc++;
342
343 (*(unsigned char **)&plSrc)--;
344 *pDst = (*plSrc) >> 8;
345
346 psrc += widthSrc;
347 }
348 break;
349
350 }
351
352 do
353 {
354 outb (0x3CE, 0x31);
355 status = inb (0x3CF);
356 }
357 while (status & 0x01);
358 }
359 else
360 {
361 vgaImageWrite(pdstBase, psrcBase, widthSrc, widthDst, x, y,
362 x1, y1, w, h, xdir, ydir, alu, planemask);
363 }
364
365 }
366
367
368 void
CirrusImageRead(pdstBase,psrcBase,widthSrc,widthDst,x,y,x1,y1,w,h,xdir,ydir,alu,planemask)369 CirrusImageRead (pdstBase, psrcBase, widthSrc, widthDst, x, y,
370 x1, y1, w, h, xdir, ydir, alu, planemask)
371 pointer pdstBase, psrcBase; /* start of src bitmap */
372 int widthSrc, widthDst;
373 int x, y, x1, y1, w, h; /* Src x,y; Dst x1,y1; Dst (w)idth,(h)eight */
374 int xdir, ydir;
375 int alu;
376 unsigned long planemask;
377 {
378 unsigned long *plDst;
379 volatile unsigned char status;
380 volatile unsigned long *pSrc;
381 pointer pdst;
382 unsigned int srcAddr;
383 unsigned int word_count, word_rem;
384 int i, j;
385
386 if (alu == GXcopy && (planemask & 0xFF) == 0xFF)
387 {
388 int width, height;
389
390 pdst = pdstBase + (y1 * widthDst) + x1;
391 srcAddr = (y * widthSrc) + x;
392
393 /* Set the SrcAddress */
394
395 outw (0x3CE, ((srcAddr & 0x000000FF) << 8) | 0x2C);
396 outw (0x3CE, ((srcAddr & 0x0000FF00)) | 0x2D);
397 outw (0x3CE, ((srcAddr & 0x001F0000) >> 8) | 0x2E);
398
399 /* Set the Src Pitch */
400
401 outw (0x3CE, ((widthSrc & 0x000000FF) << 8) | 0x26);
402 outw (0x3CE, ((widthSrc & 0x00000F00)) | 0x27);
403
404 /* Set the Width */
405
406 width = w - 1;
407 outw (0x3CE, ((width & 0x000000FF) << 8) | 0x20);
408 outw (0x3CE, ((width & 0x00000700)) | 0x21);
409
410 /* Set the Height */
411
412 height = h - 1;
413 outw (0x3CE, ((height & 0x000000FF) << 8) | 0x22);
414 outw (0x3CE, ((height & 0x00000300)) | 0x23);
415
416 /* Set the direction and destination (System Memory) */
417
418 outw (0x3CE, (0x02 << 8) | 0x30);
419
420 /* Set the ROP: Copy = 0x0D */
421 outw (0x3CE, (0x0D << 8) | 0x32);
422
423 /* Lets play DMA controller ... */
424 outw (0x3CE, (0x02 << 8) | 0x31);
425
426 /*
427 * We must transfer 4 bytes per blit line. This is cautious code and I
428 * do not read from outside of the pixmap... The 386/486 allows
429 * unaligned memory acceses, and has little endian word ordering. This
430 * is used to our advantage when dealing with the 3 byte remainder.
431 * Don't try this on your Sparc :-)
432 */
433
434 pSrc = (unsigned long *) BLITADDRESS;
435
436 word_count = w >> 2;
437 word_rem = w & 0x3;
438
439 switch (word_rem)
440 {
441
442 case 0:
443 for (i = 0; i < h; i++)
444 {
445 plDst = (unsigned long *) pdst;
446 for (j = 0; j < word_count; j++)
447 *plDst++ = *pSrc;
448 pdst += widthDst;
449 }
450 break;
451
452 case 1: /* One byte extra */
453 for (i = 0; i < h; i++)
454 {
455 plDst = (unsigned long *) pdst;
456 for (j = 0; j < word_count; j++)
457 *plDst++ = *pSrc;
458
459 *(unsigned char *)plDst = (unsigned char) *pSrc;
460
461 pdst += widthDst;
462 }
463 break;
464
465 case 2: /* Two bytes extra */
466 for (i = 0; i < h; i++)
467 {
468 plDst = (unsigned long *) pdst;
469 for (j = 0; j < word_count; j++)
470 *plDst++ = *pSrc;
471
472 *(unsigned short *)plDst = (unsigned short) *pSrc;
473
474 pdst += widthDst;
475 }
476 break;
477
478 case 3:
479
480 for (i = 0; i < h; i++)
481 { unsigned long tpix;
482
483 plDst = (unsigned long *) pdst;
484 for (j = 0; j < word_count; j++)
485 *plDst++ = *pSrc;
486
487 tpix = *pSrc;
488
489 *(*(unsigned short **)&plDst)++ = (unsigned short) tpix;
490 *(unsigned char *)plDst = (unsigned char)(tpix >>16);
491
492 pdst += widthDst;
493 }
494 break;
495
496 }
497
498 do
499 {
500 outb (0x3CE, 0x31);
501 status = inb (0x3CF);
502 }
503 while (status & 0x01);
504 }
505 else
506 {
507 vgaImageRead(pdstBase, psrcBase, widthSrc, widthDst, x, y,
508 x1, y1, w, h, xdir, ydir, alu, planemask);
509 }
510 }
511