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