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