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