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