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