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