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