grf_cv.c revision 1.13 1 /* $NetBSD: grf_cv.c,v 1.13 1996/05/01 09:59:24 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 *, char *));
73
74 static int cv_has_4mb __P((volatile caddr_t));
75 static unsigned short 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 {0xff, 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 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 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 = 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 : 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 bcopy(gv, md, sizeof(struct grfvideo_mode));
931
932 /* adjust pixel oriented values to internal rep. */
933
934 md->hblank_start /= 8;
935 md->hblank_stop /= 8;
936 md->hsync_start /= 8;
937 md->hsync_stop /= 8;
938 md->htotal /= 8;
939
940 return (0);
941 }
942
943
944 int
945 cv_getcmap(gfp, cmap)
946 struct grf_softc *gfp;
947 struct grf_colormap *cmap;
948 {
949 volatile caddr_t ba;
950 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
951 short x;
952 int error;
953
954 ba = gfp->g_regkva;
955 if (cmap->count == 0 || cmap->index >= 256)
956 return (0);
957
958 if (cmap->index + cmap->count > 256)
959 cmap->count = 256 - cmap->index;
960
961 /* first read colors out of the chip, then copyout to userspace */
962 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
963 x = cmap->count - 1;
964
965 rp = red + cmap->index;
966 gp = green + cmap->index;
967 bp = blue + cmap->index;
968
969 do {
970 *rp++ = vgar (ba, VDAC_DATA) << 2;
971 *gp++ = vgar (ba, VDAC_DATA) << 2;
972 *bp++ = vgar (ba, VDAC_DATA) << 2;
973 } while (x-- > 0);
974
975 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
976 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
977 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
978 return (0);
979
980 return (error);
981 }
982
983
984 int
985 cv_putcmap(gfp, cmap)
986 struct grf_softc *gfp;
987 struct grf_colormap *cmap;
988 {
989 volatile caddr_t ba;
990 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
991 short x;
992 int error;
993
994 ba = gfp->g_regkva;
995 if (cmap->count == 0 || cmap->index >= 256)
996 return (0);
997
998 if (cmap->index + cmap->count > 256)
999 cmap->count = 256 - cmap->index;
1000
1001 /* first copy the colors into kernelspace */
1002 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1003 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1004 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
1005 vgaw (ba, VDAC_ADDRESS_W, cmap->index);
1006 x = cmap->count - 1;
1007
1008 rp = red + cmap->index;
1009 gp = green + cmap->index;
1010 bp = blue + cmap->index;
1011
1012 do {
1013 vgaw (ba, VDAC_DATA, *rp++ >> 2);
1014 vgaw (ba, VDAC_DATA, *gp++ >> 2);
1015 vgaw (ba, VDAC_DATA, *bp++ >> 2);
1016 } while (x-- > 0);
1017 return (0);
1018 } else
1019 return (error);
1020 }
1021
1022
1023 int
1024 cv_toggle(gp)
1025 struct grf_softc *gp;
1026 {
1027 volatile caddr_t ba;
1028
1029 ba = gp->g_regkva;
1030 cvscreen(1, ba - 0x02000000);
1031
1032 return (0);
1033 }
1034
1035
1036 int
1037 cv_mondefok(gv)
1038 struct grfvideo_mode *gv;
1039 {
1040 unsigned long maxpix;
1041 int widthok = 0;
1042
1043 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
1044 if (gv->mode_num != 255 || (gv->depth != 4 && gv->depth != 8))
1045 return (0);
1046 }
1047
1048 switch(gv->depth) {
1049 case 4:
1050 case 8:
1051 maxpix = MAXPIXELCLOCK;
1052 break;
1053 case 15:
1054 case 16:
1055 #ifdef CV_AGGRESSIVE_TIMING
1056 maxpix = MAXPIXELCLOCK - 35000000;
1057 #else
1058 maxpix = MAXPIXELCLOCK - 55000000;
1059 #endif
1060 break;
1061 case 24:
1062 case 32:
1063 #ifdef CV_AGGRESSIVE_TIMING
1064 maxpix = MAXPIXELCLOCK - 75000000;
1065 #else
1066 maxpix = MAXPIXELCLOCK - 85000000;
1067 #endif
1068 break;
1069 default:
1070 return (0);
1071 }
1072
1073 if (gv->pixel_clock > maxpix)
1074 return (0);
1075
1076 /*
1077 * These are the supported witdh values for the
1078 * graphics engine. To Support other widths, one
1079 * has to use one of these widths for memory alignment, i.e.
1080 * one has to set CRT_ID_SCREEN_OFFSET to one of these values and
1081 * CRT_ID_HOR_DISP_ENA_END to the desired width.
1082 * Since a working graphics engine is essential
1083 * for the console, console modes of other width are not supported.
1084 * We could do that, though, but then you have to tell the Xserver
1085 * about this strange configuration and I don't know how at the moment :-)
1086 */
1087
1088 switch (gv->disp_width) {
1089 case 1024:
1090 case 640:
1091 case 800:
1092 case 1280:
1093 case 1152:
1094 case 1600:
1095 widthok = 1;
1096 break;
1097 default: /* XXX*/
1098 widthok = 0;
1099 break;
1100 }
1101
1102 if (widthok) return (1);
1103 else {
1104 if (gv->mode_num == 255) { /* console mode */
1105 return (1);
1106 } else {
1107 printf ("Warning for mode %d:\n", (int) gv->mode_num);
1108 printf ("Don't use a blitter-suporting Xserver with this display width\n");
1109 printf ("Use one of 640 800 1024 1152 1280 1600!\n");
1110 return (1);
1111 }
1112 }
1113 return (1);
1114 }
1115
1116
1117 int
1118 cv_load_mon(gp, md)
1119 struct grf_softc *gp;
1120 struct grfcvtext_mode *md;
1121 {
1122 struct grfvideo_mode *gv;
1123 struct grfinfo *gi;
1124 volatile caddr_t ba, fb;
1125 unsigned short mnr;
1126 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1127 VSE, VT;
1128 char LACE, DBLSCAN, TEXT, CONSOLE;
1129 int uplim, lowlim;
1130 int cr50, cr33, sr15, sr18, clock_mode, test;
1131 int m, n; /* For calc'ing display FIFO */
1132 int tfillm, temptym; /* FIFO fill and empty mclk's */
1133 int hmul; /* Multiplier for hor. Values */
1134 /* identity */
1135 gv = &md->gv;
1136
1137 TEXT = (gv->depth == 4);
1138 CONSOLE = (gv->mode_num == 255);
1139
1140 if (!cv_mondefok(gv)) {
1141 printf("grfcv: The monitor definition is not okay.\n");
1142 printf("grfcv: See the manpage of grfconfig for more informations\n");
1143 return (0);
1144 }
1145 ba = gp->g_regkva;
1146 fb = gp->g_fbkva;
1147
1148 /* turn gfx off, don't mess up the display */
1149 gfx_on_off(1, ba);
1150
1151 /* provide all needed information in grf device-independant locations */
1152 gp->g_data = (caddr_t) gv;
1153 gi = &gp->g_display;
1154 gi->gd_colors = 1 << gv->depth;
1155 gi->gd_planes = gv->depth;
1156 gi->gd_fbwidth = gv->disp_width;
1157 gi->gd_fbheight = gv->disp_height;
1158 gi->gd_fbx = 0;
1159 gi->gd_fby = 0;
1160 if (CONSOLE) {
1161 gi->gd_dwidth = md->fx * md->cols;
1162 gi->gd_dheight = md->fy * md->rows;
1163 } else {
1164 gi->gd_dwidth = gv->disp_width;
1165 gi->gd_dheight = gv->disp_height;
1166 }
1167 gi->gd_dx = 0;
1168 gi->gd_dy = 0;
1169
1170 /* get display mode parameters */
1171 switch (gv->depth) {
1172 case 15:
1173 case 16:
1174 hmul = 2;
1175 break;
1176 default:
1177 hmul = 1;
1178 break;
1179 }
1180
1181 HBS = gv->hblank_start * hmul;
1182 HBE = gv->hblank_stop * hmul;
1183 HSS = gv->hsync_start * hmul;
1184 HSE = gv->hsync_stop * hmul;
1185 HT = gv->htotal*hmul - 5;
1186 VBS = gv->vblank_start - 1;
1187 VSS = gv->vsync_start;
1188 VSE = gv->vsync_stop;
1189 VBE = gv->vblank_stop;
1190 VT = gv->vtotal - 2;
1191
1192 /* Disable enhanced Mode for text display */
1193
1194 vgaw(ba, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1195
1196 if (TEXT)
1197 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1198 else
1199 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/
1200 VDE = gv->disp_height - 1;
1201
1202 /* figure out whether lace or dblscan is needed */
1203
1204 uplim = gv->disp_height + (gv->disp_height / 4);
1205 lowlim = gv->disp_height - (gv->disp_height / 4);
1206 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1207 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1208
1209 /* adjustments */
1210
1211 if (LACE)
1212 VDE /= 2;
1213
1214 /* GFx hardware cursor off */
1215 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
1216
1217 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1218 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1219 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1220 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1221
1222 /* Set clock */
1223
1224 mnr = compute_clock(gv->pixel_clock);
1225 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1226 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1227
1228 /* load display parameters into board */
1229
1230 WCrt(ba, CRT_ID_EXT_HOR_OVF,
1231 ((HT & 0x100) ? 0x01 : 0x00) |
1232 ((HDE & 0x100) ? 0x02 : 0x00) |
1233 ((HBS & 0x100) ? 0x04 : 0x00) |
1234 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */
1235 ((HSS & 0x100) ? 0x10 : 0x00) |
1236 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1237 (((HT-5) & 0x100) ? 0x40 : 0x00) );
1238
1239 WCrt(ba, CRT_ID_EXT_VER_OVF,
1240 0x40 | /* Line compare */
1241 ((VT & 0x400) ? 0x01 : 0x00) |
1242 ((VDE & 0x400) ? 0x02 : 0x00) |
1243 ((VBS & 0x400) ? 0x04 : 0x00) |
1244 ((VSS & 0x400) ? 0x10 : 0x00) );
1245
1246 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1247 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5);
1248
1249 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1250 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1251 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80));
1252 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1253 WCrt(ba, CRT_ID_END_HOR_RETR,
1254 (HSE & 0x1f) |
1255 ((HBE & 0x20) ? 0x80 : 0x00) );
1256 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1257 WCrt(ba, CRT_ID_OVERFLOW,
1258 0x10 |
1259 ((VT & 0x100) ? 0x01 : 0x00) |
1260 ((VDE & 0x100) ? 0x02 : 0x00) |
1261 ((VSS & 0x100) ? 0x04 : 0x00) |
1262 ((VBS & 0x100) ? 0x08 : 0x00) |
1263 ((VT & 0x200) ? 0x20 : 0x00) |
1264 ((VDE & 0x200) ? 0x40 : 0x00) |
1265 ((VSS & 0x200) ? 0x80 : 0x00) );
1266
1267 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
1268 0x40 | /* TEXT ? 0x00 ??? */
1269 (DBLSCAN ? 0x80 : 0x00) |
1270 ((VBS & 0x200) ? 0x20 : 0x00) |
1271 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1272
1273 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
1274
1275 /* text cursor */
1276
1277 if (TEXT) {
1278 #if 1
1279 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1280 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1281 #else
1282 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1283 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1284 #endif
1285 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1286
1287 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1288 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1289 }
1290
1291 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1292 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1293
1294 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1295 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f));
1296 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1297 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1298 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1299
1300 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1301 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2);
1302 WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
1303
1304 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1305 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1306 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1307
1308 WSeq (ba, SEQ_ID_MEMORY_MODE,
1309 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02));
1310
1311 vgaw(ba, VDAC_MASK, 0xff);
1312
1313 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);
1314 sr15 &= 0xef;
1315 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL);
1316 sr18 &= 0x7f;
1317 cr33 = RCrt(ba, CRT_ID_BACKWAD_COMP_2);
1318 cr33 &= 0xdf;
1319 clock_mode = 0x00;
1320 cr50 = 0x00;
1321
1322 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2);
1323 test &= 0xd;
1324
1325 /* clear roxxler byte-swapping... */
1326 cv_write_port(0x0040, cv_boardaddr);
1327 cv_write_port(0x0020, cv_boardaddr);
1328
1329 switch (gv->depth) {
1330 case 1:
1331 case 4: /* text */
1332 HDE = gv->disp_width / 16;
1333 break;
1334 case 8:
1335 if (gv->pixel_clock > 80000000) {
1336 clock_mode = 0x10 | 0x02;
1337 sr15 |= 0x10;
1338 sr18 |= 0x80;
1339 cr33 |= 0x20;
1340 }
1341 HDE = gv->disp_width / 8;
1342 cr50 |= 0x00;
1343 break;
1344 case 15:
1345 cv_write_port (0x8020, cv_boardaddr);
1346 clock_mode = 0x30;
1347 HDE = gv->disp_width / 4;
1348 cr50 |= 0x10;
1349 break;
1350 case 16:
1351 cv_write_port (0x8020, cv_boardaddr);
1352 clock_mode = 0x50;
1353 HDE = gv->disp_width / 4;
1354 cr50 |= 0x10;
1355 break;
1356 case 24: /* this is really 32 Bit on CV64 */
1357 case 32:
1358 cv_write_port(0x8040, cv_boardaddr);
1359 clock_mode = 0xd0;
1360 HDE = (gv->disp_width / 2);
1361 cr50 |= 0x30;
1362 break;
1363 }
1364
1365 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
1366 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15);
1367 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18);
1368 WCrt(ba, CRT_ID_BACKWAD_COMP_2, cr33);
1369 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE);
1370
1371 WCrt(ba, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
1372
1373 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2);
1374 test &= ~0x30;
1375 /* HDE Overflow in bits 4-5 */
1376 test |= (HDE >> 4) & 0x30;
1377 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test);
1378
1379 /* Set up graphics engine */
1380 switch (gv->disp_width) {
1381 case 1024:
1382 cr50 |= 0x00;
1383 break;
1384 case 640:
1385 cr50 |= 0x40;
1386 break;
1387 case 800:
1388 cr50 |= 0x80;
1389 break;
1390 case 1280:
1391 cr50 |= 0xc0;
1392 break;
1393 case 1152:
1394 cr50 |= 0x01;
1395 break;
1396 case 1600:
1397 cr50 |= 0x81;
1398 break;
1399 default: /* XXX*/
1400 break;
1401 }
1402
1403 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50);
1404
1405 delay(100000);
1406 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
1407 delay(100000);
1408 WAttr(ba, ACT_ID_COLOR_PLANE_ENA,
1409 (gv->depth == 1) ? 0x01 : 0x0f);
1410 delay(100000);
1411
1412 /*
1413 * M-Parameter of Display FIFO
1414 * This is dependant on the pixel clock and the memory clock.
1415 * The FIFO filling bandwidth is 240 MHz and the FIFO is 96 Byte wide.
1416 * Then the time to fill the FIFO is tfill = (96/240000000) sec, the time
1417 * to empty the FIFO is tempty = (96/pixelclock) sec.
1418 * Then the M parameter maximum is ((tempty-tfill)*cv_memclk-9)/2.
1419 * This seems to be logical, ain't it?
1420 * Remember: We have to use integer arithmetics :(
1421 * Divide by 1000 to prevent overflows.
1422 */
1423
1424 tfillm = (96 * (cv_memclk/1000))/240000;
1425
1426 switch(gv->depth) {
1427 case 32:
1428 case 24:
1429 temptym = (24 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1430 break;
1431 case 15:
1432 case 16:
1433 temptym = (48 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1434 break;
1435 default:
1436 temptym = (96 * (cv_memclk/1000)) / (gv->pixel_clock/1000);
1437 break;
1438 }
1439
1440 m = (temptym - tfillm - 9) / 2;
1441 if (m < 0)
1442 m = 0; /* prevent underflow */
1443 m = (m & 0x1f) << 3;
1444 if (m < 0x18)
1445 m = 0x18;
1446 n = 0xff;
1447
1448 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, m);
1449 WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, n);
1450 delay(10000);
1451
1452 /* text initialization */
1453
1454 if (TEXT) {
1455 cv_inittextmode(gp);
1456 }
1457
1458 if (CONSOLE) {
1459 int i;
1460 vgaw(ba, VDAC_ADDRESS_W, 0);
1461 for (i = 0; i < 16; i++) {
1462 vgaw(ba, VDAC_DATA, cvconscolors[i][0]);
1463 vgaw(ba, VDAC_DATA, cvconscolors[i][1]);
1464 vgaw(ba, VDAC_DATA, cvconscolors[i][2]);
1465 }
1466 }
1467
1468 /* Some kind of Magic */
1469 WAttr(ba, 0x33, 0);
1470
1471 /* turn gfx on again */
1472 gfx_on_off(0, ba);
1473
1474 /* Pass-through */
1475 cvscreen(0, ba - 0x02000000);
1476
1477 return (1);
1478 }
1479
1480
1481 void
1482 cv_inittextmode(gp)
1483 struct grf_softc *gp;
1484 {
1485 struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data;
1486 volatile caddr_t ba, fb;
1487 unsigned char *c, *f, y;
1488 unsigned short z;
1489
1490 ba = gp->g_regkva;
1491 fb = gp->g_fbkva;
1492
1493 /* load text font into beginning of display memory.
1494 * Each character cell is 32 bytes long (enough for 4 planes)
1495 * In linear adressing text mode, the memory is organized
1496 * so, that the Bytes of all 4 planes are interleaved.
1497 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2,
1498 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,...
1499 * The font is loaded in plane 2.
1500 */
1501
1502 c = (unsigned char *) fb;
1503
1504 /* clear screen */
1505 for (z = 0; z < tm->cols * tm->rows * 3; z++) {
1506 *c++ = 0x20;
1507 *c++ = 0x07;
1508 *c++ = 0;
1509 *c++ = 0;
1510 }
1511
1512 c = (unsigned char *) (fb) + (32 * tm->fdstart * 4 + 2);
1513 f = tm->fdata;
1514 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4)
1515 for (y = 0; y < tm->fy; y++) {
1516 *c = *f++;
1517 c += 4;
1518 }
1519
1520 /* print out a little init msg */
1521 c = (unsigned char *)(fb) + (tm->cols - 6) * 4;
1522 *c++ = 'C';
1523 *c++ = 0x0a;
1524 c +=2;
1525 *c++ = 'V';
1526 *c++ = 0x0b;
1527 c +=2;
1528 *c++ = '6';
1529 *c++ = 0x0c;
1530 c +=2;
1531 *c++ = '4';
1532 *c++ = 0x0d;
1533 }
1534
1535
1536 static inline void
1537 cv_write_port(bits, BoardAddr)
1538 unsigned short bits;
1539 volatile caddr_t BoardAddr;
1540 {
1541 volatile caddr_t addr;
1542 static unsigned char CVPortBits = 0; /* mirror port bits here */
1543
1544 addr = BoardAddr + 0x40001;
1545 if (bits & 0x8000)
1546 CVPortBits |= bits & 0xFF; /* Set bits */
1547 else {
1548 bits = bits & 0xFF;
1549 bits = (~bits) & 0xFF ;
1550 CVPortBits &= bits; /* Clear bits */
1551 }
1552
1553 *addr = CVPortBits;
1554 }
1555
1556
1557 /*
1558 * Monitor Switch
1559 * 0 = CyberVision Signal
1560 * 1 = Amiga Signal,
1561 * ba = boardaddr
1562 */
1563 static inline void
1564 cvscreen(toggle, ba)
1565 int toggle;
1566 volatile caddr_t ba;
1567 {
1568
1569 if (toggle == 1)
1570 cv_write_port (0x10, ba);
1571 else
1572 cv_write_port (0x8010, ba);
1573 }
1574
1575
1576 /* 0 = on, 1= off */
1577 /* ba= registerbase */
1578 static inline void
1579 gfx_on_off(toggle, ba)
1580 int toggle;
1581 volatile caddr_t ba;
1582 {
1583 int r;
1584
1585 toggle &= 0x1;
1586 toggle = toggle << 5;
1587
1588 r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
1589 r &= 0xdf; /* set Bit 5 to 0 */
1590
1591 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
1592 }
1593
1594
1595 #ifdef CV_HARDWARE_CURSOR
1596
1597 static unsigned char cv_hotx = 0, cv_hoty = 0;
1598
1599 /* Hardware Cursor handling routines */
1600
1601 int
1602 cv_getspritepos (gp, pos)
1603 struct grf_softc *gp;
1604 struct grf_position *pos;
1605 {
1606 int hi,lo;
1607 volatile caddr_t ba = gp->g_regkva;
1608
1609 hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI);
1610 lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO);
1611
1612 pos->y = (hi << 8) + lo;
1613 hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI);
1614 lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO);
1615 pos->x = (hi << 8) + lo;
1616 return (0);
1617 }
1618
1619
1620 int
1621 cv_setspritepos (gp, pos)
1622 struct grf_softc *gp;
1623 struct grf_position *pos;
1624 {
1625 volatile caddr_t ba = gp->g_regkva;
1626 short x = pos->x, y = pos->y;
1627 short xoff, yoff;
1628
1629 x -= cv_hotx;
1630 y -= cv_hoty;
1631 if (x < 0) {
1632 xoff = ((-x) & 0xFE);
1633 x = 0;
1634 } else {
1635 xoff = 0;
1636 }
1637
1638 if (y < 0) {
1639 yoff = ((-y) & 0xFE);
1640 y = 0;
1641 } else {
1642 yoff = 0;
1643 }
1644
1645 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8));
1646 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff));
1647
1648 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff));
1649 WCrt (ba, CRT_ID_HWGC_DSTART_X, xoff);
1650 WCrt (ba, CRT_ID_HWGC_DSTART_Y, yoff);
1651 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8));
1652
1653 return(0);
1654 }
1655
1656 #define M2I(val) \
1657 asm volatile (" rorw #8,%0 ; \
1658 swap %0 ; \
1659 rorw #8,%0 ; " : "=d" (val) : "0" (val));
1660
1661 #define M2INS(val) \
1662 asm volatile (" rorw #8,%0 ; \
1663 swap %0 ; \
1664 rorw #8,%0 ; \
1665 swap %0 ; " : "=d" (val) : "0" (val));
1666
1667 #define HWC_OFF (cv_fbsize - 1024*2)
1668 #define HWC_SIZE 1024
1669
1670
1671 int
1672 cv_getspriteinfo (gp, info)
1673 struct grf_softc *gp;
1674 struct grf_spriteinfo *info;
1675 {
1676 volatile caddr_t ba, fb;
1677
1678 ba = gp->g_regkva;
1679 fb = gp->g_fbkva;
1680
1681 if (info->set & GRFSPRSET_ENABLE)
1682 info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01;
1683
1684 if (info->set & GRFSPRSET_POS)
1685 cv_getspritepos (gp, &info->pos);
1686
1687 #if 0 /* XXX */
1688 if (info->set & GRFSPRSET_SHAPE) {
1689 u_char image[512], mask[512];
1690 volatile u_long *hwp;
1691 u_char *imp, *mp;
1692 short row;
1693 info->size.x = 64;
1694 info->size.y = 64;
1695 for (row = 0, hwp = (u_long *)(fb + HWC_OFF),
1696 mp = mask, imp = image;
1697 row < 64;
1698 row++) {
1699 u_long bp10, bp20, bp11, bp21;
1700 bp10 = *hwp++;
1701 bp20 = *hwp++;
1702 bp11 = *hwp++;
1703 bp21 = *hwp++;
1704 M2I (bp10);
1705 M2I (bp20);
1706 M2I (bp11);
1707 M2I (bp21);
1708 *imp++ = (~bp10) & bp11;
1709 *imp++ = (~bp20) & bp21;
1710 *mp++ = (~bp10) | (bp10 & ~bp11);
1711 *mp++ = (~bp20) & (bp20 & ~bp21);
1712 }
1713 copyout (image, info->image, sizeof (image));
1714 copyout (mask, info->mask, sizeof (mask));
1715 }
1716 #endif
1717 return(0);
1718 }
1719
1720
1721 void
1722 cv_setup_hwc (gp, col1, col2, hsx, hsy, data)
1723 struct grf_softc *gp;
1724 unsigned char col1;
1725 unsigned char col2;
1726 unsigned char hsx;
1727 unsigned char hsy;
1728 const unsigned long *data;
1729 {
1730 volatile unsigned char *ba = gp->g_regkva;
1731 unsigned long *c = (unsigned long *)(gp->g_fbkva + HWC_OFF);
1732 const unsigned long *s = data;
1733 int test;
1734
1735 short x = (HWC_SIZE / (4*4)) - 1;
1736 /* copy only, if there is a data pointer. */
1737 if (data) do {
1738 *c++ = *s++;
1739 *c++ = *s++;
1740 *c++ = *s++;
1741 *c++ = *s++;
1742 } while (x-- > 0);
1743
1744 /* reset colour stack */
1745 test = RCrt(ba, CRT_ID_HWGC_MODE);
1746 asm volatile("nop");
1747 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1748 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1749 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1750
1751 test = RCrt(ba, CRT_ID_HWGC_MODE);
1752 asm volatile("nop");
1753 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
1754 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
1755 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
1756
1757 test = HWC_OFF / HWC_SIZE;
1758 WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8));
1759 WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff));
1760
1761 WCrt (ba, CRT_ID_HWGC_DSTART_X , 0);
1762 WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0);
1763
1764 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */
1765
1766 WCrt (ba, CRT_ID_HWGC_MODE, 0x01);
1767 }
1768
1769
1770 /* This is the reason why you shouldn't use the HGC in the Kernel:( */
1771
1772 #define VerticalRetraceWait(ba) \
1773 { \
1774 while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \
1775 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \
1776 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \
1777 }
1778
1779
1780 int
1781 cv_setspriteinfo (gp, info)
1782 struct grf_softc *gp;
1783 struct grf_spriteinfo *info;
1784 {
1785 volatile caddr_t ba, fb;
1786
1787 ba = gp->g_regkva;
1788 fb = gp->g_fbkva;
1789
1790 if (info->set & GRFSPRSET_SHAPE) {
1791 /*
1792 * For an explanation of these weird actions here, see above
1793 * when reading the shape. We set the shape directly into
1794 * the video memory, there's no reason to keep 1k on the
1795 * kernel stack just as template
1796 */
1797 u_char *image, *mask;
1798 volatile u_short *hwp;
1799 u_char *imp, *mp;
1800 unsigned short row;
1801
1802 /* Cursor off */
1803 WCrt (ba, CRT_ID_HWGC_MODE, 0x00);
1804 /* move cursor off-screen */
1805 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7);
1806 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, 0xff);
1807 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff);
1808 WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f);
1809 WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f);
1810 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7);
1811
1812 if (info->size.y > 64)
1813 info->size.y = 64;
1814 if (info->size.x > 64)
1815 info->size.x = 64;
1816 if (info->size.x < 32)
1817 info->size.x = 32;
1818
1819 image = malloc(HWC_SIZE, M_TEMP, M_WAITOK);
1820 mask = image + HWC_SIZE/2;
1821
1822 copyin(info->image, image, info->size.y * info->size.x / 8);
1823 copyin(info->mask, mask, info->size.y * info->size.x / 8);
1824
1825 hwp = (u_short *)(fb +HWC_OFF);
1826
1827 /*
1828 * setting it is slightly more difficult, because we can't
1829 * force the application to not pass a *smaller* than
1830 * supported bitmap
1831 */
1832
1833 for (row = 0, mp = mask, imp = image;
1834 row < info->size.y; row++) {
1835 u_short im1, im2, im3, im4, m1, m2, m3, m4;
1836
1837 im1 = *(unsigned short *)imp;
1838 imp += 2;
1839 m1 = *(unsigned short *)mp;
1840 mp += 2;
1841
1842 im2 = *(unsigned short *)imp;
1843 imp += 2;
1844 m2 = *(unsigned short *)mp;
1845 mp += 2;
1846
1847 if (info->size.x > 32) {
1848 im3 = *(unsigned long *)imp;
1849 imp += 4;
1850 m3 = *(unsigned long *)mp;
1851 mp += 4;
1852 im4 = *(unsigned long *)imp;
1853 imp += 4;
1854 m4 = *(unsigned long *)mp;
1855 mp += 4;
1856 }
1857 else
1858 im3 = m3 = im4 = m4 = 0;
1859
1860 *hwp++ = m1;
1861 *hwp++ = im1;
1862 *hwp++ = m2;
1863 *hwp++ = im2;
1864 *hwp++ = m3;
1865 *hwp++ = im3;
1866 *hwp++ = m4;
1867 *hwp++ = im4;
1868 }
1869 for (; row < 64; row++) {
1870 *hwp++ = 0x0000;
1871 *hwp++ = 0x0000;
1872 *hwp++ = 0x0000;
1873 *hwp++ = 0x0000;
1874 *hwp++ = 0x0000;
1875 *hwp++ = 0x0000;
1876 *hwp++ = 0x0000;
1877 *hwp++ = 0x0000;
1878 }
1879 free(image, M_TEMP);
1880 cv_setup_hwc(gp, 1, 0, 0, 0, NULL);
1881 cv_hotx = info->hot.x;
1882 cv_hoty = info->hot.y;
1883
1884 /* One must not write twice per vertical blank :-( */
1885 VerticalRetraceWait(ba);
1886
1887 cv_setspritepos (gp, &info->pos);
1888 }
1889 if (info->set & GRFSPRSET_CMAP) {
1890 int test;
1891 int depth = gp->g_display.gd_planes;
1892
1893 /* reset colour stack */
1894 test = RCrt(ba, CRT_ID_HWGC_MODE);
1895 asm volatile("nop");
1896 switch (depth) {
1897 case 24: case 32:
1898 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1899 case 8: case 16:
1900 /* info->cmap.green[1] */
1901 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1902 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1903 }
1904
1905 test = RCrt(ba, CRT_ID_HWGC_MODE);
1906 asm volatile("nop");
1907 switch (depth) {
1908 case 8:
1909 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1);
1910 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1);
1911 break;
1912 case 32: case 24:
1913 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
1914 case 16:
1915 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
1916 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
1917 }
1918 }
1919
1920 if (info->set & GRFSPRSET_ENABLE) {
1921 #if 0
1922 if (info->enable)
1923 control = 0x85;
1924 else
1925 control = 0;
1926 WSeq(ba, SEQ_ID_CURSOR_CONTROL, control);
1927 #endif
1928 }
1929 if (info->set & GRFSPRSET_POS)
1930 cv_setspritepos(gp, &info->pos);
1931 if (info->set & GRFSPRSET_HOT) {
1932
1933 cv_hotx = info->hot.x;
1934 cv_hoty = info->hot.y;
1935 cv_setspritepos (gp, &info->pos);
1936 }
1937 return(0);
1938 }
1939
1940
1941 int
1942 cv_getspritemax (gp, pos)
1943 struct grf_softc *gp;
1944 struct grf_position *pos;
1945 {
1946
1947 pos->x = 64;
1948 pos->y = 64;
1949 return(0);
1950 }
1951
1952 #endif /* CV_HARDWARE_CURSOR */
1953
1954 #endif /* NGRFCV */
1955