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