grf_cv3d.c revision 1.2 1 /* $NetBSD: grf_cv3d.c,v 1.2 1997/10/29 20:00:47 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 * 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 /* Distinct between ZorroII or ZorroIII mode */
329 cv3d_zorroIII = iszthreepa(zap->pa);
330
331 /* Lets be Paranoid: Test man and prod id */
332 if (zap->manid != 8512 || zap->prodid != 67)
333 return (0);
334
335 /* ONLY attach this driver on boards in zorroIII mode */
336 if (cv3d_zorroIII != 1) {
337 printf("grfcv3d: Unsupported ZorroII mode.\n");
338 return (0);
339 }
340
341 cv3d_boardaddr = zap->va;
342
343 #ifdef CV3DCONSOLE
344 if (amiga_realconfig == 0) {
345 cv3dcons_unit = cfp->cf_unit;
346 cfdata = cfp;
347 }
348 #endif
349
350 return (1);
351 }
352
353 void
354 grfcv3dattach(pdp, dp, auxp)
355 struct device *pdp, *dp;
356 void *auxp;
357 {
358 static struct grf_softc congrf;
359 struct zbus_args *zap;
360 struct grf_softc *gp;
361 static char attachflag = 0;
362
363 zap = auxp;
364
365 printf("\n");
366
367 /*
368 * This function is called twice, once on console init (dp == NULL)
369 * and once on "normal" grf7 init.
370 */
371
372 if (dp == NULL) /* console init */
373 gp = &congrf;
374 else
375 gp = (struct grf_softc *)dp;
376
377 if (dp != NULL && congrf.g_regkva != 0) {
378 /*
379 * inited earlier, just copy (not device struct)
380 */
381
382 bcopy(&congrf.g_display, &gp->g_display,
383 (char *) &gp[1] - (char *) &gp->g_display);
384 } else {
385 if (cv3d_zorroIII == 1) {
386 gp->g_fbkva =
387 (volatile caddr_t)cv3d_boardaddr + 0x04800000;
388 cv3d_memory_io_base =
389 (volatile caddr_t)cv3d_boardaddr + 0x05000000;
390 cv3d_register_base =
391 (volatile caddr_t)cv3d_boardaddr + 0x05008000;
392 cv3d_vcode_switch_base =
393 (volatile caddr_t)cv3d_boardaddr + 0x08000000;
394 cv3d_special_register_base =
395 (volatile caddr_t)cv3d_boardaddr + 0x0C000000;
396 } else {
397 gp->g_fbkva =
398 (volatile caddr_t)cv3d_boardaddr + 0x00000000;
399 cv3d_memory_io_base =
400 (volatile caddr_t)cv3d_boardaddr + 0x003E0000;
401 cv3d_register_base =
402 (volatile caddr_t)cv3d_boardaddr + 0x003C8000;
403 cv3d_vcode_switch_base =
404 (volatile caddr_t)cv3d_boardaddr + 0x003A0000;
405 cv3d_special_register_base =
406 (volatile caddr_t)cv3d_boardaddr + 0x003C0000;
407 }
408
409 gp->g_regkva = (volatile caddr_t)cv3d_register_base;
410
411 gp->g_unit = GRF_CV3D_UNIT;
412 gp->g_mode = cv3d_mode;
413 gp->g_conpri = grfcv3d_cnprobe();
414 gp->g_flags = GF_ALIVE;
415
416 /* wakeup the board */
417 cv3d_boardinit(gp);
418
419 #ifdef CV3DCONSOLE
420 grfcv3d_iteinit(gp);
421 (void)cv3d_load_mon(gp, &cv3dconsole_mode);
422 #endif
423 }
424
425 /*
426 * attach grf
427 */
428 if (amiga_config_found(cfdata, &gp->g_device, gp, grfcv3dprint)) {
429 if (dp != NULL)
430 printf("grfcv3d: CyberVision64/3D with %dMB being used\n",
431 cv3d_fbsize / 0x100000);
432 attachflag = 1;
433 } else {
434 if (!attachflag)
435 /*printf("grfcv3d unattached!!\n")*/;
436 }
437 }
438
439 int
440 grfcv3dprint(auxp, pnp)
441 void *auxp;
442 const char *pnp;
443 {
444 if (pnp)
445 printf("ite at %s: ", pnp);
446 return (UNCONF);
447 }
448
449
450 /*
451 * Computes M, N, and R values from
452 * given input frequency. It uses a table of
453 * precomputed values, to keep CPU time low.
454 *
455 * The return value consist of:
456 * lower byte: Bits 4-0: N Divider Value
457 * Bits 5-6: R Value for e.g. SR10 or SR12
458 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
459 */
460
461 static unsigned short
462 cv3d_compute_clock(freq)
463 unsigned long freq;
464 {
465 static unsigned char *mnr, *save; /* M, N + R vals */
466 unsigned long work_freq, r;
467 unsigned short erg;
468 long diff, d2;
469
470 if (freq < 12500000 || freq > MAXPIXELCLOCK) {
471 printf("grfcv3d: Illegal clock frequency: %ldMHz\n", freq/1000000);
472 printf("grfcv3d: Using default frequency: 25MHz\n");
473 printf("grfcv3d: See the manpage of grfconfig for more informations.\n");
474 freq = 25000000;
475 }
476
477 mnr = clocks; /* there the vals are stored */
478 d2 = 0x7fffffff;
479
480 while (*mnr) { /* mnr vals are 0-terminated */
481 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
482
483 r = (mnr[1] >> 5) & 0x03;
484 if (r != 0)
485 work_freq=work_freq >> r; /* r is the freq divider */
486
487 work_freq *= 0x3E8; /* 2nd part of OSC */
488
489 diff = abs(freq - work_freq);
490
491 if (d2 >= diff) {
492 d2 = diff;
493 /* In save are the vals for minimal diff */
494 save = mnr;
495 }
496 mnr += 2;
497 }
498 erg = *((unsigned short *)save);
499
500 return (erg);
501 }
502
503
504 void
505 cv3d_boardinit(gp)
506 struct grf_softc *gp;
507 {
508 volatile caddr_t ba, special;
509 unsigned char test;
510 unsigned int clockpar;
511 int i;
512 struct grfinfo *gi;
513
514 ba = gp->g_regkva;
515
516 /* PCI config */
517 if (cv3d_zorroIII == 1) {
518 special = (cv3d_special_register_base + 0x000E0000);
519 } else {
520 special = (cv3d_special_register_base);
521 }
522 *((short *)(special + 0x10)) = 0;
523 *((long *)(special + 0x4)) = 0x02000003;
524
525 /* Wakeup Chip */
526 vgawio(cv3d_boardaddr, SREG_VIDEO_SUBS_ENABLE, 1);
527
528 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x01);
529
530 vgaw(ba, GREG_MISC_OUTPUT_W, 0x03);
531
532 WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */
533 WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */
534
535 WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x02);
536 WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x00);
537
538 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06); /* Unlock extensions */
539
540 /*
541 * bit 0=1: enable enhanced mode functions
542 * bit 4=1: enable linear adressing
543 */
544 vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL, 0x00000011);
545
546 /* -hsync and -vsync */
547 vgaw(ba, GREG_MISC_OUTPUT_W, 0xC3);
548
549 /* Reset. This does nothing, but everyone does it:) */
550 WSeq(ba, SEQ_ID_RESET, 0x03);
551
552 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); /* 8 Dot Clock */
553 WSeq(ba, SEQ_ID_MAP_MASK, 0x0F); /* Enable write planes */
554 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* Character Font */
555
556 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02); /* Complete mem access */
557 WSeq(ba, SEQ_ID_MMIO_SELECT, 0x00);
558
559 test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */
560
561 /* enable 4MB fast Page Mode */
562 test = test | 0xC0;
563 WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test);
564
565 #if 0 /* XXX */
566 /* faster LUT write */
567 WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0);
568 #else
569 WSeq(ba, SEQ_ID_UNKNOWN6, 0x00);
570 WSeq(ba, SEQ_ID_SIGNAL_SELECT, 0x02);
571 #endif
572
573 test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */
574
575 /* immediately Clkload bit clear */
576 test = test & 0xDF;
577
578 /* 2 MCLK Memory Write.... */
579 if (cv3d_memclk >= 55000000)
580 test |= 0x80;
581
582 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test);
583
584 /* Memory CLK */
585 clockpar = cv3d_compute_clock(cv3d_memclk);
586 test = (clockpar & 0xFF00) >> 8;
587 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */
588
589 test = clockpar & 0xFF;
590 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */
591
592 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
593 /* DCLK */
594 WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
595 WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
596
597 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
598 test = test | 0x22;
599
600 /* DCLK + MCLK Clock immediate load! */
601 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
602
603 /* DCLK load */
604 test = vgar(ba, 0x3cc);
605 test = test | 0x0c;
606 vgaw(ba, 0x3c2, test);
607
608 /* Clear bit 5 again, prevent further loading. */
609 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02);
610
611 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
612 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
613 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
614 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
615 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
616 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
617 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
618
619 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */
620
621 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); /* no panning */
622
623 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */
624
625 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
626 WCrt(ba, CRT_ID_CURSOR_END, 0x00);
627
628 /* Display start adress */
629 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
630 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
631
632 /* Cursor location */
633 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
634 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
635
636 /* Vertical retrace */
637 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
638 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
639
640 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
641 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
642
643 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
644
645 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
646 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
647
648 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
649
650 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
651
652 WCrt(ba, CRT_ID_SYSTEM_CONFIG, 0x21);
653 WCrt(ba, CRT_ID_MEMORY_CONF, 0x04);
654 WCrt(ba, CRT_ID_BACKWAD_COMP_1, 0x00);
655 WCrt(ba, CRT_ID_BACKWAD_COMP_2, 0x02);
656 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
657
658 /* Refresh count 1, High speed text font, enhanced color mode */
659 WCrt(ba, CRT_ID_MISC_1, 0x35);
660
661 /* start fifo position */
662 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5A);
663
664 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x02);
665
666 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
667
668 WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x81);
669 WCrt(ba, CRT_ID_MISC_1, 0xB5);
670 WCrt(ba, CRT_ID_CONFIG_1, 0x0E);
671
672 WGfx(ba, GCT_ID_SET_RESET, 0x00);
673 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
674 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
675 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
676 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
677 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
678 WGfx(ba, GCT_ID_MISC, 0x01);
679 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
680 WGfx(ba, GCT_ID_BITMASK, 0xFF);
681
682 /* colors for text mode */
683 for (i = 0; i <= 0xf; i++)
684 WAttr (ba, i, i);
685
686 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
687 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
688 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
689 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
690 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
691
692 vgawio(cv3d_boardaddr, VDAC_MASK, 0xFF); /* DAC Mask */
693
694 /* colors initially set to greyscale */
695
696 vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, 0);
697 for (i = 255; i >= 0 ; i--) {
698 vgawio(cv3d_boardaddr, VDAC_DATA, i);
699 vgawio(cv3d_boardaddr, VDAC_DATA, i);
700 vgawio(cv3d_boardaddr, VDAC_DATA, i);
701 }
702
703 /* GFx hardware cursor off */
704 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
705
706 /* Set first to 4 MB, so test will work */
707 WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
708
709 /* find *correct* fbsize of z3 board */
710 if (cv3d_has_4mb(gp->g_fbkva)) {
711 cv3d_fbsize = 1024 * 1024 * 4;
712 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
713 } else {
714 cv3d_fbsize = 1024 * 1024 * 2;
715 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
716 }
717
718 /* Initialize graphics engine */
719 GfxBusyWait(cv3d_memory_io_base);
720 vgaw32(cv3d_memory_io_base, BLT_COMMAND_SET, CMD_NOP);
721 vgaw32(cv3d_memory_io_base, BLT_CLIP_LEFT_RIGHT, 0x000007ff);
722 vgaw32(cv3d_memory_io_base, BLT_CLIP_TOP_BOTTOM, 0x000007ff);
723 vgaw32(cv3d_memory_io_base, L2D_COMMAND_SET, CMD_NOP);
724 vgaw32(cv3d_memory_io_base, L2D_CLIP_LEFT_RIGHT, 0x000007ff);
725 vgaw32(cv3d_memory_io_base, L2D_CLIP_TOP_BOTTOM, 0x000007ff);
726 vgaw32(cv3d_memory_io_base, P2D_COMMAND_SET, CMD_NOP);
727 vgaw32(cv3d_memory_io_base, P2D_CLIP_LEFT_RIGHT, 0x000007ff);
728 vgaw32(cv3d_memory_io_base, P2D_CLIP_TOP_BOTTOM, 0x000007ff);
729
730 /* Enable Video Display (Set Bit 5) */
731 WAttr(ba, 0x33, 0);
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 == 1) {
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