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