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