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