grf_rh.c revision 1.18 1 /* $NetBSD: grf_rh.c,v 1.18 1996/05/24 19:26:12 is Exp $ */
2
3 /*
4 * Copyright (c) 1994 Markus Wild
5 * Copyright (c) 1994 Lutz Vieweg
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Lutz Vieweg.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 #include "grfrh.h"
34 #if NGRFRH > 0
35
36 /*
37 * Graphics routines for the Retina BLT Z3 board,
38 * using the NCR 77C32BLT VGA controller.
39 */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/errno.h>
44 #include <sys/ioctl.h>
45 #include <sys/device.h>
46 #include <sys/malloc.h>
47 #include <machine/cpu.h>
48 #include <amiga/amiga/device.h>
49 #include <amiga/dev/grfioctl.h>
50 #include <amiga/dev/grfvar.h>
51 #include <amiga/dev/grf_rhreg.h>
52 #include <amiga/dev/zbusvar.h>
53
54 enum mode_type { MT_TXTONLY, MT_GFXONLY, MT_BOTH };
55
56 int rh_mondefok __P((struct MonDef *));
57
58 u_short rh_CompFQ __P((u_int fq));
59 int rh_load_mon __P((struct grf_softc *gp, struct MonDef *md));
60 int rh_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm));
61 int rh_setvmode __P((struct grf_softc *gp, unsigned int mode,
62 enum mode_type type));
63
64 /* make it patchable, and settable by kernel config option */
65 #ifndef RH_MEMCLK
66 #define RH_MEMCLK 61000000 /* this is the memory clock value, you shouldn't
67 set it to less than 61000000, higher values may
68 speed up blits a little bit, if you raise this
69 value too much, some trash will appear on your
70 screen. */
71 #endif
72 int rh_memclk = RH_MEMCLK;
73
74
75 extern unsigned char kernel_font_8x8_width, kernel_font_8x8_height;
76 extern unsigned char kernel_font_8x8_lo, kernel_font_8x8_hi;
77 extern unsigned char kernel_font_8x8[];
78 #ifdef KFONT_8X11
79 extern unsigned char kernel_font_8x11_width, kernel_font_8x11_height;
80 extern unsigned char kernel_font_8x11_lo, kernel_font_8x11_hi;
81 extern unsigned char kernel_font_8x11[];
82 #endif
83
84 /*
85 * This driver for the MacroSystem Retina board was only possible,
86 * because MacroSystem provided information about the pecularities
87 * of the board. THANKS! Competition in Europe among gfx board
88 * manufacturers is rather tough, so Lutz Vieweg, who wrote the
89 * initial driver, has made an agreement with MS not to document
90 * the driver source (see also his comment below).
91 * -> ALL comments after
92 * -> " -------------- START OF CODE -------------- "
93 * -> have been added by myself (mw) from studying the publically
94 * -> available "NCR 77C32BLT" Data Manual
95 */
96 /*
97 * This code offers low-level routines to access the Retina BLT Z3
98 * graphics-board manufactured by MS MacroSystem GmbH from within NetBSD
99 * for the Amiga.
100 *
101 * Thanks to MacroSystem for providing me with the neccessary information
102 * to create theese routines. The sparse documentation of this code
103 * results from the agreements between MS and me.
104 */
105
106
107
108 #define MDF_DBL 1
109 #define MDF_LACE 2
110 #define MDF_CLKDIV2 4
111
112 /* set this as an option in your kernel config file! */
113 /* #define RH_64BIT_SPRITE */
114
115 /* -------------- START OF CODE -------------- */
116
117 /* Convert big-endian long into little-endian long. */
118
119 #define M2I(val) \
120 asm volatile (" rorw #8,%0 ; \
121 swap %0 ; \
122 rorw #8,%0 ; " : "=d" (val) : "0" (val));
123
124 #define M2INS(val) \
125 asm volatile (" rorw #8,%0 ; \
126 swap %0 ; \
127 rorw #8,%0 ; \
128 swap %0 ; " : "=d" (val) : "0" (val));
129
130 #define ACM_OFFSET (0x00b00000)
131 #define LM_OFFSET (0x00c00000)
132
133 static unsigned char optab[] = {
134 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
135 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
136 };
137 static char optabs[] = {
138 0, -1, -1, -1, -1, 0, -1, -1,
139 -1, -1, 0, -1, -1, -1, -1, 0
140 };
141
142 void
143 RZ3DisableHWC(gp)
144 struct grf_softc *gp;
145 {
146 volatile void *ba = gp->g_regkva;
147
148 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, 0x00);
149 }
150
151 void
152 RZ3SetupHWC(gp, col1, col2, hsx, hsy, data)
153 struct grf_softc *gp;
154 unsigned char col1;
155 unsigned col2;
156 unsigned char hsx;
157 unsigned char hsy;
158 const unsigned long *data;
159 {
160 volatile unsigned char *ba = gp->g_regkva;
161 unsigned long *c = (unsigned long *)(ba + LM_OFFSET + HWC_MEM_OFF);
162 const unsigned long *s = data;
163 struct MonDef *MonitorDef = (struct MonDef *) gp->g_data;
164 #ifdef RH_64BIT_SPRITE
165 short x = (HWC_MEM_SIZE / (4*4)) - 1;
166 #else
167 short x = (HWC_MEM_SIZE / (4*4*2)) - 1;
168 #endif
169 /* copy only, if there is a data pointer. */
170 if (data) do {
171 *c++ = *s++;
172 *c++ = *s++;
173 *c++ = *s++;
174 *c++ = *s++;
175 } while (x-- > 0);
176
177 WSeq(ba, SEQ_ID_CURSOR_COLOR1, col1);
178 WSeq(ba, SEQ_ID_CURSOR_COLOR0, col2);
179 if (MonitorDef->DEP <= 8) {
180 #ifdef RH_64BIT_SPRITE
181 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x85);
182 #else
183 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x03);
184 #endif
185 }
186 else if (MonitorDef->DEP <= 16) {
187 #ifdef RH_64BIT_SPRITE
188 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xa5);
189 #else
190 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x23);
191 #endif
192 }
193 else {
194 #ifdef RH_64BIT_SPRITE
195 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xc5);
196 #else
197 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x43);
198 #endif
199 }
200 WSeq(ba, SEQ_ID_CURSOR_X_LOC_HI, 0x00);
201 WSeq(ba, SEQ_ID_CURSOR_X_LOC_LO, 0x00);
202 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI, 0x00);
203 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO, 0x00);
204 WSeq(ba, SEQ_ID_CURSOR_X_INDEX, hsx);
205 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, hsy);
206 WSeq(ba, SEQ_ID_CURSOR_STORE_HI, 0x00);
207 WSeq(ba, SEQ_ID_CURSOR_STORE_LO, ((HWC_MEM_OFF / 4) & 0x0000f));
208 WSeq(ba, SEQ_ID_CURSOR_ST_OFF_HI, (((HWC_MEM_OFF / 4) & 0xff000) >> 12));
209 WSeq(ba, SEQ_ID_CURSOR_ST_OFF_LO, (((HWC_MEM_OFF / 4) & 0x00ff0) >> 4));
210 WSeq(ba, SEQ_ID_CURSOR_PIXELMASK, 0xff);
211 }
212
213 void
214 RZ3AlphaErase (gp, xd, yd, w, h)
215 struct grf_softc *gp;
216 unsigned short xd;
217 unsigned short yd;
218 unsigned short w;
219 unsigned short h;
220 {
221 const struct MonDef * md = (struct MonDef *) gp->g_data;
222 RZ3AlphaCopy(gp, xd, yd+md->TY, xd, yd, w, h);
223 }
224
225 void
226 RZ3AlphaCopy (gp, xs, ys, xd, yd, w, h)
227 struct grf_softc *gp;
228 unsigned short xs;
229 unsigned short ys;
230 unsigned short xd;
231 unsigned short yd;
232 unsigned short w;
233 unsigned short h;
234 {
235 volatile unsigned char *ba = gp->g_regkva;
236 const struct MonDef *md = (struct MonDef *) gp->g_data;
237 volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET);
238 unsigned short mod;
239
240 xs *= 4;
241 ys *= 4;
242 xd *= 4;
243 yd *= 4;
244 w *= 4;
245
246 {
247 /* anyone got Windoze GDI opcodes handy?... */
248 unsigned long tmp = 0x0000ca00;
249 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
250 }
251
252 mod = 0xc0c2;
253
254 {
255 unsigned long pat = 8 * PAT_MEM_OFF;
256 unsigned long dst = 8 * (xd + yd * md->TX);
257
258 unsigned long src = 8 * (xs + ys * md->TX);
259
260 if (xd > xs) {
261 mod &= ~0x8000;
262 src += 8 * (w - 1);
263 dst += 8 * (w - 1);
264 pat += 8 * 2;
265 }
266 if (yd > ys) {
267 mod &= ~0x4000;
268 src += 8 * (h - 1) * md->TX * 4;
269 dst += 8 * (h - 1) * md->TX * 4;
270 pat += 8 * 4;
271 }
272
273 M2I(src);
274 *(acm + ACM_SOURCE/4) = src;
275
276 M2I(pat);
277 *(acm + ACM_PATTERN/4) = pat;
278
279 M2I(dst);
280 *(acm + ACM_DESTINATION/4) = dst;
281 }
282 {
283
284 unsigned long tmp = mod << 16;
285 *(acm + ACM_CONTROL/4) = tmp;
286 }
287 {
288
289 unsigned long tmp = w | (h << 16);
290 M2I(tmp);
291 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
292 }
293
294 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
295 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
296
297 while ((*(((volatile unsigned char *)acm) +
298 (ACM_START_STATUS + 2)) & 1) == 0);
299 }
300
301 void
302 RZ3BitBlit (gp, gbb)
303 struct grf_softc *gp;
304 struct grf_bitblt * gbb;
305 {
306 volatile unsigned char *ba = gp->g_regkva;
307 volatile unsigned char *lm = ba + LM_OFFSET;
308 volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET);
309 const struct MonDef *md = (struct MonDef *) gp->g_data;
310 unsigned short mod;
311
312 {
313 unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
314 unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16);
315 *pt++ = tmp;
316 *pt = tmp;
317 }
318
319 {
320
321 unsigned long tmp = optab[ gbb->op ] << 8;
322 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
323 }
324
325 mod = 0xc0c2;
326
327 {
328 unsigned long pat = 8 * PAT_MEM_OFF;
329 unsigned long dst = 8 * (gbb->dst_x + gbb->dst_y * md->TX);
330
331 if (optabs[gbb->op]) {
332 unsigned long src = 8 * (gbb->src_x + gbb->src_y * md->TX);
333
334 if (gbb->dst_x > gbb->src_x) {
335 mod &= ~0x8000;
336 src += 8 * (gbb->w - 1);
337 dst += 8 * (gbb->w - 1);
338 pat += 8 * 2;
339 }
340 if (gbb->dst_y > gbb->src_y) {
341 mod &= ~0x4000;
342 src += 8 * (gbb->h - 1) * md->TX;
343 dst += 8 * (gbb->h - 1) * md->TX;
344 pat += 8 * 4;
345 }
346
347 M2I(src);
348 *(acm + ACM_SOURCE/4) = src;
349 }
350
351 M2I(pat);
352 *(acm + ACM_PATTERN/4) = pat;
353
354 M2I(dst);
355 *(acm + ACM_DESTINATION/4) = dst;
356 }
357 {
358
359 unsigned long tmp = mod << 16;
360 *(acm + ACM_CONTROL/4) = tmp;
361 }
362 {
363 unsigned long tmp = gbb->w | (gbb->h << 16);
364 M2I(tmp);
365 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
366 }
367
368 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
369 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
370
371 while ((*(((volatile unsigned char *)acm) +
372 (ACM_START_STATUS + 2)) & 1) == 0);
373 }
374
375 void
376 RZ3BitBlit16 (gp, gbb)
377 struct grf_softc *gp;
378 struct grf_bitblt * gbb;
379 {
380 volatile unsigned char *ba = gp->g_regkva;
381 volatile unsigned char *lm = ba + LM_OFFSET;
382 volatile unsigned long * acm = (unsigned long *) (ba + ACM_OFFSET);
383 const struct MonDef * md = (struct MonDef *) gp->g_data;
384 unsigned short mod;
385
386 {
387 unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
388 unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16);
389 *pt++ = tmp;
390 *pt++ = tmp;
391 *pt++ = tmp;
392 *pt = tmp;
393 }
394
395 {
396
397 unsigned long tmp = optab[ gbb->op ] << 8;
398 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
399 }
400
401 mod = 0xc0c2;
402
403 {
404 unsigned long pat = 8 * PAT_MEM_OFF;
405 unsigned long dst = 8 * 2 * (gbb->dst_x + gbb->dst_y * md->TX);
406
407 if (optabs[gbb->op]) {
408 unsigned long src = 8 * 2 * (gbb->src_x + gbb->src_y * md->TX);
409
410 if (gbb->dst_x > gbb->src_x) {
411 mod &= ~0x8000;
412 src += 8 * 2 * (gbb->w);
413 dst += 8 * 2 * (gbb->w);
414 pat += 8 * 2 * 2;
415 }
416 if (gbb->dst_y > gbb->src_y) {
417 mod &= ~0x4000;
418 src += 8 * 2 * (gbb->h - 1) * md->TX;
419 dst += 8 * 2 * (gbb->h - 1) * md->TX;
420 pat += 8 * 4 * 2;
421 }
422
423 M2I(src);
424 *(acm + ACM_SOURCE/4) = src;
425 }
426
427 M2I(pat);
428 *(acm + ACM_PATTERN/4) = pat;
429
430 M2I(dst);
431 *(acm + ACM_DESTINATION/4) = dst;
432 }
433 {
434
435 unsigned long tmp = mod << 16;
436 *(acm + ACM_CONTROL/4) = tmp;
437 }
438 {
439
440 unsigned long tmp = gbb->w | (gbb->h << 16);
441 M2I(tmp);
442 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
443 }
444
445 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
446 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
447
448 while ((*(((volatile unsigned char *)acm) +
449 (ACM_START_STATUS+ 2)) & 1) == 0);
450 }
451
452 void
453 RZ3BitBlit24 (gp, gbb)
454 struct grf_softc *gp;
455 struct grf_bitblt * gbb;
456 {
457 volatile unsigned char *ba = gp->g_regkva;
458 volatile unsigned char *lm = ba + LM_OFFSET;
459 volatile unsigned long * acm = (unsigned long *) (ba + ACM_OFFSET);
460 const struct MonDef * md = (struct MonDef *) gp->g_data;
461 unsigned short mod;
462
463
464 {
465 unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF);
466 unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16);
467 *pt++ = tmp;
468 *pt++ = tmp;
469 *pt++ = tmp;
470 *pt++ = tmp;
471 *pt++ = tmp;
472 *pt = tmp;
473 }
474
475 {
476
477 unsigned long tmp = optab[ gbb->op ] << 8;
478 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
479 }
480
481 mod = 0xc0c2;
482
483 {
484 unsigned long pat = 8 * PAT_MEM_OFF;
485 unsigned long dst = 8 * 3 * (gbb->dst_x + gbb->dst_y * md->TX);
486
487 if (optabs[gbb->op]) {
488 unsigned long src = 8 * 3 * (gbb->src_x + gbb->src_y * md->TX);
489
490 if (gbb->dst_x > gbb->src_x ) {
491 mod &= ~0x8000;
492 src += 8 * 3 * (gbb->w);
493 dst += 8 * 3 * (gbb->w);
494 pat += 8 * 3 * 2;
495 }
496 if (gbb->dst_y > gbb->src_y) {
497 mod &= ~0x4000;
498 src += 8 * 3 * (gbb->h - 1) * md->TX;
499 dst += 8 * 3 * (gbb->h - 1) * md->TX;
500 pat += 8 * 4 * 3;
501 }
502
503 M2I(src);
504 *(acm + ACM_SOURCE/4) = src;
505 }
506
507
508 M2I(pat);
509 *(acm + ACM_PATTERN/4) = pat;
510
511
512 M2I(dst);
513 *(acm + ACM_DESTINATION/4) = dst;
514 }
515 {
516
517 unsigned long tmp = mod << 16;
518 *(acm + ACM_CONTROL/4) = tmp;
519 }
520 {
521
522 unsigned long tmp = gbb->w | (gbb->h << 16);
523 M2I(tmp);
524 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
525 }
526
527
528 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
529 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
530
531 while ( (*(((volatile unsigned char *)acm)
532 + (ACM_START_STATUS+ 2)) & 1) == 0 ) {};
533
534 }
535
536
537 void
538 RZ3SetCursorPos (gp, pos)
539 struct grf_softc *gp;
540 unsigned short pos;
541 {
542 volatile unsigned char *ba = gp->g_regkva;
543
544 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, (unsigned char)pos);
545 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (unsigned char)(pos >> 8));
546
547 }
548
549 void
550 RZ3LoadPalette (gp, pal, firstcol, colors)
551 struct grf_softc *gp;
552 unsigned char * pal;
553 unsigned char firstcol;
554 unsigned char colors;
555 {
556 volatile unsigned char *ba = gp->g_regkva;
557
558 if (colors == 0)
559 return;
560
561 vgaw(ba, VDAC_ADDRESS_W, firstcol);
562
563 {
564
565 short x = colors-1;
566 const unsigned char * col = pal;
567 do {
568
569 vgaw(ba, VDAC_DATA, (*col++ >> 2));
570 vgaw(ba, VDAC_DATA, (*col++ >> 2));
571 vgaw(ba, VDAC_DATA, (*col++ >> 2));
572
573 } while (x-- > 0);
574
575 }
576 }
577
578 void
579 RZ3SetPalette (gp, colornum, red, green, blue)
580 struct grf_softc *gp;
581 unsigned char colornum;
582 unsigned char red, green, blue;
583 {
584 volatile unsigned char *ba = gp->g_regkva;
585
586 vgaw(ba, VDAC_ADDRESS_W, colornum);
587
588 vgaw(ba, VDAC_DATA, (red >> 2));
589 vgaw(ba, VDAC_DATA, (green >> 2));
590 vgaw(ba, VDAC_DATA, (blue >> 2));
591
592 }
593
594 /* XXXXXXXXX !! */
595 static unsigned short xpan;
596 static unsigned short ypan;
597
598 void
599 RZ3SetPanning (gp, xoff, yoff)
600 struct grf_softc *gp;
601 unsigned short xoff, yoff;
602 {
603 volatile unsigned char *ba = gp->g_regkva;
604 const struct MonDef * md = (struct MonDef *) gp->g_data;
605 unsigned long off;
606
607 xpan = xoff;
608 ypan = yoff;
609
610
611 if (md->DEP > 8 && md->DEP <= 16) xoff *= 2;
612 else if (md->DEP > 16) xoff *= 3;
613
614 vgar(ba, ACT_ADDRESS_RESET);
615 WAttr(ba, ACT_ID_HOR_PEL_PANNING, (unsigned char)((xoff << 1) & 0x07));
616 /* have the color lookup function normally again */
617 vgaw(ba, ACT_ADDRESS_W, 0x20);
618
619 if (md->DEP == 8)
620 off = ((yoff * md->TX)/ 4) + (xoff >> 2);
621 else if (md->DEP == 16)
622 off = ((yoff * md->TX * 2)/ 4) + (xoff >> 2);
623 else
624 off = ((yoff * md->TX * 3)/ 4) + (xoff >> 2);
625 WCrt(ba, CRT_ID_START_ADDR_LOW, ((unsigned char)off));
626 off >>= 8;
627 WCrt(ba, CRT_ID_START_ADDR_HIGH, ((unsigned char)off));
628 off >>= 8;
629 WCrt(ba, CRT_ID_EXT_START_ADDR,
630 ((RCrt(ba, CRT_ID_EXT_START_ADDR) & 0xf0) | (off & 0x0f)));
631
632
633 }
634
635 void
636 RZ3SetHWCloc (gp, x, y)
637 struct grf_softc *gp;
638 unsigned short x, y;
639 {
640 volatile unsigned char *ba = gp->g_regkva;
641 const struct MonDef *md = (struct MonDef *) gp->g_data;
642 volatile unsigned char *acm = ba + ACM_OFFSET;
643
644 if (x < xpan)
645 RZ3SetPanning(gp, x, ypan);
646
647 if (x >= (xpan+md->MW))
648 RZ3SetPanning(gp, (1 + x - md->MW) , ypan);
649
650 if (y < ypan)
651 RZ3SetPanning(gp, xpan, y);
652
653 if (y >= (ypan+md->MH))
654 RZ3SetPanning(gp, xpan, (1 + y - md->MH));
655
656 x -= xpan;
657 y -= ypan;
658
659 *(acm + (ACM_CURSOR_POSITION+0)) = x & 0xff;
660 *(acm + (ACM_CURSOR_POSITION+1)) = x >> 8;
661 *(acm + (ACM_CURSOR_POSITION+2)) = y & 0xff;
662 *(acm + (ACM_CURSOR_POSITION+3)) = y >> 8;
663 }
664
665 u_short
666 rh_CompFQ(fq)
667 u_int fq;
668 {
669 /* yuck... this sure could need some explanation.. */
670
671 unsigned long f = fq;
672 long n2 = 3;
673 long abw = 0x7fffffff;
674 long n1 = 3;
675 unsigned long m;
676 unsigned short erg = 0;
677
678 f *= 8;
679
680 do {
681
682 if (f <= 250000000)
683 break;
684 f /= 2;
685
686 } while (n2-- > 0);
687
688 if (n2 < 0)
689 return(0);
690
691
692 do {
693 long tmp;
694
695 f = fq;
696 f >>= 3;
697 f <<= n2;
698 f >>= 7;
699
700 m = (f * n1) / (14318180/1024);
701
702 if (m > 129)
703 break;
704
705 tmp = (((m * 14318180) >> n2) / n1) - fq;
706 if (tmp < 0)
707 tmp = -tmp;
708
709 if (tmp < abw) {
710 abw = tmp;
711 erg = (((n2 << 5) | (n1-2)) << 8) | (m-2);
712 }
713
714 } while ( (++n1) <= 21);
715
716 return(erg);
717 }
718
719 int
720 rh_mondefok(mdp)
721 struct MonDef *mdp;
722 {
723 switch(mdp->DEP) {
724 case 8:
725 case 16:
726 case 24:
727 return(1);
728 case 4:
729 if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16))
730 return(1);
731 /*FALLTHROUGH*/
732 default:
733 return(0);
734 }
735 }
736
737
738 int
739 rh_load_mon(gp, md)
740 struct grf_softc *gp;
741 struct MonDef *md;
742 {
743 struct grfinfo *gi = &gp->g_display;
744 volatile caddr_t ba;
745 volatile caddr_t fb;
746 short FW, clksel, HDE = 0, VDE;
747 unsigned short *c, z;
748 const unsigned char *f;
749
750 ba = gp->g_regkva;;
751 fb = gp->g_fbkva;
752
753 /* provide all needed information in grf device-independant
754 * locations */
755 gp->g_data = (caddr_t) md;
756 gi->gd_regaddr = (caddr_t) kvtop (ba);
757 gi->gd_regsize = LM_OFFSET;
758 gi->gd_fbaddr = (caddr_t) kvtop (fb);
759 gi->gd_fbsize = MEMSIZE *1024*1024;
760 #ifdef BANKEDDEVPAGER
761 /* we're not using banks NO MORE! */
762 gi->gd_bank_size = 0;
763 #endif
764 gi->gd_colors = 1 << md->DEP;
765 gi->gd_planes = md->DEP;
766
767 if (md->DEP == 4) {
768 gi->gd_fbwidth = md->MW;
769 gi->gd_fbheight = md->MH;
770 gi->gd_fbx = 0;
771 gi->gd_fby = 0;
772 gi->gd_dwidth = md->TX * md->FX;
773 gi->gd_dheight = md->TY * md->FY;
774 gi->gd_dx = 0;
775 gi->gd_dy = 0;
776 } else {
777 gi->gd_fbwidth = md->TX;
778 gi->gd_fbheight = md->TY;
779 gi->gd_fbx = 0;
780 gi->gd_fby = 0;
781 gi->gd_dwidth = md->MW;
782 gi->gd_dheight = md->MH;
783 gi->gd_dx = 0;
784 gi->gd_dy = 0;
785 }
786
787 FW =0;
788 if (md->DEP == 4) { /* XXX some text-mode! */
789 switch (md->FX) {
790 case 4:
791 FW = 0;
792 break;
793 case 7:
794 FW = 1;
795 break;
796 case 8:
797 FW = 2;
798 break;
799 case 9:
800 FW = 3;
801 break;
802 case 10:
803 FW = 4;
804 break;
805 case 11:
806 FW = 5;
807 break;
808 case 12:
809 FW = 6;
810 break;
811 case 13:
812 FW = 7;
813 break;
814 case 14:
815 FW = 8;
816 break;
817 case 15:
818 FW = 9;
819 break;
820 case 16:
821 FW = 11;
822 break;
823 default:
824 return(0);
825 break;
826 }
827 }
828
829 if (md->DEP == 4) HDE = (md->MW+md->FX-1)/md->FX;
830 else if (md->DEP == 8) HDE = (md->MW+3)/4;
831 else if (md->DEP == 16) HDE = (md->MW*2+3)/4;
832 else if (md->DEP == 24) HDE = (md->MW*3+3)/4;
833
834 VDE = md->MH-1;
835
836 clksel = 0;
837
838 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
839 vgaw(ba, GREG_FEATURE_CONTROL_W, 0x00);
840
841 WSeq(ba, SEQ_ID_RESET, 0x00);
842 WSeq(ba, SEQ_ID_RESET, 0x03);
843 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8));
844 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
845 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
846 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x06);
847 WSeq(ba, SEQ_ID_RESET, 0x01);
848 WSeq(ba, SEQ_ID_RESET, 0x03);
849
850 WSeq(ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
851 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x00);
852 WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
853 WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
854 WSeq(ba, SEQ_ID_LINEAR_0, 0x4a);
855 WSeq(ba, SEQ_ID_LINEAR_1, 0x00);
856
857 WSeq(ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
858 WSeq(ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
859 WSeq(ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
860 WSeq(ba, SEQ_ID_EXT_CLOCK_MODE, 0x10 | (FW & 0x0f));
861 WSeq(ba, SEQ_ID_EXT_VIDEO_ADDR, 0x03);
862 if (md->DEP == 4) {
863 /* 8bit pixel, no gfx byte path */
864 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
865 }
866 else if (md->DEP == 8) {
867 /* 8bit pixel, gfx byte path */
868 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
869 }
870 else if (md->DEP == 16) {
871 /* 16bit pixel, gfx byte path */
872 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11);
873 }
874 else if (md->DEP == 24) {
875 /* 24bit pixel, gfx byte path */
876 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x21);
877 }
878 WSeq(ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x04);
879 WSeq(ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
880 WSeq(ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
881 WSeq(ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
882 WSeq(ba, SEQ_ID_MISC_FEATURE_SEL, (0x51 | (clksel & 8)));
883 WSeq(ba, SEQ_ID_COLOR_KEY_CNTL, 0x40);
884 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH0, 0x00);
885 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH1, 0x00);
886 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH2, 0x00);
887 WSeq(ba, SEQ_ID_CRC_CONTROL, 0x00);
888 WSeq(ba, SEQ_ID_PERF_SELECT, 0x10);
889 WSeq(ba, SEQ_ID_ACM_APERTURE_1, 0x00);
890 WSeq(ba, SEQ_ID_ACM_APERTURE_2, 0x30);
891 WSeq(ba, SEQ_ID_ACM_APERTURE_3, 0x00);
892 WSeq(ba, SEQ_ID_MEMORY_MAP_CNTL, 0x07);
893
894 WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x20);
895 WCrt(ba, CRT_ID_HOR_TOTAL, md->HT & 0xff);
896 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff);
897 WCrt(ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff);
898 WCrt(ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80);
899
900 WCrt(ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff);
901 WCrt(ba, CRT_ID_END_HOR_RETR,
902 (md->HSE & 0x1f) |
903 ((md->HBE & 0x20)/ 0x20 * 0x80));
904 WCrt(ba, CRT_ID_VER_TOTAL, (md->VT & 0xff));
905 WCrt(ba, CRT_ID_OVERFLOW,
906 ((md->VSS & 0x200) / 0x200 * 0x80) |
907 ((VDE & 0x200) / 0x200 * 0x40) |
908 ((md->VT & 0x200) / 0x200 * 0x20) |
909 0x10 |
910 ((md->VBS & 0x100) / 0x100 * 8) |
911 ((md->VSS & 0x100) / 0x100 * 4) |
912 ((VDE & 0x100) / 0x100 * 2) |
913 ((md->VT & 0x100) / 0x100));
914 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
915
916 if (md->DEP == 4) {
917 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
918 ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
919 0x40 |
920 ((md->VBS & 0x200)/0x200*0x20) |
921 ((md->FY-1) & 0x1f));
922 } else {
923 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
924 ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
925 0x40 |
926 ((md->VBS & 0x200)/0x200*0x20) |
927 (0 & 0x1f));
928 }
929
930 /* I prefer "_" cursor to "block" cursor.. */
931 #if 1
932 WCrt(ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
933 WCrt(ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
934 #else
935 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
936 WCrt(ba, CRT_ID_CURSOR_END, md->FY & 0x1f);
937 #endif
938
939 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
940 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
941
942 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
943 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
944
945 WCrt(ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
946 WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x80 | 0x20);
947 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff);
948
949 if (md->DEP == 4) {
950 WCrt(ba, CRT_ID_OFFSET, (HDE / 2) & 0xff );
951 }
952 /* all gfx-modes are in byte-mode, means values are multiplied by 8 */
953 else if (md->DEP == 8) {
954 WCrt(ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff );
955 } else if (md->DEP == 16) {
956 WCrt(ba, CRT_ID_OFFSET, (md->TX / 4) & 0xff );
957 } else {
958 WCrt(ba, CRT_ID_OFFSET, (md->TX * 3 / 8) & 0xff );
959 }
960
961 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
962 WCrt(ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
963 WCrt(ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
964 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
965 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
966
967 WCrt(ba, CRT_ID_EXT_HOR_TIMING1,
968 0 | 0x20 |
969 ((md->FLG & MDF_LACE) / MDF_LACE * 0x10) |
970 ((md->HT & 0x100) / 0x100) |
971 (((HDE-1) & 0x100) / 0x100 * 2) |
972 ((md->HBS & 0x100) / 0x100 * 4) |
973 ((md->HSS & 0x100) / 0x100 * 8));
974
975 if (md->DEP == 4) {
976 WCrt(ba, CRT_ID_EXT_START_ADDR, (((HDE / 2) & 0x100)/0x100 * 16));
977 }
978 else if (md->DEP == 8) {
979 WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX / 8) & 0x100)/0x100 * 16));
980 } else if (md->DEP == 16) {
981 WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX / 4) & 0x100)/0x100 * 16));
982 } else {
983 WCrt(ba, CRT_ID_EXT_START_ADDR, (((md->TX * 3 / 8) & 0x100)/0x100 * 16));
984 }
985
986 WCrt(ba, CRT_ID_EXT_HOR_TIMING2,
987 ((md->HT & 0x200)/ 0x200) |
988 (((HDE-1) & 0x200)/ 0x200 * 2 ) |
989 ((md->HBS & 0x200)/ 0x200 * 4 ) |
990 ((md->HSS & 0x200)/ 0x200 * 8 ) |
991 ((md->HBE & 0xc0) / 0x40 * 16 ) |
992 ((md->HSE & 0x60) / 0x20 * 64));
993
994 WCrt(ba, CRT_ID_EXT_VER_TIMING,
995 ((md->VSE & 0x10) / 0x10 * 0x80 ) |
996 ((md->VBE & 0x300)/ 0x100 * 0x20 ) |
997 0x10 |
998 ((md->VSS & 0x400)/ 0x400 * 8 ) |
999 ((md->VBS & 0x400)/ 0x400 * 4 ) |
1000 ((VDE & 0x400)/ 0x400 * 2 ) |
1001 ((md->VT & 0x400)/ 0x400));
1002 WCrt(ba, CRT_ID_MONITOR_POWER, 0x00);
1003
1004 {
1005 unsigned short tmp = rh_CompFQ(md->FQ);
1006 WPLL(ba, 2 , tmp);
1007 tmp = rh_CompFQ(rh_memclk);
1008 WPLL(ba,10 , tmp);
1009 WPLL(ba,14 , 0x22);
1010 }
1011
1012 WGfx(ba, GCT_ID_SET_RESET, 0x00);
1013 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
1014 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
1015 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
1016 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1017 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
1018 if (md->DEP == 4)
1019 WGfx(ba, GCT_ID_MISC, 0x04);
1020 else
1021 WGfx(ba, GCT_ID_MISC, 0x05);
1022 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
1023 WGfx(ba, GCT_ID_BITMASK, 0xff);
1024
1025 vgar(ba, ACT_ADDRESS_RESET);
1026 WAttr(ba, ACT_ID_PALETTE0 , 0x00);
1027 WAttr(ba, ACT_ID_PALETTE1 , 0x01);
1028 WAttr(ba, ACT_ID_PALETTE2 , 0x02);
1029 WAttr(ba, ACT_ID_PALETTE3 , 0x03);
1030 WAttr(ba, ACT_ID_PALETTE4 , 0x04);
1031 WAttr(ba, ACT_ID_PALETTE5 , 0x05);
1032 WAttr(ba, ACT_ID_PALETTE6 , 0x06);
1033 WAttr(ba, ACT_ID_PALETTE7 , 0x07);
1034 WAttr(ba, ACT_ID_PALETTE8 , 0x08);
1035 WAttr(ba, ACT_ID_PALETTE9 , 0x09);
1036 WAttr(ba, ACT_ID_PALETTE10, 0x0a);
1037 WAttr(ba, ACT_ID_PALETTE11, 0x0b);
1038 WAttr(ba, ACT_ID_PALETTE12, 0x0c);
1039 WAttr(ba, ACT_ID_PALETTE13, 0x0d);
1040 WAttr(ba, ACT_ID_PALETTE14, 0x0e);
1041 WAttr(ba, ACT_ID_PALETTE15, 0x0f);
1042
1043 vgar(ba, ACT_ADDRESS_RESET);
1044 if (md->DEP == 4)
1045 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
1046 else
1047 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
1048
1049 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
1050 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
1051 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
1052 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
1053
1054 vgar(ba, ACT_ADDRESS_RESET);
1055 vgaw(ba, ACT_ADDRESS_W, 0x20);
1056
1057 vgaw(ba, VDAC_MASK, 0xff);
1058 /* probably some PLL timing stuff here. The value
1059 for 24bit was found by trial&error :-) */
1060 if (md->DEP < 16) {
1061 vgaw(ba, 0x83c6, ((0 & 7) << 5) );
1062 }
1063 else if (md->DEP == 16) {
1064 /* well... */
1065 vgaw(ba, 0x83c6, ((3 & 7) << 5) );
1066 }
1067 else if (md->DEP == 24) {
1068 vgaw(ba, 0x83c6, 0xe0);
1069 }
1070 vgaw(ba, VDAC_ADDRESS_W, 0x00);
1071
1072 if (md->DEP < 16) {
1073 short x = 256-17;
1074 unsigned char cl = 16;
1075 RZ3LoadPalette(gp, md->PAL, 0, 16);
1076 do {
1077 vgaw(ba, VDAC_DATA, (cl >> 2));
1078 vgaw(ba, VDAC_DATA, (cl >> 2));
1079 vgaw(ba, VDAC_DATA, (cl >> 2));
1080 cl++;
1081 } while (x-- > 0);
1082 }
1083
1084 if (md->DEP == 4) {
1085 {
1086 struct grf_bitblt bb = {
1087 GRFBBOPset,
1088 0, 0,
1089 0, 0,
1090 md->TX*4, 2*md->TY,
1091 EMPTY_ALPHA
1092 };
1093 RZ3BitBlit(gp, &bb);
1094 }
1095
1096 c = (unsigned short *)(ba + LM_OFFSET);
1097 c += 2 * md->FLo*32;
1098 c += 1;
1099 f = md->FData;
1100 for (z = md->FLo; z <= md->FHi; z++) {
1101 short y = md->FY-1;
1102 if (md->FX > 8){
1103 do {
1104 *c = *((const unsigned short *)f);
1105 c += 2;
1106 f += 2;
1107 } while (y-- > 0);
1108 } else {
1109 do {
1110 *c = (*f++) << 8;
1111 c += 2;
1112 } while (y-- > 0);
1113 }
1114
1115 c += 2 * (32-md->FY);
1116 }
1117 {
1118 unsigned long * pt = (unsigned long *) (ba + LM_OFFSET + PAT_MEM_OFF);
1119 unsigned long tmp = 0xffff0000;
1120 *pt++ = tmp;
1121 *pt = tmp;
1122 }
1123
1124 WSeq(ba, SEQ_ID_MAP_MASK, 3);
1125
1126 c = (unsigned short *)(ba + LM_OFFSET);
1127 c += (md->TX-6)*2;
1128 {
1129 /* it's show-time :-) */
1130 static unsigned short init_msg[6] = {
1131 0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f
1132 };
1133 unsigned short * m = init_msg;
1134 short x = 5;
1135 do {
1136 *c = *m++;
1137 c += 2;
1138 } while (x-- > 0);
1139 }
1140
1141 return(1);
1142 } else if (md->DEP == 8) {
1143 struct grf_bitblt bb = {
1144 GRFBBOPset,
1145 0, 0,
1146 0, 0,
1147 md->TX, md->TY,
1148 0x0000
1149 };
1150 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
1151
1152 RZ3BitBlit(gp, &bb);
1153
1154 xpan = 0;
1155 ypan = 0;
1156
1157 return(1);
1158 } else if (md->DEP == 16) {
1159 struct grf_bitblt bb = {
1160 GRFBBOPset,
1161 0, 0,
1162 0, 0,
1163 md->TX, md->TY,
1164 0x0000
1165 };
1166 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
1167
1168 RZ3BitBlit16(gp, &bb);
1169
1170 xpan = 0;
1171 ypan = 0;
1172
1173 return(1);
1174 } else if (md->DEP == 24) {
1175 struct grf_bitblt bb = {
1176 GRFBBOPset,
1177 0, 0,
1178 0, 0,
1179 md->TX, md->TY,
1180 0x0000
1181 };
1182 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f );
1183
1184 RZ3BitBlit24(gp, &bb );
1185
1186 xpan = 0;
1187 ypan = 0;
1188
1189 return 1;
1190 } else
1191 return(0);
1192 }
1193
1194 /* standard-palette definition */
1195
1196 unsigned char RZ3StdPalette[16*3] = {
1197 /* R G B */
1198 0, 0, 0,
1199 192,192,192,
1200 128, 0, 0,
1201 0,128, 0,
1202 0, 0,128,
1203 128,128, 0,
1204 0,128,128,
1205 128, 0,128,
1206 64, 64, 64, /* the higher 8 colors have more intensity for */
1207 255,255,255, /* compatibility with standard attributes */
1208 255, 0, 0,
1209 0,255, 0,
1210 0, 0,255,
1211 255,255, 0,
1212 0,255,255,
1213 255, 0,255
1214 };
1215
1216 /*
1217 * The following structures are examples for monitor-definitions. To make one
1218 * of your own, first use "DefineMonitor" and create the 8-bit or 16-bit
1219 * monitor-mode of your dreams. Then save it, and make a structure from the
1220 * values provided in the file DefineMonitor stored - the labels in the comment
1221 * above the structure definition show where to put what value.
1222 *
1223 * If you want to use your definition for the text-mode, you'll need to adapt
1224 * your 8-bit monitor-definition to the font you want to use. Be FX the width of
1225 * the font, then the following modifications have to be applied to your values:
1226 *
1227 * HBS = (HBS * 4) / FX
1228 * HSS = (HSS * 4) / FX
1229 * HSE = (HSE * 4) / FX
1230 * HBE = (HBE * 4) / FX
1231 * HT = (HT * 4) / FX
1232 *
1233 * Make sure your maximum width (MW) and height (MH) are even multiples of
1234 * the fonts' width and height.
1235 *
1236 * You may use definitons created by the old DefineMonitor, but you'll get
1237 * better results with the new DefineMonitor supplied along with the Retin Z3.
1238 */
1239
1240 /*
1241 * FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT
1242 * Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi
1243 */
1244 #ifdef KFONT_8X11
1245 #define KERNEL_FONT kernel_font_8x11
1246 #define FY 11
1247 #define FX 8
1248 #else
1249 #define KERNEL_FONT kernel_font_8x8
1250 #define FY 8
1251 #define FX 8
1252 #endif
1253
1254
1255 static struct MonDef monitor_defs[] = {
1256 /* Text-mode definitions */
1257
1258 /* horizontal 31.5 kHz */
1259 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535,
1260 4, RZ3StdPalette, 80, 64, 5120, FX, FY, KERNEL_FONT, 32, 255},
1261
1262 /* horizontal 38kHz */
1263 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
1264 4, RZ3StdPalette, 96, 75, 7200, FX, FY, KERNEL_FONT, 32, 255},
1265
1266 /* horizontal 64kHz */
1267 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
1268 4, RZ3StdPalette, 96, 75, 7200, FX, FY, KERNEL_FONT, 32, 255},
1269
1270 /* 8-bit gfx-mode definitions */
1271
1272 /* IMPORTANT: the "logical" screen size can be up to 2048x2048 pixels,
1273 independent from the "physical" screen size. If your code does NOT
1274 support panning, please adjust the "logical" screen sizes below to
1275 match the physical ones
1276 */
1277
1278 /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
1279 { 26000000, 0, 640, 480, 161,175,188,200,199, 481, 483, 491, 502, 502,
1280 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1281 /* This is the logical ^ ^ screen size */
1282
1283 /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
1284 { 31000000, 0, 640, 480, 161,169,182,198,197, 481, 482, 490, 502, 502,
1285 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1286
1287 /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
1288 { 39000000, 0, 800, 600, 201,211,227,249,248, 601, 603, 613, 628, 628,
1289 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1290
1291 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1292 { 82000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
1293 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1294
1295 /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
1296 { 97000000, 0, 1120, 896, 281,283,306,369,368, 897, 898, 913, 938, 938,
1297 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1298
1299 /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
1300 {110000000, 0, 1152, 910, 289,310,333,357,356, 911, 923, 938, 953, 953,
1301 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1302
1303 /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
1304 {110000000, 0, 1184, 848, 297,319,342,370,369, 849, 852, 866, 888, 888,
1305 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1306
1307 /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
1308 {104000000, 0, 1280,1024, 321,323,348,399,398,1025,1026,1043,1073,1073,
1309 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1310
1311 /* WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1312 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1313 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
1314 /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
1315 {121000000, 0, 1280,1024, 321,322,347,397,396,1025,1026,1043,1073,1073,
1316 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1317
1318
1319 /* 16-bit gfx-mode definitions */
1320
1321 /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
1322 { 51000000, 0, 640, 480, 321,344,369,397,396, 481, 482, 490, 502, 502,
1323 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1324
1325 /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
1326 { 77000000, 0, 800, 600, 401,418,449,496,495, 601, 602, 612, 628, 628,
1327 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1328
1329 /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
1330 {110000000, 0, 1024, 768, 513,514,554,639,638, 769, 770, 783, 804, 804,
1331 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1332
1333 /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
1334 {109000000, 0, 864, 648, 433,434,468,537,536, 649, 650, 661, 678, 678,
1335 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1336
1337 /* WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1338 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1339 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */
1340 /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
1341 {124000000, 0, 1024, 768, 513,537,577,636,635, 769, 770, 783, 804, 804,
1342 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1343
1344
1345 /* 24-bit gfx-mode definitions */
1346
1347 /* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
1348 { 46000000, 1, 320, 200, 241,268,287,324,323, 401, 405, 412, 418, 418,
1349 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1350
1351 /* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
1352 { 76000000, 0, 640, 400, 481,514,552,601,600, 401, 402, 409, 418, 418,
1353 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1354
1355 /* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
1356 {101000000, 0, 724, 482, 544,576,619,682,678, 483, 487, 495, 495, 504,
1357 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1358
1359 /* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
1360 {110000000, 0, 800, 600, 601,602,647,723,722, 601, 602, 612, 628, 628,
1361 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1362
1363 /* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
1364 {132000000, 0, 800, 600, 601,641,688,749,748, 601, 611, 621, 628, 628,
1365 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1366
1367 /*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
1368 {110000000, 2, 1024, 768, 769,770,824,854,853, 385, 386, 392, 401, 401,
1369 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1370 };
1371 #undef KERNEL_FONT
1372 #undef FX
1373 #undef FY
1374
1375 static const char *monitor_descr[] = {
1376 #ifdef KFONT_8X11
1377 "80x46 (640x506) 31.5kHz",
1378 "96x54 (768x594) 38kHz",
1379 "96x54 (768x594) 64kHz",
1380 #else
1381 "80x64 (640x512) 31.5kHz",
1382 "96x75 (768x600) 38kHz",
1383 "96x75 (768x600) 64kHz",
1384 #endif
1385
1386 "GFX-8 (640x480) 31.5kHz",
1387 "GFX-8 (640x480) 38kHz",
1388 "GFX-8 (800x600) 38.5kHz",
1389 "GFX-8 (1024x768) 64kHz",
1390 "GFX-8 (1120x896) 64kHz",
1391 "GFX-8 (1152x910) 76kHz",
1392 "GFX-8 (1182x848) 73kHz",
1393 "GFX-8 (1280x1024) 64.5kHz",
1394 "GFX-8 (1280x1024) 75.5kHz ***EXCEEDS CHIP LIMIT!!!***",
1395
1396 "GFX-16 (640x480) 31.8kHz",
1397 "GFX-16 (800x600) 38.5kHz",
1398 "GFX-16 (1024x768) 42.8kHz",
1399 "GFX-16 (864x648) 50kHz",
1400 "GFX-16 (1024x768) 48.5kHz ***EXCEEDS CHIP LIMIT!!!***",
1401
1402 "GFX-24 (320x200 d) 35kHz",
1403 "GFX-24 (640x400) 31.4kHz",
1404 "GFX-24 (724x482) 37kHz",
1405 "GFX-24 (800x600) 38kHz",
1406 "GFX-24 (800x600) 44kHz ***EXCEEDS CHIP LIMIT!!!***",
1407 "GFX-24 (1024x768) 32kHz-i",
1408 };
1409
1410 int rh_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
1411
1412 /* patchable */
1413 int rh_default_mon = 0;
1414 int rh_default_gfx = 4;
1415
1416 static struct MonDef *current_mon; /* EVIL */
1417
1418 int rh_mode __P((struct grf_softc *, u_long, void *, u_long, int));
1419 void grfrhattach __P((struct device *, struct device *, void *));
1420 int grfrhprint __P((void *, char *));
1421 int grfrhmatch __P((struct device *, void *, void *));
1422
1423 struct cfattach grfrh_ca = {
1424 sizeof(struct grf_softc), grfrhmatch, grfrhattach
1425 };
1426
1427 struct cfdriver grfrh_cd = {
1428 NULL, "grfrh", DV_DULL, NULL, 0
1429 };
1430
1431 static struct cfdata *cfdata;
1432
1433 int
1434 grfrhmatch(pdp, match, auxp)
1435 struct device *pdp;
1436 void *match, *auxp;
1437 {
1438 #ifdef RETINACONSOLE
1439 struct cfdata *cfp = match;
1440 static int rhconunit = -1;
1441 #endif
1442 struct zbus_args *zap;
1443
1444 zap = auxp;
1445
1446 if (amiga_realconfig == 0)
1447 #ifdef RETINACONSOLE
1448 if (rhconunit != -1)
1449 #endif
1450 return(0);
1451 if (zap->manid != 18260 ||
1452 ((zap->prodid != 16) && (zap->prodid != 19)))
1453 return(0);
1454 #ifdef RETINACONSOLE
1455 if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) {
1456 #endif
1457 if ((unsigned)rh_default_mon >= rh_mon_max ||
1458 monitor_defs[rh_default_mon].DEP == 8)
1459 rh_default_mon = 0;
1460 current_mon = monitor_defs + rh_default_mon;
1461 if (rh_mondefok(current_mon) == 0)
1462 return(0);
1463 #ifdef RETINACONSOLE
1464 if (amiga_realconfig == 0) {
1465 rhconunit = cfp->cf_unit;
1466 cfdata = cfp;
1467 }
1468 }
1469 #endif
1470 return(1);
1471 }
1472
1473 void
1474 grfrhattach(pdp, dp, auxp)
1475 struct device *pdp, *dp;
1476 void *auxp;
1477 {
1478 static struct grf_softc congrf;
1479 struct zbus_args *zap;
1480 struct grf_softc *gp;
1481
1482 zap = auxp;
1483
1484 if (dp == NULL)
1485 gp = &congrf;
1486 else
1487 gp = (struct grf_softc *)dp;
1488 if (dp != NULL && congrf.g_regkva != 0) {
1489 /*
1490 * inited earlier, just copy (not device struct)
1491 */
1492 bcopy(&congrf.g_display, &gp->g_display,
1493 (char *)&gp[1] - (char *)&gp->g_display);
1494 } else {
1495 gp->g_regkva = (volatile caddr_t)zap->va;
1496
1497 gp->g_regkva[0x3c8]=0;
1498 gp->g_regkva[0x3c9]=30;
1499 gp->g_regkva[0x3c9]=30;
1500 gp->g_regkva[0x3c9]=00;
1501
1502 gp->g_fbkva = (volatile caddr_t)zap->va + LM_OFFSET;
1503 gp->g_unit = GRF_RETINAIII_UNIT;
1504 gp->g_mode = rh_mode;
1505 gp->g_conpri = grfrh_cnprobe();
1506 gp->g_flags = GF_ALIVE;
1507 grfrh_iteinit(gp);
1508 (void)rh_load_mon(gp, current_mon);
1509 }
1510 if (dp != NULL)
1511 printf("\n");
1512 /*
1513 * attach grf
1514 */
1515 amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint);
1516 }
1517
1518 int
1519 grfrhprint(auxp, pnp)
1520 void *auxp;
1521 char *pnp;
1522 {
1523 if (pnp)
1524 printf("ite at %s", pnp);
1525 return(UNCONF);
1526 }
1527
1528 int
1529 rh_getvmode(gp, vm)
1530 struct grf_softc *gp;
1531 struct grfvideo_mode *vm;
1532 {
1533 struct MonDef *md;
1534
1535 if (vm->mode_num && vm->mode_num > rh_mon_max)
1536 return(EINVAL);
1537
1538 if (! vm->mode_num)
1539 vm->mode_num = (current_mon - monitor_defs) + 1;
1540
1541 md = monitor_defs + (vm->mode_num - 1);
1542 strncpy (vm->mode_descr, monitor_descr[vm->mode_num - 1],
1543 sizeof (vm->mode_descr));
1544 vm->pixel_clock = md->FQ;
1545 vm->disp_width = (md->DEP == 4) ? md->MW : md->TX;
1546 vm->disp_height = (md->DEP == 4) ? md->MH : md->TY;
1547 vm->depth = md->DEP;
1548
1549 /*
1550 * From observation of the monitor definition table above, I guess
1551 * that the horizontal timings are in units of longwords. Hence, I
1552 * get the pixels by multiplication with 32 and division by the depth.
1553 * The text modes, apparently marked by depth == 4, are even more
1554 * wierd. According to a comment above, they are computed from a
1555 * depth==8 mode thats for us: * 32 / 8) by applying another factor
1556 * of 4 / font width.
1557 * Reverse applying the latter formula most of the constants cancel
1558 * themselves and we are left with a nice (* font width).
1559 * That is, internal timings are in units of longwords for graphics
1560 * modes, or in units of characters widths for text modes.
1561 * We better don't WRITE modes until this has been real live checked.
1562 * - Ignatios Souvatzis
1563 */
1564
1565 if (md->DEP == 4) {
1566 vm->hblank_start = md->HBS * 32 / md->DEP;
1567 vm->hblank_stop = md->HBE * 32 / md->DEP;
1568 vm->hsync_start = md->HSS * 32 / md->DEP;
1569 vm->hsync_stop = md->HSE * 32 / md->DEP;
1570 vm->htotal = md->HT * 32 / md->DEP;
1571 } else {
1572 vm->hblank_start = md->HBS * md->FX;
1573 vm->hblank_stop = md->HBE * md->FX;
1574 vm->hsync_start = md->HSS * md->FX;
1575 vm->hsync_stop = md->HSE * md->FX;
1576 vm->htotal = md->HT * md->FX;
1577 }
1578
1579 vm->vblank_start = md->VBS;
1580 vm->vblank_stop = md->VBE;
1581 vm->vsync_start = md->VSS;
1582 vm->vsync_stop = md->VSE;
1583 vm->vtotal = md->VT;
1584
1585 return(0);
1586 }
1587
1588
1589 int
1590 rh_setvmode(gp, mode, type)
1591 struct grf_softc *gp;
1592 unsigned mode;
1593 enum mode_type type;
1594 {
1595 int error;
1596
1597 if (!mode || mode > rh_mon_max)
1598 return(EINVAL);
1599
1600 if ((type == MT_TXTONLY && monitor_defs[mode-1].DEP != 4)
1601 || (type == MT_GFXONLY && monitor_defs[mode-1].DEP == 4))
1602 return(EINVAL);
1603
1604 current_mon = monitor_defs + (mode - 1);
1605
1606 error = rh_load_mon (gp, current_mon) ? 0 : EINVAL;
1607
1608 return(error);
1609 }
1610
1611
1612 /*
1613 * Change the mode of the display.
1614 * Return a UNIX error number or 0 for success.
1615 */
1616 int
1617 rh_mode(gp, cmd, arg, a2, a3)
1618 register struct grf_softc *gp;
1619 u_long cmd;
1620 void *arg;
1621 u_long a2;
1622 int a3;
1623 {
1624 switch (cmd) {
1625 case GM_GRFON:
1626 rh_setvmode (gp, rh_default_gfx + 1, MT_GFXONLY);
1627 return(0);
1628
1629 case GM_GRFOFF:
1630 rh_setvmode (gp, rh_default_mon + 1, MT_TXTONLY);
1631 return(0);
1632
1633 case GM_GRFCONFIG:
1634 return(0);
1635
1636 case GM_GRFGETVMODE:
1637 return(rh_getvmode (gp, (struct grfvideo_mode *) arg));
1638
1639 case GM_GRFSETVMODE:
1640 return(rh_setvmode (gp, *(unsigned *) arg,
1641 (gp->g_flags & GF_GRFON) ? MT_GFXONLY : MT_TXTONLY));
1642
1643 case GM_GRFGETNUMVM:
1644 *(int *)arg = rh_mon_max;
1645 return(0);
1646
1647 #ifdef BANKEDDEVPAGER
1648 case GM_GRFGETBANK:
1649 case GM_GRFGETCURBANK:
1650 case GM_GRFSETBANK:
1651 return(EINVAL);
1652 #endif
1653 case GM_GRFIOCTL:
1654 return(rh_ioctl (gp, a2, arg));
1655
1656 default:
1657 break;
1658 }
1659
1660 return(EINVAL);
1661 }
1662
1663 int
1664 rh_ioctl (gp, cmd, data)
1665 register struct grf_softc *gp;
1666 u_long cmd;
1667 void *data;
1668 {
1669 switch (cmd) {
1670 case GRFIOCGSPRITEPOS:
1671 return(rh_getspritepos (gp, (struct grf_position *) data));
1672
1673 case GRFIOCSSPRITEPOS:
1674 return(rh_setspritepos (gp, (struct grf_position *) data));
1675
1676 case GRFIOCSSPRITEINF:
1677 return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data));
1678
1679 case GRFIOCGSPRITEINF:
1680 return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data));
1681
1682 case GRFIOCGSPRITEMAX:
1683 return(rh_getspritemax (gp, (struct grf_position *) data));
1684
1685 case GRFIOCGETCMAP:
1686 return(rh_getcmap (gp, (struct grf_colormap *) data));
1687
1688 case GRFIOCPUTCMAP:
1689 return(rh_putcmap (gp, (struct grf_colormap *) data));
1690
1691 case GRFIOCBITBLT:
1692 return(rh_bitblt (gp, (struct grf_bitblt *) data));
1693
1694 case GRFIOCBLANK:
1695 return (rh_blank(gp, (int *)data));
1696 }
1697
1698 return(EINVAL);
1699 }
1700
1701
1702 int
1703 rh_getcmap (gfp, cmap)
1704 struct grf_softc *gfp;
1705 struct grf_colormap *cmap;
1706 {
1707 volatile unsigned char *ba;
1708 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1709 short x;
1710 int error;
1711
1712 if (cmap->count == 0 || cmap->index >= 256)
1713 return 0;
1714
1715 if (cmap->index + cmap->count > 256)
1716 cmap->count = 256 - cmap->index;
1717
1718 ba = gfp->g_regkva;
1719 /* first read colors out of the chip, then copyout to userspace */
1720 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1721 x = cmap->count - 1;
1722 rp = red + cmap->index;
1723 gp = green + cmap->index;
1724 bp = blue + cmap->index;
1725 do {
1726 *rp++ = vgar (ba, VDAC_DATA) << 2;
1727 *gp++ = vgar (ba, VDAC_DATA) << 2;
1728 *bp++ = vgar (ba, VDAC_DATA) << 2;
1729 } while (x-- > 0);
1730
1731 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
1732 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
1733 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
1734 return(0);
1735
1736 return(error);
1737 }
1738
1739 int
1740 rh_putcmap (gfp, cmap)
1741 struct grf_softc *gfp;
1742 struct grf_colormap *cmap;
1743 {
1744 volatile unsigned char *ba;
1745 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1746 short x;
1747 int error;
1748
1749 if (cmap->count == 0 || cmap->index >= 256)
1750 return(0);
1751
1752 if (cmap->index + cmap->count > 256)
1753 cmap->count = 256 - cmap->index;
1754
1755 /* first copy the colors into kernelspace */
1756 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1757 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1758 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
1759 /* argl.. LoadPalette wants a different format, so do it like with
1760 * Retina2.. */
1761 ba = gfp->g_regkva;
1762 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1763 x = cmap->count - 1;
1764 rp = red + cmap->index;
1765 gp = green + cmap->index;
1766 bp = blue + cmap->index;
1767 do {
1768 vgaw (ba, VDAC_DATA, *rp++ >> 2);
1769 vgaw (ba, VDAC_DATA, *gp++ >> 2);
1770 vgaw (ba, VDAC_DATA, *bp++ >> 2);
1771 } while (x-- > 0);
1772 return(0);
1773 }
1774 else
1775 return(error);
1776 }
1777
1778 int
1779 rh_getspritepos (gp, pos)
1780 struct grf_softc *gp;
1781 struct grf_position *pos;
1782 {
1783 volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET;
1784
1785 pos->x = acm[ACM_CURSOR_POSITION + 0] +
1786 (acm[ACM_CURSOR_POSITION + 1] << 8);
1787 pos->y = acm[ACM_CURSOR_POSITION + 2] +
1788 (acm[ACM_CURSOR_POSITION + 3] << 8);
1789
1790 pos->x += xpan;
1791 pos->y += ypan;
1792
1793 return(0);
1794 }
1795
1796 int
1797 rh_setspritepos (gp, pos)
1798 struct grf_softc *gp;
1799 struct grf_position *pos;
1800 {
1801 RZ3SetHWCloc (gp, pos->x, pos->y);
1802 return(0);
1803 }
1804
1805 int
1806 rh_getspriteinfo (gp, info)
1807 struct grf_softc *gp;
1808 struct grf_spriteinfo *info;
1809 {
1810 volatile unsigned char *ba, *fb;
1811
1812 ba = gp->g_regkva;
1813 fb = gp->g_fbkva;
1814 if (info->set & GRFSPRSET_ENABLE)
1815 info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
1816 if (info->set & GRFSPRSET_POS)
1817 rh_getspritepos (gp, &info->pos);
1818 if (info->set & GRFSPRSET_HOT) {
1819 info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f;
1820 info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
1821 }
1822 if (info->set & GRFSPRSET_CMAP) {
1823 struct grf_colormap cmap;
1824 int index;
1825 cmap.index = 0;
1826 cmap.count = 256;
1827 rh_getcmap (gp, &cmap);
1828 index = RSeq (ba, SEQ_ID_CURSOR_COLOR0);
1829 info->cmap.red[0] = cmap.red[index];
1830 info->cmap.green[0] = cmap.green[index];
1831 info->cmap.blue[0] = cmap.blue[index];
1832 index = RSeq (ba, SEQ_ID_CURSOR_COLOR1);
1833 info->cmap.red[1] = cmap.red[index];
1834 info->cmap.green[1] = cmap.green[index];
1835 info->cmap.blue[1] = cmap.blue[index];
1836 }
1837 if (info->set & GRFSPRSET_SHAPE) {
1838 u_char image[128], mask[128];
1839 volatile u_long *hwp;
1840 u_char *imp, *mp;
1841 short row;
1842
1843 /* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h
1844 * for an explanation. To convert to "our" format, the
1845 * following holds:
1846 * col2 = !image & mask
1847 * col1 = image & mask
1848 * transp = !mask
1849 * and thus:
1850 * image = col1
1851 * mask = col1 | col2
1852 * hope I got these bool-eqs right below..
1853 */
1854
1855 #ifdef RH_64BIT_SPRITE
1856 info->size.x = 64;
1857 info->size.y = 64;
1858 for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
1859 mp = mask, imp = image;
1860 row < 64;
1861 row++) {
1862 u_long bp10, bp20, bp11, bp21;
1863 bp10 = *hwp++;
1864 bp20 = *hwp++;
1865 bp11 = *hwp++;
1866 bp21 = *hwp++;
1867 M2I (bp10);
1868 M2I (bp20);
1869 M2I (bp11);
1870 M2I (bp21);
1871 *imp++ = (~bp10) & bp11;
1872 *imp++ = (~bp20) & bp21;
1873 *mp++ = (~bp10) | (bp10 & ~bp11);
1874 *mp++ = (~bp20) & (bp20 & ~bp21);
1875 }
1876 #else
1877 info->size.x = 32;
1878 info->size.y = 32;
1879 for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
1880 mp = mask, imp = image;
1881 row < 32;
1882 row++) {
1883 u_long bp10, bp11;
1884 bp10 = *hwp++;
1885 bp11 = *hwp++;
1886 M2I (bp10);
1887 M2I (bp11);
1888 *imp++ = (~bp10) & bp11;
1889 *mp++ = (~bp10) | (bp10 & ~bp11);
1890 }
1891 #endif
1892 copyout (image, info->image, sizeof (image));
1893 copyout (mask, info->mask, sizeof (mask));
1894 }
1895 return(0);
1896 }
1897
1898 int
1899 rh_setspriteinfo (gp, info)
1900 struct grf_softc *gp;
1901 struct grf_spriteinfo *info;
1902 {
1903 volatile unsigned char *ba, *fb;
1904 #if 0
1905 u_char control;
1906 #endif
1907
1908 ba = gp->g_regkva;
1909 fb = gp->g_fbkva;
1910
1911 if (info->set & GRFSPRSET_SHAPE) {
1912 /*
1913 * For an explanation of these weird actions here, see above
1914 * when reading the shape. We set the shape directly into
1915 * the video memory, there's no reason to keep 1k on the
1916 * kernel stack just as template
1917 */
1918 u_char *image, *mask;
1919 volatile u_long *hwp;
1920 u_char *imp, *mp;
1921 short row;
1922
1923 #ifdef RH_64BIT_SPRITE
1924 if (info->size.y > 64)
1925 info->size.y = 64;
1926 if (info->size.x > 64)
1927 info->size.x = 64;
1928 #else
1929 if (info->size.y > 32)
1930 info->size.y = 32;
1931 if (info->size.x > 32)
1932 info->size.x = 32;
1933 #endif
1934
1935 if (info->size.x < 32)
1936 info->size.x = 32;
1937
1938 image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK);
1939 mask = image + HWC_MEM_SIZE/2;
1940
1941 copyin(info->image, image, info->size.y * info->size.x / 8);
1942 copyin(info->mask, mask, info->size.y * info->size.x / 8);
1943
1944 hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
1945
1946 /*
1947 * setting it is slightly more difficult, because we can't
1948 * force the application to not pass a *smaller* than
1949 * supported bitmap
1950 */
1951
1952 for (row = 0, mp = mask, imp = image;
1953 row < info->size.y;
1954 row++) {
1955 u_long im1, im2, m1, m2;
1956
1957 im1 = *(unsigned long *)imp;
1958 imp += 4;
1959 m1 = *(unsigned long *)mp;
1960 mp += 4;
1961 #ifdef RH_64BIT_SPRITE
1962 if (info->size.x > 32) {
1963 im2 = *(unsigned long *)imp;
1964 imp += 4;
1965 m2 = *(unsigned long *)mp;
1966 mp += 4;
1967 }
1968 else
1969 #endif
1970 im2 = m2 = 0;
1971
1972 M2I(im1);
1973 M2I(im2);
1974 M2I(m1);
1975 M2I(m2);
1976
1977 *hwp++ = ~m1;
1978 #ifdef RH_64BIT_SPRITE
1979 *hwp++ = ~m2;
1980 #endif
1981 *hwp++ = m1 & im1;
1982 #ifdef RH_64BIT_SPRITE
1983 *hwp++ = m2 & im2;
1984 #endif
1985 }
1986 #ifdef RH_64BIT_SPRITE
1987 for (; row < 64; row++) {
1988 *hwp++ = 0xffffffff;
1989 *hwp++ = 0xffffffff;
1990 *hwp++ = 0x00000000;
1991 *hwp++ = 0x00000000;
1992 }
1993 #else
1994 for (; row < 32; row++) {
1995 *hwp++ = 0xffffffff;
1996 *hwp++ = 0x00000000;
1997 }
1998 #endif
1999
2000 free(image, M_TEMP);
2001 RZ3SetupHWC(gp, 1, 0, 0, 0, 0);
2002 }
2003 if (info->set & GRFSPRSET_CMAP) {
2004 /* hey cheat a bit here.. XXX */
2005 WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0);
2006 WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1);
2007 }
2008 if (info->set & GRFSPRSET_ENABLE) {
2009 #if 0
2010 if (info->enable)
2011 control = 0x85;
2012 else
2013 control = 0;
2014 WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
2015 #endif
2016 }
2017 if (info->set & GRFSPRSET_POS)
2018 rh_setspritepos(gp, &info->pos);
2019 if (info->set & GRFSPRSET_HOT) {
2020 WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f);
2021 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
2022 }
2023
2024 return(0);
2025 }
2026
2027 int
2028 rh_getspritemax (gp, pos)
2029 struct grf_softc *gp;
2030 struct grf_position *pos;
2031 {
2032 #ifdef RH_64BIT_SPRITE
2033 pos->x = 64;
2034 pos->y = 64;
2035 #else
2036 pos->x = 32;
2037 pos->y = 32;
2038 #endif
2039
2040 return(0);
2041 }
2042
2043
2044 int
2045 rh_bitblt (gp, bb)
2046 struct grf_softc *gp;
2047 struct grf_bitblt *bb;
2048 {
2049 struct MonDef *md = (struct MonDef *)gp->g_data;
2050 if (md->DEP <= 8)
2051 RZ3BitBlit(gp, bb);
2052 else if (md->DEP <= 16)
2053 RZ3BitBlit16(gp, bb);
2054 else
2055 RZ3BitBlit24(gp, bb);
2056
2057 return(0);
2058 }
2059
2060
2061 int
2062 rh_blank(gp, on)
2063 struct grf_softc *gp;
2064 int *on;
2065 {
2066 struct MonDef *md = (struct MonDef *)gp->g_data;
2067 int r;
2068
2069 r = 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8);
2070
2071 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on ? r : 0x21);
2072
2073 return(0);
2074 }
2075
2076 #endif /* NGRF */
2077