grf_cv.c revision 1.19 1 /* $NetBSD: grf_cv.c,v 1.19 1996/10/22 16:59:56 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) mail.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 * Bugfree Hardware Cursor support.
49 * The HWC routines provided here are buggy in 16/24 bit
50 * and may cause a Vertical Bar Crash of the Trio64.
51 * On the other hand it's better to put the routines in the Xserver,
52 * so please _don't_ put CV_HARDWARE_CURSOR in your config file.
53 */
54
55 #include <sys/param.h>
56 #include <sys/errno.h>
57 #include <sys/ioctl.h>
58 #include <sys/device.h>
59 #include <sys/malloc.h>
60 #include <sys/systm.h>
61 #include <machine/cpu.h>
62 #include <dev/cons.h>
63 #include <amiga/dev/itevar.h>
64 #include <amiga/amiga/device.h>
65 #include <amiga/dev/grfioctl.h>
66 #include <amiga/dev/grfvar.h>
67 #include <amiga/dev/grf_cvreg.h>
68 #include <amiga/dev/zbusvar.h>
69
70 int grfcvmatch __P((struct device *, void *, void *));
71 void grfcvattach __P((struct device *, struct device *, void *));
72 int grfcvprint __P((void *, const char *));
73
74 static int cv_has_4mb __P((volatile caddr_t));
75 static unsigned short cv_compute_clock __P((unsigned long));
76 void cv_boardinit __P((struct grf_softc *));
77 int cv_getvmode __P((struct grf_softc *, struct grfvideo_mode *));
78 int cv_setvmode __P((struct grf_softc *, unsigned int));
79 int cv_blank __P((struct grf_softc *, int *));
80 int cv_mode __P((register struct grf_softc *, u_long, void *, u_long, int));
81 int cv_ioctl __P((register struct grf_softc *gp, u_long cmd, void *data));
82 int cv_setmonitor __P((struct grf_softc *, struct grfvideo_mode *));
83 int cv_getcmap __P((struct grf_softc *, struct grf_colormap *));
84 int cv_putcmap __P((struct grf_softc *, struct grf_colormap *));
85 int cv_toggle __P((struct grf_softc *));
86 int cv_mondefok __P((struct grfvideo_mode *));
87 int cv_load_mon __P((struct grf_softc *, struct grfcvtext_mode *));
88 void cv_inittextmode __P((struct grf_softc *));
89 static inline void cv_write_port __P((unsigned short, volatile caddr_t));
90 static inline void cvscreen __P((int, volatile caddr_t));
91 static inline void gfx_on_off __P((int, volatile caddr_t));
92
93 #ifdef CV_HARDWARE_CURSOR
94 int cv_getspritepos __P((struct grf_softc *, struct grf_position *));
95 int cv_setspritepos __P((struct grf_softc *, struct grf_position *));
96 int cv_getspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *));
97 void cv_setup_hwc __P((struct grf_softc *,
98 unsigned char, unsigned char, unsigned char, unsigned char,
99 const unsigned long *));
100 int cv_setspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *));
101 int cv_getspritemax __P((struct grf_softc *,struct grf_position *));
102 #endif /* CV_HARDWARE_CURSOR */
103
104 /* Graphics display definitions.
105 * These are filled by 'grfconfig' using GRFIOCSETMON.
106 */
107 #define monitor_def_max 24
108 static struct grfvideo_mode monitor_def[24] = {
109 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
110 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
111 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
112 };
113 static struct grfvideo_mode *monitor_current = &monitor_def[0];
114 #define MAXPIXELCLOCK 135000000 /* safety */
115
116 unsigned char cv_pass_toggle; /* passthru status tracker */
117
118 /* Console display definition.
119 * Default hardcoded text mode. This grf_cv is set up to
120 * use one text mode only, and this is it. You may use
121 * grfconfig to change the mode after boot.
122 */
123
124 /* Console font */
125 #ifdef KFONT_8X11
126 #define S3FONT kernel_font_8x11
127 #define S3FONTY 11
128 #else
129 #define S3FONT kernel_font_8x8
130 #define S3FONTY 8
131 #endif
132 extern unsigned char S3FONT[];
133
134 /*
135 * Define default console mode
136 * (Internally, we still have to use hvalues/8!)
137 */
138 struct grfcvtext_mode cvconsole_mode = {
139 {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
140 481, 521, 491, 493, 525},
141 8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255
142 };
143
144 /* Console colors */
145 unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */
146 /* R G B */
147 {0x30, 0x30, 0x30},
148 {0x00, 0x00, 0x00},
149 {0x80, 0x00, 0x00},
150 {0x00, 0x80, 0x00},
151 {0x00, 0x00, 0x80},
152 {0x80, 0x80, 0x00},
153 {0x00, 0x80, 0x80},
154 {0x80, 0x00, 0x80},
155 {0xff, 0xff, 0xff},
156 {0x40, 0x40, 0x40},
157 {0xff, 0x00, 0x00},
158 {0x00, 0xff, 0x00},
159 {0x00, 0x00, 0xff},
160 {0xff, 0xff, 0x00},
161 {0x00, 0xff, 0xff},
162 {0x00, 0x00, 0xff}
163 };
164
165 static unsigned char clocks[]={
166 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
167 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
168 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
169 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
170 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
171 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
172 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
173 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
174 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
175 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
176 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
177 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
178 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
179 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
180 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
181 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
182 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
183 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
184 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
185 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
186 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
187 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
188 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
189 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
190 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
191 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
192 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
193 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
194 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
195 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
196 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
197 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
198 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
199 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
200 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
201 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
202 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
203 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
204 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
205 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
206 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
207 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
208 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
209 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
210 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
211 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
212 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
213 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
214 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
215 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
216 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
217 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
218 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
219 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
220 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
221 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
222 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
223 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
224 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
225 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
226 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
227 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
228 };
229
230
231 /* Board Address of CV64 */
232 static volatile caddr_t cv_boardaddr;
233 static int cv_fbsize;
234
235 /*
236 * Memory clock (binpatchable).
237 * Let's be defensive: 50 MHz runs on all boards I know of.
238 * 55 MHz runs on most boards. But you should know what you're doing
239 * if you set this flag. Again: This flag may destroy your CV Board.
240 * Use it at your own risk!!!
241 * Anyway, this doesn't imply that I'm responsible if your board breaks
242 * without setting this flag :-).
243 */
244 #ifdef CV_AGGRESSIVE_TIMING
245 long cv_memclk = 55000000;
246 #else
247 long cv_memclk = 50000000;
248 #endif
249
250 /* standard driver stuff */
251 struct cfattach grfcv_ca = {
252 sizeof(struct grf_softc), grfcvmatch, grfcvattach
253 };
254
255 struct cfdriver grfcv_cd = {
256 NULL, "grfcv", DV_DULL, NULL, 0
257 };
258 static struct cfdata *cfdata;
259
260
261 /*
262 * Get frambuffer memory size.
263 * phase5 didn't provide the bit in CR36,
264 * so we have to do it this way.
265 * Return 0 for 2MB, 1 for 4MB
266 */
267 static int
268 cv_has_4mb(fb)
269 volatile caddr_t fb;
270 {
271 volatile unsigned long *testfbw, *testfbr;
272
273 /* write patterns in memory and test if they can be read */
274 testfbw = (volatile unsigned long *)fb;
275 testfbr = (volatile unsigned long *)(fb + 0x02000000);
276 *testfbw = 0x87654321;
277 if (*testfbr != 0x87654321)
278 return (0);
279
280 /* upper memory region */
281 testfbw = (volatile unsigned long *)(fb + 0x00200000);
282 testfbr = (volatile unsigned long *)(fb + 0x02200000);
283 *testfbw = 0x87654321;
284 if (*testfbr != 0x87654321)
285 return (0);
286 *testfbw = 0xAAAAAAAA;
287 if (*testfbr != 0xAAAAAAAA)
288 return (0);
289 *testfbw = 0x55555555;
290 if (*testfbr != 0x55555555)
291 return (0);
292 return (1);
293 }
294
295 int
296 grfcvmatch(pdp, match, auxp)
297 struct device *pdp;
298 void *match, *auxp;
299 {
300 #ifdef CV64CONSOLE
301 struct cfdata *cfp = match;
302 static int cvcons_unit = -1;
303 #endif
304 struct zbus_args *zap;
305
306 zap = auxp;
307
308 if (amiga_realconfig == 0)
309 #ifdef CV64CONSOLE
310 if (cvcons_unit != -1)
311 #endif
312 return (0);
313
314 /* Lets be Paranoid: Test man and prod id */
315 if (zap->manid != 8512 || zap->prodid != 34)
316 return (0);
317
318 cv_boardaddr = zap->va;
319
320 #ifdef CV64CONSOLE
321 if (amiga_realconfig == 0) {
322 cvcons_unit = cfp->cf_unit;
323 cfdata = cfp;
324 }
325 #endif
326
327 return (1);
328 }
329
330 void
331 grfcvattach(pdp, dp, auxp)
332 struct device *pdp, *dp;
333 void *auxp;
334 {
335 static struct grf_softc congrf;
336 struct zbus_args *zap;
337 struct grf_softc *gp;
338 static char attachflag = 0;
339
340 zap = auxp;
341
342 /*
343 * This function is called twice, once on console init (dp == NULL)
344 * and once on "normal" grf5 init.
345 */
346
347 if (dp == NULL) /* console init */
348 gp = &congrf;
349 else
350 gp = (struct grf_softc *)dp;
351
352 if (dp != NULL && congrf.g_regkva != 0) {
353 /*
354 * inited earlier, just copy (not device struct)
355 */
356
357 printf("\n");
358 #ifdef CV64CONSOLE
359 bcopy(&congrf.g_display, &gp->g_display,
360 (char *) &gp[1] - (char *) &gp->g_display);
361 #else
362 gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000;
363 gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000;
364
365 gp->g_unit = GRF_CV64_UNIT;
366 gp->g_mode = cv_mode;
367 gp->g_conpri = grfcv_cnprobe();
368 gp->g_flags = GF_ALIVE;
369 #endif
370 } else {
371 gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000;
372 gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000;
373
374 gp->g_unit = GRF_CV64_UNIT;
375 gp->g_mode = cv_mode;
376 gp->g_conpri = grfcv_cnprobe();
377 gp->g_flags = GF_ALIVE;
378
379 /* wakeup the board */
380 cv_boardinit(gp);
381
382 #ifdef CV64CONSOLE
383 grfcv_iteinit(gp);
384 (void)cv_load_mon(gp, &cvconsole_mode);
385 #endif
386 }
387
388 /*
389 * attach grf
390 */
391 if (amiga_config_found(cfdata, &gp->g_device, gp, grfcvprint)) {
392 if (dp != NULL)
393 printf("grfcv: CyberVision64 with %dMB being used\n", cv_fbsize/0x100000);
394 attachflag = 1;
395 } else {
396 if (!attachflag)
397 /*printf("grfcv unattached!!\n")*/;
398 }
399 }
400
401 int
402 grfcvprint(auxp, pnp)
403 void *auxp;
404 const char *pnp;
405 {
406 if (pnp)
407 printf("ite at %s: ", pnp);
408 return (UNCONF);
409 }
410
411
412 /*
413 * Computes M, N, and R values from
414 * given input frequency. It uses a table of
415 * precomputed values, to keep CPU time low.
416 *
417 * The return value consist of:
418 * lower byte: Bits 4-0: N Divider Value
419 * Bits 5-6: R Value for e.g. SR10 or SR12
420 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
421 */
422
423 static unsigned short
424 cv_compute_clock(freq)
425 unsigned long freq;
426 {
427 static unsigned char *mnr, *save; /* M, N + R vals */
428 unsigned long work_freq, r;
429 unsigned short erg;
430 long diff, d2;
431
432 if (freq < 12500000 || freq > MAXPIXELCLOCK) {
433 printf("grfcv: Illegal clock frequency: %ldMHz\n", freq/1000000);
434 printf("grfcv: Using default frequency: 25MHz\n");
435 printf("grfcv: See the manpage of grfconfig for more informations.\n");
436 freq = 25000000;
437 }
438
439 mnr = clocks; /* there the vals are stored */
440 d2 = 0x7fffffff;
441
442 while (*mnr) { /* mnr vals are 0-terminated */
443 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
444
445 r = (mnr[1] >> 5) & 0x03;
446 if (r != 0)
447 work_freq=work_freq >> r; /* r is the freq divider */
448
449 work_freq *= 0x3E8; /* 2nd part of OSC */
450
451 diff = abs(freq - work_freq);
452
453 if (d2 >= diff) {
454 d2 = diff;
455 /* In save are the vals for minimal diff */
456 save = mnr;
457 }
458 mnr += 2;
459 }
460 erg = *((unsigned short *)save);
461
462 return (erg);
463 }
464
465
466 void
467 cv_boardinit(gp)
468 struct grf_softc *gp;
469 {
470 volatile caddr_t ba;
471 unsigned char test;
472 unsigned int clockpar;
473 int i;
474 struct grfinfo *gi;
475
476 ba = gp->g_regkva;
477 /* Reset board */
478 for (i = 0; i < 6; i++)
479 cv_write_port (0xff, ba - 0x02000000); /* Clear all bits */
480
481 /* Return to operational Mode */
482 cv_write_port(0x8004, ba - 0x02000000);
483
484 /* Wakeup Chip */
485 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x10);
486 vgaw(ba, SREG_OPTION_SELECT, 0x01);
487 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x08);
488
489 vgaw(ba, GREG_MISC_OUTPUT_W, 0x03);
490
491 WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */
492 WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */
493
494 test = RCrt(ba, CRT_ID_SYSTEM_CONFIG);
495 test = test | 0x01; /* enable enhaced register access */
496 test = test & 0xEF; /* clear bit 4, 0 wait state */
497 WCrt(ba, CRT_ID_SYSTEM_CONFIG, test);
498
499 /*
500 * bit 1=1: enable enhanced mode functions
501 * bit 4=1: enable linear adressing
502 * bit 5=1: enable MMIO
503 */
504 vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31);
505
506 /* enable cpu acess, color mode, high 64k page */
507 vgaw(ba, GREG_MISC_OUTPUT_W, 0x23);
508
509 /* Cpu base addr */
510 WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x00);
511
512 /* Reset. This does nothing, but everyone does it:) */
513 WSeq(ba, SEQ_ID_RESET, 0x03);
514
515 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); /* 8 Dot Clock */
516 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); /* Enable write planes */
517 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* Character Font */
518
519 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02); /* Complete mem access */
520
521 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06); /* Unlock extensions */
522 test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */
523
524 /* enable 4MB fast Page Mode */
525 test = test | 1 << 6;
526 WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test);
527 /* faster LUT write */
528 WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0);
529
530 test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */
531
532 /* immediately Clkload bit clear */
533 test = test & 0xDF;
534
535 /* 2 MCLK Memory Write.... */
536 if (cv_memclk >= 55000000)
537 test |= 0x80;
538
539 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test);
540
541 /* Memory CLK */
542 clockpar = cv_compute_clock(cv_memclk);
543 test = (clockpar & 0xFF00) >> 8;
544 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */
545
546 test = clockpar & 0xFF;
547 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */
548
549 if (RCrt(ba, CRT_ID_REVISION) == 0x10) /* bugfix for new S3 chips */
550 WSeq(ba, SEQ_ID_MORE_MAGIC, test);
551
552 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
553 /* DCLK */
554 WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
555 WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
556
557 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
558 test = test | 0x22;
559
560 /* DCLK + MCLK Clock immediate load! */
561 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
562
563 /* DCLK load */
564 test = vgar(ba, 0x3cc);
565 test = test | 0x0c;
566 vgaw(ba, 0x3c2, test);
567
568 /* Clear bit 5 again, prevent further loading. */
569 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02);
570
571 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
572 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
573 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
574 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
575 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
576 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
577 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
578
579 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */
580
581 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); /* no panning */
582
583 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */
584
585 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
586 WCrt(ba, CRT_ID_CURSOR_END, 0x00);
587
588 /* Display start adress */
589 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
590 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
591
592 /* Cursor location */
593 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
594 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
595
596 /* Vertical retrace */
597 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
598 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
599
600 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
601 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
602
603 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
604
605 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
606 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
607
608 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
609
610 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
611
612 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
613
614 /* Refresh count 1, High speed text font, enhanced color mode */
615 WCrt(ba, CRT_ID_MISC_1, 0x35);
616
617 /* start fifo position */
618 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a);
619
620 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70);
621
622 /* address window position */
623 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
624
625 /* N Parameter for Display FIFO */
626 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
627
628 WGfx(ba, GCT_ID_SET_RESET, 0x00);
629 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
630 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
631 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
632 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
633 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
634 WGfx(ba, GCT_ID_MISC, 0x01);
635 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
636 WGfx(ba, GCT_ID_BITMASK, 0xFF);
637
638 /* colors for text mode */
639 for (i = 0; i <= 0xf; i++)
640 WAttr (ba, i, i);
641
642 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
643 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
644 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
645 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
646 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
647
648 vgaw(ba, VDAC_MASK, 0xFF); /* DAC Mask */
649
650 *((unsigned long *)(ba + ECR_FRGD_COLOR)) = 0xFF;
651 *((unsigned long *)(ba + ECR_BKGD_COLOR)) = 0;
652
653 /* colors initially set to greyscale */
654
655 vgaw(ba, VDAC_ADDRESS_W, 0);
656 for (i = 255; i >= 0 ; i--) {
657 vgaw(ba, VDAC_DATA, i);
658 vgaw(ba, VDAC_DATA, i);
659 vgaw(ba, VDAC_DATA, i);
660 }
661
662 /* GFx hardware cursor off */
663 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
664
665 /* Set first to 4 MB, so test will work */
666 WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
667
668 /* find *correct* fbsize of z3 board */
669 if (cv_has_4mb((volatile caddr_t)cv_boardaddr + 0x01400000)) {
670 cv_fbsize = 1024 * 1024 * 4;
671 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
672 } else {
673 cv_fbsize = 1024 * 1024 * 2;
674 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
675 }
676
677 /* Initialize graphics engine */
678 GfxBusyWait(ba);
679 vgaw16(ba, ECR_FRGD_MIX, 0x27);
680 vgaw16(ba, ECR_BKGD_MIX, 0x07);
681
682 vgaw16(ba, ECR_READ_REG_DATA, 0x1000);
683 delay(200000);
684 vgaw16(ba, ECR_READ_REG_DATA, 0x2000);
685 GfxBusyWait(ba);
686 vgaw16(ba, ECR_READ_REG_DATA, 0x3fff);
687 GfxBusyWait(ba);
688 delay(200000);
689 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff);
690 GfxBusyWait(ba);
691
692 vgaw16(ba, ECR_BITPLANE_WRITE_MASK, ~0);
693
694 GfxBusyWait (ba);
695 vgaw16(ba, ECR_READ_REG_DATA, 0xe000);
696 vgaw16(ba, ECR_CURRENT_Y_POS2, 0x00);
697 vgaw16(ba, ECR_CURRENT_X_POS2, 0x00);
698 vgaw16(ba, ECR_READ_REG_DATA, 0xa000);
699 vgaw16(ba, ECR_DEST_Y__AX_STEP, 0x00);
700 vgaw16(ba, ECR_DEST_Y2__AX_STEP2, 0x00);
701 vgaw16(ba, ECR_DEST_X__DIA_STEP, 0x00);
702 vgaw16(ba, ECR_DEST_X2__DIA_STEP2, 0x00);
703 vgaw16(ba, ECR_SHORT_STROKE, 0x00);
704 vgaw16(ba, ECR_DRAW_CMD, 0x01);
705 GfxBusyWait (ba);
706
707 /* It ain't easy to write here, so let's do it again */
708 vgaw16(ba, ECR_READ_REG_DATA, 0x4fff);
709
710 vgaw16(ba, ECR_BKGD_COLOR, 0x01);
711 vgaw16(ba, ECR_FRGD_COLOR, 0x00);
712
713 /* Enable Video Display (Set Bit 5) */
714 WAttr(ba, 0x33, 0);
715
716 gi = &gp->g_display;
717 gi->gd_regaddr = (caddr_t) kvtop (ba);
718 gi->gd_regsize = 64 * 1024;
719 gi->gd_fbaddr = (caddr_t) kvtop (gp->g_fbkva);
720 gi->gd_fbsize = cv_fbsize;
721 }
722
723
724 int
725 cv_getvmode(gp, vm)
726 struct grf_softc *gp;
727 struct grfvideo_mode *vm;
728 {
729 struct grfvideo_mode *gv;
730
731 #ifdef CV64CONSOLE
732 /* Handle grabbing console mode */
733 if (vm->mode_num == 255) {
734 bcopy(&cvconsole_mode, vm, sizeof(struct grfvideo_mode));
735 /* XXX so grfconfig can tell us the correct text dimensions. */
736 vm->depth = cvconsole_mode.fy;
737 } else
738 #endif
739 {
740 if (vm->mode_num == 0)
741 vm->mode_num = (monitor_current - monitor_def) + 1;
742 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
743 return (EINVAL);
744 gv = monitor_def + (vm->mode_num - 1);
745 if (gv->mode_num == 0)
746 return (EINVAL);
747
748 bcopy(gv, vm, sizeof(struct grfvideo_mode));
749 }
750
751 /* adjust internal values to pixel values */
752
753 vm->hblank_start *= 8;
754 vm->hblank_stop *= 8;
755 vm->hsync_start *= 8;
756 vm->hsync_stop *= 8;
757 vm->htotal *= 8;
758
759 return (0);
760 }
761
762
763 int
764 cv_setvmode(gp, mode)
765 struct grf_softc *gp;
766 unsigned mode;
767 {
768
769 if (!mode || (mode > monitor_def_max) ||
770 monitor_def[mode - 1].mode_num == 0)
771 return (EINVAL);
772
773 monitor_current = monitor_def + (mode - 1);
774
775 return (0);
776 }
777
778
779 int
780 cv_blank(gp, on)
781 struct grf_softc *gp;
782 int *on;
783 {
784 volatile caddr_t ba;
785
786 ba = gp->g_regkva;
787 gfx_on_off(*on > 0 ? 0 : 1, ba);
788 return (0);
789 }
790
791
792 /*
793 * Change the mode of the display.
794 * Return a UNIX error number or 0 for success.
795 */
796 int
797 cv_mode(gp, cmd, arg, a2, a3)
798 register struct grf_softc *gp;
799 u_long cmd;
800 void *arg;
801 u_long a2;
802 int a3;
803 {
804 int error;
805
806 switch (cmd) {
807 case GM_GRFON:
808 error = cv_load_mon (gp,
809 (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL;
810 return (error);
811
812 case GM_GRFOFF:
813 #ifndef CV64CONSOLE
814 cvscreen(1, gp->g_regkva - 0x02000000)
815 #else
816 cv_load_mon(gp, &cvconsole_mode);
817 ite_reinit(gp->g_itedev);
818 #endif
819 return (0);
820
821 case GM_GRFCONFIG:
822 return (0);
823
824 case GM_GRFGETVMODE:
825 return (cv_getvmode (gp, (struct grfvideo_mode *) arg));
826
827 case GM_GRFSETVMODE:
828 error = cv_setvmode (gp, *(unsigned *) arg);
829 if (!error && (gp->g_flags & GF_GRFON))
830 cv_load_mon(gp,
831 (struct grfcvtext_mode *) monitor_current);
832 return (error);
833
834 case GM_GRFGETNUMVM:
835 *(int *)arg = monitor_def_max;
836 return (0);
837
838 case GM_GRFIOCTL:
839 return (cv_ioctl (gp, a2, arg));
840
841 default:
842 break;
843 }
844
845 return (EINVAL);
846 }
847
848
849 int
850 cv_ioctl (gp, cmd, data)
851 register struct grf_softc *gp;
852 u_long cmd;
853 void *data;
854 {
855 switch (cmd) {
856 #ifdef CV_HARDWARE_CURSOR
857 case GRFIOCGSPRITEPOS:
858 return(cv_getspritepos (gp, (struct grf_position *) data));
859
860 case GRFIOCSSPRITEPOS:
861 return(cv_setspritepos (gp, (struct grf_position *) data));
862
863 case GRFIOCSSPRITEINF:
864 return(cv_setspriteinfo (gp, (struct grf_spriteinfo *) data));
865
866 case GRFIOCGSPRITEINF:
867 return(cv_getspriteinfo (gp, (struct grf_spriteinfo *) data));
868
869 case GRFIOCGSPRITEMAX:
870 return(cv_getspritemax (gp, (struct grf_position *) data));
871 #else /* CV_HARDWARE_CURSOR */
872 case GRFIOCGSPRITEPOS:
873 case GRFIOCSSPRITEPOS:
874 case GRFIOCSSPRITEINF:
875 case GRFIOCGSPRITEINF:
876 case GRFIOCGSPRITEMAX:
877 break;
878 #endif /* CV_HARDWARE_CURSOR */
879
880 case GRFIOCGETCMAP:
881 return (cv_getcmap (gp, (struct grf_colormap *) data));
882
883 case GRFIOCPUTCMAP:
884 return (cv_putcmap (gp, (struct grf_colormap *) data));
885
886 case GRFIOCBITBLT:
887 break;
888
889 case GRFTOGGLE:
890 return (cv_toggle (gp));
891
892 case GRFIOCSETMON:
893 return (cv_setmonitor (gp, (struct grfvideo_mode *)data));
894
895 case GRFIOCBLANK:
896 return (cv_blank (gp, (int *)data));
897 }
898 return (EINVAL);
899 }
900
901
902 int
903 cv_setmonitor(gp, gv)
904 struct grf_softc *gp;
905 struct grfvideo_mode *gv;
906 {
907 struct grfvideo_mode *md;
908
909 if (!cv_mondefok(gv))
910 return (EINVAL);
911
912 #ifdef CV64CONSOLE
913 /* handle interactive setting of console mode */
914 if (gv->mode_num == 255) {
915 bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode));
916 cvconsole_mode.gv.hblank_start /= 8;
917 cvconsole_mode.gv.hblank_stop /= 8;
918 cvconsole_mode.gv.hsync_start /= 8;
919 cvconsole_mode.gv.hsync_stop /= 8;
920 cvconsole_mode.gv.htotal /= 8;
921 cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy;
922 cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx;
923 if (!(gp->g_flags & GF_GRFON))
924 cv_load_mon(gp, &cvconsole_mode);
925 ite_reinit(gp->g_itedev);
926 return (0);
927 }
928 #endif
929
930 md = monitor_def + (gv->mode_num - 1);
931
932 /*
933 * Prevent user from crashing the system by using
934 * grfconfig while in X
935 */
936 if (gp->g_flags & GF_GRFON)
937 if (md == monitor_current) {
938 printf("grf_cv: Changing the used mode not allowed!\n");
939 return (EINVAL);
940 }
941
942 bcopy(gv, md, sizeof(struct grfvideo_mode));
943
944 /* adjust pixel oriented values to internal rep. */
945
946 md->hblank_start /= 8;
947 md->hblank_stop /= 8;
948 md->hsync_start /= 8;
949 md->hsync_stop /= 8;
950 md->htotal /= 8;
951
952 return (0);
953 }
954
955
956 int
957 cv_getcmap(gfp, cmap)
958 struct grf_softc *gfp;
959 struct grf_colormap *cmap;
960 {
961 volatile caddr_t ba;
962 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
963 short x;
964 int error;
965
966 ba = gfp->g_regkva;
967 if (cmap->count == 0 || cmap->index >= 256)
968 return (0);
969
970 if (cmap->index + cmap->count > 256)
971 cmap->count = 256 - cmap->index;
972
973 /* first read colors out of the chip, then copyout to userspace */
974 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
975 x = cmap->count - 1;
976
977 rp = red + cmap->index;
978 gp = green + cmap->index;
979 bp = blue + cmap->index;
980
981 do {
982 *rp++ = vgar (ba, VDAC_DATA) << 2;
983 *gp++ = vgar (ba, VDAC_DATA) << 2;
984 *bp++ = vgar (ba, VDAC_DATA) << 2;
985 } while (x-- > 0);
986
987 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
988 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
989 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
990 return (0);
991
992 return (error);
993 }
994
995
996 int
997 cv_putcmap(gfp, cmap)
998 struct grf_softc *gfp;
999 struct grf_colormap *cmap;
1000 {
1001 volatile caddr_t ba;
1002 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1003 short x;
1004 int error;
1005
1006 ba = gfp->g_regkva;
1007 if (cmap->count == 0 || cmap->index >= 256)
1008 return (0);
1009
1010 if (cmap->index + cmap->count > 256)
1011 cmap->count = 256 - cmap->index;
1012
1013 /* first copy the colors into kernelspace */
1014 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1015 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1016 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
1017 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1018 x = cmap->count - 1;
1019
1020 rp = red + cmap->index;
1021 gp = green + cmap->index;
1022 bp = blue + cmap->index;
1023
1024 do {
1025 vgaw (ba, VDAC_DATA, *rp++ >> 2);
1026 vgaw (ba, VDAC_DATA, *gp++ >> 2);
1027 vgaw (ba, VDAC_DATA, *bp++ >> 2);
1028 } while (x-- > 0);
1029 return (0);
1030 } else
1031 return (error);
1032 }
1033
1034
1035 int
1036 cv_toggle(gp)
1037 struct grf_softc *gp;
1038 {
1039 volatile caddr_t ba;
1040
1041 ba = gp->g_regkva;
1042 #ifndef CV64CONSOLE
1043 cv_pass_toggle = 1;
1044 #endif /* !CV64CONSOLE */
1045
1046 if (cv_pass_toggle) {
1047 cvscreen(0, ba - 0x02000000);
1048 cv_pass_toggle = 0;
1049 } else {
1050 cvscreen(1, ba - 0x02000000);
1051 cv_pass_toggle = 1;
1052 }
1053
1054 return (0);
1055 }
1056
1057
1058 int
1059 cv_mondefok(gv)
1060 struct grfvideo_mode *gv;
1061 {
1062 unsigned long maxpix;
1063
1064 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
1065 if (gv->mode_num != 255 || gv->depth != 4)
1066 return (0);
1067 }
1068
1069 switch(gv->depth) {
1070 case 4:
1071 maxpix = MAXPIXELCLOCK - 55000000;
1072 break;
1073 case 8:
1074 maxpix = MAXPIXELCLOCK;
1075 break;
1076 case 15:
1077 case 16:
1078 #ifdef CV_AGGRESSIVE_TIMING
1079 maxpix = MAXPIXELCLOCK - 35000000;
1080 #else
1081 maxpix = MAXPIXELCLOCK - 55000000;
1082 #endif
1083 break;
1084 case 24:
1085 case 32:
1086 #ifdef CV_AGGRESSIVE_TIMING
1087 maxpix = MAXPIXELCLOCK - 75000000;
1088 #else
1089 maxpix = MAXPIXELCLOCK - 85000000;
1090 #endif
1091 break;
1092 default:
1093 printf("grf_cv: Illegal depth in mode %d\n",
1094 (int) gv->mode_num);
1095 return (0);
1096 }
1097
1098 if (gv->pixel_clock > maxpix) {
1099 printf("grf_cv: Pixelclock too high in mode %d\n",
1100 (int) gv->mode_num);
1101 return (0);
1102 }
1103
1104 if (gv->mode_num == 255) { /* console mode */
1105 if ((gv->disp_width / 8) > MAXCOLS) {
1106 printf ("grfcv: Too many columns for console\n");
1107 return (0);
1108 } else if ((gv->disp_height / S3FONTY) > MAXROWS) {
1109 printf ("grfcv: Too many rows for console\n");
1110 return (0);
1111 }
1112 }
1113
1114 return (1);
1115 }
1116
1117
1118 int
1119 cv_load_mon(gp, md)
1120 struct grf_softc *gp;
1121 struct grfcvtext_mode *md;
1122 {
1123 struct grfvideo_mode *gv;
1124 struct grfinfo *gi;
1125 volatile caddr_t ba, fb;
1126 unsigned short mnr;
1127 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1128 VSE, VT;
1129 char LACE, DBLSCAN, TEXT, CONSOLE;
1130 int uplim, lowlim;
1131 int cr50, sr15, sr18, clock_mode, test;
1132 int m, n; /* For calc'ing display FIFO */
1133 int tfillm, temptym; /* FIFO fill and empty mclk's */
1134 int hmul; /* Multiplier for hor. Values */
1135 /* identity */
1136 gv = &md->gv;
1137
1138 TEXT = (gv->depth == 4);
1139 CONSOLE = (gv->mode_num == 255);
1140
1141 if (!cv_mondefok(gv)) {
1142 printf("grfcv: The monitor definition is illegal.\n");
1143 printf("grfcv: See the manpage of grfconfig for more informations\n");
1144 return (0);
1145 }
1146 ba = gp->g_regkva;
1147 fb = gp->g_fbkva;
1148
1149 /* turn gfx off, don't mess up the display */
1150 gfx_on_off(1, ba);
1151
1152 /* provide all needed information in grf device-independant locations */
1153 gp->g_data = (caddr_t) gv;
1154 gi = &gp->g_display;
1155 gi->gd_colors = 1 << gv->depth;
1156 gi->gd_planes = gv->depth;
1157 gi->gd_fbwidth = gv->disp_width;
1158 gi->gd_fbheight = gv->disp_height;
1159 gi->gd_fbx = 0;
1160 gi->gd_fby = 0;
1161 if (CONSOLE) {
1162 gi->gd_dwidth = md->fx * md->cols;
1163 gi->gd_dheight = md->fy * md->rows;
1164 } else {
1165 gi->gd_dwidth = gv->disp_width;
1166 gi->gd_dheight = gv->disp_height;
1167 }
1168 gi->gd_dx = 0;
1169 gi->gd_dy = 0;
1170
1171 /* get display mode parameters */
1172 switch (gv->depth) {
1173 case 15:
1174 case 16:
1175 hmul = 2;
1176 break;
1177 default:
1178 hmul = 1;
1179 break;
1180 }
1181
1182 HBS = gv->hblank_start * hmul;
1183 HBE = gv->hblank_stop * hmul;
1184 HSS = gv->hsync_start * hmul;
1185 HSE = gv->hsync_stop * hmul;
1186 HT = gv->htotal*hmul - 5;
1187 VBS = gv->vblank_start - 1;
1188 VSS = gv->vsync_start;
1189 VSE = gv->vsync_stop;
1190 VBE = gv->vblank_stop;
1191 VT = gv->vtotal - 2;
1192
1193 /* Disable enhanced Mode for text display */
1194
1195 vgaw(ba, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1196
1197 if (TEXT)
1198 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1199 else
1200 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/
1201 VDE = gv->disp_height - 1;
1202
1203 /* figure out whether lace or dblscan is needed */
1204
1205 uplim = gv->disp_height + (gv->disp_height / 4);
1206 lowlim = gv->disp_height - (gv->disp_height / 4);
1207 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1208 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1209
1210 /* adjustments */
1211
1212 if (LACE)
1213 VDE /= 2;
1214
1215 /* GFX hardware cursor off */
1216 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
1217 WCrt(ba, CRT_ID_EXT_DAC_CNTL, 0x00);
1218
1219 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1220 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1221 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1222 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1223
1224 /* Set clock */
1225
1226 mnr = cv_compute_clock(gv->pixel_clock);
1227 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1228 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1229
1230 /* load display parameters into board */
1231
1232 WCrt(ba, CRT_ID_EXT_HOR_OVF,
1233 ((HT & 0x100) ? 0x01 : 0x00) |
1234 ((HDE & 0x100) ? 0x02 : 0x00) |
1235 ((HBS & 0x100) ? 0x04 : 0x00) |
1236 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */
1237 ((HSS & 0x100) ? 0x10 : 0x00) |
1238 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1239 (((HT-5) & 0x100) ? 0x40 : 0x00) );
1240
1241 WCrt(ba, CRT_ID_EXT_VER_OVF,
1242 0x40 | /* Line compare */
1243 ((VT & 0x400) ? 0x01 : 0x00) |
1244 ((VDE & 0x400) ? 0x02 : 0x00) |
1245 ((VBS & 0x400) ? 0x04 : 0x00) |
1246 ((VSS & 0x400) ? 0x10 : 0x00) );
1247
1248 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1249 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5);
1250
1251 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1252 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1253 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80));
1254 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1255 WCrt(ba, CRT_ID_END_HOR_RETR,
1256 (HSE & 0x1f) |
1257 ((HBE & 0x20) ? 0x80 : 0x00) );
1258 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1259 WCrt(ba, CRT_ID_OVERFLOW,
1260 0x10 |
1261 ((VT & 0x100) ? 0x01 : 0x00) |
1262 ((VDE & 0x100) ? 0x02 : 0x00) |
1263 ((VSS & 0x100) ? 0x04 : 0x00) |
1264 ((VBS & 0x100) ? 0x08 : 0x00) |
1265 ((VT & 0x200) ? 0x20 : 0x00) |
1266 ((VDE & 0x200) ? 0x40 : 0x00) |
1267 ((VSS & 0x200) ? 0x80 : 0x00) );
1268
1269 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
1270 0x40 | /* TEXT ? 0x00 ??? */
1271 (DBLSCAN ? 0x80 : 0x00) |
1272 ((VBS & 0x200) ? 0x20 : 0x00) |
1273 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1274
1275 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
1276
1277 /* text cursor */
1278
1279 if (TEXT) {
1280 #if 1
1281 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1282 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1283 #else
1284 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1285 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1286 #endif
1287 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1288
1289 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1290 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1291 }
1292
1293 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1294 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1295
1296 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1297 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f));
1298 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1299 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1300 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1301
1302 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1303 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2);
1304 WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
1305
1306 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1307 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1308 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1309
1310 WSeq (ba, SEQ_ID_MEMORY_MODE,
1311 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02));
1312
1313 vgaw(ba, VDAC_MASK, 0xff);
1314
1315 /* Blank border */
1316 test = RCrt(ba, CRT_ID_BACKWAD_COMP_2);
1317 WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
1318
1319 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);
1320 sr15 &= 0xef;
1321 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL);
1322 sr18 &= 0x7f;
1323 clock_mode = 0x00;
1324 cr50 = 0x00;
1325
1326 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2);
1327 test &= 0xd;
1328
1329 /* clear roxxler byte-swapping... */
1330 cv_write_port(0x0040, cv_boardaddr);
1331 cv_write_port(0x0020, cv_boardaddr);
1332
1333 switch (gv->depth) {
1334 case 1:
1335 case 4: /* text */
1336 HDE = gv->disp_width / 16;
1337 break;
1338 case 8:
1339 if (gv->pixel_clock > 80000000) {
1340 clock_mode = 0x10 | 0x02;
1341 sr15 |= 0x10;
1342 sr18 |= 0x80;
1343 }
1344 HDE = gv->disp_width / 8;
1345 cr50 |= 0x00;
1346 break;
1347 case 15:
1348 cv_write_port (0x8020, cv_boardaddr);
1349 clock_mode = 0x30;
1350 HDE = gv->disp_width / 4;
1351 cr50 |= 0x10;
1352 break;
1353 case 16:
1354 cv_write_port (0x8020, cv_boardaddr);
1355 clock_mode = 0x50;
1356 HDE = gv->disp_width / 4;
1357 cr50 |= 0x10;
1358 break;
1359 case 24: /* this is really 32 Bit on CV64 */
1360 case 32:
1361 cv_write_port(0x8040, cv_boardaddr);
1362 clock_mode = 0xd0;
1363 HDE = (gv->disp_width / 2);
1364 cr50 |= 0x30;
1365 break;
1366 }
1367
1368 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
1369 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15);
1370 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18);
1371 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE);
1372
1373 WCrt(ba, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
1374
1375 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2);
1376 test &= ~0x30;
1377 /* HDE Overflow in bits 4-5 */
1378 test |= (HDE >> 4) & 0x30;
1379 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test);
1380
1381 /* Set up graphics engine */
1382 switch (gv->disp_width) {
1383 case 1024:
1384 cr50 |= 0x00;
1385 break;
1386 case 640:
1387 cr50 |= 0x40;
1388 break;
1389 case 800:
1390 cr50 |= 0x80;
1391 break;
1392 case 1280:
1393 cr50 |= 0xc0;
1394 break;
1395 case 1152:
1396 cr50 |= 0x01;
1397 break;
1398 case 1600:
1399 cr50 |= 0x81;
1400 break;
1401 default: /* XXX The Xserver has to handle this */
1402 break;
1403 }
1404
1405 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50);
1406
1407 delay(100000);
1408 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
1409 delay(100000);
1410 WAttr(ba, ACT_ID_COLOR_PLANE_ENA,
1411 (gv->depth == 1) ? 0x01 : 0x0f);
1412 delay(100000);
1413
1414 /*
1415 * M-Parameter of Display FIFO
1416 * This is dependant on the pixel clock and the memory clock.
1417 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide.
1418 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time
1419 * to empty the FIFO is tempty = (96/pixelclock) sec.
1420 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2.
1421 * This seems to be logical, ain't it?
1422 * Remember: We have to use integer arithmetics :(
1423 * Divide by 1000 to prevent overflows.
1424 */
1425
1426 tfillm = (96 * (cv_memclk/1000))/240000;
1427
1428 switch(gv->depth) {
1429 case 32:
1430 case 24:
1431 temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1432 break;
1433 case 15:
1434 case 16:
1435 temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1436 break;
1437 case 4:
1438 temptym = (192 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1439 break;
1440 default:
1441 temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1442 break;
1443 }
1444
1445 m = (temptym - tfillm - 9) / 2;
1446 if (m < 0)
1447 m = 0; /* prevent underflow */
1448 m = (m & 0x1f) << 3;
1449 if (m < 0x18)
1450 m = 0x18;
1451 n = 0xff;
1452
1453 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m);
1454 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n);
1455 delay(10000);
1456
1457 /* text initialization */
1458
1459 if (TEXT) {
1460 cv_inittextmode(gp);
1461 }
1462
1463 if (CONSOLE) {
1464 int i;
1465 vgaw(ba, VDAC_ADDRESS_W, 0);
1466 for (i = 0; i < 16; i++) {
1467 vgaw(ba, VDAC_DATA, cvconscolors[i][0]);
1468 vgaw(ba, VDAC_DATA, cvconscolors[i][1]);
1469 vgaw(ba, VDAC_DATA, cvconscolors[i][2]);
1470 }
1471 }
1472
1473 /* Some kind of Magic */
1474 WAttr(ba, 0x33, 0);
1475
1476 /* turn gfx on again */
1477 gfx_on_off(0, ba);
1478
1479 /* Pass-through */
1480 cvscreen(0, ba - 0x02000000);
1481
1482 return (1);
1483 }
1484
1485
1486 void
1487 cv_inittextmode(gp)
1488 struct grf_softc *gp;
1489 {
1490 struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data;
1491 volatile caddr_t ba, fb;
1492 unsigned char *c, *f, y;
1493 unsigned short z;
1494
1495 ba = gp->g_regkva;
1496 fb = gp->g_fbkva;
1497
1498 /* load text font into beginning of display memory.
1499 * Each character cell is 32 bytes long (enough for 4 planes)
1500 * In linear adressing text mode, the memory is organized
1501 * so, that the Bytes of all 4 planes are interleaved.
1502 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2,
1503 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,...
1504 * The font is loaded in plane 2.
1505 */
1506
1507 c = (unsigned char *) fb;
1508
1509 /* clear screen */
1510 for (z = 0; z < tm->cols * tm->rows * 3; z++) {
1511 *c++ = 0x20;
1512 *c++ = 0x07;
1513 *c++ = 0;
1514 *c++ = 0;
1515 }
1516
1517 c = (unsigned char *) (fb) + (32 * tm->fdstart * 4 + 2);
1518 f = tm->fdata;
1519 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4)
1520 for (y = 0; y < tm->fy; y++) {
1521 *c = *f++;
1522 c += 4;
1523 }
1524
1525 /* print out a little init msg */
1526 c = (unsigned char *)(fb) + (tm->cols - 6) * 4;
1527 *c++ = 'C';
1528 *c++ = 0x0a;
1529 c +=2;
1530 *c++ = 'V';
1531 *c++ = 0x0b;
1532 c +=2;
1533 *c++ = '6';
1534 *c++ = 0x0c;
1535 c +=2;
1536 *c++ = '4';
1537 *c++ = 0x0d;
1538 }
1539
1540
1541 static inline void
1542 cv_write_port(bits, BoardAddr)
1543 unsigned short bits;
1544 volatile caddr_t BoardAddr;
1545 {
1546 volatile caddr_t addr;
1547 static unsigned char CVPortBits = 0; /* mirror port bits here */
1548
1549 addr = BoardAddr + 0x40001;
1550 if (bits & 0x8000)
1551 CVPortBits |= bits & 0xFF; /* Set bits */
1552 else {
1553 bits = bits & 0xFF;
1554 bits = (~bits) & 0xFF ;
1555 CVPortBits &= bits; /* Clear bits */
1556 }
1557
1558 *addr = CVPortBits;
1559 }
1560
1561
1562 /*
1563 * Monitor Switch
1564 * 0 = CyberVision Signal
1565 * 1 = Amiga Signal,
1566 * ba = boardaddr
1567 */
1568 static inline void
1569 cvscreen(toggle, ba)
1570 int toggle;
1571 volatile caddr_t ba;
1572 {
1573
1574 if (toggle == 1)
1575 cv_write_port (0x10, ba);
1576 else
1577 cv_write_port (0x8010, ba);
1578 }
1579
1580
1581 /* 0 = on, 1= off */
1582 /* ba= registerbase */
1583 static inline void
1584 gfx_on_off(toggle, ba)
1585 int toggle;
1586 volatile caddr_t ba;
1587 {
1588 int r;
1589
1590 toggle &= 0x1;
1591 toggle = toggle << 5;
1592
1593 r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
1594 r &= 0xdf; /* set Bit 5 to 0 */
1595
1596 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
1597 }
1598
1599
1600 #ifdef CV_HARDWARE_CURSOR
1601
1602 static unsigned char cv_hotx = 0, cv_hoty = 0;
1603
1604 /* Hardware Cursor handling routines */
1605
1606 int
1607 cv_getspritepos (gp, pos)
1608 struct grf_softc *gp;
1609 struct grf_position *pos;
1610 {
1611 int hi,lo;
1612 volatile caddr_t ba = gp->g_regkva;
1613
1614 hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI);
1615 lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO);
1616
1617 pos->y = (hi << 8) + lo;
1618 hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI);
1619 lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO);
1620 pos->x = (hi << 8) + lo;
1621 return (0);
1622 }
1623
1624
1625 int
1626 cv_setspritepos (gp, pos)
1627 struct grf_softc *gp;
1628 struct grf_position *pos;
1629 {
1630 volatile caddr_t ba = gp->g_regkva;
1631 short x = pos->x, y = pos->y;
1632 short xoff, yoff;
1633
1634 x -= cv_hotx;
1635 y -= cv_hoty;
1636 if (x < 0) {
1637 xoff = ((-x) & 0xFE);
1638 x = 0;
1639 } else {
1640 xoff = 0;
1641 }
1642
1643 if (y < 0) {
1644 yoff = ((-y) & 0xFE);
1645 y = 0;
1646 } else {
1647 yoff = 0;
1648 }
1649
1650 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8));
1651 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff));
1652
1653 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff));
1654 WCrt (ba, CRT_ID_HWGC_DSTART_X, xoff);
1655 WCrt (ba, CRT_ID_HWGC_DSTART_Y, yoff);
1656 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8));
1657
1658 return(0);
1659 }
1660
1661 static inline short
1662 M2I(short val) {
1663 asm volatile (" rorw #8,%0 ; \
1664 swap %0 ; \
1665 rorw #8,%0 ; " : "=d" (val) : "0" (val));
1666 return (val);
1667 }
1668
1669 #define M2INS(val) \
1670 asm volatile (" rorw #8,%0 ; \
1671 swap %0 ; \
1672 rorw #8,%0 ; \
1673 swap %0 ; " : "=d" (val) : "0" (val));
1674
1675 #define HWC_OFF (cv_fbsize - 1024*2)
1676 #define HWC_SIZE 1024
1677
1678
1679 int
1680 cv_getspriteinfo (gp, info)
1681 struct grf_softc *gp;
1682 struct grf_spriteinfo *info;
1683 {
1684 volatile caddr_t ba, fb;
1685
1686 ba = gp->g_regkva;
1687 fb = gp->g_fbkva;
1688
1689 if (info->set & GRFSPRSET_ENABLE)
1690 info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01;
1691
1692 if (info->set & GRFSPRSET_POS)
1693 cv_getspritepos (gp, &info->pos);
1694
1695 #if 0 /* XXX */
1696 if (info->set & GRFSPRSET_SHAPE) {
1697 u_char image[512], mask[512];
1698 volatile u_long *hwp;
1699 u_char *imp, *mp;
1700 short row;
1701 info->size.x = 64;
1702 info->size.y = 64;
1703 for (row = 0, hwp = (u_long *)(fb + HWC_OFF),
1704 mp = mask, imp = image;
1705 row < 64;
1706 row++) {
1707 u_long bp10, bp20, bp11, bp21;
1708 bp10 = *hwp++;
1709 bp20 = *hwp++;
1710 bp11 = *hwp++;
1711 bp21 = *hwp++;
1712 M2I (bp10);
1713 M2I (bp20);
1714 M2I (bp11);
1715 M2I (bp21);
1716 *imp++ = (~bp10) & bp11;
1717 *imp++ = (~bp20) & bp21;
1718 *mp++ = (~bp10) | (bp10 & ~bp11);
1719 *mp++ = (~bp20) & (bp20 & ~bp21);
1720 }
1721 copyout (image, info->image, sizeof (image));
1722 copyout (mask, info->mask, sizeof (mask));
1723 }
1724 #endif
1725 return(0);
1726 }
1727
1728
1729 void
1730 cv_setup_hwc (gp, col1, col2, hsx, hsy, data)
1731 struct grf_softc *gp;
1732 unsigned char col1;
1733 unsigned char col2;
1734 unsigned char hsx;
1735 unsigned char hsy;
1736 const unsigned long *data;
1737 {
1738 volatile caddr_t ba = gp->g_regkva;
1739 unsigned long *c = (unsigned long *)(gp->g_fbkva + HWC_OFF);
1740 const unsigned long *s = data;
1741 int test;
1742
1743 short x = (HWC_SIZE / (4*4)) - 1;
1744 /* copy only, if there is a data pointer. */
1745 if (data) do {
1746 *c++ = *s++;
1747 *c++ = *s++;
1748 *c++ = *s++;
1749 *c++ = *s++;
1750 } while (x-- > 0);
1751
1752 /* reset colour stack */
1753 test = RCrt(ba, CRT_ID_HWGC_MODE);
1754 asm volatile("nop");
1755 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1756 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1757 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1758
1759 test = RCrt(ba, CRT_ID_HWGC_MODE);
1760 asm volatile("nop");
1761 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
1762 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
1763 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
1764
1765 test = HWC_OFF / HWC_SIZE;
1766 WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8));
1767 WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff));
1768
1769 WCrt (ba, CRT_ID_HWGC_DSTART_X , 0);
1770 WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0);
1771
1772 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */
1773
1774 WCrt (ba, CRT_ID_HWGC_MODE, 0x01);
1775 }
1776
1777
1778 /* This is the reason why you shouldn't use the HGC in the Kernel:( */
1779
1780 #define VerticalRetraceWait(ba) \
1781 { \
1782 while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \
1783 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \
1784 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \
1785 }
1786
1787
1788 int
1789 cv_setspriteinfo (gp, info)
1790 struct grf_softc *gp;
1791 struct grf_spriteinfo *info;
1792 {
1793 volatile caddr_t ba, fb;
1794 int depth = gp->g_display.gd_planes;
1795
1796 ba = gp->g_regkva;
1797 fb = gp->g_fbkva;
1798
1799 if (info->set & GRFSPRSET_SHAPE) {
1800 /*
1801 * For an explanation of these weird actions here, see above
1802 * when reading the shape. We set the shape directly into
1803 * the video memory, there's no reason to keep 1k on the
1804 * kernel stack just as template
1805 */
1806 u_char *image, *mask;
1807 volatile u_short *hwp;
1808 u_char *imp, *mp;
1809 unsigned short row;
1810
1811 /* Cursor off */
1812 WCrt (ba, CRT_ID_HWGC_MODE, 0x00);
1813
1814 /*
1815 * The Trio64 crashes if the cursor data is written
1816 * while the cursor is displayed.
1817 * Sadly, turning the cursor off is not enough.
1818 * What we have to do is:
1819 * 1. Wait for vertical retrace, to make sure no-one
1820 * has moved the cursor in this sync period (because
1821 * another write then would have no effect, argh!).
1822 * 2. Move the cursor off-screen
1823 * 3. Another wait for v. retrace to make sure the cursor
1824 * is really off.
1825 * 4. Write the data, finally.
1826 * (thanks to Harald Koenig for this tip!)
1827 */
1828
1829 VerticalRetraceWait(ba);
1830
1831 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7);
1832 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, 0xff);
1833 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff);
1834 WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f);
1835 WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f);
1836 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7);
1837
1838 if (info->size.y > 64)
1839 info->size.y = 64;
1840 if (info->size.x > 64)
1841 info->size.x = 64;
1842 if (info->size.x < 32)
1843 info->size.x = 32;
1844
1845 image = malloc(HWC_SIZE, M_TEMP, M_WAITOK);
1846 mask = image + HWC_SIZE/2;
1847
1848 copyin(info->image, image, info->size.y * info->size.x / 8);
1849 copyin(info->mask, mask, info->size.y * info->size.x / 8);
1850
1851 hwp = (u_short *)(fb +HWC_OFF);
1852
1853 /* This is necessary in order not to crash the board */
1854
1855 VerticalRetraceWait(ba);
1856
1857 /*
1858 * setting it is slightly more difficult, because we can't
1859 * force the application to not pass a *smaller* than
1860 * supported bitmap
1861 */
1862
1863 for (row = 0, mp = mask, imp = image;
1864 row < info->size.y; row++) {
1865 u_short im1, im2, im3, im4, m1, m2, m3, m4;
1866
1867 im1 = *(unsigned short *)imp;
1868 imp += 2;
1869 m1 = *(unsigned short *)mp;
1870 mp += 2;
1871
1872 im2 = *(unsigned short *)imp;
1873 imp += 2;
1874 m2 = *(unsigned short *)mp;
1875 mp += 2;
1876
1877 if (info->size.x > 32) {
1878 im3 = *(unsigned long *)imp;
1879 imp += 4;
1880 m3 = *(unsigned long *)mp;
1881 mp += 4;
1882 im4 = *(unsigned long *)imp;
1883 imp += 4;
1884 m4 = *(unsigned long *)mp;
1885 mp += 4;
1886 }
1887 else
1888 im3 = m3 = im4 = m4 = 0;
1889
1890 switch (depth) {
1891 case 8:
1892 *hwp++ = m1;
1893 *hwp++ = im1;
1894 *hwp++ = m2;
1895 *hwp++ = im2;
1896 *hwp++ = m3;
1897 *hwp++ = im3;
1898 *hwp++ = m4;
1899 *hwp++ = im4;
1900 break;
1901 case 15:
1902 case 16:
1903 *hwp++ = M2I(m1);
1904 *hwp++ = M2I(im1);
1905 *hwp++ = M2I(m2);
1906 *hwp++ = M2I(im2);
1907 *hwp++ = M2I(m3);
1908 *hwp++ = M2I(im3);
1909 *hwp++ = M2I(m4);
1910 *hwp++ = M2I(im4);
1911 break;
1912 case 24:
1913 case 32:
1914 *hwp++ = M2I(im1);
1915 *hwp++ = M2I(m1);
1916 *hwp++ = M2I(im2);
1917 *hwp++ = M2I(m2);
1918 *hwp++ = M2I(im3);
1919 *hwp++ = M2I(m3);
1920 *hwp++ = M2I(im4);
1921 *hwp++ = M2I(m4);
1922 break;
1923 }
1924 }
1925 for (; row < 64; row++) {
1926 *hwp++ = 0x0000;
1927 *hwp++ = 0x0000;
1928 *hwp++ = 0x0000;
1929 *hwp++ = 0x0000;
1930 *hwp++ = 0x0000;
1931 *hwp++ = 0x0000;
1932 *hwp++ = 0x0000;
1933 *hwp++ = 0x0000;
1934 }
1935 free(image, M_TEMP);
1936 cv_setup_hwc(gp, 1, 0, 0, 0, NULL);
1937 cv_hotx = info->hot.x;
1938 cv_hoty = info->hot.y;
1939
1940 /* One must not write twice per vertical blank :-( */
1941 /* VerticalRetraceWait(ba); */
1942
1943 cv_setspritepos (gp, &info->pos);
1944 }
1945 if (info->set & GRFSPRSET_CMAP) {
1946 int test;
1947
1948 VerticalRetraceWait(ba);
1949
1950 /* reset colour stack */
1951 test = RCrt(ba, CRT_ID_HWGC_MODE);
1952 asm volatile("nop");
1953 switch (depth) {
1954 case 32:
1955 case 24:
1956 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1957 case 16:
1958 case 8:
1959 /* info->cmap.green[1] */
1960 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1961 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1962 }
1963
1964 test = RCrt(ba, CRT_ID_HWGC_MODE);
1965 asm volatile("nop");
1966 switch (depth) {
1967 case 8:
1968 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1);
1969 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1);
1970 break;
1971 case 32: case 24:
1972 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
1973 case 16:
1974 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
1975 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
1976 }
1977 }
1978
1979 if (info->set & GRFSPRSET_ENABLE) {
1980 #if 0
1981 if (info->enable)
1982 control = 0x85;
1983 else
1984 control = 0;
1985 WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
1986 #endif
1987 }
1988 if (info->set & GRFSPRSET_POS)
1989 cv_setspritepos(gp, &info->pos);
1990 if (info->set & GRFSPRSET_HOT) {
1991
1992 cv_hotx = info->hot.x;
1993 cv_hoty = info->hot.y;
1994 cv_setspritepos (gp, &info->pos);
1995 }
1996 return(0);
1997 }
1998
1999
2000 int
2001 cv_getspritemax (gp, pos)
2002 struct grf_softc *gp;
2003 struct grf_position *pos;
2004 {
2005
2006 pos->x = 64;
2007 pos->y = 64;
2008 return(0);
2009 }
2010
2011 #endif /* CV_HARDWARE_CURSOR */
2012
2013 #endif /* NGRFCV */
2014