grf_cv.c revision 1.7 1 /* $NetBSD: grf_cv.c,v 1.7 1996/03/02 14:02:55 veego 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 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */
509 if (RCrt(ba, CRT_ID_REVISION) == 0x10) /* bugfix for new S3 chips */
510 WSeq(ba, SEQ_ID_MORE_MAGIC, test);
511
512 test = clockpar & 0xFF;
513 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */
514
515 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
516 /* DCLK */
517 WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
518 WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
519
520 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
521 test = test | 0x22;
522
523 /* DCLK + MCLK Clock immediate load! */
524 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
525
526 /* DCLK load */
527 test = vgar(ba, 0x3cc);
528 test = test | 0x0c;
529 vgaw(ba, 0x3c2, test);
530
531 /* Clear bit 5 again, prevent further loading. */
532 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x2);
533
534 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
535 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
536 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
537 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
538 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
539 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
540 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
541
542 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */
543
544 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x0); /* no panning */
545
546 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */
547
548 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
549 WCrt(ba, CRT_ID_CURSOR_END, 0x00);
550
551 /* Display start adress */
552 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
553 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
554
555 /* Cursor location */
556 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
557 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
558
559 /* Vertical retrace */
560 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
561 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
562
563 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
564 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
565
566 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
567
568 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
569 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
570
571 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
572
573 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
574
575 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
576
577 /* Refresh count 1, High speed text font, enhanced color mode */
578 WCrt(ba, CRT_ID_MISC_1, 0x35);
579
580 /* start fifo position */
581 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a);
582
583 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70);
584
585 /* address window position */
586 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
587
588 /* N Parameter for Display FIFO */
589 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
590
591 WGfx(ba, GCT_ID_SET_RESET, 0x0);
592 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x0);
593 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x0);
594 WGfx(ba, GCT_ID_DATA_ROTATE, 0x0);
595 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x0);
596 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
597 WGfx(ba, GCT_ID_MISC, 0x01);
598 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
599 WGfx(ba, GCT_ID_BITMASK, 0xFF);
600
601 /* colors for text mode */
602 for (i = 0; i <= 0xf; i++)
603 WAttr (ba, i, i);
604
605 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
606 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
607 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
608 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x0);
609 WAttr(ba, ACT_ID_COLOR_SELECT, 0x0);
610
611 vgaw(ba, VDAC_MASK, 0xFF); /* DAC Mask */
612
613 *((unsigned long *)(ba + ECR_FRGD_COLOR)) = 0xFF;
614 *((unsigned long *)(ba + ECR_BKGD_COLOR)) = 0;
615
616 /* colors initially set to greyscale */
617
618 vgaw(ba, VDAC_ADDRESS_W, 0);
619 for (i = 255; i >= 0 ; i--) {
620 vgaw(ba, VDAC_DATA, i);
621 vgaw(ba, VDAC_DATA, i);
622 vgaw(ba, VDAC_DATA, i);
623 }
624
625 /* GFx hardware cursor off */
626 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
627
628 /* Set first to 4 MB, so test will work */
629 WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
630
631 /* find *correct* fbsize of z3 board */
632 if (cv_has_4mb((volatile caddr_t)cv_boardaddr + 0x01400000)) {
633 cv_fbsize = 1024 * 1024 * 4;
634 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
635 } else {
636 cv_fbsize = 1024 * 1024 * 2;
637 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
638 }
639
640 /* Enable Video Display (Set Bit 5) */
641 WAttr(ba, 0x33, 0);
642
643 gi = &gp->g_display;
644 gi->gd_regaddr = (caddr_t) kvtop (ba);
645 gi->gd_regsize = 64 * 1024;
646 gi->gd_fbaddr = (caddr_t) kvtop (gp->g_fbkva);
647 gi->gd_fbsize = cv_fbsize;
648 }
649
650
651 int
652 cv_getvmode(gp, vm)
653 struct grf_softc *gp;
654 struct grfvideo_mode *vm;
655 {
656 struct grfvideo_mode *gv;
657
658 #ifdef CV64CONSOLE
659 /* Handle grabbing console mode */
660 if (vm->mode_num == 255) {
661 bcopy(&cvconsole_mode, vm, sizeof(struct grfvideo_mode));
662 /* XXX so grfconfig can tell us the correct text dimensions. */
663 vm->depth = cvconsole_mode.fy;
664 } else
665 #endif
666 {
667 if (vm->mode_num == 0)
668 vm->mode_num = (monitor_current - monitor_def) + 1;
669 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
670 return (EINVAL);
671 gv = monitor_def + (vm->mode_num - 1);
672 if (gv->mode_num == 0)
673 return (EINVAL);
674
675 bcopy(gv, vm, sizeof(struct grfvideo_mode));
676 }
677
678 /* adjust internal values to pixel values */
679
680 vm->hblank_start *= 8;
681 vm->hblank_stop *= 8;
682 vm->hsync_start *= 8;
683 vm->hsync_stop *= 8;
684 vm->htotal *= 8;
685
686 return (0);
687 }
688
689
690 int
691 cv_setvmode(gp, mode)
692 struct grf_softc *gp;
693 unsigned mode;
694 {
695
696 if (!mode || (mode > monitor_def_max) ||
697 monitor_def[mode - 1].mode_num == 0)
698 return (EINVAL);
699
700 monitor_current = monitor_def + (mode - 1);
701
702 return (0);
703 }
704
705
706 int
707 cv_blank(gp, on)
708 struct grf_softc *gp;
709 int *on;
710 {
711 volatile caddr_t ba;
712
713 ba = gp->g_regkva;
714 gfx_on_off(*on ? 0 : 1, ba);
715 return (0);
716 }
717
718
719 /*
720 * Change the mode of the display.
721 * Return a UNIX error number or 0 for success.
722 */
723 int
724 cv_mode(gp, cmd, arg, a2, a3)
725 register struct grf_softc *gp;
726 int cmd;
727 void *arg;
728 int a2, a3;
729 {
730 int error;
731
732 switch (cmd) {
733 case GM_GRFON:
734 error = cv_load_mon (gp,
735 (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL;
736 return (error);
737
738 case GM_GRFOFF:
739 #ifndef CV64CONSOLE
740 (void)cv_toggle(gp);
741 #else
742 cv_load_mon(gp, &cvconsole_mode);
743 ite_reinit(gp->g_itedev);
744 #endif
745 return (0);
746
747 case GM_GRFCONFIG:
748 return (0);
749
750 case GM_GRFGETVMODE:
751 return (cv_getvmode (gp, (struct grfvideo_mode *) arg));
752
753 case GM_GRFSETVMODE:
754 error = cv_setvmode (gp, *(unsigned *) arg);
755 if (!error && (gp->g_flags & GF_GRFON))
756 cv_load_mon(gp,
757 (struct grfcvtext_mode *) monitor_current);
758 return (error);
759
760 case GM_GRFGETNUMVM:
761 *(int *)arg = monitor_def_max;
762 return (0);
763
764 case GM_GRFIOCTL:
765 return (cv_ioctl (gp, (int) arg, (caddr_t) a2));
766
767 default:
768 break;
769 }
770
771 return (EINVAL);
772 }
773
774 int
775 cv_ioctl (gp, cmd, data)
776 register struct grf_softc *gp;
777 int cmd;
778 void *data;
779 {
780 switch (cmd) {
781 case GRFIOCGSPRITEPOS:
782 case GRFIOCSSPRITEPOS:
783 case GRFIOCSSPRITEINF:
784 case GRFIOCGSPRITEINF:
785 case GRFIOCGSPRITEMAX:
786 break;
787
788 case GRFIOCGETCMAP:
789 return (cv_getcmap (gp, (struct grf_colormap *) data));
790
791 case GRFIOCPUTCMAP:
792 return (cv_putcmap (gp, (struct grf_colormap *) data));
793
794 case GRFIOCBITBLT:
795 break;
796
797 case GRFTOGGLE:
798 return (cv_toggle (gp));
799
800 case GRFIOCSETMON:
801 return (cv_setmonitor (gp, (struct grfvideo_mode *)data));
802
803 case GRFIOCBLANK:
804 return (cv_blank (gp, (int *)data));
805 }
806 return (EINVAL);
807 }
808
809 int
810 cv_setmonitor(gp, gv)
811 struct grf_softc *gp;
812 struct grfvideo_mode *gv;
813 {
814 struct grfvideo_mode *md;
815
816 if (!cv_mondefok(gv))
817 return (EINVAL);
818
819 #ifdef CV64CONSOLE
820 /* handle interactive setting of console mode */
821 if (gv->mode_num == 255) {
822 bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode));
823 cvconsole_mode.gv.hblank_start /= 8;
824 cvconsole_mode.gv.hblank_stop /= 8;
825 cvconsole_mode.gv.hsync_start /= 8;
826 cvconsole_mode.gv.hsync_stop /= 8;
827 cvconsole_mode.gv.htotal /= 8;
828 cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy;
829 cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx;
830 if (!(gp->g_flags & GF_GRFON))
831 cv_load_mon(gp, &cvconsole_mode);
832 ite_reinit(gp->g_itedev);
833 return (0);
834 }
835 #endif
836
837 md = monitor_def + (gv->mode_num - 1);
838 bcopy(gv, md, sizeof(struct grfvideo_mode));
839
840 /* adjust pixel oriented values to internal rep. */
841
842 md->hblank_start /= 8;
843 md->hblank_stop /= 8;
844 md->hsync_start /= 8;
845 md->hsync_stop /= 8;
846 md->htotal /= 8;
847
848 return (0);
849 }
850
851 int
852 cv_getcmap(gfp, cmap)
853 struct grf_softc *gfp;
854 struct grf_colormap *cmap;
855 {
856 volatile caddr_t ba;
857 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
858 short x;
859 int error;
860
861 ba = gfp->g_regkva;
862 if (cmap->count == 0 || cmap->index >= 256)
863 return (0);
864
865 if (cmap->index + cmap->count > 256)
866 cmap->count = 256 - cmap->index;
867
868 /* first read colors out of the chip, then copyout to userspace */
869 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
870 x = cmap->count - 1;
871
872 rp = red + cmap->index;
873 gp = green + cmap->index;
874 bp = blue + cmap->index;
875
876 do {
877 *rp++ = vgar (ba, VDAC_DATA) << 2;
878 *gp++ = vgar (ba, VDAC_DATA) << 2;
879 *bp++ = vgar (ba, VDAC_DATA) << 2;
880 } while (x-- > 0);
881
882 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
883 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
884 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
885 return (0);
886
887 return (error);
888 }
889
890 int
891 cv_putcmap(gfp, cmap)
892 struct grf_softc *gfp;
893 struct grf_colormap *cmap;
894 {
895 volatile caddr_t ba;
896 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
897 short x;
898 int error;
899
900 ba = gfp->g_regkva;
901 if (cmap->count == 0 || cmap->index >= 256)
902 return (0);
903
904 if (cmap->index + cmap->count > 256)
905 cmap->count = 256 - cmap->index;
906
907 /* first copy the colors into kernelspace */
908 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
909 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
910 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
911 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
912 x = cmap->count - 1;
913
914 rp = red + cmap->index;
915 gp = green + cmap->index;
916 bp = blue + cmap->index;
917
918 do {
919 vgaw (ba, VDAC_DATA, *rp++ >> 2);
920 vgaw (ba, VDAC_DATA, *gp++ >> 2);
921 vgaw (ba, VDAC_DATA, *bp++ >> 2);
922 } while (x-- > 0);
923 return (0);
924 } else
925 return (error);
926 }
927
928
929 int
930 cv_toggle(gp)
931 struct grf_softc *gp;
932 {
933 volatile caddr_t ba;
934
935 ba = gp->g_regkva;
936 cvscreen(1, ba - 0x02000000);
937
938 return (0);
939 }
940
941
942 int
943 cv_mondefok(gv)
944 struct grfvideo_mode *gv;
945 {
946 unsigned long maxpix;
947 int widthok = 0;
948
949 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
950 if (gv->mode_num != 255 || (gv->depth != 4 && gv->depth != 8))
951 return (0);
952 else
953 /*
954 * We have 8 bit console modes. This _is_
955 * a hack but necessary to be compatible.
956 */
957 gv->depth = 8;
958 }
959
960 switch(gv->depth) {
961 case 1:
962 case 4:
963 return (0);
964 case 8:
965 maxpix = MAXPIXELCLOCK;
966 break;
967 case 15:
968 case 16:
969 #ifdef CV_AGGRESSIVE_TIMING
970 maxpix = MAXPIXELCLOCK - 35000000;
971 #else
972 maxpix = MAXPIXELCLOCK - 55000000;
973 #endif
974 break;
975 case 24:
976 case 32:
977 #ifdef CV_AGGRESSIVE_TIMING
978 maxpix = MAXPIXELCLOCK - 75000000;
979 #else
980 maxpix = MAXPIXELCLOCK - 85000000;
981 #endif
982 break;
983 default:
984 return (0);
985 }
986
987 if (gv->pixel_clock > maxpix)
988 return (0);
989
990 /*
991 * These are the supported witdh values for the
992 * graphics engine. To Support other widths, one
993 * has to use one of these widths for memory alignment, i.e.
994 * one has to set CRT_ID_SCREEN_OFFSET to one of these values and
995 * CRT_ID_HOR_DISP_ENA_END to the desired width.
996 * Since a working graphics engine is essential
997 * for the console, console modes of other width are not supported.
998 * We could do that, though, but then you have to tell the Xserver
999 * about this strange configuration and I don't know how at the moment :-)
1000 */
1001
1002 switch (gv->disp_width) {
1003 case 1024:
1004 case 640:
1005 case 800:
1006 case 1280:
1007 case 1152:
1008 case 1600:
1009 widthok = 1;
1010 break;
1011 default: /* XXX*/
1012 widthok = 0;
1013 break;
1014 }
1015
1016 if (widthok) return (1);
1017 else {
1018 if (gv->mode_num == 255) { /* console mode */
1019 printf ("This display width is not supported by the CV64 console.\n");
1020 printf ("Use one of 640 800 1024 1152 1280 1600!\n");
1021 return (0);
1022 } else {
1023 printf ("Warning for mode %d:\n", (int) gv->mode_num);
1024 printf ("Don't use a blitter-suporting Xserver with this display width\n");
1025 printf ("Use one of 640 800 1024 1152 1280 1600!\n");
1026 return (1);
1027 }
1028 }
1029 return (1);
1030 }
1031
1032 int
1033 cv_load_mon(gp, md)
1034 struct grf_softc *gp;
1035 struct grfcvtext_mode *md;
1036 {
1037 struct grfvideo_mode *gv;
1038 struct grfinfo *gi;
1039 volatile caddr_t ba, fb;
1040 unsigned short mnr;
1041 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1042 VSE, VT;
1043 char LACE, DBLSCAN, TEXT, CONSOLE;
1044 int uplim, lowlim;
1045 int cr50, cr33, sr15, sr18, clock_mode, test;
1046 int m, n; /* For calc'ing display FIFO */
1047 int tfillm, temptym; /* FIFO fill and empty mclk's */
1048 int hmul; /* Multiplier for hor. Values */
1049 /* identity */
1050 gv = &md->gv;
1051
1052 /*
1053 * No way to get text modes to work.
1054 * Blame phase5, not me!
1055 */
1056 TEXT = 0; /* (gv->depth == 4); */
1057 CONSOLE = (gv->mode_num == 255);
1058
1059 if (!cv_mondefok(gv)) {
1060 printf("grfcv: The monitor definition is not okay.\n");
1061 printf("grfcv: See the manpage of grfconfig for more informations\n");
1062 return (0);
1063 }
1064 ba = gp->g_regkva;
1065 fb = gp->g_fbkva;
1066
1067 /* turn gfx off, don't mess up the display */
1068 gfx_on_off(1, ba);
1069
1070 /* provide all needed information in grf device-independant locations */
1071 gp->g_data = (caddr_t) gv;
1072 gi = &gp->g_display;
1073 gi->gd_colors = 1 << gv->depth;
1074 gi->gd_planes = gv->depth;
1075 gi->gd_fbwidth = gv->disp_width;
1076 gi->gd_fbheight = gv->disp_height;
1077 gi->gd_fbx = 0;
1078 gi->gd_fby = 0;
1079 if (CONSOLE) {
1080 gi->gd_dwidth = md->fx * md->cols;
1081 gi->gd_dheight = md->fy * md->rows;
1082 } else {
1083 gi->gd_dwidth = gv->disp_width;
1084 gi->gd_dheight = gv->disp_height;
1085 }
1086 gi->gd_dx = 0;
1087 gi->gd_dy = 0;
1088
1089 /* get display mode parameters */
1090 switch (gv->depth) {
1091 case 15:
1092 case 16:
1093 hmul = 2;
1094 break;
1095 default:
1096 hmul = 1;
1097 break;
1098 }
1099
1100 HBS = gv->hblank_start * hmul;
1101 HBE = gv->hblank_stop * hmul;
1102 HSS = gv->hsync_start * hmul;
1103 HSE = gv->hsync_stop * hmul;
1104 HT = gv->htotal*hmul - 5;
1105 VBS = gv->vblank_start - 1;
1106 VSS = gv->vsync_start;
1107 VSE = gv->vsync_stop;
1108 VBE = gv->vblank_stop;
1109 VT = gv->vtotal - 2;
1110
1111 if (TEXT)
1112 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1113 else
1114 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/
1115 VDE = gv->disp_height - 1;
1116
1117 /* figure out whether lace or dblscan is needed */
1118
1119 uplim = gv->disp_height + (gv->disp_height / 4);
1120 lowlim = gv->disp_height - (gv->disp_height / 4);
1121 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1122 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1123
1124 /* adjustments */
1125
1126 if (LACE)
1127 VDE /= 2;
1128
1129 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1130 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1131 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1132 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1133
1134 /* Set clock */
1135
1136 mnr = compute_clock(gv->pixel_clock);
1137 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8) );
1138 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1139
1140 /* load display parameters into board */
1141
1142 WCrt(ba, CRT_ID_EXT_HOR_OVF,
1143 ((HT & 0x100) ? 0x01 : 0x00) |
1144 ((HDE & 0x100) ? 0x02 : 0x00) |
1145 ((HBS & 0x100) ? 0x04 : 0x00) |
1146 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */
1147 ((HSS & 0x100) ? 0x10 : 0x00) |
1148 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1149 (((HT-5) & 0x100) ? 0x40 : 0x00) );
1150
1151 WCrt(ba, CRT_ID_EXT_VER_OVF,
1152 0x40 | /* Line compare */
1153 ((VT & 0x400) ? 0x01 : 0x00) |
1154 ((VDE & 0x400) ? 0x02 : 0x00) |
1155 ((VBS & 0x400) ? 0x04 : 0x00) |
1156 ((VSS & 0x400) ? 0x10 : 0x00) );
1157
1158 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1159 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5);
1160
1161 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1162 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1163 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80));
1164 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1165 WCrt(ba, CRT_ID_END_HOR_RETR,
1166 (HSE & 0x1f) |
1167 ((HBE & 0x20) ? 0x80 : 0x00) );
1168 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1169 WCrt(ba, CRT_ID_OVERFLOW,
1170 0x10 |
1171 ((VT & 0x100) ? 0x01 : 0x00) |
1172 ((VDE & 0x100) ? 0x02 : 0x00) |
1173 ((VSS & 0x100) ? 0x04 : 0x00) |
1174 ((VBS & 0x100) ? 0x08 : 0x00) |
1175 ((VT & 0x200) ? 0x20 : 0x00) |
1176 ((VDE & 0x200) ? 0x40 : 0x00) |
1177 ((VSS & 0x200) ? 0x80 : 0x00) );
1178
1179 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
1180 0x40 | /* TEXT ? 0x00 ??? */
1181 (DBLSCAN ? 0x80 : 0x00) |
1182 ((VBS & 0x200) ? 0x20 : 0x00) |
1183 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1184
1185 WCrt(ba, CRT_ID_MODE_CONTROL,
1186 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xe3));
1187
1188 /* text cursor */
1189
1190 if (TEXT) {
1191 #if 1
1192 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1193 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1194 #else
1195 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1196 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1197 #endif
1198 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1199
1200 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1201 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1202 }
1203
1204 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1205 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1206
1207 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1208 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f));
1209 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1210 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1211 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1212
1213 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1214 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2);
1215 WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
1216
1217 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1218 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1219 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1220
1221 WSeq (ba, SEQ_ID_MEMORY_MODE,
1222 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02));
1223
1224 vgaw(ba, VDAC_MASK, 0xff);
1225
1226 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);
1227 sr15 &= 0xef;
1228 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL);
1229 sr18 &= 0x7f;
1230 cr33 = RCrt(ba, CRT_ID_BACKWAD_COMP_2);
1231 cr33 &= 0xdf;
1232 clock_mode = 0x00;
1233 cr50 = 0x00;
1234
1235 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2);
1236 test &= 0xd;
1237
1238 /* clear roxxler byte-swapping... */
1239 cv_write_port(0x0040, cv_boardaddr);
1240 cv_write_port(0x0020, cv_boardaddr);
1241
1242 switch (gv->depth) {
1243 case 1:
1244 case 4: /* text */
1245 HDE = gv->disp_width / 16;
1246 break;
1247 case 8:
1248 if (gv->pixel_clock > 80000000) {
1249 clock_mode = 0x10 | 0x02;
1250 sr15 |= 0x10;
1251 sr18 |= 0x80;
1252 cr33 |= 0x20;
1253 }
1254 HDE = gv->disp_width / 8;
1255 cr50 |= 0x00;
1256 break;
1257 case 15:
1258 cv_write_port (0x8020, cv_boardaddr);
1259 clock_mode = 0x30;
1260 HDE = gv->disp_width / 4;
1261 cr50 |= 0x10;
1262 break;
1263 case 16:
1264 cv_write_port (0x8020, cv_boardaddr);
1265 clock_mode = 0x50;
1266 HDE = gv->disp_width / 4;
1267 cr50 |= 0x10;
1268 break;
1269 case 24: /* this is really 32 Bit on CV64 */
1270 case 32:
1271 cv_write_port(0x8040, cv_boardaddr);
1272 clock_mode = 0xd0;
1273 HDE = (gv->disp_width / 2);
1274 cr50 |= 0x30;
1275 break;
1276 }
1277
1278 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
1279 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15);
1280 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18);
1281 WCrt(ba, CRT_ID_BACKWAD_COMP_2, cr33);
1282 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE);
1283
1284 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2);
1285 test &= ~0x30;
1286 /* HDE Overflow in bits 4-5 */
1287 test |= (HDE >> 4) & 0x30;
1288 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test);
1289
1290 /* Set up graphics engine */
1291 switch (gv->disp_width) {
1292 case 1024:
1293 cr50 |= 0x00;
1294 break;
1295 case 640:
1296 cr50 |= 0x40;
1297 break;
1298 case 800:
1299 cr50 |= 0x80;
1300 break;
1301 case 1280:
1302 cr50 |= 0xc0;
1303 break;
1304 case 1152:
1305 cr50 |= 0x01;
1306 break;
1307 case 1600:
1308 cr50 |= 0x81;
1309 break;
1310 default: /* XXX*/
1311 break;
1312 }
1313
1314 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50);
1315
1316 delay(100000);
1317 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x41));
1318 delay(100000);
1319 WAttr(ba, ACT_ID_COLOR_PLANE_ENA,
1320 (gv->depth == 1) ? 0x01 : 0x0f);
1321 delay(100000);
1322
1323 /*
1324 * M-Parameter of Display FIFO
1325 * This is dependant on the pixel clock and the memory clock.
1326 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide.
1327 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time
1328 * to empty the FIFO is tempty = (96/pixelclock) sec.
1329 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2.
1330 * This seems to be logical, ain't it?
1331 * Remember: We have to use integer arithmetics :(
1332 * Divide by 1000 to prevent overflows.
1333 */
1334
1335 tfillm = (96 * (cv_memclk/1000))/240000;
1336
1337 switch(gv->depth) {
1338 case 32:
1339 case 24:
1340 temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1341 break;
1342 case 15:
1343 case 16:
1344 temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1345 break;
1346 default:
1347 temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1348 break;
1349 }
1350
1351 m = (temptym - tfillm - 9) / 2;
1352 m = (m & 0x1f) << 3;
1353 if (m < 0x18)
1354 m = 0x18;
1355 n = 0xff;
1356
1357 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m);
1358 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n);
1359 delay(10000);
1360
1361 /* text initialization */
1362
1363 if (TEXT) {
1364 cv_inittextmode(gp);
1365 }
1366
1367 if (CONSOLE) {
1368 int i;
1369 vgaw(ba, VDAC_ADDRESS_W, 0);
1370 for (i = 0; i < 4; i++) {
1371 vgaw(ba, VDAC_DATA, cvconscolors[i][0]);
1372 vgaw(ba, VDAC_DATA, cvconscolors[i][1]);
1373 vgaw(ba, VDAC_DATA, cvconscolors[i][2]);
1374 }
1375 }
1376
1377 /* Some kind of Magic */
1378 WAttr(ba, 0x33, 0);
1379
1380 /* turn gfx on again */
1381 gfx_on_off(0, ba);
1382
1383 /* Pass-through */
1384 cvscreen(0, ba - 0x02000000);
1385
1386 return (1);
1387 }
1388
1389 void
1390 cv_inittextmode(gp)
1391 struct grf_softc *gp;
1392 {
1393 struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data;
1394 volatile caddr_t ba, fb;
1395 unsigned char *c, *f, y;
1396 unsigned short z;
1397
1398 ba = gp->g_regkva;
1399 fb = gp->g_fbkva;
1400
1401 /* load text font into beginning of display memory.
1402 * Each character cell is 32 bytes long (enough for 4 planes)
1403 */
1404
1405 SetTextPlane(ba, 0x02);
1406 cv_memset(fb, 0, 256 * 32);
1407 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1408 f = tm->fdata;
1409 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1410 for (y = 0; y < tm->fy; y++)
1411 *c++ = *f++;
1412
1413 /* clear out text/attr planes (three screens worth) */
1414
1415 SetTextPlane(ba, 0x01);
1416 cv_memset(fb, 0x07, tm->cols * tm->rows * 3);
1417 SetTextPlane(ba, 0x00);
1418 cv_memset(fb, 0x20, tm->cols * tm->rows * 3);
1419
1420 /* print out a little init msg */
1421
1422 c = (unsigned char *)(fb) + (tm->cols-16);
1423 strcpy(c, "CV64");
1424 c[6] = 0x20;
1425
1426 /* set colors (B&W) */
1427
1428 vgaw(ba, VDAC_ADDRESS_W, 0);
1429 for (z=0; z<256; z++) {
1430 unsigned char r, g, b;
1431
1432 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1433
1434 r = cvconscolors[y][0];
1435 g = cvconscolors[y][1];
1436 b = cvconscolors[y][2];
1437 vgaw(ba, VDAC_DATA, r >> 2);
1438 vgaw(ba, VDAC_DATA, g >> 2);
1439 vgaw(ba, VDAC_DATA, b >> 2);
1440 }
1441 }
1442
1443 void
1444 cv_memset(d, c, l)
1445 unsigned char *d;
1446 unsigned char c;
1447 int l;
1448 {
1449 for(; l > 0; l--)
1450 *d++ = c;
1451 }
1452
1453
1454 static inline void
1455 cv_write_port(bits, BoardAddr)
1456 unsigned short bits;
1457 volatile caddr_t BoardAddr;
1458 {
1459 volatile caddr_t addr;
1460 static unsigned char CVPortBits = 0; /* mirror port bits here */
1461
1462 addr = BoardAddr + 0x40001;
1463 if (bits & 0x8000)
1464 CVPortBits |= bits & 0xFF; /* Set bits */
1465 else {
1466 bits = bits & 0xFF;
1467 bits = (~bits) & 0xFF ;
1468 CVPortBits &= bits; /* Clear bits */
1469 }
1470
1471 *addr = CVPortBits;
1472 }
1473
1474
1475 /*
1476 * Monitor Switch
1477 * 0 = CyberVision Signal
1478 * 1 = Amiga Signal,
1479 * ba = boardaddr
1480 */
1481 static inline void
1482 cvscreen(toggle, ba)
1483 int toggle;
1484 volatile caddr_t ba;
1485 {
1486
1487 if (toggle == 1)
1488 cv_write_port (0x10, ba);
1489 else
1490 cv_write_port (0x8010, ba);
1491 }
1492
1493 /* 0 = on, 1= off */
1494 /* ba= registerbase */
1495 static inline void
1496 gfx_on_off(toggle, ba)
1497 int toggle;
1498 volatile caddr_t ba;
1499 {
1500 int r;
1501
1502 toggle &= 0x1;
1503 toggle = toggle << 5;
1504
1505 r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
1506 r &= 0xdf; /* set Bit 5 to 0 */
1507
1508 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
1509 }
1510
1511 #endif /* NGRFCV */
1512