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