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