grf_cv.c revision 1.11 1 /* $NetBSD: grf_cv.c,v 1.11 1996/03/17 05:58:36 mhitch Exp $ */
2
3 /*
4 * Copyright (c) 1995 Michael Teske
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Ezra Story, by Kari
18 * Mettinen and by Bernd Ernesti.
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 "grfcv.h"
34 #if NGRFCV > 0
35
36 /*
37 * Graphics routines for the CyberVision 64 board, using the S3 Trio64.
38 *
39 * Modified for CV64 from
40 * Kari Mettinen's Cirrus driver by Michael Teske 10/95
41 * For questions mail me at teske (at) dice2.desy.de
42 *
43 * Thanks to Tekelec Airtronic for providing me with a S3 Trio64 documentation.
44 * Thanks to Bernd 'the fabulous bug-finder' Ernesti for bringing my messy
45 * source to NetBSD style :)
46 *
47 * TODO:
48 * Hardware Cursor support
49 */
50
51 #include <sys/param.h>
52 #include <sys/errno.h>
53 #include <sys/ioctl.h>
54 #include <sys/device.h>
55 #include <sys/malloc.h>
56 #include <sys/systm.h>
57 #include <machine/cpu.h>
58 #include <dev/cons.h>
59 #include <amiga/dev/itevar.h>
60 #include <amiga/amiga/device.h>
61 #include <amiga/dev/grfioctl.h>
62 #include <amiga/dev/grfvar.h>
63 #include <amiga/dev/grf_cvreg.h>
64 #include <amiga/dev/zbusvar.h>
65
66 int grfcvmatch __P((struct device *, void *, void *));
67 void grfcvattach __P((struct device *, struct device *, void *));
68 int grfcvprint __P((void *, char *));
69
70 static int cv_has_4mb __P((volatile caddr_t));
71 static unsigned short compute_clock __P((unsigned long));
72 void cv_boardinit __P((struct grf_softc *));
73 int cv_getvmode __P((struct grf_softc *, struct grfvideo_mode *));
74 int cv_setvmode __P((struct grf_softc *, unsigned int));
75 int cv_blank __P((struct grf_softc *, int *));
76 int cv_mode __P((register struct grf_softc *, int, void *, int, int));
77 int cv_ioctl __P((register struct grf_softc *gp, int cmd, void *data));
78 int cv_setmonitor __P((struct grf_softc *, struct grfvideo_mode *));
79 int cv_getcmap __P((struct grf_softc *, struct grf_colormap *));
80 int cv_putcmap __P((struct grf_softc *, struct grf_colormap *));
81 int cv_toggle __P((struct grf_softc *));
82 int cv_mondefok __P((struct grfvideo_mode *));
83 int cv_load_mon __P((struct grf_softc *, struct grfcvtext_mode *));
84 void cv_inittextmode __P((struct grf_softc *));
85 void cv_memset __P((unsigned char *, unsigned char, int));
86 static inline void cv_write_port __P((unsigned short, volatile caddr_t));
87 static inline void cvscreen __P((int, volatile caddr_t));
88 static inline void gfx_on_off __P((int, volatile caddr_t));
89
90 /* Graphics display definitions.
91 * These are filled by 'grfconfig' using GRFIOCSETMON.
92 */
93 #define monitor_def_max 24
94 static struct grfvideo_mode monitor_def[24] = {
95 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
96 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
97 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
98 };
99 static struct grfvideo_mode *monitor_current = &monitor_def[0];
100 #define MAXPIXELCLOCK 135000000 /* safety */
101
102
103 /* Console display definition.
104 * Default hardcoded text mode. This grf_cv is set up to
105 * use one text mode only, and this is it. You may use
106 * grfconfig to change the mode after boot.
107 */
108
109 /* Console font */
110 #ifdef KFONT_8X11
111 #define S3FONT kernel_font_8x11
112 #define S3FONTY 11
113 #else
114 #define S3FONT kernel_font_8x8
115 #define S3FONTY 8
116 #endif
117 extern unsigned char S3FONT[];
118
119 /*
120 * Define default console mode
121 * (Internally, we still have to use hvalues/8!)
122 */
123 struct grfcvtext_mode cvconsole_mode = {
124 {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
125 481, 521, 491, 493, 525},
126 8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255
127 };
128
129 /* Console colors */
130 unsigned char cvconscolors[4][3] = { /* background, foreground, hilite */
131 {0x30, 0x30, 0x30}, {0, 0, 0}, {0x18, 0x20, 0x34}, {0x2a, 0x2a, 0x2a}
132 };
133
134 static unsigned char clocks[]={
135 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
136 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
137 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
138 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
139 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
140 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
141 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
142 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
143 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
144 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
145 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
146 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
147 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
148 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
149 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
150 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
151 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
152 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
153 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
154 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
155 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
156 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
157 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
158 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
159 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
160 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
161 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
162 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
163 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
164 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
165 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
166 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
167 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
168 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
169 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
170 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
171 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
172 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
173 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
174 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
175 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
176 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
177 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
178 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
179 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
180 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
181 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
182 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
183 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
184 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
185 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
186 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
187 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
188 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
189 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
190 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
191 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
192 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
193 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
194 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
195 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
196 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
197 };
198
199
200 /* Board Address of CV64 */
201 static volatile caddr_t cv_boardaddr;
202 static int cv_fbsize;
203
204 /*
205 * Memory clock (binpatchable).
206 * Let's be defensive: 45 MHz runs on all boards I know of.
207 * 55 MHz runs on most boards. But you should know what you're doing
208 * if you set this flag. Again: This flag may destroy your CV Board.
209 * Use it at your own risk!!!
210 * Anyway, this doesn't imply that I'm responsible if your board breaks
211 * without setting this flag :-).
212 */
213 #ifdef CV_AGGRESSIVE_TIMING
214 long cv_memclk = 55000000;
215 #else
216 long cv_memclk = 45000000;
217 #endif
218
219 /* standard driver stuff */
220 struct cfattach grfcv_ca = {
221 sizeof(struct grf_softc), grfcvmatch, grfcvattach
222 };
223
224 struct cfdriver grfcv_cd = {
225 NULL, "grfcv", DV_DULL, NULL, 0
226 };
227 static struct cfdata *cfdata;
228
229
230 /*
231 * Get frambuffer memory size.
232 * phase5 didn't provide the bit in CR36,
233 * so we have to do it this way.
234 * Return 0 for 2MB, 1 for 4MB
235 */
236 static int
237 cv_has_4mb(fb)
238 volatile caddr_t fb;
239 {
240 volatile unsigned long *testfbw, *testfbr;
241
242 /* write patterns in memory and test if they can be read */
243 testfbw = (volatile unsigned long *)fb;
244 testfbr = (volatile unsigned long *)(fb + 0x02000000);
245 *testfbw = 0x87654321;
246 if (*testfbr != 0x87654321)
247 return (0);
248
249 /* upper memory region */
250 testfbw = (volatile unsigned long *)(fb + 0x00200000);
251 testfbr = (volatile unsigned long *)(fb + 0x02200000);
252 *testfbw = 0x87654321;
253 if (*testfbr != 0x87654321)
254 return (0);
255 *testfbw = 0xAAAAAAAA;
256 if (*testfbr != 0xAAAAAAAA)
257 return (0);
258 *testfbw = 0x55555555;
259 if (*testfbr != 0x55555555)
260 return (0);
261 return (1);
262 }
263
264 int
265 grfcvmatch(pdp, match, auxp)
266 struct device *pdp;
267 void *match, *auxp;
268 {
269 struct cfdata *cfp = match;
270 struct zbus_args *zap;
271 static int cvcons_unit = -1;
272
273 zap = auxp;
274
275 if (amiga_realconfig == 0)
276 #ifdef CV64CONSOLE
277 if (cvcons_unit != -1)
278 #endif
279 return (0);
280
281 /* Lets be Paranoid: Test man and prod id */
282 if (zap->manid != 8512 || zap->prodid != 34)
283 return (0);
284
285 cv_boardaddr = zap->va;
286
287 #ifdef CV64CONSOLE
288 if (amiga_realconfig == 0) {
289 cvcons_unit = cfp->cf_unit;
290 cfdata = cfp;
291 }
292 #endif
293
294 return (1);
295 }
296
297 void
298 grfcvattach(pdp, dp, auxp)
299 struct device *pdp, *dp;
300 void *auxp;
301 {
302 static struct grf_softc congrf;
303 struct zbus_args *zap;
304 struct grf_softc *gp;
305 static char attachflag = 0;
306
307 zap = auxp;
308
309 /*
310 * This function is called twice, once on console init (dp == NULL)
311 * and once on "normal" grf5 init.
312 */
313
314 if (dp == NULL) /* console init */
315 gp = &congrf;
316 else
317 gp = (struct grf_softc *)dp;
318
319 if (dp != NULL && congrf.g_regkva != 0) {
320 /*
321 * inited earlier, just copy (not device struct)
322 */
323
324 printf("\n");
325 #ifdef CV64CONSOLE
326 bcopy(&congrf.g_display, &gp->g_display,
327 (char *) &gp[1] - (char *) &gp->g_display);
328 #else
329 gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000;
330 gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000;
331
332 gp->g_unit = GRF_CV64_UNIT;
333 gp->g_mode = cv_mode;
334 gp->g_conpri = grfcv_cnprobe();
335 gp->g_flags = GF_ALIVE;
336 #endif
337 } else {
338 gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000;
339 gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000;
340
341 gp->g_unit = GRF_CV64_UNIT;
342 gp->g_mode = cv_mode;
343 gp->g_conpri = grfcv_cnprobe();
344 gp->g_flags = GF_ALIVE;
345
346 /* wakeup the board */
347 cv_boardinit(gp);
348
349 #ifdef CV64CONSOLE
350 grfcv_iteinit(gp);
351 (void)cv_load_mon(gp, &cvconsole_mode);
352 #endif
353 }
354
355 /*
356 * attach grf
357 */
358 if (amiga_config_found(cfdata, &gp->g_device, gp, grfcvprint)) {
359 if (dp != NULL)
360 printf("grfcv: CyberVision64 with %dMB being used\n", cv_fbsize/0x100000);
361 attachflag = 1;
362 } else {
363 if (!attachflag)
364 /*printf("grfcv unattached!!\n")*/;
365 }
366 }
367
368 int
369 grfcvprint(auxp, pnp)
370 void *auxp;
371 char *pnp;
372 {
373 if (pnp)
374 printf("ite at %s: ", pnp);
375 return (UNCONF);
376 }
377
378
379 /*
380 * Computes M, N, and R values from
381 * given input frequency. It uses a table of
382 * precomputed values, to keep CPU time low.
383 *
384 * The return value consist of:
385 * lower byte: Bits 4-0: N Divider Value
386 * Bits 5-6: R Value for e.g. SR10 or SR12
387 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
388 */
389
390 static unsigned short
391 compute_clock(freq)
392 unsigned long freq;
393 {
394 static unsigned char *mnr, *save; /* M, N + R vals */
395 unsigned long work_freq, r;
396 unsigned short erg;
397 long diff, d2;
398
399 if (freq < 12500000 || freq > MAXPIXELCLOCK) {
400 printf("grfcv: Illegal clock frequency: %ldMHz\n", freq/1000000);
401 printf("grfcv: Using default frequency: 25MHz\n");
402 printf("grfcv: See the manpage of grfconfig for more informations.\n");
403 freq = 25000000;
404 }
405
406 mnr = clocks; /* there the vals are stored */
407 d2 = 0x7fffffff;
408
409 while (*mnr) { /* mnr vals are 0-terminated */
410 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
411
412 r = (mnr[1] >> 5) & 0x03;
413 if (r != 0)
414 work_freq=work_freq >> r; /* r is the freq divider */
415
416 work_freq *= 0x3E8; /* 2nd part of OSC */
417
418 diff = abs(freq - work_freq);
419
420 if (d2 >= diff) {
421 d2 = diff;
422 /* In save are the vals for minimal diff */
423 save = mnr;
424 }
425 mnr += 2;
426 }
427 erg = *((unsigned short *)save);
428
429 return (erg);
430 }
431
432
433 void
434 cv_boardinit(gp)
435 struct grf_softc *gp;
436 {
437 volatile caddr_t ba;
438 unsigned char test;
439 unsigned int clockpar;
440 int i;
441 struct grfinfo *gi;
442
443 ba = gp->g_regkva;
444 /* Reset board */
445 for (i = 0; i < 6; i++)
446 cv_write_port (0xff, ba - 0x02000000); /* Clear all bits */
447
448 /* Return to operational Mode */
449 cv_write_port(0x8004, ba - 0x02000000);
450
451 /* Wakeup Chip */
452 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x10);
453 vgaw(ba, SREG_OPTION_SELECT, 0x1);
454 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x8);
455
456 vgaw(ba, GREG_MISC_OUTPUT_W, 0x23);
457
458 WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */
459 WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */
460
461 test = RCrt(ba, CRT_ID_SYSTEM_CONFIG);
462 test = test | 0x01; /* enable enhaced register access */
463 test = test & 0xEF; /* clear bit 4, 0 wait state */
464 WCrt(ba, CRT_ID_SYSTEM_CONFIG, test);
465
466 /*
467 * bit 1=1: enable enhanced mode functions
468 * bit 4=1: enable linear adressing
469 * bit 5=1: enable MMIO
470 */
471 vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31);
472
473 /* enable cpu acess, color mode, high 64k page */
474 vgaw(ba, GREG_MISC_OUTPUT_W, 0x23);
475
476 /* Cpu base addr */
477 WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x0);
478
479 /* Reset. This does nothing, but everyone does it:) */
480 WSeq(ba, SEQ_ID_RESET, 0x3);
481
482 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x1); /* 8 Dot Clock */
483 WSeq(ba, SEQ_ID_MAP_MASK, 0xF); /* Enable write planes */
484 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x0); /* Character Font */
485
486 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x2); /* Complete mem access */
487
488 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x6); /* Unlock extensions */
489 test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */
490
491 /* enable 4MB fast Page Mode */
492 test = test | 1 << 6;
493 WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test);
494 /* faster LUT write */
495 WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0);
496
497 test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */
498
499 /* immediately Clkload bit clear */
500 test = test & 0xDF;
501
502 /* 2 MCLK Memory Write.... */
503 if (cv_memclk >= 55000000)
504 test |= 0x80;
505
506 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test);
507
508 /* Memory CLK */
509 clockpar = compute_clock(cv_memclk);
510 test = (clockpar & 0xFF00) >> 8;
511 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */
512 if (RCrt(ba, CRT_ID_REVISION) == 0x10) /* bugfix for new S3 chips */
513 WSeq(ba, SEQ_ID_MORE_MAGIC, test);
514
515 test = clockpar & 0xFF;
516 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */
517
518 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
519 /* DCLK */
520 WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
521 WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
522
523 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
524 test = test | 0x22;
525
526 /* DCLK + MCLK Clock immediate load! */
527 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
528
529 /* DCLK load */
530 test = vgar(ba, 0x3cc);
531 test = test | 0x0c;
532 vgaw(ba, 0x3c2, test);
533
534 /* Clear bit 5 again, prevent further loading. */
535 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x2);
536
537 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
538 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
539 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
540 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
541 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
542 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
543 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
544
545 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */
546
547 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x0); /* no panning */
548
549 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */
550
551 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
552 WCrt(ba, CRT_ID_CURSOR_END, 0x00);
553
554 /* Display start adress */
555 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
556 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
557
558 /* Cursor location */
559 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
560 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
561
562 /* Vertical retrace */
563 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
564 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
565
566 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
567 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
568
569 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
570
571 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
572 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
573
574 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
575
576 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
577
578 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
579
580 /* Refresh count 1, High speed text font, enhanced color mode */
581 WCrt(ba, CRT_ID_MISC_1, 0x35);
582
583 /* start fifo position */
584 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a);
585
586 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70);
587
588 /* address window position */
589 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
590
591 /* N Parameter for Display FIFO */
592 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
593
594 WGfx(ba, GCT_ID_SET_RESET, 0x0);
595 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x0);
596 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x0);
597 WGfx(ba, GCT_ID_DATA_ROTATE, 0x0);
598 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x0);
599 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
600 WGfx(ba, GCT_ID_MISC, 0x01);
601 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
602 WGfx(ba, GCT_ID_BITMASK, 0xFF);
603
604 /* colors for text mode */
605 for (i = 0; i <= 0xf; i++)
606 WAttr (ba, i, i);
607
608 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
609 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
610 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
611 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x0);
612 WAttr(ba, ACT_ID_COLOR_SELECT, 0x0);
613
614 vgaw(ba, VDAC_MASK, 0xFF); /* DAC Mask */
615
616 *((unsigned long *)(ba + ECR_FRGD_COLOR)) = 0xFF;
617 *((unsigned long *)(ba + ECR_BKGD_COLOR)) = 0;
618
619 /* colors initially set to greyscale */
620
621 vgaw(ba, VDAC_ADDRESS_W, 0);
622 for (i = 255; i >= 0 ; i--) {
623 vgaw(ba, VDAC_DATA, i);
624 vgaw(ba, VDAC_DATA, i);
625 vgaw(ba, VDAC_DATA, i);
626 }
627
628 /* GFx hardware cursor off */
629 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
630
631 /* Set first to 4 MB, so test will work */
632 WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
633
634 /* find *correct* fbsize of z3 board */
635 if (cv_has_4mb((volatile caddr_t)cv_boardaddr + 0x01400000)) {
636 cv_fbsize = 1024 * 1024 * 4;
637 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
638 } else {
639 cv_fbsize = 1024 * 1024 * 2;
640 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
641 }
642
643 /* Enable Video Display (Set Bit 5) */
644 WAttr(ba, 0x33, 0);
645
646 gi = &gp->g_display;
647 gi->gd_regaddr = (caddr_t) kvtop (ba);
648 gi->gd_regsize = 64 * 1024;
649 gi->gd_fbaddr = (caddr_t) kvtop (gp->g_fbkva);
650 gi->gd_fbsize = cv_fbsize;
651 }
652
653
654 int
655 cv_getvmode(gp, vm)
656 struct grf_softc *gp;
657 struct grfvideo_mode *vm;
658 {
659 struct grfvideo_mode *gv;
660
661 #ifdef CV64CONSOLE
662 /* Handle grabbing console mode */
663 if (vm->mode_num == 255) {
664 bcopy(&cvconsole_mode, vm, sizeof(struct grfvideo_mode));
665 /* XXX so grfconfig can tell us the correct text dimensions. */
666 vm->depth = cvconsole_mode.fy;
667 } else
668 #endif
669 {
670 if (vm->mode_num == 0)
671 vm->mode_num = (monitor_current - monitor_def) + 1;
672 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
673 return (EINVAL);
674 gv = monitor_def + (vm->mode_num - 1);
675 if (gv->mode_num == 0)
676 return (EINVAL);
677
678 bcopy(gv, vm, sizeof(struct grfvideo_mode));
679 }
680
681 /* adjust internal values to pixel values */
682
683 vm->hblank_start *= 8;
684 vm->hblank_stop *= 8;
685 vm->hsync_start *= 8;
686 vm->hsync_stop *= 8;
687 vm->htotal *= 8;
688
689 return (0);
690 }
691
692
693 int
694 cv_setvmode(gp, mode)
695 struct grf_softc *gp;
696 unsigned mode;
697 {
698
699 if (!mode || (mode > monitor_def_max) ||
700 monitor_def[mode - 1].mode_num == 0)
701 return (EINVAL);
702
703 monitor_current = monitor_def + (mode - 1);
704
705 return (0);
706 }
707
708
709 int
710 cv_blank(gp, on)
711 struct grf_softc *gp;
712 int *on;
713 {
714 volatile caddr_t ba;
715
716 ba = gp->g_regkva;
717 gfx_on_off(*on ? 0 : 1, ba);
718 return (0);
719 }
720
721
722 /*
723 * Change the mode of the display.
724 * Return a UNIX error number or 0 for success.
725 */
726 int
727 cv_mode(gp, cmd, arg, a2, a3)
728 register struct grf_softc *gp;
729 int cmd;
730 void *arg;
731 int a2, a3;
732 {
733 int error;
734
735 switch (cmd) {
736 case GM_GRFON:
737 error = cv_load_mon (gp,
738 (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL;
739 return (error);
740
741 case GM_GRFOFF:
742 #ifndef CV64CONSOLE
743 (void)cv_toggle(gp);
744 #else
745 cv_load_mon(gp, &cvconsole_mode);
746 ite_reinit(gp->g_itedev);
747 #endif
748 return (0);
749
750 case GM_GRFCONFIG:
751 return (0);
752
753 case GM_GRFGETVMODE:
754 return (cv_getvmode (gp, (struct grfvideo_mode *) arg));
755
756 case GM_GRFSETVMODE:
757 error = cv_setvmode (gp, *(unsigned *) arg);
758 if (!error && (gp->g_flags & GF_GRFON))
759 cv_load_mon(gp,
760 (struct grfcvtext_mode *) monitor_current);
761 return (error);
762
763 case GM_GRFGETNUMVM:
764 *(int *)arg = monitor_def_max;
765 return (0);
766
767 case GM_GRFIOCTL:
768 return (cv_ioctl (gp, (int) arg, (caddr_t) a2));
769
770 default:
771 break;
772 }
773
774 return (EINVAL);
775 }
776
777 int
778 cv_ioctl (gp, cmd, data)
779 register struct grf_softc *gp;
780 int cmd;
781 void *data;
782 {
783 switch (cmd) {
784 case GRFIOCGSPRITEPOS:
785 case GRFIOCSSPRITEPOS:
786 case GRFIOCSSPRITEINF:
787 case GRFIOCGSPRITEINF:
788 case GRFIOCGSPRITEMAX:
789 break;
790
791 case GRFIOCGETCMAP:
792 return (cv_getcmap (gp, (struct grf_colormap *) data));
793
794 case GRFIOCPUTCMAP:
795 return (cv_putcmap (gp, (struct grf_colormap *) data));
796
797 case GRFIOCBITBLT:
798 break;
799
800 case GRFTOGGLE:
801 return (cv_toggle (gp));
802
803 case GRFIOCSETMON:
804 return (cv_setmonitor (gp, (struct grfvideo_mode *)data));
805
806 case GRFIOCBLANK:
807 return (cv_blank (gp, (int *)data));
808 }
809 return (EINVAL);
810 }
811
812 int
813 cv_setmonitor(gp, gv)
814 struct grf_softc *gp;
815 struct grfvideo_mode *gv;
816 {
817 struct grfvideo_mode *md;
818
819 if (!cv_mondefok(gv))
820 return (EINVAL);
821
822 #ifdef CV64CONSOLE
823 /* handle interactive setting of console mode */
824 if (gv->mode_num == 255) {
825 bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode));
826 cvconsole_mode.gv.hblank_start /= 8;
827 cvconsole_mode.gv.hblank_stop /= 8;
828 cvconsole_mode.gv.hsync_start /= 8;
829 cvconsole_mode.gv.hsync_stop /= 8;
830 cvconsole_mode.gv.htotal /= 8;
831 cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy;
832 cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx;
833 if (!(gp->g_flags & GF_GRFON))
834 cv_load_mon(gp, &cvconsole_mode);
835 ite_reinit(gp->g_itedev);
836 return (0);
837 }
838 #endif
839
840 md = monitor_def + (gv->mode_num - 1);
841 bcopy(gv, md, sizeof(struct grfvideo_mode));
842
843 /* adjust pixel oriented values to internal rep. */
844
845 md->hblank_start /= 8;
846 md->hblank_stop /= 8;
847 md->hsync_start /= 8;
848 md->hsync_stop /= 8;
849 md->htotal /= 8;
850
851 return (0);
852 }
853
854 int
855 cv_getcmap(gfp, cmap)
856 struct grf_softc *gfp;
857 struct grf_colormap *cmap;
858 {
859 volatile caddr_t ba;
860 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
861 short x;
862 int error;
863
864 ba = gfp->g_regkva;
865 if (cmap->count == 0 || cmap->index >= 256)
866 return (0);
867
868 if (cmap->index + cmap->count > 256)
869 cmap->count = 256 - cmap->index;
870
871 /* first read colors out of the chip, then copyout to userspace */
872 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
873 x = cmap->count - 1;
874
875 rp = red + cmap->index;
876 gp = green + cmap->index;
877 bp = blue + cmap->index;
878
879 do {
880 *rp++ = vgar (ba, VDAC_DATA) << 2;
881 *gp++ = vgar (ba, VDAC_DATA) << 2;
882 *bp++ = vgar (ba, VDAC_DATA) << 2;
883 } while (x-- > 0);
884
885 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
886 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
887 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
888 return (0);
889
890 return (error);
891 }
892
893 int
894 cv_putcmap(gfp, cmap)
895 struct grf_softc *gfp;
896 struct grf_colormap *cmap;
897 {
898 volatile caddr_t ba;
899 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
900 short x;
901 int error;
902
903 ba = gfp->g_regkva;
904 if (cmap->count == 0 || cmap->index >= 256)
905 return (0);
906
907 if (cmap->index + cmap->count > 256)
908 cmap->count = 256 - cmap->index;
909
910 /* first copy the colors into kernelspace */
911 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
912 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
913 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
914 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
915 x = cmap->count - 1;
916
917 rp = red + cmap->index;
918 gp = green + cmap->index;
919 bp = blue + cmap->index;
920
921 do {
922 vgaw (ba, VDAC_DATA, *rp++ >> 2);
923 vgaw (ba, VDAC_DATA, *gp++ >> 2);
924 vgaw (ba, VDAC_DATA, *bp++ >> 2);
925 } while (x-- > 0);
926 return (0);
927 } else
928 return (error);
929 }
930
931
932 int
933 cv_toggle(gp)
934 struct grf_softc *gp;
935 {
936 volatile caddr_t ba;
937
938 ba = gp->g_regkva;
939 cvscreen(1, ba - 0x02000000);
940
941 return (0);
942 }
943
944
945 int
946 cv_mondefok(gv)
947 struct grfvideo_mode *gv;
948 {
949 unsigned long maxpix;
950 int widthok = 0;
951
952 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
953 if (gv->mode_num != 255 || (gv->depth != 4 && gv->depth != 8))
954 return (0);
955 else
956 /*
957 * We have 8 bit console modes. This _is_
958 * a hack but necessary to be compatible.
959 */
960 gv->depth = 8;
961 }
962
963 switch(gv->depth) {
964 case 1:
965 case 4:
966 return (0);
967 case 8:
968 maxpix = MAXPIXELCLOCK;
969 break;
970 case 15:
971 case 16:
972 #ifdef CV_AGGRESSIVE_TIMING
973 maxpix = MAXPIXELCLOCK - 35000000;
974 #else
975 maxpix = MAXPIXELCLOCK - 55000000;
976 #endif
977 break;
978 case 24:
979 case 32:
980 #ifdef CV_AGGRESSIVE_TIMING
981 maxpix = MAXPIXELCLOCK - 75000000;
982 #else
983 maxpix = MAXPIXELCLOCK - 85000000;
984 #endif
985 break;
986 default:
987 return (0);
988 }
989
990 if (gv->pixel_clock > maxpix)
991 return (0);
992
993 /*
994 * These are the supported witdh values for the
995 * graphics engine. To Support other widths, one
996 * has to use one of these widths for memory alignment, i.e.
997 * one has to set CRT_ID_SCREEN_OFFSET to one of these values and
998 * CRT_ID_HOR_DISP_ENA_END to the desired width.
999 * Since a working graphics engine is essential
1000 * for the console, console modes of other width are not supported.
1001 * We could do that, though, but then you have to tell the Xserver
1002 * about this strange configuration and I don't know how at the moment :-)
1003 */
1004
1005 switch (gv->disp_width) {
1006 case 1024:
1007 case 640:
1008 case 800:
1009 case 1280:
1010 case 1152:
1011 case 1600:
1012 widthok = 1;
1013 break;
1014 default: /* XXX*/
1015 widthok = 0;
1016 break;
1017 }
1018
1019 if (widthok) return (1);
1020 else {
1021 if (gv->mode_num == 255) { /* console mode */
1022 printf ("This display width is not supported by the CV64 console.\n");
1023 printf ("Use one of 640 800 1024 1152 1280 1600!\n");
1024 return (0);
1025 } else {
1026 printf ("Warning for mode %d:\n", (int) gv->mode_num);
1027 printf ("Don't use a blitter-suporting Xserver with this display width\n");
1028 printf ("Use one of 640 800 1024 1152 1280 1600!\n");
1029 return (1);
1030 }
1031 }
1032 return (1);
1033 }
1034
1035 int
1036 cv_load_mon(gp, md)
1037 struct grf_softc *gp;
1038 struct grfcvtext_mode *md;
1039 {
1040 struct grfvideo_mode *gv;
1041 struct grfinfo *gi;
1042 volatile caddr_t ba, fb;
1043 unsigned short mnr;
1044 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1045 VSE, VT;
1046 char LACE, DBLSCAN, TEXT, CONSOLE;
1047 int uplim, lowlim;
1048 int cr50, cr33, sr15, sr18, clock_mode, test;
1049 int m, n; /* For calc'ing display FIFO */
1050 int tfillm, temptym; /* FIFO fill and empty mclk's */
1051 int hmul; /* Multiplier for hor. Values */
1052 /* identity */
1053 gv = &md->gv;
1054
1055 /*
1056 * No way to get text modes to work.
1057 * Blame phase5, not me!
1058 */
1059 TEXT = 0; /* (gv->depth == 4); */
1060 CONSOLE = (gv->mode_num == 255);
1061
1062 if (!cv_mondefok(gv)) {
1063 printf("grfcv: The monitor definition is not okay.\n");
1064 printf("grfcv: See the manpage of grfconfig for more informations\n");
1065 return (0);
1066 }
1067 ba = gp->g_regkva;
1068 fb = gp->g_fbkva;
1069
1070 /* turn gfx off, don't mess up the display */
1071 gfx_on_off(1, ba);
1072
1073 /* provide all needed information in grf device-independant locations */
1074 gp->g_data = (caddr_t) gv;
1075 gi = &gp->g_display;
1076 gi->gd_colors = 1 << gv->depth;
1077 gi->gd_planes = gv->depth;
1078 gi->gd_fbwidth = gv->disp_width;
1079 gi->gd_fbheight = gv->disp_height;
1080 gi->gd_fbx = 0;
1081 gi->gd_fby = 0;
1082 if (CONSOLE) {
1083 gi->gd_dwidth = md->fx * md->cols;
1084 gi->gd_dheight = md->fy * md->rows;
1085 } else {
1086 gi->gd_dwidth = gv->disp_width;
1087 gi->gd_dheight = gv->disp_height;
1088 }
1089 gi->gd_dx = 0;
1090 gi->gd_dy = 0;
1091
1092 /* get display mode parameters */
1093 switch (gv->depth) {
1094 case 15:
1095 case 16:
1096 hmul = 2;
1097 break;
1098 default:
1099 hmul = 1;
1100 break;
1101 }
1102
1103 HBS = gv->hblank_start * hmul;
1104 HBE = gv->hblank_stop * hmul;
1105 HSS = gv->hsync_start * hmul;
1106 HSE = gv->hsync_stop * hmul;
1107 HT = gv->htotal*hmul - 5;
1108 VBS = gv->vblank_start - 1;
1109 VSS = gv->vsync_start;
1110 VSE = gv->vsync_stop;
1111 VBE = gv->vblank_stop;
1112 VT = gv->vtotal - 2;
1113
1114 if (TEXT)
1115 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1116 else
1117 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/
1118 VDE = gv->disp_height - 1;
1119
1120 /* figure out whether lace or dblscan is needed */
1121
1122 uplim = gv->disp_height + (gv->disp_height / 4);
1123 lowlim = gv->disp_height - (gv->disp_height / 4);
1124 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1125 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1126
1127 /* adjustments */
1128
1129 if (LACE)
1130 VDE /= 2;
1131
1132 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1133 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1134 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1135 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1136
1137 /* Set clock */
1138
1139 mnr = compute_clock(gv->pixel_clock);
1140 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8) );
1141 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1142
1143 /* load display parameters into board */
1144
1145 WCrt(ba, CRT_ID_EXT_HOR_OVF,
1146 ((HT & 0x100) ? 0x01 : 0x00) |
1147 ((HDE & 0x100) ? 0x02 : 0x00) |
1148 ((HBS & 0x100) ? 0x04 : 0x00) |
1149 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */
1150 ((HSS & 0x100) ? 0x10 : 0x00) |
1151 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1152 (((HT-5) & 0x100) ? 0x40 : 0x00) );
1153
1154 WCrt(ba, CRT_ID_EXT_VER_OVF,
1155 0x40 | /* Line compare */
1156 ((VT & 0x400) ? 0x01 : 0x00) |
1157 ((VDE & 0x400) ? 0x02 : 0x00) |
1158 ((VBS & 0x400) ? 0x04 : 0x00) |
1159 ((VSS & 0x400) ? 0x10 : 0x00) );
1160
1161 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1162 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5);
1163
1164 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1165 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1166 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80));
1167 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1168 WCrt(ba, CRT_ID_END_HOR_RETR,
1169 (HSE & 0x1f) |
1170 ((HBE & 0x20) ? 0x80 : 0x00) );
1171 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1172 WCrt(ba, CRT_ID_OVERFLOW,
1173 0x10 |
1174 ((VT & 0x100) ? 0x01 : 0x00) |
1175 ((VDE & 0x100) ? 0x02 : 0x00) |
1176 ((VSS & 0x100) ? 0x04 : 0x00) |
1177 ((VBS & 0x100) ? 0x08 : 0x00) |
1178 ((VT & 0x200) ? 0x20 : 0x00) |
1179 ((VDE & 0x200) ? 0x40 : 0x00) |
1180 ((VSS & 0x200) ? 0x80 : 0x00) );
1181
1182 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
1183 0x40 | /* TEXT ? 0x00 ??? */
1184 (DBLSCAN ? 0x80 : 0x00) |
1185 ((VBS & 0x200) ? 0x20 : 0x00) |
1186 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1187
1188 WCrt(ba, CRT_ID_MODE_CONTROL,
1189 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xe3));
1190
1191 /* text cursor */
1192
1193 if (TEXT) {
1194 #if 1
1195 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1196 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1197 #else
1198 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1199 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1200 #endif
1201 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1202
1203 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1204 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1205 }
1206
1207 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1208 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1209
1210 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1211 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f));
1212 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1213 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1214 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1215
1216 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1217 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2);
1218 WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
1219
1220 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1221 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1222 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1223
1224 WSeq (ba, SEQ_ID_MEMORY_MODE,
1225 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02));
1226
1227 vgaw(ba, VDAC_MASK, 0xff);
1228
1229 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);
1230 sr15 &= 0xef;
1231 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL);
1232 sr18 &= 0x7f;
1233 cr33 = RCrt(ba, CRT_ID_BACKWAD_COMP_2);
1234 cr33 &= 0xdf;
1235 clock_mode = 0x00;
1236 cr50 = 0x00;
1237
1238 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2);
1239 test &= 0xd;
1240
1241 /* clear roxxler byte-swapping... */
1242 cv_write_port(0x0040, cv_boardaddr);
1243 cv_write_port(0x0020, cv_boardaddr);
1244
1245 switch (gv->depth) {
1246 case 1:
1247 case 4: /* text */
1248 HDE = gv->disp_width / 16;
1249 break;
1250 case 8:
1251 if (gv->pixel_clock > 80000000) {
1252 clock_mode = 0x10 | 0x02;
1253 sr15 |= 0x10;
1254 sr18 |= 0x80;
1255 cr33 |= 0x20;
1256 }
1257 HDE = gv->disp_width / 8;
1258 cr50 |= 0x00;
1259 break;
1260 case 15:
1261 cv_write_port (0x8020, cv_boardaddr);
1262 clock_mode = 0x30;
1263 HDE = gv->disp_width / 4;
1264 cr50 |= 0x10;
1265 break;
1266 case 16:
1267 cv_write_port (0x8020, cv_boardaddr);
1268 clock_mode = 0x50;
1269 HDE = gv->disp_width / 4;
1270 cr50 |= 0x10;
1271 break;
1272 case 24: /* this is really 32 Bit on CV64 */
1273 case 32:
1274 cv_write_port(0x8040, cv_boardaddr);
1275 clock_mode = 0xd0;
1276 HDE = (gv->disp_width / 2);
1277 cr50 |= 0x30;
1278 break;
1279 }
1280
1281 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
1282 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15);
1283 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18);
1284 WCrt(ba, CRT_ID_BACKWAD_COMP_2, cr33);
1285 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE);
1286
1287 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2);
1288 test &= ~0x30;
1289 /* HDE Overflow in bits 4-5 */
1290 test |= (HDE >> 4) & 0x30;
1291 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test);
1292
1293 /* Set up graphics engine */
1294 switch (gv->disp_width) {
1295 case 1024:
1296 cr50 |= 0x00;
1297 break;
1298 case 640:
1299 cr50 |= 0x40;
1300 break;
1301 case 800:
1302 cr50 |= 0x80;
1303 break;
1304 case 1280:
1305 cr50 |= 0xc0;
1306 break;
1307 case 1152:
1308 cr50 |= 0x01;
1309 break;
1310 case 1600:
1311 cr50 |= 0x81;
1312 break;
1313 default: /* XXX*/
1314 break;
1315 }
1316
1317 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50);
1318
1319 delay(100000);
1320 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x41));
1321 delay(100000);
1322 WAttr(ba, ACT_ID_COLOR_PLANE_ENA,
1323 (gv->depth == 1) ? 0x01 : 0x0f);
1324 delay(100000);
1325
1326 /*
1327 * M-Parameter of Display FIFO
1328 * This is dependant on the pixel clock and the memory clock.
1329 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide.
1330 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time
1331 * to empty the FIFO is tempty = (96/pixelclock) sec.
1332 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2.
1333 * This seems to be logical, ain't it?
1334 * Remember: We have to use integer arithmetics :(
1335 * Divide by 1000 to prevent overflows.
1336 */
1337
1338 tfillm = (96 * (cv_memclk/1000))/240000;
1339
1340 switch(gv->depth) {
1341 case 32:
1342 case 24:
1343 temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1344 break;
1345 case 15:
1346 case 16:
1347 temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1348 break;
1349 default:
1350 temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1351 break;
1352 }
1353
1354 m = (temptym - tfillm - 9) / 2;
1355 m = (m & 0x1f) << 3;
1356 if (m < 0x18)
1357 m = 0x18;
1358 n = 0xff;
1359
1360 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m);
1361 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n);
1362 delay(10000);
1363
1364 /* text initialization */
1365
1366 if (TEXT) {
1367 cv_inittextmode(gp);
1368 }
1369
1370 if (CONSOLE) {
1371 int i;
1372 vgaw(ba, VDAC_ADDRESS_W, 0);
1373 for (i = 0; i < 4; i++) {
1374 vgaw(ba, VDAC_DATA, cvconscolors[i][0]);
1375 vgaw(ba, VDAC_DATA, cvconscolors[i][1]);
1376 vgaw(ba, VDAC_DATA, cvconscolors[i][2]);
1377 }
1378 }
1379
1380 /* Some kind of Magic */
1381 WAttr(ba, 0x33, 0);
1382
1383 /* turn gfx on again */
1384 gfx_on_off(0, ba);
1385
1386 /* Pass-through */
1387 cvscreen(0, ba - 0x02000000);
1388
1389 return (1);
1390 }
1391
1392 void
1393 cv_inittextmode(gp)
1394 struct grf_softc *gp;
1395 {
1396 struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data;
1397 volatile caddr_t ba, fb;
1398 unsigned char *c, *f, y;
1399 unsigned short z;
1400
1401 ba = gp->g_regkva;
1402 fb = gp->g_fbkva;
1403
1404 /* load text font into beginning of display memory.
1405 * Each character cell is 32 bytes long (enough for 4 planes)
1406 */
1407
1408 SetTextPlane(ba, 0x02);
1409 cv_memset(fb, 0, 256 * 32);
1410 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1411 f = tm->fdata;
1412 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1413 for (y = 0; y < tm->fy; y++)
1414 *c++ = *f++;
1415
1416 /* clear out text/attr planes (three screens worth) */
1417
1418 SetTextPlane(ba, 0x01);
1419 cv_memset(fb, 0x07, tm->cols * tm->rows * 3);
1420 SetTextPlane(ba, 0x00);
1421 cv_memset(fb, 0x20, tm->cols * tm->rows * 3);
1422
1423 /* print out a little init msg */
1424
1425 c = (unsigned char *)(fb) + (tm->cols-16);
1426 strcpy(c, "CV64");
1427 c[6] = 0x20;
1428
1429 /* set colors (B&W) */
1430
1431 vgaw(ba, VDAC_ADDRESS_W, 0);
1432 for (z=0; z<256; z++) {
1433 unsigned char r, g, b;
1434
1435 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1436
1437 r = cvconscolors[y][0];
1438 g = cvconscolors[y][1];
1439 b = cvconscolors[y][2];
1440 vgaw(ba, VDAC_DATA, r >> 2);
1441 vgaw(ba, VDAC_DATA, g >> 2);
1442 vgaw(ba, VDAC_DATA, b >> 2);
1443 }
1444 }
1445
1446 void
1447 cv_memset(d, c, l)
1448 unsigned char *d;
1449 unsigned char c;
1450 int l;
1451 {
1452 for(; l > 0; l--)
1453 *d++ = c;
1454 }
1455
1456
1457 static inline void
1458 cv_write_port(bits, BoardAddr)
1459 unsigned short bits;
1460 volatile caddr_t BoardAddr;
1461 {
1462 volatile caddr_t addr;
1463 static unsigned char CVPortBits = 0; /* mirror port bits here */
1464
1465 addr = BoardAddr + 0x40001;
1466 if (bits & 0x8000)
1467 CVPortBits |= bits & 0xFF; /* Set bits */
1468 else {
1469 bits = bits & 0xFF;
1470 bits = (~bits) & 0xFF ;
1471 CVPortBits &= bits; /* Clear bits */
1472 }
1473
1474 *addr = CVPortBits;
1475 }
1476
1477
1478 /*
1479 * Monitor Switch
1480 * 0 = CyberVision Signal
1481 * 1 = Amiga Signal,
1482 * ba = boardaddr
1483 */
1484 static inline void
1485 cvscreen(toggle, ba)
1486 int toggle;
1487 volatile caddr_t ba;
1488 {
1489
1490 if (toggle == 1)
1491 cv_write_port (0x10, ba);
1492 else
1493 cv_write_port (0x8010, ba);
1494 }
1495
1496 /* 0 = on, 1= off */
1497 /* ba= registerbase */
1498 static inline void
1499 gfx_on_off(toggle, ba)
1500 int toggle;
1501 volatile caddr_t ba;
1502 {
1503 int r;
1504
1505 toggle &= 0x1;
1506 toggle = toggle << 5;
1507
1508 r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
1509 r &= 0xdf; /* set Bit 5 to 0 */
1510
1511 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
1512 }
1513
1514 #endif /* NGRFCV */
1515