Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / amiga / dev / grf_rh.c
blobde60d794b9a1d70fdd8e436b1afd79f7516c9def
1 /* $NetBSD: grf_rh.c,v 1.52 2009/03/18 17:06:42 cegger Exp $ */
3 /*
4 * Copyright (c) 1994 Markus Wild
5 * Copyright (c) 1994 Lutz Vieweg
6 * All rights reserved.
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
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.
33 #include "opt_amigacons.h"
34 #include "opt_retina.h"
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: grf_rh.c,v 1.52 2009/03/18 17:06:42 cegger Exp $");
39 #include "grfrh.h"
40 #if NGRFRH > 0
43 * Graphics routines for the Retina BLT Z3 board,
44 * using the NCR 77C32BLT VGA controller.
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/errno.h>
50 #include <sys/ioctl.h>
51 #include <sys/device.h>
52 #include <sys/malloc.h>
53 #include <machine/cpu.h>
54 #include <amiga/amiga/device.h>
55 #include <amiga/dev/grfioctl.h>
56 #include <amiga/dev/grfvar.h>
57 #include <amiga/dev/grf_rhreg.h>
58 #include <amiga/dev/zbusvar.h>
60 enum mode_type { MT_TXTONLY, MT_GFXONLY, MT_BOTH };
62 int rh_mondefok(struct MonDef *);
64 u_short rh_CompFQ(u_int fq);
65 int rh_load_mon(struct grf_softc *gp, struct MonDef *md);
66 int rh_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm);
67 int rh_setvmode(struct grf_softc *gp, unsigned int mode, enum mode_type type);
69 /* make it patchable, and settable by kernel config option */
70 #ifndef RH_MEMCLK
71 #define RH_MEMCLK 61000000 /* this is the memory clock value, you shouldn't
72 set it to less than 61000000, higher values may
73 speed up blits a little bit, if you raise this
74 value too much, some trash will appear on your
75 screen. */
76 #endif
77 int rh_memclk = RH_MEMCLK;
80 extern unsigned char kernel_font_8x8_width, kernel_font_8x8_height;
81 extern unsigned char kernel_font_8x8_lo, kernel_font_8x8_hi;
82 extern unsigned char kernel_font_8x8[];
83 #ifdef KFONT_8X11
84 extern unsigned char kernel_font_8x11_width, kernel_font_8x11_height;
85 extern unsigned char kernel_font_8x11_lo, kernel_font_8x11_hi;
86 extern unsigned char kernel_font_8x11[];
87 #endif
90 * This driver for the MacroSystem Retina board was only possible,
91 * because MacroSystem provided information about the pecularities
92 * of the board. THANKS! Competition in Europe among gfx board
93 * manufacturers is rather tough, so Lutz Vieweg, who wrote the
94 * initial driver, has made an agreement with MS not to document
95 * the driver source (see also his comment below).
96 * -> ALL comments after
97 * -> " -------------- START OF CODE -------------- "
98 * -> have been added by myself (mw) from studying the publically
99 * -> available "NCR 77C32BLT" Data Manual
102 * This code offers low-level routines to access the Retina BLT Z3
103 * graphics-board manufactured by MS MacroSystem GmbH from within NetBSD
104 * for the Amiga.
106 * Thanks to MacroSystem for providing me with the necessary information
107 * to create theese routines. The sparse documentation of this code
108 * results from the agreements between MS and me.
113 #define MDF_DBL 1
114 #define MDF_LACE 2
115 #define MDF_CLKDIV2 4
117 /* set this as an option in your kernel config file! */
118 /* #define RH_64BIT_SPRITE */
120 /* -------------- START OF CODE -------------- */
122 /* Convert big-endian long into little-endian long. */
124 #ifdef __m68k__
125 #define M2I(val) \
126 __asm volatile (" rorw #8,%0 ; \
127 swap %0 ; \
128 rorw #8,%0 ; " : "=d" (val) : "0" (val));
129 #else
130 #define M2I(val) \
131 val = ((val & 0xff000000) >> 24) | \
132 ((val & 0x00ff0000) >> 8 ) | \
133 ((val & 0x0000ff00) << 8 ) | \
134 ((val & 0x000000ff) << 24)
135 #endif
137 #define ACM_OFFSET (0x00b00000)
138 #define LM_OFFSET (0x00c00000)
140 static unsigned char optab[] = {
141 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
142 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
144 static char optabs[] = {
145 0, -1, -1, -1, -1, 0, -1, -1,
146 -1, -1, 0, -1, -1, -1, -1, 0
149 void
150 RZ3DisableHWC(struct grf_softc *gp)
152 volatile void *ba = gp->g_regkva;
154 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, 0x00);
157 void
158 RZ3SetupHWC(struct grf_softc *gp, unsigned char col1, unsigned col2,
159 unsigned char hsx, unsigned char hsy, const unsigned long *data)
161 volatile unsigned char *ba = gp->g_regkva;
162 unsigned long *c = (unsigned long *)__UNVOLATILE(ba);
163 c += LM_OFFSET + HWC_MEM_OFF;
164 const unsigned long *s = data;
165 struct MonDef *MonitorDef = (struct MonDef *) gp->g_data;
166 #ifdef RH_64BIT_SPRITE
167 short x = (HWC_MEM_SIZE / (4*4)) - 1;
168 #else
169 short x = (HWC_MEM_SIZE / (4*4*2)) - 1;
170 #endif
171 /* copy only, if there is a data pointer. */
172 if (data) do {
173 *c++ = *s++;
174 *c++ = *s++;
175 *c++ = *s++;
176 *c++ = *s++;
177 } while (x-- > 0);
179 WSeq(ba, SEQ_ID_CURSOR_COLOR1, col1);
180 WSeq(ba, SEQ_ID_CURSOR_COLOR0, col2);
181 if (MonitorDef->DEP <= 8) {
182 #ifdef RH_64BIT_SPRITE
183 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x85);
184 #else
185 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x03);
186 #endif
188 else if (MonitorDef->DEP <= 16) {
189 #ifdef RH_64BIT_SPRITE
190 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xa5);
191 #else
192 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x23);
193 #endif
195 else {
196 #ifdef RH_64BIT_SPRITE
197 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xc5);
198 #else
199 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x43);
200 #endif
202 WSeq(ba, SEQ_ID_CURSOR_X_LOC_HI, 0x00);
203 WSeq(ba, SEQ_ID_CURSOR_X_LOC_LO, 0x00);
204 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI, 0x00);
205 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO, 0x00);
206 WSeq(ba, SEQ_ID_CURSOR_X_INDEX, hsx);
207 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, hsy);
208 WSeq(ba, SEQ_ID_CURSOR_STORE_HI, 0x00);
209 WSeq(ba, SEQ_ID_CURSOR_STORE_LO, ((HWC_MEM_OFF / 4) & 0x0000f));
210 WSeq(ba, SEQ_ID_CURSOR_ST_OFF_HI,
211 (((HWC_MEM_OFF / 4) & 0xff000) >> 12));
212 WSeq(ba, SEQ_ID_CURSOR_ST_OFF_LO,
213 (((HWC_MEM_OFF / 4) & 0x00ff0) >> 4));
214 WSeq(ba, SEQ_ID_CURSOR_PIXELMASK, 0xff);
217 void
218 RZ3AlphaErase(struct grf_softc *gp, unsigned short xd, unsigned short yd,
219 unsigned short w, unsigned short h)
221 const struct MonDef * md = (struct MonDef *) gp->g_data;
222 RZ3AlphaCopy(gp, xd, yd+md->TY, xd, yd, w, h);
225 void
226 RZ3AlphaCopy(struct grf_softc *gp, unsigned short xs, unsigned short ys,
227 unsigned short xd, unsigned short yd, unsigned short w,
228 unsigned short h)
230 volatile unsigned char *ba = gp->g_regkva;
231 const struct MonDef *md = (struct MonDef *) gp->g_data;
232 volatile unsigned long *acm = (volatile unsigned long *) (ba +
233 ACM_OFFSET);
234 unsigned short mod;
236 xs *= 4;
237 ys *= 4;
238 xd *= 4;
239 yd *= 4;
240 w *= 4;
243 /* anyone got Windoze GDI opcodes handy?... */
244 unsigned long tmp = 0x0000ca00;
245 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
248 mod = 0xc0c2;
251 unsigned long pat = 8 * PAT_MEM_OFF;
252 unsigned long dst = 8 * (xd + yd * md->TX);
254 unsigned long src = 8 * (xs + ys * md->TX);
256 if (xd > xs) {
257 mod &= ~0x8000;
258 src += 8 * (w - 1);
259 dst += 8 * (w - 1);
260 pat += 8 * 2;
262 if (yd > ys) {
263 mod &= ~0x4000;
264 src += 8 * (h - 1) * md->TX * 4;
265 dst += 8 * (h - 1) * md->TX * 4;
266 pat += 8 * 4;
269 M2I(src);
270 *(acm + ACM_SOURCE/4) = src;
272 M2I(pat);
273 *(acm + ACM_PATTERN/4) = pat;
275 M2I(dst);
276 *(acm + ACM_DESTINATION/4) = dst;
280 unsigned long tmp = mod << 16;
281 *(acm + ACM_CONTROL/4) = tmp;
285 unsigned long tmp = w | (h << 16);
286 M2I(tmp);
287 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
290 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
291 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
293 while ((*(((volatile unsigned char *)acm) +
294 (ACM_START_STATUS + 2)) & 1) == 0);
297 void
298 RZ3BitBlit(struct grf_softc *gp, struct grf_bitblt *gbb)
300 volatile unsigned char *ba = gp->g_regkva;
301 volatile unsigned char *lm = ba + LM_OFFSET;
302 volatile unsigned long *acm = (volatile unsigned long *) (ba +
303 ACM_OFFSET);
304 const struct MonDef *md = (struct MonDef *) gp->g_data;
305 unsigned short mod;
308 volatile unsigned long * pt =
309 (volatile unsigned long *) (lm + PAT_MEM_OFF);
310 unsigned long tmp =
311 gbb->mask | ((unsigned long) gbb->mask << 16);
312 *pt++ = tmp;
313 *pt = tmp;
318 unsigned long tmp = optab[ gbb->op ] << 8;
319 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
322 mod = 0xc0c2;
325 unsigned long pat = 8 * PAT_MEM_OFF;
326 unsigned long dst = 8 * (gbb->dst_x + gbb->dst_y * md->TX);
328 if (optabs[gbb->op]) {
329 unsigned long src =
330 8 * (gbb->src_x + gbb->src_y * md->TX);
332 if (gbb->dst_x > gbb->src_x) {
333 mod &= ~0x8000;
334 src += 8 * (gbb->w - 1);
335 dst += 8 * (gbb->w - 1);
336 pat += 8 * 2;
338 if (gbb->dst_y > gbb->src_y) {
339 mod &= ~0x4000;
340 src += 8 * (gbb->h - 1) * md->TX;
341 dst += 8 * (gbb->h - 1) * md->TX;
342 pat += 8 * 4;
345 M2I(src);
346 *(acm + ACM_SOURCE/4) = src;
349 M2I(pat);
350 *(acm + ACM_PATTERN/4) = pat;
352 M2I(dst);
353 *(acm + ACM_DESTINATION/4) = dst;
357 unsigned long tmp = mod << 16;
358 *(acm + ACM_CONTROL/4) = tmp;
361 unsigned long tmp = gbb->w | (gbb->h << 16);
362 M2I(tmp);
363 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
366 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
367 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
369 while ((*(((volatile unsigned char *)acm) +
370 (ACM_START_STATUS + 2)) & 1) == 0);
373 void
374 RZ3BitBlit16(struct grf_softc *gp, struct grf_bitblt *gbb)
376 volatile unsigned char *ba = gp->g_regkva;
377 volatile unsigned char *lm = ba + LM_OFFSET;
378 volatile unsigned long * acm = (volatile unsigned long *) (ba +
379 ACM_OFFSET);
380 const struct MonDef * md = (struct MonDef *) gp->g_data;
381 unsigned short mod;
384 volatile unsigned long * pt =
385 (volatile unsigned long *) (lm + PAT_MEM_OFF);
386 unsigned long tmp =
387 gbb->mask | ((unsigned long) gbb->mask << 16);
388 *pt++ = tmp;
389 *pt++ = tmp;
390 *pt++ = tmp;
391 *pt = tmp;
396 unsigned long tmp = optab[ gbb->op ] << 8;
397 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
400 mod = 0xc0c2;
403 unsigned long pat = 8 * PAT_MEM_OFF;
404 unsigned long dst = 8 * 2 * (gbb->dst_x + gbb->dst_y * md->TX);
406 if (optabs[gbb->op]) {
407 unsigned long src =
408 8 * 2 * (gbb->src_x + gbb->src_y * md->TX);
410 if (gbb->dst_x > gbb->src_x) {
411 mod &= ~0x8000;
412 src += 8 * 2 * (gbb->w);
413 dst += 8 * 2 * (gbb->w);
414 pat += 8 * 2 * 2;
416 if (gbb->dst_y > gbb->src_y) {
417 mod &= ~0x4000;
418 src += 8 * 2 * (gbb->h - 1) * md->TX;
419 dst += 8 * 2 * (gbb->h - 1) * md->TX;
420 pat += 8 * 4 * 2;
423 M2I(src);
424 *(acm + ACM_SOURCE/4) = src;
427 M2I(pat);
428 *(acm + ACM_PATTERN/4) = pat;
430 M2I(dst);
431 *(acm + ACM_DESTINATION/4) = dst;
435 unsigned long tmp = mod << 16;
436 *(acm + ACM_CONTROL/4) = tmp;
440 unsigned long tmp = gbb->w | (gbb->h << 16);
441 M2I(tmp);
442 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
445 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
446 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
448 while ((*(((volatile unsigned char *)acm) +
449 (ACM_START_STATUS+ 2)) & 1) == 0);
452 void
453 RZ3BitBlit24(struct grf_softc *gp, struct grf_bitblt *gbb)
455 volatile unsigned char *ba = gp->g_regkva;
456 volatile unsigned char *lm = ba + LM_OFFSET;
457 volatile unsigned long * acm = (volatile unsigned long *) (ba +
458 ACM_OFFSET);
459 const struct MonDef * md = (struct MonDef *) gp->g_data;
460 unsigned short mod;
464 volatile unsigned long * pt =
465 (volatile unsigned long *) (lm + PAT_MEM_OFF);
466 unsigned long tmp =
467 gbb->mask | ((unsigned long) gbb->mask << 16);
468 *pt++ = tmp;
469 *pt++ = tmp;
470 *pt++ = tmp;
471 *pt++ = tmp;
472 *pt++ = tmp;
473 *pt = tmp;
477 unsigned long tmp = optab[ gbb->op ] << 8;
478 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
481 mod = 0xc0c2;
484 unsigned long pat = 8 * PAT_MEM_OFF;
485 unsigned long dst = 8 * 3 * (gbb->dst_x + gbb->dst_y * md->TX);
487 if (optabs[gbb->op]) {
488 unsigned long src =
489 8 * 3 * (gbb->src_x + gbb->src_y * md->TX);
491 if (gbb->dst_x > gbb->src_x ) {
492 mod &= ~0x8000;
493 src += 8 * 3 * (gbb->w);
494 dst += 8 * 3 * (gbb->w);
495 pat += 8 * 3 * 2;
497 if (gbb->dst_y > gbb->src_y) {
498 mod &= ~0x4000;
499 src += 8 * 3 * (gbb->h - 1) * md->TX;
500 dst += 8 * 3 * (gbb->h - 1) * md->TX;
501 pat += 8 * 4 * 3;
504 M2I(src);
505 *(acm + ACM_SOURCE/4) = src;
508 M2I(pat);
509 *(acm + ACM_PATTERN/4) = pat;
511 M2I(dst);
512 *(acm + ACM_DESTINATION/4) = dst;
515 unsigned long tmp = mod << 16;
516 *(acm + ACM_CONTROL/4) = tmp;
519 unsigned long tmp = gbb->w | (gbb->h << 16);
520 M2I(tmp);
521 *(acm + ACM_BITMAP_DIMENSION/4) = tmp;
524 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
525 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
527 while ( (*(((volatile unsigned char *)acm)
528 + (ACM_START_STATUS+ 2)) & 1) == 0 ) {};
533 void
534 RZ3SetCursorPos(struct grf_softc *gp, unsigned short pos)
536 volatile unsigned char *ba = gp->g_regkva;
538 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, (unsigned char)pos);
539 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (unsigned char)(pos >> 8));
543 void
544 RZ3LoadPalette(struct grf_softc *gp, unsigned char *pal,
545 unsigned char firstcol, unsigned char colors)
547 volatile unsigned char *ba = gp->g_regkva;
549 if (colors == 0)
550 return;
552 vgaw(ba, VDAC_ADDRESS_W, firstcol);
556 short x = colors-1;
557 const unsigned char * col = pal;
558 do {
560 vgaw(ba, VDAC_DATA, (*col++ >> 2));
561 vgaw(ba, VDAC_DATA, (*col++ >> 2));
562 vgaw(ba, VDAC_DATA, (*col++ >> 2));
564 } while (x-- > 0);
569 void
570 RZ3SetPalette(struct grf_softc *gp, unsigned char colornum, unsigned char red,
571 unsigned char green, unsigned char blue)
573 volatile unsigned char *ba = gp->g_regkva;
575 vgaw(ba, VDAC_ADDRESS_W, colornum);
577 vgaw(ba, VDAC_DATA, (red >> 2));
578 vgaw(ba, VDAC_DATA, (green >> 2));
579 vgaw(ba, VDAC_DATA, (blue >> 2));
583 void
584 RZ3SetPanning(struct grf_softc *gp, unsigned short xoff, unsigned short yoff)
586 volatile unsigned char *ba = gp->g_regkva;
587 struct grfinfo *gi = &gp->g_display;
588 const struct MonDef * md = (struct MonDef *) gp->g_data;
589 unsigned long off;
591 gi->gd_fbx = xoff;
592 gi->gd_fby = yoff;
594 if (md->DEP > 8 && md->DEP <= 16) xoff *= 2;
595 else if (md->DEP > 16) xoff *= 3;
597 vgar(ba, ACT_ADDRESS_RESET);
598 WAttr(ba, ACT_ID_HOR_PEL_PANNING, (unsigned char)((xoff << 1) & 0x07));
599 /* have the color lookup function normally again */
600 vgaw(ba, ACT_ADDRESS_W, 0x20);
602 if (md->DEP == 8)
603 off = ((yoff * md->TX)/ 4) + (xoff >> 2);
604 else if (md->DEP == 16)
605 off = ((yoff * md->TX * 2)/ 4) + (xoff >> 2);
606 else
607 off = ((yoff * md->TX * 3)/ 4) + (xoff >> 2);
608 WCrt(ba, CRT_ID_START_ADDR_LOW, ((unsigned char)off));
609 off >>= 8;
610 WCrt(ba, CRT_ID_START_ADDR_HIGH, ((unsigned char)off));
611 off >>= 8;
612 WCrt(ba, CRT_ID_EXT_START_ADDR,
613 ((RCrt(ba, CRT_ID_EXT_START_ADDR) & 0xf0) | (off & 0x0f)));
618 void
619 RZ3SetHWCloc(struct grf_softc *gp, unsigned short x, unsigned short y)
621 volatile unsigned char *ba = gp->g_regkva;
622 const struct MonDef *md = (struct MonDef *) gp->g_data;
623 /*volatile unsigned char *acm = ba + ACM_OFFSET;*/
624 struct grfinfo *gi = &gp->g_display;
626 if (x < gi->gd_fbx)
627 RZ3SetPanning(gp, x, gi->gd_fby);
629 if (x >= (gi->gd_fbx+md->MW))
630 RZ3SetPanning(gp, (1 + x - md->MW) , gi->gd_fby);
632 if (y < gi->gd_fby)
633 RZ3SetPanning(gp, gi->gd_fbx, y);
635 if (y >= (gi->gd_fby+md->MH))
636 RZ3SetPanning(gp, gi->gd_fbx, (1 + y - md->MH));
638 x -= gi->gd_fbx;
639 y -= gi->gd_fby;
641 #if 1
642 WSeq(ba, SEQ_ID_CURSOR_X_LOC_HI, x >> 8);
643 WSeq(ba, SEQ_ID_CURSOR_X_LOC_LO, x & 0xff);
644 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI, y >> 8);
645 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO, y & 0xff);
646 #else
647 *(acm + (ACM_CURSOR_POSITION+1)) = x >> 8;
648 *(acm + (ACM_CURSOR_POSITION+0)) = x & 0xff;
649 *(acm + (ACM_CURSOR_POSITION+3)) = y >> 8;
650 *(acm + (ACM_CURSOR_POSITION+2)) = y & 0xff;
651 #endif
654 u_short
655 rh_CompFQ(u_int fq)
657 /* yuck... this sure could need some explanation.. */
659 unsigned long f = fq;
660 long n2 = 3;
661 long abw = 0x7fffffff;
662 long n1 = 3;
663 unsigned long m;
664 unsigned short erg = 0;
666 f *= 8;
668 do {
670 if (f <= 250000000)
671 break;
672 f /= 2;
674 } while (n2-- > 0);
676 if (n2 < 0)
677 return(0);
680 do {
681 long tmp;
683 f = fq;
684 f >>= 3;
685 f <<= n2;
686 f >>= 7;
688 m = (f * n1) / (14318180/1024);
690 if (m > 129)
691 break;
693 tmp = (((m * 14318180) >> n2) / n1) - fq;
694 if (tmp < 0)
695 tmp = -tmp;
697 if (tmp < abw) {
698 abw = tmp;
699 erg = (((n2 << 5) | (n1-2)) << 8) | (m-2);
702 } while ( (++n1) <= 21);
704 return(erg);
708 rh_mondefok(struct MonDef *mdp)
710 switch(mdp->DEP) {
711 case 8:
712 case 16:
713 case 24:
714 return(1);
715 case 4:
716 if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16))
717 return(1);
718 /*FALLTHROUGH*/
719 default:
720 return(0);
726 rh_load_mon(struct grf_softc *gp, struct MonDef *md)
728 struct grfinfo *gi = &gp->g_display;
729 volatile void *ba;
730 volatile void *fb;
731 short FW, clksel, HDE = 0, VDE;
732 volatile unsigned short *c;
733 unsigned short z;
734 const unsigned char *f;
736 ba = gp->g_regkva;
737 fb = gp->g_fbkva;
739 /* provide all needed information in grf device-independent
740 * locations */
741 gp->g_data = (void *) md;
742 gi->gd_regaddr = (void *) kvtop (__UNVOLATILE(ba));
743 gi->gd_regsize = LM_OFFSET;
744 gi->gd_fbaddr = (void *) kvtop (__UNVOLATILE(fb));
745 gi->gd_fbsize = MEMSIZE *1024*1024;
746 gi->gd_colors = 1 << md->DEP;
747 gi->gd_planes = md->DEP;
749 if (md->DEP == 4) {
750 gi->gd_fbwidth = md->MW;
751 gi->gd_fbheight = md->MH;
752 gi->gd_fbx = 0;
753 gi->gd_fby = 0;
754 gi->gd_dwidth = md->TX * md->FX;
755 gi->gd_dheight = md->TY * md->FY;
756 gi->gd_dx = 0;
757 gi->gd_dy = 0;
758 } else {
759 gi->gd_fbwidth = md->TX;
760 gi->gd_fbheight = md->TY;
761 gi->gd_fbx = 0;
762 gi->gd_fby = 0;
763 gi->gd_dwidth = md->MW;
764 gi->gd_dheight = md->MH;
765 gi->gd_dx = 0;
766 gi->gd_dy = 0;
769 FW =0;
770 if (md->DEP == 4) { /* XXX some text-mode! */
771 switch (md->FX) {
772 case 4:
773 FW = 0;
774 break;
775 case 7:
776 FW = 1;
777 break;
778 case 8:
779 FW = 2;
780 break;
781 case 9:
782 FW = 3;
783 break;
784 case 10:
785 FW = 4;
786 break;
787 case 11:
788 FW = 5;
789 break;
790 case 12:
791 FW = 6;
792 break;
793 case 13:
794 FW = 7;
795 break;
796 case 14:
797 FW = 8;
798 break;
799 case 15:
800 FW = 9;
801 break;
802 case 16:
803 FW = 11;
804 break;
805 default:
806 return(0);
807 break;
811 if (md->DEP == 4) HDE = (md->MW+md->FX-1)/md->FX;
812 else if (md->DEP == 8) HDE = (md->MW+3)/4;
813 else if (md->DEP == 16) HDE = (md->MW*2+3)/4;
814 else if (md->DEP == 24) HDE = (md->MW*3+3)/4;
816 VDE = md->MH-1;
818 clksel = 0;
820 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04));
821 vgaw(ba, GREG_FEATURE_CONTROL_W, 0x00);
823 WSeq(ba, SEQ_ID_RESET, 0x00);
824 WSeq(ba, SEQ_ID_RESET, 0x03);
825 WSeq(ba, SEQ_ID_CLOCKING_MODE,
826 0x01 | ((md->FLG & MDF_CLKDIV2) / MDF_CLKDIV2 * 8));
827 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
828 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
829 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x06);
830 WSeq(ba, SEQ_ID_RESET, 0x01);
831 WSeq(ba, SEQ_ID_RESET, 0x03);
833 WSeq(ba, SEQ_ID_EXTENDED_ENABLE, 0x05);
834 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x00);
835 WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
836 WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00);
837 WSeq(ba, SEQ_ID_LINEAR_0, 0x4a);
838 WSeq(ba, SEQ_ID_LINEAR_1, 0x00);
840 WSeq(ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00);
841 WSeq(ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00);
842 WSeq(ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
843 WSeq(ba, SEQ_ID_EXT_CLOCK_MODE, 0x10 | (FW & 0x0f));
844 WSeq(ba, SEQ_ID_EXT_VIDEO_ADDR, 0x03);
845 if (md->DEP == 4) {
846 /* 8bit pixel, no gfx byte path */
847 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00);
849 else if (md->DEP == 8) {
850 /* 8bit pixel, gfx byte path */
851 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01);
853 else if (md->DEP == 16) {
854 /* 16bit pixel, gfx byte path */
855 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11);
857 else if (md->DEP == 24) {
858 /* 24bit pixel, gfx byte path */
859 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x21);
861 WSeq(ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x04);
862 WSeq(ba, SEQ_ID_COLOR_EXP_WFG, 0x01);
863 WSeq(ba, SEQ_ID_COLOR_EXP_WBG, 0x00);
864 WSeq(ba, SEQ_ID_EXT_RW_CONTROL, 0x00);
865 WSeq(ba, SEQ_ID_MISC_FEATURE_SEL, (0x51 | (clksel & 8)));
866 WSeq(ba, SEQ_ID_COLOR_KEY_CNTL, 0x40);
867 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH0, 0x00);
868 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH1, 0x00);
869 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH2, 0x00);
870 WSeq(ba, SEQ_ID_CRC_CONTROL, 0x00);
871 WSeq(ba, SEQ_ID_PERF_SELECT, 0x10);
872 WSeq(ba, SEQ_ID_ACM_APERTURE_1, 0x00);
873 WSeq(ba, SEQ_ID_ACM_APERTURE_2, 0x30);
874 WSeq(ba, SEQ_ID_ACM_APERTURE_3, 0x00);
875 WSeq(ba, SEQ_ID_MEMORY_MAP_CNTL, 0x03); /* was 7, but stupid cursor */
877 WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x20);
878 WCrt(ba, CRT_ID_HOR_TOTAL, md->HT & 0xff);
879 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff);
880 WCrt(ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff);
881 WCrt(ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80);
883 WCrt(ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff);
884 WCrt(ba, CRT_ID_END_HOR_RETR,
885 (md->HSE & 0x1f) |
886 ((md->HBE & 0x20)/ 0x20 * 0x80));
887 WCrt(ba, CRT_ID_VER_TOTAL, (md->VT & 0xff));
888 WCrt(ba, CRT_ID_OVERFLOW,
889 ((md->VSS & 0x200) / 0x200 * 0x80) |
890 ((VDE & 0x200) / 0x200 * 0x40) |
891 ((md->VT & 0x200) / 0x200 * 0x20) |
892 0x10 |
893 ((md->VBS & 0x100) / 0x100 * 8) |
894 ((md->VSS & 0x100) / 0x100 * 4) |
895 ((VDE & 0x100) / 0x100 * 2) |
896 ((md->VT & 0x100) / 0x100));
897 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
899 if (md->DEP == 4) {
900 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
901 ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
902 0x40 |
903 ((md->VBS & 0x200)/0x200*0x20) |
904 ((md->FY-1) & 0x1f));
905 } else {
906 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
907 ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) |
908 0x40 |
909 ((md->VBS & 0x200)/0x200*0x20) |
910 (0 & 0x1f));
913 /* I prefer "_" cursor to "block" cursor.. */
914 #if 1
915 WCrt(ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2);
916 WCrt(ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1);
917 #else
918 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
919 WCrt(ba, CRT_ID_CURSOR_END, md->FY & 0x1f);
920 #endif
922 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
923 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
925 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
926 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
928 WCrt(ba, CRT_ID_START_VER_RETR, md->VSS & 0xff);
929 WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x80 | 0x20);
930 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff);
932 if (md->DEP == 4) {
933 WCrt(ba, CRT_ID_OFFSET, (HDE / 2) & 0xff );
935 /* all gfx-modes are in byte-mode, means values are multiplied by 8 */
936 else if (md->DEP == 8) {
937 WCrt(ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff );
938 } else if (md->DEP == 16) {
939 WCrt(ba, CRT_ID_OFFSET, (md->TX / 4) & 0xff );
940 } else {
941 WCrt(ba, CRT_ID_OFFSET, (md->TX * 3 / 8) & 0xff );
944 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f);
945 WCrt(ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff);
946 WCrt(ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff);
947 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
948 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
950 WCrt(ba, CRT_ID_EXT_HOR_TIMING1,
951 0 | 0x20 |
952 ((md->FLG & MDF_LACE) / MDF_LACE * 0x10) |
953 ((md->HT & 0x100) / 0x100) |
954 (((HDE-1) & 0x100) / 0x100 * 2) |
955 ((md->HBS & 0x100) / 0x100 * 4) |
956 ((md->HSS & 0x100) / 0x100 * 8));
958 if (md->DEP == 4)
959 WCrt(ba, CRT_ID_EXT_START_ADDR,
960 (((HDE / 2) & 0x100)/0x100 * 16));
961 else if (md->DEP == 8)
962 WCrt(ba, CRT_ID_EXT_START_ADDR,
963 (((md->TX / 8) & 0x100)/0x100 * 16));
964 else if (md->DEP == 16)
965 WCrt(ba, CRT_ID_EXT_START_ADDR,
966 (((md->TX / 4) & 0x100)/0x100 * 16));
967 else
968 WCrt(ba, CRT_ID_EXT_START_ADDR,
969 (((md->TX * 3 / 8) & 0x100)/0x100 * 16));
971 WCrt(ba, CRT_ID_EXT_HOR_TIMING2,
972 ((md->HT & 0x200)/ 0x200) |
973 (((HDE-1) & 0x200)/ 0x200 * 2 ) |
974 ((md->HBS & 0x200)/ 0x200 * 4 ) |
975 ((md->HSS & 0x200)/ 0x200 * 8 ) |
976 ((md->HBE & 0xc0) / 0x40 * 16 ) |
977 ((md->HSE & 0x60) / 0x20 * 64));
979 WCrt(ba, CRT_ID_EXT_VER_TIMING,
980 ((md->VSE & 0x10) / 0x10 * 0x80 ) |
981 ((md->VBE & 0x300)/ 0x100 * 0x20 ) |
982 0x10 |
983 ((md->VSS & 0x400)/ 0x400 * 8 ) |
984 ((md->VBS & 0x400)/ 0x400 * 4 ) |
985 ((VDE & 0x400)/ 0x400 * 2 ) |
986 ((md->VT & 0x400)/ 0x400));
987 WCrt(ba, CRT_ID_MONITOR_POWER, 0x00);
990 unsigned short tmp = rh_CompFQ(md->FQ);
991 WPLL(ba, 2 , tmp);
992 tmp = rh_CompFQ(rh_memclk);
993 WPLL(ba,10 , tmp);
994 WPLL(ba,14 , 0x22);
997 WGfx(ba, GCT_ID_SET_RESET, 0x00);
998 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
999 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
1000 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
1001 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1002 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
1003 if (md->DEP == 4)
1004 WGfx(ba, GCT_ID_MISC, 0x04);
1005 else
1006 WGfx(ba, GCT_ID_MISC, 0x05);
1007 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
1008 WGfx(ba, GCT_ID_BITMASK, 0xff);
1010 vgar(ba, ACT_ADDRESS_RESET);
1011 WAttr(ba, ACT_ID_PALETTE0 , 0x00);
1012 WAttr(ba, ACT_ID_PALETTE1 , 0x01);
1013 WAttr(ba, ACT_ID_PALETTE2 , 0x02);
1014 WAttr(ba, ACT_ID_PALETTE3 , 0x03);
1015 WAttr(ba, ACT_ID_PALETTE4 , 0x04);
1016 WAttr(ba, ACT_ID_PALETTE5 , 0x05);
1017 WAttr(ba, ACT_ID_PALETTE6 , 0x06);
1018 WAttr(ba, ACT_ID_PALETTE7 , 0x07);
1019 WAttr(ba, ACT_ID_PALETTE8 , 0x08);
1020 WAttr(ba, ACT_ID_PALETTE9 , 0x09);
1021 WAttr(ba, ACT_ID_PALETTE10, 0x0a);
1022 WAttr(ba, ACT_ID_PALETTE11, 0x0b);
1023 WAttr(ba, ACT_ID_PALETTE12, 0x0c);
1024 WAttr(ba, ACT_ID_PALETTE13, 0x0d);
1025 WAttr(ba, ACT_ID_PALETTE14, 0x0e);
1026 WAttr(ba, ACT_ID_PALETTE15, 0x0f);
1028 vgar(ba, ACT_ADDRESS_RESET);
1029 if (md->DEP == 4)
1030 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x08);
1031 else
1032 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x09);
1034 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
1035 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
1036 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
1037 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
1039 vgar(ba, ACT_ADDRESS_RESET);
1040 vgaw(ba, ACT_ADDRESS_W, 0x20);
1042 vgaw(ba, VDAC_MASK, 0xff);
1043 /* probably some PLL timing stuff here. The value
1044 for 24bit was found by trial&error :-) */
1045 if (md->DEP < 16) {
1046 vgaw(ba, 0x83c6, ((0 & 7) << 5) );
1048 else if (md->DEP == 16) {
1049 /* well... */
1050 vgaw(ba, 0x83c6, ((3 & 7) << 5) );
1052 else if (md->DEP == 24) {
1053 vgaw(ba, 0x83c6, 0xe0);
1055 vgaw(ba, VDAC_ADDRESS_W, 0x00);
1057 if (md->DEP < 16) {
1058 short x = 256-17;
1059 unsigned char cl = 16;
1060 RZ3LoadPalette(gp, md->PAL, 0, 16);
1061 do {
1062 vgaw(ba, VDAC_DATA, (cl >> 2));
1063 vgaw(ba, VDAC_DATA, (cl >> 2));
1064 vgaw(ba, VDAC_DATA, (cl >> 2));
1065 cl++;
1066 } while (x-- > 0);
1069 if (md->DEP == 4) {
1071 struct grf_bitblt bb = {
1072 GRFBBOPset,
1073 0, 0,
1074 0, 0,
1075 md->TX*4, 2*md->TY,
1076 EMPTY_ALPHA
1078 RZ3BitBlit(gp, &bb);
1081 c = (volatile unsigned short *)((volatile char*)ba + LM_OFFSET);
1082 c += 2 * md->FLo*32;
1083 c += 1;
1084 f = md->FData;
1085 for (z = md->FLo; z <= md->FHi; z++) {
1086 short y = md->FY-1;
1087 if (md->FX > 8){
1088 do {
1089 *c = *((const unsigned short *)f);
1090 c += 2;
1091 f += 2;
1092 } while (y-- > 0);
1093 } else {
1094 do {
1095 *c = (*f++) << 8;
1096 c += 2;
1097 } while (y-- > 0);
1100 c += 2 * (32-md->FY);
1103 volatile unsigned long *pt = (volatile unsigned long *)
1104 ((volatile char *)ba +
1105 LM_OFFSET + PAT_MEM_OFF);
1106 unsigned long tmp = 0xffff0000;
1107 *pt++ = tmp;
1108 *pt = tmp;
1111 WSeq(ba, SEQ_ID_MAP_MASK, 3);
1113 c = (volatile unsigned short *)((volatile char*)ba + LM_OFFSET);
1114 c += (md->TX-6)*2;
1116 /* it's show-time :-) */
1117 static unsigned short init_msg[6] = {
1118 0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f
1120 unsigned short * m = init_msg;
1121 short x = 5;
1122 do {
1123 *c = *m++;
1124 c += 2;
1125 } while (x-- > 0);
1128 return(1);
1129 } else if (md->DEP == 8) {
1130 struct grf_bitblt bb = {
1131 GRFBBOPset,
1132 0, 0,
1133 0, 0,
1134 md->TX, md->TY,
1135 0x0000
1137 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
1139 RZ3BitBlit(gp, &bb);
1141 gi->gd_fbx = 0;
1142 gi->gd_fby = 0;
1144 return(1);
1145 } else if (md->DEP == 16) {
1146 struct grf_bitblt bb = {
1147 GRFBBOPset,
1148 0, 0,
1149 0, 0,
1150 md->TX, md->TY,
1151 0x0000
1153 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
1155 RZ3BitBlit16(gp, &bb);
1157 gi->gd_fbx = 0;
1158 gi->gd_fby = 0;
1160 return(1);
1161 } else if (md->DEP == 24) {
1162 struct grf_bitblt bb = {
1163 GRFBBOPset,
1164 0, 0,
1165 0, 0,
1166 md->TX, md->TY,
1167 0x0000
1169 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f );
1171 RZ3BitBlit24(gp, &bb );
1173 gi->gd_fbx = 0;
1174 gi->gd_fby = 0;
1176 return 1;
1177 } else
1178 return(0);
1181 /* standard-palette definition */
1183 unsigned char RZ3StdPalette[16*3] = {
1184 /* R G B */
1185 0, 0, 0,
1186 192,192,192,
1187 128, 0, 0,
1188 0,128, 0,
1189 0, 0,128,
1190 128,128, 0,
1191 0,128,128,
1192 128, 0,128,
1193 64, 64, 64, /* the higher 8 colors have more intensity for */
1194 255,255,255, /* compatibility with standard attributes */
1195 255, 0, 0,
1196 0,255, 0,
1197 0, 0,255,
1198 255,255, 0,
1199 0,255,255,
1200 255, 0,255
1204 * The following structures are examples for monitor-definitions. To make one
1205 * of your own, first use "DefineMonitor" and create the 8-bit or 16-bit
1206 * monitor-mode of your dreams. Then save it, and make a structure from the
1207 * values provided in the file DefineMonitor stored - the labels in the comment
1208 * above the structure definition show where to put what value.
1210 * If you want to use your definition for the text-mode, you'll need to adapt
1211 * your 8-bit monitor-definition to the font you want to use. Be FX the width of
1212 * the font, then the following modifications have to be applied to your values:
1214 * HBS = (HBS * 4) / FX
1215 * HSS = (HSS * 4) / FX
1216 * HSE = (HSE * 4) / FX
1217 * HBE = (HBE * 4) / FX
1218 * HT = (HT * 4) / FX
1220 * Make sure your maximum width (MW) and height (MH) are even multiples of
1221 * the fonts' width and height.
1223 * You may use definitons created by the old DefineMonitor, but you'll get
1224 * better results with the new DefineMonitor supplied along with the Retin Z3.
1228 * FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT
1229 * Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi
1231 #ifdef KFONT_8X11
1232 #define KERNEL_FONT kernel_font_8x11
1233 #define FY 11
1234 #define FX 8
1235 #else
1236 #define KERNEL_FONT kernel_font_8x8
1237 #define FY 8
1238 #define FX 8
1239 #endif
1242 static struct MonDef monitor_defs[] = {
1243 /* Text-mode definitions */
1245 /* horizontal 31.5 kHz */
1246 { 50000000, 28, 640, 440, 81, 86, 93, 98, 95, 481, 490, 498, 522, 522,
1247 4, RZ3StdPalette, 80, 55, 5120, FX, FY, KERNEL_FONT, 32, 255},
1249 /* horizontal 38kHz */
1250 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638,
1251 4, RZ3StdPalette, 96, 75, 7200, FX, FY, KERNEL_FONT, 32, 255},
1253 /* horizontal 64kHz */
1254 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628,
1255 4, RZ3StdPalette, 96, 75, 7200, FX, FY, KERNEL_FONT, 32, 255},
1257 /* 8-bit gfx-mode definitions */
1259 /* IMPORTANT: the "logical" screen size can be up to 2048x2048 pixels,
1260 independent from the "physical" screen size. If your code does NOT
1261 support panning, please adjust the "logical" screen sizes below to
1262 match the physical ones
1265 #ifdef RH_HARDWARECURSOR
1267 /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
1268 { 26000000, 0, 640, 480, 161,175,188,200,199, 481, 483, 491, 502, 502,
1269 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1270 /* This is the logical ^ ^ screen size */
1272 /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
1273 { 31000000, 0, 640, 480, 161,169,182,198,197, 481, 482, 490, 502, 502,
1274 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1276 /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
1277 { 39000000, 0, 800, 600, 201,211,227,249,248, 601, 603, 613, 628, 628,
1278 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1280 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1281 { 62000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
1282 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1284 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1285 { 77000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
1286 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1288 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1289 { 82000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
1290 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1292 /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
1293 { 97000000, 0, 1120, 896, 281,283,306,369,368, 897, 898, 913, 938, 938,
1294 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1296 /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
1297 {110000000, 0, 1152, 910, 289,310,333,357,356, 911, 923, 938, 953, 953,
1298 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1300 /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
1301 {110000000, 0, 1184, 848, 297,319,342,370,369, 849, 852, 866, 888, 888,
1302 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1304 /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
1305 {104000000, 0, 1280,1024, 321,323,348,399,398,1025,1026,1043,1073,1073,
1306 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1309 * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1310 * HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1311 * MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1313 /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
1314 {121000000, 0, 1280,1024, 321,322,347,397,396,1025,1026,1043,1073,1073,
1315 8, RZ3StdPalette,1280,1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1318 /* 16-bit gfx-mode definitions */
1320 /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
1321 { 51000000, 0, 640, 480, 321,344,369,397,396, 481, 482, 490, 502, 502,
1322 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1324 /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
1325 { 77000000, 0, 800, 600, 401,418,449,496,495, 601, 602, 612, 628, 628,
1326 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1328 /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
1329 {110000000, 0, 1024, 768, 513,514,554,639,638, 769, 770, 783, 804, 804,
1330 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1332 /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
1333 {109000000, 0, 864, 648, 433,434,468,537,536, 649, 650, 661, 678, 678,
1334 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1337 * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1338 * HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1339 * MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1341 /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
1342 {124000000, 0, 1024, 768, 513,537,577,636,635, 769, 770, 783, 804, 804,
1343 16, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1346 /* 24-bit gfx-mode definitions */
1348 /* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
1349 { 46000000, 1, 320, 200, 241,268,287,324,323, 401, 405, 412, 418, 418,
1350 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1352 /* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
1353 { 76000000, 0, 640, 400, 481,514,552,601,600, 401, 402, 409, 418, 418,
1354 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1356 /* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
1357 {101000000, 0, 724, 482, 544,576,619,682,678, 483, 487, 495, 495, 504,
1358 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1360 /* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
1361 {110000000, 0, 800, 600, 601,602,647,723,722, 601, 602, 612, 628, 628,
1362 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1364 /* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
1365 {132000000, 0, 800, 600, 601,641,688,749,748, 601, 611, 621, 628, 628,
1366 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1368 /*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
1369 {110000000, 2, 1024, 768, 769,770,824,854,853, 385, 386, 392, 401, 401,
1370 24, 0,1280, 1024, 7200, FX, FY, KERNEL_FONT, 32, 255},
1372 #else /* RH_HARDWARECURSOR */
1374 /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */
1375 { 26000000, 0, 640, 480, 161,175,188,200,199, 481, 483, 491, 502, 502,
1376 8, RZ3StdPalette, 640, 480, 5120, FX, FY, KERNEL_FONT, 32, 255},
1377 /* This is the logical ^ ^ screen size */
1379 /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */
1380 { 31000000, 0, 640, 480, 161,169,182,198,197, 481, 482, 490, 502, 502,
1381 8, RZ3StdPalette, 640, 480, 5120, FX, FY, KERNEL_FONT, 32, 255},
1383 /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */
1384 { 39000000, 0, 800, 600, 201,211,227,249,248, 601, 603, 613, 628, 628,
1385 8, RZ3StdPalette, 800, 600, 5120, FX, FY, KERNEL_FONT, 32, 255},
1387 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1388 { 62000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
1389 8, RZ3StdPalette, 1024, 768, 5120, FX, FY, KERNEL_FONT, 32, 255},
1391 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1392 { 77000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
1393 8, RZ3StdPalette, 1024, 768, 5120, FX, FY, KERNEL_FONT, 32, 255},
1395 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */
1396 { 82000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804,
1397 8, RZ3StdPalette, 1024, 768, 5120, FX, FY, KERNEL_FONT, 32, 255},
1399 /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */
1400 { 97000000, 0, 1120, 896, 281,283,306,369,368, 897, 898, 913, 938, 938,
1401 8, RZ3StdPalette, 1120, 896, 5120, FX, FY, KERNEL_FONT, 32, 255},
1403 /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */
1404 {110000000, 0, 1152, 910, 289,310,333,357,356, 911, 923, 938, 953, 953,
1405 8, RZ3StdPalette, 1152, 910, 5120, FX, FY, KERNEL_FONT, 32, 255},
1407 /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */
1408 {110000000, 0, 1184, 848, 297,319,342,370,369, 849, 852, 866, 888, 888,
1409 8, RZ3StdPalette, 1184, 848, 5120, FX, FY, KERNEL_FONT, 32, 255},
1411 /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */
1412 {104000000, 0, 1280,1024, 321,323,348,399,398,1025,1026,1043,1073,1073,
1413 8, RZ3StdPalette, 1280, 1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1416 * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1417 * HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1418 * MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1420 /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */
1421 {121000000, 0, 1280,1024, 321,322,347,397,396,1025,1026,1043,1073,1073,
1422 8, RZ3StdPalette, 1280, 1024, 5120, FX, FY, KERNEL_FONT, 32, 255},
1425 /* 16-bit gfx-mode definitions */
1427 /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */
1428 { 51000000, 0, 640, 480, 321,344,369,397,396, 481, 482, 490, 502, 502,
1429 16, 0, 640, 480, 7200, FX, FY, KERNEL_FONT, 32, 255},
1431 /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */
1432 { 77000000, 0, 800, 600, 401,418,449,496,495, 601, 602, 612, 628, 628,
1433 16, 0, 800, 600, 7200, FX, FY, KERNEL_FONT, 32, 255},
1435 /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */
1436 {110000000, 0, 1024, 768, 513,514,554,639,638, 769, 770, 783, 804, 804,
1437 16, 0, 1024, 768, 7200, FX, FY, KERNEL_FONT, 32, 255},
1439 /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */
1440 {109000000, 0, 864, 648, 433,434,468,537,536, 649, 650, 661, 678, 678,
1441 16, 0, 864, 648, 7200, FX, FY, KERNEL_FONT, 32, 255},
1444 * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR
1445 * HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT
1446 * MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)!
1448 /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */
1449 {124000000, 0, 1024, 768, 513,537,577,636,635, 769, 770, 783, 804, 804,
1450 16, 0, 1024, 768, 7200, FX, FY, KERNEL_FONT, 32, 255},
1453 /* 24-bit gfx-mode definitions */
1455 /* 320 x 200, 24 Bit, 35060 Hz, 83 Hz d */
1456 { 46000000, 1, 320, 200, 241,268,287,324,323, 401, 405, 412, 418, 418,
1457 24, 0, 320, 200, 7200, FX, FY, KERNEL_FONT, 32, 255},
1459 /* 640 x 400, 24 Bit, 31404 Hz, 75 Hz */
1460 { 76000000, 0, 640, 400, 481,514,552,601,600, 401, 402, 409, 418, 418,
1461 24, 0, 640, 400, 7200, FX, FY, KERNEL_FONT, 32, 255},
1463 /* 724 x 482, 24 Bit, 36969 Hz, 73 Hz */
1464 {101000000, 0, 724, 482, 544,576,619,682,678, 483, 487, 495, 495, 504,
1465 24, 0, 724, 482, 7200, FX, FY, KERNEL_FONT, 32, 255},
1467 /* 800 x 600, 24 Bit, 37826 Hz, 60 Hz */
1468 {110000000, 0, 800, 600, 601,602,647,723,722, 601, 602, 612, 628, 628,
1469 24, 0, 800, 600, 7200, FX, FY, KERNEL_FONT, 32, 255},
1471 /* 800 x 600, 24 Bit, 43824 Hz, 69 Hz */
1472 {132000000, 0, 800, 600, 601,641,688,749,748, 601, 611, 621, 628, 628,
1473 24, 0, 800, 600, 7200, FX, FY, KERNEL_FONT, 32, 255},
1475 /*1024 x 768, 24 Bit, 32051 Hz, 79 Hz i */
1476 {110000000, 2, 1024, 768, 769,770,824,854,853, 385, 386, 392, 401, 401,
1477 24, 0, 1024, 768, 7200, FX, FY, KERNEL_FONT, 32, 255},
1479 #endif /* RH_HARDWARECURSOR */
1481 #undef KERNEL_FONT
1482 #undef FX
1483 #undef FY
1485 static const char *monitor_descr[] = {
1486 #ifdef KFONT_8X11
1487 "80x46 (640x506) 31.5kHz",
1488 "96x54 (768x594) 38kHz",
1489 "96x54 (768x594) 64kHz",
1490 #else
1491 "80x64 (640x512) 31.5kHz",
1492 "96x75 (768x600) 38kHz",
1493 "96x75 (768x600) 64kHz",
1494 #endif
1496 "GFX-8 (640x480) 31.5kHz",
1497 "GFX-8 (640x480) 38kHz",
1498 "GFX-8 (800x600) 38.5kHz",
1499 "GFX-8 (1024x768) 44kHz",
1500 "GFX-8 (1024x768) 50kHz",
1501 "GFX-8 (1024x768) 64kHz",
1502 "GFX-8 (1120x896) 64kHz",
1503 "GFX-8 (1152x910) 76kHz",
1504 "GFX-8 (1182x848) 73kHz",
1505 "GFX-8 (1280x1024) 64.5kHz",
1506 "GFX-8 (1280x1024) 75.5kHz ***EXCEEDS CHIP LIMIT!!!***",
1508 "GFX-16 (640x480) 31.8kHz",
1509 "GFX-16 (800x600) 38.5kHz",
1510 "GFX-16 (1024x768) 42.8kHz",
1511 "GFX-16 (864x648) 50kHz",
1512 "GFX-16 (1024x768) 48.5kHz ***EXCEEDS CHIP LIMIT!!!***",
1514 "GFX-24 (320x200 d) 35kHz",
1515 "GFX-24 (640x400) 31.4kHz",
1516 "GFX-24 (724x482) 37kHz",
1517 "GFX-24 (800x600) 38kHz",
1518 "GFX-24 (800x600) 44kHz ***EXCEEDS CHIP LIMIT!!!***",
1519 "GFX-24 (1024x768) 32kHz-i",
1522 int rh_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]);
1524 /* patchable */
1525 int rh_default_mon = 0;
1526 int rh_default_gfx = 4;
1528 static struct MonDef *current_mon; /* EVIL */
1530 int rh_mode(struct grf_softc *, u_long, void *, u_long, int);
1531 void grfrhattach(struct device *, struct device *, void *);
1532 int grfrhprint(void *, const char *);
1533 int grfrhmatch(struct device *, struct cfdata *, void *);
1535 CFATTACH_DECL(grfrh, sizeof(struct grf_softc),
1536 grfrhmatch, grfrhattach, NULL, NULL);
1538 static struct cfdata *cfdata;
1541 grfrhmatch(struct device *pdp, struct cfdata *cfp, void *auxp)
1543 #ifdef RETINACONSOLE
1544 static int rhconunit = -1;
1545 #endif
1546 struct zbus_args *zap;
1548 zap = auxp;
1550 if (amiga_realconfig == 0)
1551 #ifdef RETINACONSOLE
1552 if (rhconunit != -1)
1553 #endif
1554 return(0);
1555 if (zap->manid != 18260 ||
1556 ((zap->prodid != 16) && (zap->prodid != 19)))
1557 return(0);
1558 #ifdef RETINACONSOLE
1559 if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) {
1560 #endif
1561 if ((unsigned)rh_default_mon >= rh_mon_max ||
1562 monitor_defs[rh_default_mon].DEP == 8)
1563 rh_default_mon = 0;
1564 current_mon = monitor_defs + rh_default_mon;
1565 if (rh_mondefok(current_mon) == 0)
1566 return(0);
1567 #ifdef RETINACONSOLE
1568 if (amiga_realconfig == 0) {
1569 rhconunit = cfp->cf_unit;
1570 cfdata = cfp;
1573 #endif
1574 return(1);
1577 void
1578 grfrhattach(struct device *pdp, struct device *dp, void *auxp)
1580 static struct grf_softc congrf;
1581 struct zbus_args *zap;
1582 struct grf_softc *gp;
1584 zap = auxp;
1586 if (dp == NULL)
1587 gp = &congrf;
1588 else
1589 gp = (struct grf_softc *)dp;
1590 if (dp != NULL && congrf.g_regkva != 0) {
1592 * inited earlier, just copy (not device struct)
1594 memcpy(&gp->g_display, &congrf.g_display,
1595 (char *)&gp[1] - (char *)&gp->g_display);
1596 } else {
1597 gp->g_regkva = (volatile void *)zap->va;
1598 gp->g_fbkva = (volatile char *)zap->va + LM_OFFSET;
1599 gp->g_unit = GRF_RETINAIII_UNIT;
1600 gp->g_mode = rh_mode;
1601 gp->g_conpri = grfrh_cnprobe();
1602 gp->g_flags = GF_ALIVE;
1603 grfrh_iteinit(gp);
1604 (void)rh_load_mon(gp, current_mon);
1606 if (dp != NULL)
1607 printf("\n");
1609 * attach grf
1611 amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint);
1615 grfrhprint(void *auxp, const char *pnp)
1617 if (pnp)
1618 aprint_normal("ite at %s", pnp);
1619 return(UNCONF);
1623 rh_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
1625 struct MonDef *md;
1626 int vmul;
1628 if (vm->mode_num && vm->mode_num > rh_mon_max)
1629 return(EINVAL);
1631 if (! vm->mode_num)
1632 vm->mode_num = (current_mon - monitor_defs) + 1;
1634 md = monitor_defs + (vm->mode_num - 1);
1635 strncpy (vm->mode_descr, monitor_descr[vm->mode_num - 1],
1636 sizeof (vm->mode_descr));
1637 vm->pixel_clock = md->FQ;
1638 vm->disp_width = (md->DEP == 4) ? md->MW : md->TX;
1639 vm->disp_height = (md->DEP == 4) ? md->MH : md->TY;
1640 vm->depth = md->DEP;
1643 * From observation of the monitor definition table above, I guess
1644 * that the horizontal timings are in units of longwords. Hence, I
1645 * get the pixels by multiplication with 32 and division by the depth.
1646 * The text modes, apparently marked by depth == 4, are even more
1647 * weird. According to a comment above, they are computed from a
1648 * depth==8 mode thats for us: * 32 / 8) by applying another factor
1649 * of 4 / font width.
1650 * Reverse applying the latter formula most of the constants cancel
1651 * themselves and we are left with a nice (* font width).
1652 * That is, internal timings are in units of longwords for graphics
1653 * modes, or in units of characters widths for text modes.
1654 * We better don't WRITE modes until this has been real live checked.
1655 * - Ignatios Souvatzis
1658 if (md->DEP != 4) {
1659 vm->hblank_start = md->HBS * 32 / md->DEP;
1660 vm->hsync_start = md->HSS * 32 / md->DEP;
1661 vm->hsync_stop = md->HSE * 32 / md->DEP;
1662 vm->htotal = md->HT * 32 / md->DEP;
1663 } else {
1664 vm->hblank_start = md->HBS * md->FX;
1665 vm->hsync_start = md->HSS * md->FX;
1666 vm->hsync_stop = md->HSE * md->FX;
1667 vm->htotal = md->HT * md->FX;
1670 /* XXX move vm->disp_flags and vmul to rh_load_mon
1671 * if rh_setvmode can add new modes with grfconfig */
1672 vm->disp_flags = 0;
1673 vmul = 2;
1674 if (md->FLG & MDF_DBL) {
1675 vm->disp_flags |= GRF_FLAGS_DBLSCAN;
1676 vmul = 4;
1678 if (md->FLG & MDF_LACE) {
1679 vm->disp_flags |= GRF_FLAGS_LACE;
1680 vmul = 1;
1682 vm->vblank_start = md->VBS * vmul / 2;
1683 vm->vsync_start = md->VSS * vmul / 2;
1684 vm->vsync_stop = md->VSE * vmul / 2;
1685 vm->vtotal = md->VT * vmul / 2;
1687 return(0);
1692 rh_setvmode(struct grf_softc *gp, unsigned mode, enum mode_type type)
1694 int error;
1696 if (!mode || mode > rh_mon_max)
1697 return(EINVAL);
1699 if ((type == MT_TXTONLY && monitor_defs[mode-1].DEP != 4)
1700 || (type == MT_GFXONLY && monitor_defs[mode-1].DEP == 4))
1701 return(EINVAL);
1703 current_mon = monitor_defs + (mode - 1);
1705 error = rh_load_mon (gp, current_mon) ? 0 : EINVAL;
1707 return(error);
1712 * Change the mode of the display.
1713 * Return a UNIX error number or 0 for success.
1716 rh_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
1717 int a3)
1719 switch (cmd) {
1720 case GM_GRFON:
1721 rh_setvmode (gp, rh_default_gfx + 1, MT_GFXONLY);
1722 return(0);
1724 case GM_GRFOFF:
1725 rh_setvmode (gp, rh_default_mon + 1, MT_TXTONLY);
1726 return(0);
1728 case GM_GRFCONFIG:
1729 return(0);
1731 case GM_GRFGETVMODE:
1732 return(rh_getvmode (gp, (struct grfvideo_mode *) arg));
1734 case GM_GRFSETVMODE:
1735 return(rh_setvmode(gp, *(unsigned *) arg,
1736 (gp->g_flags & GF_GRFON) ? MT_GFXONLY : MT_TXTONLY));
1738 case GM_GRFGETNUMVM:
1739 *(int *)arg = rh_mon_max;
1740 return(0);
1742 case GM_GRFIOCTL:
1743 return(rh_ioctl (gp, a2, arg));
1745 default:
1746 break;
1749 return(EPASSTHROUGH);
1753 rh_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
1755 switch (cmd) {
1756 #ifdef RH_HARDWARECURSOR
1757 case GRFIOCGSPRITEPOS:
1758 return(rh_getspritepos (gp, (struct grf_position *) data));
1760 case GRFIOCSSPRITEPOS:
1761 return(rh_setspritepos (gp, (struct grf_position *) data));
1763 case GRFIOCSSPRITEINF:
1764 return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data));
1766 case GRFIOCGSPRITEINF:
1767 return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data));
1769 case GRFIOCGSPRITEMAX:
1770 return(rh_getspritemax (gp, (struct grf_position *) data));
1771 #else /* RH_HARDWARECURSOR */
1772 case GRFIOCGSPRITEPOS:
1773 case GRFIOCSSPRITEPOS:
1774 case GRFIOCSSPRITEINF:
1775 case GRFIOCGSPRITEMAX:
1776 break;
1777 #endif /* RH_HARDWARECURSOR */
1779 case GRFIOCGETCMAP:
1780 return(rh_getcmap (gp, (struct grf_colormap *) data));
1782 case GRFIOCPUTCMAP:
1783 return(rh_putcmap (gp, (struct grf_colormap *) data));
1785 case GRFIOCBITBLT:
1786 return(rh_bitblt (gp, (struct grf_bitblt *) data));
1788 case GRFIOCBLANK:
1789 return (rh_blank(gp, (int *)data));
1792 return(EPASSTHROUGH);
1797 rh_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1799 volatile unsigned char *ba;
1800 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1801 short x;
1802 int error;
1804 if (cmap->count == 0 || cmap->index >= 256)
1805 return 0;
1807 if (cmap->count > 256 - cmap->index)
1808 cmap->count = 256 - cmap->index;
1810 ba = gfp->g_regkva;
1811 /* first read colors out of the chip, then copyout to userspace */
1812 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1813 x = cmap->count - 1;
1814 rp = red + cmap->index;
1815 gp = green + cmap->index;
1816 bp = blue + cmap->index;
1817 do {
1818 *rp++ = vgar (ba, VDAC_DATA) << 2;
1819 *gp++ = vgar (ba, VDAC_DATA) << 2;
1820 *bp++ = vgar (ba, VDAC_DATA) << 2;
1821 } while (x-- > 0);
1823 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
1824 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
1825 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
1826 return(0);
1828 return(error);
1832 rh_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1834 volatile unsigned char *ba;
1835 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1836 short x;
1837 int error;
1839 if (cmap->count == 0 || cmap->index >= 256)
1840 return(0);
1842 if (cmap->count > 256 - cmap->index)
1843 cmap->count = 256 - cmap->index;
1845 /* first copy the colors into kernelspace */
1846 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1847 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1848 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
1849 /* argl.. LoadPalette wants a different format, so do it like with
1850 * Retina2.. */
1851 ba = gfp->g_regkva;
1852 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1853 x = cmap->count - 1;
1854 rp = red + cmap->index;
1855 gp = green + cmap->index;
1856 bp = blue + cmap->index;
1857 do {
1858 vgaw (ba, VDAC_DATA, *rp++ >> 2);
1859 vgaw (ba, VDAC_DATA, *gp++ >> 2);
1860 vgaw (ba, VDAC_DATA, *bp++ >> 2);
1861 } while (x-- > 0);
1862 return(0);
1864 else
1865 return(error);
1869 rh_getspritepos(struct grf_softc *gp, struct grf_position *pos)
1871 struct grfinfo *gi = &gp->g_display;
1872 #if 1
1873 volatile unsigned char *ba = gp->g_regkva;
1875 pos->x = (RSeq(ba, SEQ_ID_CURSOR_X_LOC_HI) << 8) |
1876 RSeq(ba, SEQ_ID_CURSOR_X_LOC_LO);
1877 pos->y = (RSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI) << 8) |
1878 RSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO);
1879 #else
1880 volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET;
1882 pos->x = acm[ACM_CURSOR_POSITION + 0] +
1883 (acm[ACM_CURSOR_POSITION + 1] << 8);
1884 pos->y = acm[ACM_CURSOR_POSITION + 2] +
1885 (acm[ACM_CURSOR_POSITION + 3] << 8);
1886 #endif
1887 pos->x += gi->gd_fbx;
1888 pos->y += gi->gd_fby;
1890 return(0);
1894 rh_setspritepos (struct grf_softc *gp, struct grf_position *pos)
1896 RZ3SetHWCloc (gp, pos->x, pos->y);
1897 return(0);
1901 rh_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
1903 volatile unsigned char *ba, *fb;
1905 ba = gp->g_regkva;
1906 fb = gp->g_fbkva;
1907 if (info->set & GRFSPRSET_ENABLE)
1908 info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01;
1909 if (info->set & GRFSPRSET_POS)
1910 rh_getspritepos (gp, &info->pos);
1911 if (info->set & GRFSPRSET_HOT) {
1912 info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f;
1913 info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f;
1915 if (info->set & GRFSPRSET_CMAP) {
1916 struct grf_colormap cmap;
1917 int index;
1918 cmap.index = 0;
1919 cmap.count = 256;
1920 rh_getcmap (gp, &cmap);
1921 index = RSeq (ba, SEQ_ID_CURSOR_COLOR0);
1922 info->cmap.red[0] = cmap.red[index];
1923 info->cmap.green[0] = cmap.green[index];
1924 info->cmap.blue[0] = cmap.blue[index];
1925 index = RSeq (ba, SEQ_ID_CURSOR_COLOR1);
1926 info->cmap.red[1] = cmap.red[index];
1927 info->cmap.green[1] = cmap.green[index];
1928 info->cmap.blue[1] = cmap.blue[index];
1930 if (info->set & GRFSPRSET_SHAPE) {
1931 u_char image[128], mask[128];
1932 volatile u_long *hwp;
1933 u_char *imp, *mp;
1934 short row;
1936 /* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h
1937 * for an explanation. To convert to "our" format, the
1938 * following holds:
1939 * col2 = !image & mask
1940 * col1 = image & mask
1941 * transp = !mask
1942 * and thus:
1943 * image = col1
1944 * mask = col1 | col2
1945 * hope I got these bool-eqs right below..
1948 #ifdef RH_64BIT_SPRITE
1949 info->size.x = 64;
1950 info->size.y = 64;
1951 for (row = 0,
1952 hwp = (volatile u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
1953 mp = mask, imp = image;
1954 row < 64;
1955 row++) {
1956 u_long bp10, bp20, bp11, bp21;
1957 bp10 = *hwp++;
1958 bp20 = *hwp++;
1959 bp11 = *hwp++;
1960 bp21 = *hwp++;
1961 M2I (bp10);
1962 M2I (bp20);
1963 M2I (bp11);
1964 M2I (bp21);
1965 *imp++ = (~bp10) & bp11;
1966 *imp++ = (~bp20) & bp21;
1967 *mp++ = (~bp10) | (bp10 & ~bp11);
1968 *mp++ = (~bp20) & (bp20 & ~bp21);
1970 #else
1971 info->size.x = 32;
1972 info->size.y = 32;
1973 for (row = 0,
1974 hwp = (volatile u_long *)(ba + LM_OFFSET + HWC_MEM_OFF),
1975 mp = mask, imp = image;
1976 row < 32;
1977 row++) {
1978 u_long bp10, bp11;
1979 bp10 = *hwp++;
1980 bp11 = *hwp++;
1981 M2I (bp10);
1982 M2I (bp11);
1983 *imp++ = (~bp10) & bp11;
1984 *mp++ = (~bp10) | (bp10 & ~bp11);
1986 #endif
1987 copyout (image, info->image, sizeof (image));
1988 copyout (mask, info->mask, sizeof (mask));
1990 return(0);
1994 rh_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
1996 volatile unsigned char *ba, *fb;
1997 #if 0
1998 u_char control;
1999 #endif
2001 ba = gp->g_regkva;
2002 fb = gp->g_fbkva;
2004 if (info->set & GRFSPRSET_SHAPE) {
2006 * For an explanation of these weird actions here, see above
2007 * when reading the shape. We set the shape directly into
2008 * the video memory, there's no reason to keep 1k on the
2009 * kernel stack just as template
2011 u_char *image, *mask;
2012 volatile u_long *hwp;
2013 u_char *imp, *mp;
2014 short row;
2016 #ifdef RH_64BIT_SPRITE
2017 if (info->size.y > 64)
2018 info->size.y = 64;
2019 if (info->size.x > 64)
2020 info->size.x = 64;
2021 #else
2022 if (info->size.y > 32)
2023 info->size.y = 32;
2024 if (info->size.x > 32)
2025 info->size.x = 32;
2026 #endif
2028 if (info->size.x < 32)
2029 info->size.x = 32;
2031 image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK);
2032 mask = image + HWC_MEM_SIZE/2;
2034 copyin(info->image, image, info->size.y * info->size.x / 8);
2035 copyin(info->mask, mask, info->size.y * info->size.x / 8);
2037 hwp = (volatile u_long *)(ba + LM_OFFSET + HWC_MEM_OFF);
2040 * setting it is slightly more difficult, because we can't
2041 * force the application to not pass a *smaller* than
2042 * supported bitmap
2045 for (row = 0, mp = mask, imp = image;
2046 row < info->size.y;
2047 row++) {
2048 u_long im1, im2, m1, m2;
2050 im1 = *(unsigned long *)imp;
2051 imp += 4;
2052 m1 = *(unsigned long *)mp;
2053 mp += 4;
2054 #ifdef RH_64BIT_SPRITE
2055 if (info->size.x > 32) {
2056 im2 = *(unsigned long *)imp;
2057 imp += 4;
2058 m2 = *(unsigned long *)mp;
2059 mp += 4;
2061 else
2062 #endif
2063 im2 = m2 = 0;
2065 M2I(im1);
2066 M2I(im2);
2067 M2I(m1);
2068 M2I(m2);
2070 *hwp++ = ~m1;
2071 #ifdef RH_64BIT_SPRITE
2072 *hwp++ = ~m2;
2073 #endif
2074 *hwp++ = m1 & im1;
2075 #ifdef RH_64BIT_SPRITE
2076 *hwp++ = m2 & im2;
2077 #endif
2079 #ifdef RH_64BIT_SPRITE
2080 for (; row < 64; row++) {
2081 *hwp++ = 0xffffffff;
2082 *hwp++ = 0xffffffff;
2083 *hwp++ = 0x00000000;
2084 *hwp++ = 0x00000000;
2086 #else
2087 for (; row < 32; row++) {
2088 *hwp++ = 0xffffffff;
2089 *hwp++ = 0x00000000;
2091 #endif
2093 free(image, M_TEMP);
2094 RZ3SetupHWC(gp, 1, 0, 0, 0, 0);
2096 if (info->set & GRFSPRSET_CMAP) {
2097 /* hey cheat a bit here.. XXX */
2098 WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0);
2099 WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1);
2101 if (info->set & GRFSPRSET_ENABLE) {
2102 #if 0
2103 if (info->enable)
2104 control = 0x85;
2105 else
2106 control = 0;
2107 WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
2108 #endif
2110 if (info->set & GRFSPRSET_POS)
2111 rh_setspritepos(gp, &info->pos);
2112 if (info->set & GRFSPRSET_HOT) {
2113 WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f);
2114 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f);
2117 return(0);
2121 rh_getspritemax(struct grf_softc *gp, struct grf_position *pos)
2123 #ifdef RH_64BIT_SPRITE
2124 pos->x = 64;
2125 pos->y = 64;
2126 #else
2127 pos->x = 32;
2128 pos->y = 32;
2129 #endif
2131 return(0);
2136 rh_bitblt(struct grf_softc *gp, struct grf_bitblt *bb)
2138 struct MonDef *md = (struct MonDef *)gp->g_data;
2139 if (md->DEP <= 8)
2140 RZ3BitBlit(gp, bb);
2141 else if (md->DEP <= 16)
2142 RZ3BitBlit16(gp, bb);
2143 else
2144 RZ3BitBlit24(gp, bb);
2146 return(0);
2151 rh_blank(struct grf_softc *gp, int *on)
2153 struct MonDef *md = (struct MonDef *)gp->g_data;
2154 int r;
2156 r = 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8);
2158 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? r : 0x21);
2160 return(0);
2163 #endif /* NGRF */