grf_cv3d.c revision 1.34.34.1 1 /* $NetBSD: grf_cv3d.c,v 1.34.34.1 2021/05/13 00:47:23 thorpej 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.34.34.1 2021/05/13 00:47:23 thorpej Exp $");
37
38 #include "grfcv3d.h"
39 #include "ite.h"
40 #include "wsdisplay.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 * the 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 for 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/grfvar.h>
103 #include <amiga/dev/grf_cv3dreg.h>
104 #include <amiga/dev/zbusvar.h>
105
106
107 /*
108 * finish all bus operations, flush pipelines
109 */
110 #if defined(__m68k__)
111 #define cpu_sync() __asm volatile ("nop")
112 #elif defined(__powerpc__)
113 #define cpu_sync() __asm volatile ("sync; isync")
114 #endif
115
116 int grfcv3dmatch(device_t, cfdata_t, void *);
117 void grfcv3dattach(device_t, device_t, void *);
118 int grfcv3dprint(void *, const char *);
119
120 static int cv3d_has_4mb(volatile void *);
121 static unsigned short cv3d_compute_clock(unsigned long);
122 void cv3d_boardinit(struct grf_softc *);
123 int cv3d_getvmode(struct grf_softc *, struct grfvideo_mode *);
124 int cv3d_setvmode(struct grf_softc *, unsigned int);
125 int cv3d_blank(struct grf_softc *, int);
126 int cv3d_isblank(struct grf_softc *);
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 int cv3d_wsioctl(void *, void *, u_long, void *, int, struct lwp *);
294 static int cv3d_get_fbinfo(struct grf_softc *, struct wsdisplayio_fbinfo *);
295
296 static void cv3d_wscursor(void *, int, int, int);
297 static void cv3d_wsputchar(void *, int, int, u_int, long);
298 static void cv3d_wscopycols(void *, int, int, int, int);
299 static void cv3d_wserasecols(void *, int, int, int, long);
300 static void cv3d_wscopyrows(void *, int, int, int);
301 static void cv3d_wseraserows(void *, int, int, long);
302 static int cv3d_wsallocattr(void *, int, int, int, long *);
303 static int cv3d_wsmapchar(void *, int, unsigned int *);
304
305 struct wsdisplay_accessops cv3d_accessops = {
306 .ioctl = cv3d_wsioctl,
307 .mmap = grf_wsmmap
308 };
309
310 static struct wsdisplay_emulops cv3d_textops = {
311 .cursor = cv3d_wscursor,
312 .mapchar = cv3d_wsmapchar,
313 .putchar = cv3d_wsputchar,
314 .copycols = cv3d_wscopycols,
315 .copyrows = cv3d_wscopyrows,
316 .erasecols = cv3d_wserasecols,
317 .eraserows = cv3d_wseraserows,
318 .allocattr = cv3d_wsallocattr
319 };
320
321 static struct wsscreen_descr cv3d_defaultscreen = {
322 .name = "default",
323 .textops = &cv3d_textops,
324 .fontwidth = 8,
325 .fontheight = S3FONTY,
326 .capabilities = WSSCREEN_HILIT | WSSCREEN_BLINK |
327 WSSCREEN_REVERSE | WSSCREEN_UNDERLINE
328 };
329
330 static const struct wsscreen_descr *cv3d_screens[] = {
331 &cv3d_defaultscreen,
332 };
333
334 static struct wsscreen_list cv3d_screenlist = {
335 sizeof(cv3d_screens) / sizeof(struct wsscreen_descr *), cv3d_screens
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_defaultscr = &cv3d_defaultscreen;
494 gp->g_scrlist = &cv3d_screenlist;
495 #else
496 #if NITE > 0
497 grfcv3d_iteinit(gp);
498 #endif
499 #endif /* NWSDISPLAY > 0 */
500 (void)cv3d_load_mon(gp, &cv3dconsole_mode);
501 #endif
502 }
503
504 /*
505 * attach grf
506 */
507 if (amiga_config_found(cfdata, gp->g_device, gp, grfcv3dprint,
508 CFARG_EOL)) {
509 if (self != NULL)
510 printf("%s: CyberVision64/3D with %dMB being used\n",
511 device_xname(self), cv3d_fbsize / 0x100000);
512 attachflag = 1;
513 } else {
514 if (!attachflag)
515 /*printf("grfcv3d unattached!!\n")*/;
516 }
517 }
518
519 int
520 grfcv3dprint(void *aux, const char *pnp)
521 {
522 if (pnp)
523 aprint_normal("ite at %s: ", pnp);
524 return (UNCONF);
525 }
526
527
528 /*
529 * Computes M, N, and R values from
530 * given input frequency. It uses a table of
531 * precomputed values, to keep CPU time low.
532 *
533 * The return value consist of:
534 * lower byte: Bits 4-0: N Divider Value
535 * Bits 5-6: R Value for e.g. SR10 or SR12
536 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
537 */
538
539 static unsigned short
540 cv3d_compute_clock(unsigned long freq)
541 {
542 static unsigned char *mnr, *save; /* M, N + R vals */
543 unsigned long work_freq, r;
544 unsigned short erg;
545 long diff, d2;
546
547 if (freq < 12500000 || freq > MAXPIXELCLOCK) {
548 printf("grfcv3d: Illegal clock frequency: %ldMHz\n", freq/1000000);
549 printf("grfcv3d: Using default frequency: 25MHz\n");
550 printf("grfcv3d: See the manpage of grfconfig for more informations.\n");
551 freq = 25000000;
552 }
553
554 mnr = clocks; /* there the vals are stored */
555 d2 = 0x7fffffff;
556
557 while (*mnr) { /* mnr vals are 0-terminated */
558 work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
559
560 r = (mnr[1] >> 5) & 0x03;
561 if (r != 0)
562 work_freq=work_freq >> r; /* r is the freq divider */
563
564 work_freq *= 0x3E8; /* 2nd part of OSC */
565
566 diff = abs(freq - work_freq);
567
568 if (d2 >= diff) {
569 d2 = diff;
570 /* In save are the vals for minimal diff */
571 save = mnr;
572 }
573 mnr += 2;
574 }
575 erg = *((unsigned short *)save);
576
577 return (erg);
578 }
579
580
581 void
582 cv3d_boardinit(struct grf_softc *gp)
583 {
584 volatile void *ba;
585 volatile char *special;
586 unsigned char test;
587 unsigned int clockpar;
588 int i;
589 struct grfinfo *gi;
590
591 ba = gp->g_regkva;
592
593 /* PCI config */
594 if (cv3d_zorroIII) {
595 special = ((volatile char*)cv3d_special_register_base +
596 0x000E0000);
597 } else {
598 special = ((volatile char*)cv3d_special_register_base);
599 }
600 *((volatile short *)(special + 0x10)) = 0;
601 *((volatile long *)(special + 0x4)) = 0x02000003;
602
603 /* Wakeup Chip */
604 vgawio(cv3d_boardaddr, SREG_VIDEO_SUBS_ENABLE, 1);
605
606 vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x01);
607
608 vgaw(ba, GREG_MISC_OUTPUT_W, 0x03);
609
610 WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */
611 WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */
612
613 WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x02);
614 WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x00);
615
616 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x06); /* Unlock extensions */
617
618 /*
619 * bit 0=1: enable enhanced mode functions
620 * bit 4=1: enable linear addressing
621 */
622 vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL, 0x00000011);
623
624 /* -hsync and -vsync */
625 vgaw(ba, GREG_MISC_OUTPUT_W, 0xC3);
626
627 /* Reset. This does nothing, but everyone does it:) */
628 WSeq(ba, SEQ_ID_RESET, 0x03);
629
630 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01); /* 8 Dot Clock */
631 WSeq(ba, SEQ_ID_MAP_MASK, 0x0F); /* Enable write planes */
632 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* Character Font */
633
634 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x02); /* Complete mem access */
635 WSeq(ba, SEQ_ID_MMIO_SELECT, 0x00);
636
637 test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */
638
639 /* enable 4MB fast Page Mode */
640 test = test | 0xC0;
641 WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test);
642
643 #if 0 /* XXX */
644 /* faster LUT write */
645 WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0xC0);
646 #else
647 WSeq(ba, SEQ_ID_UNKNOWN6, 0x00);
648 WSeq(ba, SEQ_ID_SIGNAL_SELECT, 0x02);
649 #endif
650
651 test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */
652
653 /* immediately Clkload bit clear */
654 test = test & 0xDF;
655
656 /* 2 MCLK Memory Write.... */
657 if (cv3d_memclk >= 55000000)
658 test |= 0x80;
659
660 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test);
661
662 /* Memory CLK */
663 clockpar = cv3d_compute_clock(cv3d_memclk);
664 test = (clockpar & 0xFF00) >> 8;
665 WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */
666
667 test = clockpar & 0xFF;
668 WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */
669
670 /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */
671 /* DCLK */
672 WSeq(ba, SEQ_ID_DCLK_HI, 0x13);
673 WSeq(ba, SEQ_ID_DCLK_LO, 0x41);
674
675 test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2);
676 test = test | 0x22;
677
678 /* DCLK + MCLK Clock immediate load! */
679 WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test);
680
681 /* DCLK load */
682 test = vgar(ba, 0x3cc);
683 test = test | 0x0c;
684 vgaw(ba, 0x3c2, test);
685
686 /* Clear bit 5 again, prevent further loading. */
687 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x02);
688
689 WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F);
690 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F);
691 WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50);
692 WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82);
693 WCrt(ba, CRT_ID_START_HOR_RETR, 0x54);
694 WCrt(ba, CRT_ID_END_HOR_RETR, 0x80);
695 WCrt(ba, CRT_ID_VER_TOTAL, 0xBF);
696
697 WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */
698
699 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); /* no panning */
700
701 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */
702
703 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
704 WCrt(ba, CRT_ID_CURSOR_END, 0x00);
705
706 /* Display start address */
707 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
708 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
709
710 /* Cursor location */
711 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
712 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
713
714 /* Vertical retrace */
715 WCrt(ba, CRT_ID_START_VER_RETR, 0x9C);
716 WCrt(ba, CRT_ID_END_VER_RETR, 0x0E);
717
718 WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F);
719 WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50);
720
721 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00);
722
723 WCrt(ba, CRT_ID_START_VER_BLANK, 0x96);
724 WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9);
725
726 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
727
728 WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF);
729
730 WCrt(ba, CRT_ID_SYSTEM_CONFIG, 0x21);
731 WCrt(ba, CRT_ID_MEMORY_CONF, 0x04);
732 WCrt(ba, CRT_ID_BACKWAD_COMP_1, 0x00);
733 WCrt(ba, CRT_ID_BACKWAD_COMP_2, 0x02);
734 WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
735
736 /* Refresh count 1, High speed text font, enhanced color mode */
737 WCrt(ba, CRT_ID_MISC_1, 0x35);
738
739 /* start fifo position */
740 WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5A);
741
742 WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x02);
743
744 WCrt(ba, CRT_ID_LAW_POS_LO, 0x40);
745
746 WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, 0x81);
747 WCrt(ba, CRT_ID_MISC_1, 0xB5);
748 WCrt(ba, CRT_ID_CONFIG_1, 0x0E);
749
750 WGfx(ba, GCT_ID_SET_RESET, 0x00);
751 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
752 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
753 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
754 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
755 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
756 WGfx(ba, GCT_ID_MISC, 0x01);
757 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F);
758 WGfx(ba, GCT_ID_BITMASK, 0xFF);
759
760 /* colors for text mode */
761 for (i = 0; i <= 0xf; i++)
762 WAttr (ba, i, i);
763
764 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x41);
765 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x01);
766 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0F);
767 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
768 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
769
770 vgawio(cv3d_boardaddr, VDAC_MASK, 0xFF); /* DAC Mask */
771
772 /* colors initially set to greyscale */
773
774 vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, 0);
775
776 for (i = 255; i >= 0 ; i--) {
777 vgawio(cv3d_boardaddr, VDAC_DATA, i);
778 vgawio(cv3d_boardaddr, VDAC_DATA, i);
779 vgawio(cv3d_boardaddr, VDAC_DATA, i);
780 }
781
782 /* GFx hardware cursor off */
783 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
784
785 /* Set first to 4 MB, so test will work */
786 WCrt(ba, CRT_ID_LAW_CNTL, 0x13);
787
788 /* find *correct* fbsize of z3 board */
789 if (cv3d_has_4mb(gp->g_fbkva)) {
790 cv3d_fbsize = 1024 * 1024 * 4;
791 WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
792 } else {
793 cv3d_fbsize = 1024 * 1024 * 2;
794 WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
795 }
796
797 /* Initialize graphics engine */
798 GfxBusyWait(cv3d_memory_io_base);
799 vgaw32(cv3d_memory_io_base, BLT_COMMAND_SET, CMD_NOP);
800 vgaw32(cv3d_memory_io_base, BLT_CLIP_LEFT_RIGHT, 0x000007ff);
801 vgaw32(cv3d_memory_io_base, BLT_CLIP_TOP_BOTTOM, 0x000007ff);
802 vgaw32(cv3d_memory_io_base, L2D_COMMAND_SET, CMD_NOP);
803 vgaw32(cv3d_memory_io_base, L2D_CLIP_LEFT_RIGHT, 0x000007ff);
804 vgaw32(cv3d_memory_io_base, L2D_CLIP_TOP_BOTTOM, 0x000007ff);
805 vgaw32(cv3d_memory_io_base, P2D_COMMAND_SET, CMD_NOP);
806 vgaw32(cv3d_memory_io_base, P2D_CLIP_LEFT_RIGHT, 0x000007ff);
807 vgaw32(cv3d_memory_io_base, P2D_CLIP_TOP_BOTTOM, 0x000007ff);
808
809 /* Enable Video Display (Set Bit 5) */
810 WAttr(ba, 0x33, 0);
811
812
813 gi = &gp->g_display;
814 gi->gd_regaddr = (void *) kvtop (__UNVOLATILE(ba));
815 gi->gd_regsize = 64 * 1024;
816 gi->gd_fbaddr = (void *) kvtop (__UNVOLATILE(gp->g_fbkva));
817 gi->gd_fbsize = cv3d_fbsize;
818 }
819
820
821 int
822 cv3d_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
823 {
824 struct grfvideo_mode *gv;
825
826 #ifdef CV3DCONSOLE
827 /* Handle grabbing console mode */
828 if (vm->mode_num == 255) {
829 memcpy(vm, &cv3dconsole_mode, sizeof(struct grfvideo_mode));
830 /* XXX so grfconfig can tell us the correct text dimensions. */
831 vm->depth = cv3dconsole_mode.fy;
832 } else
833 #endif
834 {
835 if (vm->mode_num == 0)
836 vm->mode_num = (monitor_current - monitor_def) + 1;
837 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
838 return (EINVAL);
839 gv = monitor_def + (vm->mode_num - 1);
840 if (gv->mode_num == 0)
841 return (EINVAL);
842
843 memcpy(vm, gv, sizeof(struct grfvideo_mode));
844 }
845
846 /* adjust internal values to pixel values */
847
848 vm->hblank_start *= 8;
849 vm->hsync_start *= 8;
850 vm->hsync_stop *= 8;
851 vm->htotal *= 8;
852
853 return (0);
854 }
855
856
857 int
858 cv3d_setvmode(struct grf_softc *gp, unsigned mode)
859 {
860
861 if (!mode || (mode > monitor_def_max) ||
862 monitor_def[mode - 1].mode_num == 0)
863 return (EINVAL);
864
865 monitor_current = monitor_def + (mode - 1);
866
867 return (0);
868 }
869
870
871 int
872 cv3d_blank(struct grf_softc *gp, int on)
873 {
874 volatile void *ba;
875
876 ba = gp->g_regkva;
877 cv3d_gfx_on_off(on > 0 ? 0 : 1, ba);
878 return (0);
879 }
880
881
882 int
883 cv3d_isblank(struct grf_softc *gp)
884 {
885 volatile void *ba;
886 int r;
887
888 ba = gp->g_regkva;
889 r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
890 return (r & 0x20) != 0;
891 }
892
893
894 /*
895 * Change the mode of the display.
896 * Return a UNIX error number or 0 for success.
897 */
898 int
899 cv3d_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
900 int a3)
901 {
902 int error;
903
904 switch (cmd) {
905 case GM_GRFON:
906 error = cv3d_load_mon (gp,
907 (struct grfcv3dtext_mode *) monitor_current) ? 0 : EINVAL;
908 return (error);
909
910 case GM_GRFOFF:
911 #ifndef CV3DCONSOLE
912 cv3dscreen(1, cv3d_vcode_switch_base);
913 #else
914 cv3d_load_mon(gp, &cv3dconsole_mode);
915 #if NITE > 0
916 ite_reinit(gp->g_itedev);
917 #endif
918 #endif
919 return (0);
920
921 case GM_GRFCONFIG:
922 return (0);
923
924 case GM_GRFGETVMODE:
925 return (cv3d_getvmode (gp, (struct grfvideo_mode *) arg));
926
927 case GM_GRFSETVMODE:
928 error = cv3d_setvmode (gp, *(unsigned *) arg);
929 if (!error && (gp->g_flags & GF_GRFON))
930 cv3d_load_mon(gp,
931 (struct grfcv3dtext_mode *) monitor_current);
932 return (error);
933
934 case GM_GRFGETNUMVM:
935 *(int *)arg = monitor_def_max;
936 return (0);
937
938 case GM_GRFIOCTL:
939 return (cv3d_ioctl (gp, a2, arg));
940
941 default:
942 break;
943 }
944
945 return (EPASSTHROUGH);
946 }
947
948
949 int
950 cv3d_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
951 {
952 switch (cmd) {
953 #ifdef CV3D_HARDWARE_CURSOR
954 case GRFIOCGSPRITEPOS:
955 return(cv3d_getspritepos (gp, (struct grf_position *) data));
956
957 case GRFIOCSSPRITEPOS:
958 return(cv3d_setspritepos (gp, (struct grf_position *) data));
959
960 case GRFIOCSSPRITEINF:
961 return(cv3d_setspriteinfo (gp, (struct grf_spriteinfo *) data));
962
963 case GRFIOCGSPRITEINF:
964 return(cv3d_getspriteinfo (gp, (struct grf_spriteinfo *) data));
965
966 case GRFIOCGSPRITEMAX:
967 return(cv3d_getspritemax (gp, (struct grf_position *) data));
968 #else /* CV3D_HARDWARE_CURSOR */
969 case GRFIOCGSPRITEPOS:
970 case GRFIOCSSPRITEPOS:
971 case GRFIOCSSPRITEINF:
972 case GRFIOCGSPRITEINF:
973 case GRFIOCGSPRITEMAX:
974 break;
975 #endif /* CV3D_HARDWARE_CURSOR */
976
977 case GRFIOCGETCMAP:
978 return (cv3d_getcmap (gp, (struct grf_colormap *) data));
979
980 case GRFIOCPUTCMAP:
981 return (cv3d_putcmap (gp, (struct grf_colormap *) data));
982
983 case GRFIOCBITBLT:
984 break;
985
986 case GRFTOGGLE:
987 return (cv3d_toggle (gp));
988
989 case GRFIOCSETMON:
990 return (cv3d_setmonitor (gp, (struct grfvideo_mode *)data));
991
992 case GRFIOCBLANK:
993 return (cv3d_blank (gp, *(int *)data));
994 }
995 return (EPASSTHROUGH);
996 }
997
998
999 int
1000 cv3d_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
1001 {
1002 struct grfvideo_mode *md;
1003
1004 if (!cv3d_mondefok(gv))
1005 return (EINVAL);
1006
1007 #ifdef CV3DCONSOLE
1008 /* handle interactive setting of console mode */
1009 if (gv->mode_num == 255) {
1010 memcpy(&cv3dconsole_mode.gv, gv, sizeof(struct grfvideo_mode));
1011 cv3dconsole_mode.gv.hblank_start /= 8;
1012 cv3dconsole_mode.gv.hsync_start /= 8;
1013 cv3dconsole_mode.gv.hsync_stop /= 8;
1014 cv3dconsole_mode.gv.htotal /= 8;
1015 cv3dconsole_mode.rows = gv->disp_height / cv3dconsole_mode.fy;
1016 cv3dconsole_mode.cols = gv->disp_width / cv3dconsole_mode.fx;
1017 if (!(gp->g_flags & GF_GRFON))
1018 cv3d_load_mon(gp, &cv3dconsole_mode);
1019 #if NITE > 0
1020 ite_reinit(gp->g_itedev);
1021 #endif
1022 return (0);
1023 }
1024 #endif
1025
1026 md = monitor_def + (gv->mode_num - 1);
1027
1028 /*
1029 * Prevent user from crashing the system by using
1030 * grfconfig while in X
1031 */
1032 if (gp->g_flags & GF_GRFON)
1033 if (md == monitor_current) {
1034 printf("grfcv3d: Changing the used mode not allowed!\n");
1035 return (EINVAL);
1036 }
1037
1038 memcpy(md, gv, sizeof(struct grfvideo_mode));
1039
1040 /* adjust pixel oriented values to internal rep. */
1041
1042 md->hblank_start /= 8;
1043 md->hsync_start /= 8;
1044 md->hsync_stop /= 8;
1045 md->htotal /= 8;
1046
1047 return (0);
1048 }
1049
1050
1051 int
1052 cv3d_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1053 {
1054 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1055 short x;
1056 int error;
1057
1058 if (cmap->count == 0 || cmap->index >= 256)
1059 return (0);
1060
1061 if (cmap->count > 256 - cmap->index)
1062 cmap->count = 256 - cmap->index;
1063
1064 /* first read colors out of the chip, then copyout to userspace */
1065 vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, cmap->index);
1066 x = cmap->count - 1;
1067
1068 rp = red + cmap->index;
1069 gp = green + cmap->index;
1070 bp = blue + cmap->index;
1071
1072 do {
1073 *rp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
1074 *gp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
1075 *bp++ = vgario(cv3d_special_register_base, VDAC_DATA) << 2;
1076 } while (x-- > 0);
1077
1078 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count))
1079 && !(error = copyout (green + cmap->index, cmap->green, cmap->count))
1080 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count)))
1081 return (0);
1082
1083 return (error);
1084 }
1085
1086
1087 int
1088 cv3d_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1089 {
1090 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1091 short x;
1092 int error;
1093
1094 if (cmap->count == 0 || cmap->index >= 256)
1095 return (0);
1096
1097 if (cmap->index + cmap->count > 256)
1098 cmap->count = 256 - cmap->index;
1099
1100 /* first copy the colors into kernelspace */
1101 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count))
1102 && !(error = copyin (cmap->green, green + cmap->index, cmap->count))
1103 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) {
1104 vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, cmap->index);
1105 x = cmap->count - 1;
1106
1107 rp = red + cmap->index;
1108 gp = green + cmap->index;
1109 bp = blue + cmap->index;
1110
1111 do {
1112 vgawio(cv3d_boardaddr, VDAC_DATA, *rp++ >> 2);
1113 vgawio(cv3d_boardaddr, VDAC_DATA, *gp++ >> 2);
1114 vgawio(cv3d_boardaddr, VDAC_DATA, *bp++ >> 2);
1115 } while (x-- > 0);
1116 return (0);
1117 } else
1118 return (error);
1119 }
1120
1121
1122 int
1123 cv3d_toggle(struct grf_softc *gp)
1124 {
1125 #ifndef CV3DCONSOLE
1126 cv3d_pass_toggle = 1;
1127 #endif /* !CV3DCONSOLE */
1128
1129 if (cv3d_pass_toggle) {
1130 cv3dscreen(0, cv3d_vcode_switch_base);
1131 cv3d_pass_toggle = 0;
1132 } else {
1133 cv3dscreen(1, cv3d_vcode_switch_base);
1134 cv3d_pass_toggle = 1;
1135 }
1136
1137 return (0);
1138 }
1139
1140
1141 int
1142 cv3d_mondefok(struct grfvideo_mode *gv)
1143 {
1144 unsigned long maxpix;
1145
1146 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) {
1147 if (gv->mode_num != 255 || gv->depth != 4)
1148 return (0);
1149 }
1150
1151 switch(gv->depth) {
1152 case 4:
1153 maxpix = MAXPIXELCLOCK - 55000000;
1154 break;
1155 case 8:
1156 maxpix = MAXPIXELCLOCK;
1157 break;
1158 case 15:
1159 case 16:
1160 #ifdef CV3D_AGGRESSIVE_TIMING
1161 maxpix = MAXPIXELCLOCK - 35000000;
1162 #else
1163 maxpix = MAXPIXELCLOCK - 55000000;
1164 #endif
1165 break;
1166 case 24:
1167 case 32:
1168 #ifdef CV3D_AGGRESSIVE_TIMING
1169 maxpix = MAXPIXELCLOCK - 75000000;
1170 #else
1171 maxpix = MAXPIXELCLOCK - 85000000;
1172 #endif
1173 break;
1174 default:
1175 printf("grfcv3d: Illegal depth in mode %d\n",
1176 (int) gv->mode_num);
1177 return (0);
1178 }
1179
1180 if (gv->pixel_clock > maxpix) {
1181 printf("grfcv3d: Pixelclock too high in mode %d\n",
1182 (int) gv->mode_num);
1183 return (0);
1184 }
1185
1186 if (gv->mode_num == 255) { /* console mode */
1187 if ((gv->disp_width / 8) > MAXCOLS) {
1188 printf ("grfcv3d: Too many columns for console\n");
1189 return (0);
1190 } else if ((gv->disp_height / S3FONTY) > MAXROWS) {
1191 printf ("grfcv3d: Too many rows for console\n");
1192 return (0);
1193 }
1194 }
1195
1196 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
1197 printf("grfcv3d: sync-on-green is not supported\n");
1198 return (0);
1199 }
1200
1201 return (1);
1202 }
1203
1204
1205 int
1206 cv3d_load_mon(struct grf_softc *gp, struct grfcv3dtext_mode *md)
1207 {
1208 struct grfvideo_mode *gv;
1209 struct grfinfo *gi;
1210 volatile void *ba;
1211 unsigned short mnr;
1212 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1213 VSE, VT;
1214 int cr50, cr66, sr15, sr18, clock_mode, test;
1215 int hmul; /* Multiplier for hor. Values */
1216 int fb_flag = 2; /* default value for 8bit memory access */
1217 unsigned char hvsync_pulse;
1218 char TEXT, CONSOLE;
1219
1220 /* identity */
1221 gv = &md->gv;
1222
1223 TEXT = (gv->depth == 4);
1224 CONSOLE = (gv->mode_num == 255);
1225
1226 if (!cv3d_mondefok(gv)) {
1227 printf("grfcv3d: Monitor definition not ok\n");
1228 return (0);
1229 }
1230
1231 ba = gp->g_regkva;
1232
1233 /* turn gfx off, don't mess up the display */
1234 cv3d_gfx_on_off(1, ba);
1235
1236 /* provide all needed information in grf device-independent locations */
1237 gp->g_data = (void *) gv;
1238 gi = &gp->g_display;
1239 gi->gd_colors = 1 << gv->depth;
1240 gi->gd_planes = gv->depth;
1241 gi->gd_fbwidth = gv->disp_width;
1242 gi->gd_fbheight = gv->disp_height;
1243 gi->gd_fbx = 0;
1244 gi->gd_fby = 0;
1245 if (CONSOLE) {
1246 gi->gd_dwidth = md->fx * md->cols;
1247 gi->gd_dheight = md->fy * md->rows;
1248 } else {
1249 gi->gd_dwidth = gv->disp_width;
1250 gi->gd_dheight = gv->disp_height;
1251 }
1252 gi->gd_dx = 0;
1253 gi->gd_dy = 0;
1254
1255 /* get display mode parameters */
1256 switch (gv->depth) {
1257 case 15:
1258 case 16:
1259 hmul = 2;
1260 break;
1261 default:
1262 hmul = 1;
1263 break;
1264 }
1265
1266 HBS = gv->hblank_start * hmul;
1267 HSS = gv->hsync_start * hmul;
1268 HSE = gv->hsync_stop * hmul;
1269 HBE = gv->htotal * hmul - 6;
1270 HT = gv->htotal * hmul - 5;
1271 VBS = gv->vblank_start - 1;
1272 VSS = gv->vsync_start;
1273 VSE = gv->vsync_stop;
1274 VBE = gv->vtotal - 3;
1275 VT = gv->vtotal - 2;
1276
1277 /*
1278 * Disable enhanced Mode for text display
1279 *
1280 * XXX You need to set this bit in CRT_ID_EXT_MISC_CNTL_1
1281 * _and_ MR_ADVANCED_FUNCTION_CONTROL, because the same
1282 * function exists in both registers.
1283 */
1284 cr66 = RCrt(ba, CRT_ID_EXT_MISC_CNTL_1);
1285 if (TEXT) {
1286 cr66 &= ~0x01;
1287 vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL,
1288 0x00000010);
1289 } else {
1290 cr66 |= 0x01;
1291 vgaw32(cv3d_memory_io_base, MR_ADVANCED_FUNCTION_CONTROL,
1292 0x00000011);
1293 }
1294 WCrt(ba, CRT_ID_EXT_MISC_CNTL_1, cr66);
1295
1296 if (TEXT)
1297 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1298 else
1299 HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/
1300 VDE = gv->disp_height - 1;
1301
1302 /* adjustments */
1303
1304 if (gv->disp_flags & GRF_FLAGS_LACE) {
1305 VDE = VDE / 2;
1306 VBS = VBS / 2;
1307 VSS = VSS / 2;
1308 VSE = VSE / 2;
1309 VBE = VBE / 2;
1310 VT = VT / 2;
1311 }
1312
1313 /* Horizontal/Vertical Sync Pulse */
1314 /*
1315 * GREG_MISC_OUTPUT_W Register:
1316 * bit description (0/1)
1317 * 0 Monochrome/Color emulation
1318 * 1 Disable/Enable access of the display memory from the CPU
1319 * 5 Select the low/high 64K page of memory
1320 * 6 Select a positive/negative horizontal retrace sync pulse
1321 * 7 Select a positive/negative vertical retrace sync pulse
1322 */
1323 hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R);
1324 if (gv->disp_flags & GRF_FLAGS_PHSYNC)
1325 hvsync_pulse &= ~0x40;
1326 else
1327 hvsync_pulse |= 0x40;
1328 if (gv->disp_flags & GRF_FLAGS_PVSYNC)
1329 hvsync_pulse &= ~0x80;
1330 else
1331 hvsync_pulse |= 0x80;
1332 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse);
1333
1334 /* GFX hardware cursor off */
1335 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
1336 WCrt(ba, CRT_ID_EXT_DAC_CNTL, 0x00);
1337
1338 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1339 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1340 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1341 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1342
1343 /* Set clock */
1344
1345 mnr = cv3d_compute_clock(gv->pixel_clock);
1346 WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1347 WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1348
1349 /* load display parameters into board */
1350
1351 WCrt(ba, CRT_ID_EXT_HOR_OVF,
1352 ((HT & 0x100) ? 0x01 : 0x00) |
1353 ((HDE & 0x100) ? 0x02 : 0x00) |
1354 ((HBS & 0x100) ? 0x04 : 0x00) |
1355 /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */
1356 ((HSS & 0x100) ? 0x10 : 0x00) |
1357 /* ((HSE & 0x20) ? 0x20 : 0x00) | */
1358 (((HT-5) & 0x100) ? 0x40 : 0x00) );
1359
1360 WCrt(ba, CRT_ID_EXT_VER_OVF,
1361 0x40 | /* Line compare */
1362 ((VT & 0x400) ? 0x01 : 0x00) |
1363 ((VDE & 0x400) ? 0x02 : 0x00) |
1364 ((VBS & 0x400) ? 0x04 : 0x00) |
1365 ((VSS & 0x400) ? 0x10 : 0x00) );
1366
1367 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1368 WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5);
1369
1370 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1371 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1372 WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80));
1373 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1374 WCrt(ba, CRT_ID_END_HOR_RETR,
1375 (HSE & 0x1f) |
1376 ((HBE & 0x20) ? 0x80 : 0x00) );
1377 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1378 WCrt(ba, CRT_ID_OVERFLOW,
1379 0x10 |
1380 ((VT & 0x100) ? 0x01 : 0x00) |
1381 ((VDE & 0x100) ? 0x02 : 0x00) |
1382 ((VSS & 0x100) ? 0x04 : 0x00) |
1383 ((VBS & 0x100) ? 0x08 : 0x00) |
1384 ((VT & 0x200) ? 0x20 : 0x00) |
1385 ((VDE & 0x200) ? 0x40 : 0x00) |
1386 ((VSS & 0x200) ? 0x80 : 0x00) );
1387
1388 WCrt(ba, CRT_ID_MAX_SCAN_LINE,
1389 0x40 | /* TEXT ? 0x00 ??? */
1390 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) |
1391 ((VBS & 0x200) ? 0x20 : 0x00) |
1392 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1393
1394 WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3);
1395
1396 /* text cursor */
1397
1398 if (TEXT) {
1399 #if CV3D_ULCURSOR
1400 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1401 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1402 #else
1403 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1404 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1405 #endif
1406 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1407
1408 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1409 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1410 }
1411
1412 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1413 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1414
1415 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1416 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f));
1417 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1418 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1419 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1420
1421 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1422 WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2);
1423 WCrt(ba, CRT_ID_LACE_CONTROL,
1424 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x20 : 0x00));
1425
1426 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1427 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1428 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1429
1430 WSeq (ba, SEQ_ID_MEMORY_MODE,
1431 ((TEXT || (gv->depth == 1)) ? 0x06 : 0x02));
1432
1433 vgawio(cv3d_boardaddr, VDAC_MASK, 0xff);
1434
1435 /* Blank border */
1436 test = RCrt(ba, CRT_ID_BACKWAD_COMP_2);
1437 WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
1438
1439 sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2);
1440 sr15 &= ~0x10;
1441 sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL);
1442 sr18 &= ~0x80;
1443 clock_mode = 0x00;
1444 cr50 = 0x00;
1445
1446 test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2);
1447 test &= 0xd;
1448
1449 switch (gv->depth) {
1450 case 1:
1451 case 4: /* text */
1452 fb_flag = 2;
1453 HDE = gv->disp_width / 16;
1454 break;
1455 case 8:
1456 fb_flag = 2;
1457 if (gv->pixel_clock > 80000000) {
1458 /*
1459 * CR67 bit 1 is undocumented but needed to prevent
1460 * a white line on the left side of the screen.
1461 */
1462 clock_mode = 0x10 | 0x02;
1463 sr15 |= 0x10;
1464 sr18 |= 0x80;
1465 }
1466 HDE = gv->disp_width / 8;
1467 cr50 |= 0x00;
1468 break;
1469 case 15:
1470 fb_flag = 1;
1471 clock_mode = 0x30;
1472 HDE = gv->disp_width / 4;
1473 cr50 |= 0x10;
1474 break;
1475 case 16:
1476 fb_flag = 1;
1477 clock_mode = 0x50;
1478 HDE = gv->disp_width / 4;
1479 cr50 |= 0x10;
1480 break;
1481 case 24: /* this is really 32 Bit on CV64/3D */
1482 case 32:
1483 fb_flag = 0;
1484 clock_mode = 0xd0;
1485 HDE = (gv->disp_width / 2);
1486 cr50 |= 0x30;
1487 break;
1488 }
1489
1490 if (cv3d_zorroIII) {
1491 gp->g_fbkva = (volatile char *)cv3d_boardaddr + 0x04000000 +
1492 (0x00400000 * fb_flag);
1493 } else {
1494 Select_Zorro2_FrameBuffer(fb_flag);
1495 }
1496
1497 WCrt(ba, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
1498 WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, sr15);
1499 WSeq(ba, SEQ_ID_RAMDAC_CNTL, sr18);
1500 WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE);
1501
1502 WCrt(ba, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
1503
1504 test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2);
1505 test &= ~0x30;
1506 /* HDE Overflow in bits 4-5 */
1507 test |= (HDE >> 4) & 0x30;
1508 WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test);
1509
1510 #if 0 /* XXX */
1511 /* Set up graphics engine */
1512 switch (gv->disp_width) {
1513 case 1024:
1514 cr50 |= 0x00;
1515 break;
1516 case 640:
1517 cr50 |= 0x40;
1518 break;
1519 case 800:
1520 cr50 |= 0x80;
1521 break;
1522 case 1280:
1523 cr50 |= 0xc0;
1524 break;
1525 case 1152:
1526 cr50 |= 0x01;
1527 break;
1528 case 1600:
1529 cr50 |= 0x81;
1530 break;
1531 default: /* XXX The Xserver has to handle this */
1532 break;
1533 }
1534
1535 WCrt(ba, CRT_ID_EXT_SYS_CNTL_1, cr50);
1536 #endif
1537
1538 delay(100000);
1539 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
1540 delay(100000);
1541 WAttr(ba, ACT_ID_COLOR_PLANE_ENA,
1542 (gv->depth == 1) ? 0x01 : 0x0f);
1543 delay(100000);
1544
1545 /* text initialization */
1546
1547 if (TEXT) {
1548 cv3d_inittextmode(gp);
1549 }
1550
1551 if (CONSOLE) {
1552 int i;
1553 vgawio(cv3d_boardaddr, VDAC_ADDRESS_W, 0);
1554 for (i = 0; i < 16; i++) {
1555 vgawio(cv3d_boardaddr, VDAC_DATA, cv3dconscolors[i][0]);
1556 vgawio(cv3d_boardaddr, VDAC_DATA, cv3dconscolors[i][1]);
1557 vgawio(cv3d_boardaddr, VDAC_DATA, cv3dconscolors[i][2]);
1558 }
1559 }
1560
1561 /* Set display enable flag */
1562 WAttr(ba, 0x33, 0);
1563
1564 /* turn gfx on again */
1565 cv3d_gfx_on_off(0, ba);
1566
1567 /* Pass-through */
1568 cv3dscreen(0, cv3d_vcode_switch_base);
1569
1570 return (1);
1571 }
1572
1573
1574 void
1575 cv3d_inittextmode(struct grf_softc *gp)
1576 {
1577 struct grfcv3dtext_mode *tm = (struct grfcv3dtext_mode *)gp->g_data;
1578 volatile void *fb;
1579 volatile unsigned char *c;
1580 unsigned char *f, y;
1581 unsigned short z;
1582
1583 fb = gp->g_fbkva;
1584
1585 /* load text font into beginning of display memory.
1586 * Each character cell is 32 bytes long (enough for 4 planes)
1587 * In linear addressing text mode, the memory is organized
1588 * so, that the Bytes of all 4 planes are interleaved.
1589 * 1st byte plane 0, 1st byte plane 1, 1st byte plane 2,
1590 * 1st byte plane 3, 2nd byte plane 0, 2nd byte plane 1,...
1591 * The font is loaded in plane 2.
1592 */
1593
1594 c = (volatile unsigned char *) fb;
1595
1596 /* clear screen */
1597 for (z = 0; z < tm->cols * tm->rows * 3; z++) {
1598 *c++ = 0x20;
1599 *c++ = 0x07;
1600 *c++ = 0;
1601 *c++ = 0;
1602 }
1603
1604 c = (volatile unsigned char *)fb + (32 * tm->fdstart * 4 + 2);
1605 f = tm->fdata;
1606 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy) * 4)
1607 for (y = 0; y < tm->fy; y++) {
1608 *c = *f++;
1609 c += 4;
1610 }
1611
1612 /* print out a little init msg */
1613 c = (volatile unsigned char *)fb + (tm->cols - 9) * 4;
1614 *c++ = 'C';
1615 *c++ = 0x0c;
1616 c +=2;
1617 *c++ = 'V';
1618 *c++ = 0x0c;
1619 c +=2;
1620 *c++ = '6';
1621 *c++ = 0x0b;
1622 c +=2;
1623 *c++ = '4';
1624 *c++ = 0x0f;
1625 c +=2;
1626 *c++ = '/';
1627 *c++ = 0x0e;
1628 c +=2;
1629 *c++ = '3';
1630 *c++ = 0x0a;
1631 c +=2;
1632 *c++ = 'D';
1633 *c++ = 0x0a;
1634 }
1635
1636 /*
1637 * Monitor Switch
1638 * 0 = CyberVision Signal
1639 * 1 = Amiga Signal,
1640 * ba = boardaddr
1641 */
1642 static inline void
1643 cv3dscreen(int toggle, volatile void *ba)
1644 {
1645 *((volatile short *)(ba)) = (toggle & 1);
1646 }
1647
1648
1649 /* 0 = on, 1= off */
1650 /* ba= registerbase */
1651 static inline void
1652 cv3d_gfx_on_off(int toggle, volatile void *ba)
1653 {
1654 int r;
1655
1656 toggle &= 0x1;
1657 toggle = toggle << 5;
1658
1659 r = RSeq(ba, SEQ_ID_CLOCKING_MODE);
1660 r &= ~0x20; /* set Bit 5 to 0 */
1661
1662 WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle);
1663 }
1664
1665
1666 #ifdef CV3D_HARDWARE_CURSOR
1667
1668 static unsigned char cv3d_hotx = 0, cv3d_hoty = 0;
1669 static char cv_cursor_on = 0;
1670
1671 #define HWC_OFF (cv3d_fbsize - 1024*2)
1672 #define HWC_SIZE 1024
1673
1674 /* Hardware Cursor handling routines */
1675
1676 int
1677 cv3d_getspritepos(struct grf_softc *gp, struct grf_position *pos)
1678 {
1679 int hi,lo;
1680 volatile void *ba = gp->g_regkva;
1681
1682 hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI);
1683 lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO);
1684
1685 pos->y = (hi << 8) + lo;
1686 hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI);
1687 lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO);
1688 pos->x = (hi << 8) + lo;
1689 return (0);
1690 }
1691
1692
1693 int
1694 cv3d_setspritepos(struct grf_softc *gp, struct grf_position *pos)
1695 {
1696 volatile void *ba = gp->g_regkva;
1697 short x, y;
1698 static short savex, savey;
1699 short xoff, yoff;
1700
1701 if (pos) {
1702 x = pos->x;
1703 y = pos->y;
1704 savex = x;
1705 savey= y;
1706 } else { /* restore cursor */
1707 x = savex;
1708 y = savey;
1709 }
1710 x -= cv3d_hotx;
1711 y -= cv3d_hoty;
1712 if (x < 0) {
1713 xoff = ((-x) & 0xFE);
1714 x = 0;
1715 } else {
1716 xoff = 0;
1717 }
1718
1719 if (y < 0) {
1720 yoff = ((-y) & 0xFE);
1721 y = 0;
1722 } else {
1723 yoff = 0;
1724 }
1725
1726 WCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8));
1727 WCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff));
1728
1729 WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff));
1730 WCrt(ba, CRT_ID_HWGC_DSTART_X, xoff);
1731 WCrt(ba, CRT_ID_HWGC_DSTART_Y, yoff);
1732 WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8));
1733
1734 return(0);
1735 }
1736
1737 static inline short
1738 M2I(short val)
1739 {
1740 return ( ((val & 0xff00) >> 8) | ((val & 0xff) << 8));
1741 }
1742
1743 int
1744 cv3d_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
1745 {
1746 volatile void *ba, fb;
1747
1748 ba = gp->g_regkva;
1749 fb = gp->g_fbkva;
1750
1751 if (info->set & GRFSPRSET_ENABLE)
1752 info->enable = RCrt(ba, CRT_ID_HWGC_MODE) & 0x01;
1753
1754 if (info->set & GRFSPRSET_POS)
1755 cv3d_getspritepos (gp, &info->pos);
1756
1757 #if 0 /* XXX */
1758 if (info->set & GRFSPRSET_SHAPE) {
1759 u_char image[512], mask[512];
1760 volatile u_long *hwp;
1761 u_char *imp, *mp;
1762 short row;
1763 info->size.x = 64;
1764 info->size.y = 64;
1765 for (row = 0, hwp = (u_long *)(fb + HWC_OFF),
1766 mp = mask, imp = image;
1767 row < 64;
1768 row++) {
1769 u_long bp10, bp20, bp11, bp21;
1770 bp10 = *hwp++;
1771 bp20 = *hwp++;
1772 bp11 = *hwp++;
1773 bp21 = *hwp++;
1774 M2I (bp10);
1775 M2I (bp20);
1776 M2I (bp11);
1777 M2I (bp21);
1778 *imp++ = (~bp10) & bp11;
1779 *imp++ = (~bp20) & bp21;
1780 *mp++ = (~bp10) | (bp10 & ~bp11);
1781 *mp++ = (~bp20) & (bp20 & ~bp21);
1782 }
1783 copyout (image, info->image, sizeof (image));
1784 copyout (mask, info->mask, sizeof (mask));
1785 }
1786 #endif
1787 return(0);
1788 }
1789
1790
1791 void
1792 cv3d_setup_hwc(struct grf_softc *gp)
1793 {
1794 volatile void *ba = gp->g_regkva;
1795 volatile void *hwc;
1796 int test;
1797
1798 if (gp->g_display.gd_planes <= 4)
1799 cv3d_cursor_on = 0; /* don't enable hwc in text modes */
1800 if (cv3d_cursor_on == 0)
1801 return;
1802
1803 /* reset colour stack */
1804 #if !defined(__m68k__)
1805 test = RCrt(ba, CRT_ID_HWGC_MODE);
1806 cpu_sync();
1807 #else
1808 /* do it in assembler, the above does't seem to work */
1809 __asm volatile ("moveb #0x45, %1@(0x3d4); \
1810 moveb %1@(0x3d5),%0" : "=r" (test) : "a" (ba));
1811 #endif
1812
1813 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
1814
1815 hwc = ba + CRT_ADDRESS_W;
1816 *hwc = 0;
1817 *hwc = 0;
1818
1819 #if !defined(__m68k__)
1820 test = RCrt(ba, CRT_ID_HWGC_MODE);
1821 cpu_sync();
1822 #else
1823 /* do it in assembler, the above does't seem to work */
1824 __asm volatile ("moveb #0x45, %1@(0x3d4); \
1825 moveb %1@(0x3d5),%0" : "=r" (test) : "a" (ba));
1826 #endif
1827 switch (gp->g_display.gd_planes) {
1828 case 8:
1829 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1);
1830 *hwc = 1;
1831 break;
1832 default:
1833 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
1834 *hwc = 0xff;
1835 *hwc = 0xff;
1836 }
1837
1838 test = HWC_OFF / HWC_SIZE;
1839 WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8));
1840 WCrt (ba, CRT_ID_HWGC_START_AD_LO, (test & 0xff));
1841
1842 WCrt (ba, CRT_ID_HWGC_DSTART_X , 0);
1843 WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0);
1844
1845 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */
1846 /*
1847 * Put it into Windoze Mode or you'll see sometimes a white stripe
1848 * on the right side (in double clocking modes with a screen bigger
1849 * > 1023 pixels).
1850 */
1851 WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x00); /* Cursor Windoze Mode */
1852
1853 WCrt (ba, CRT_ID_HWGC_MODE, 0x01);
1854 }
1855
1856
1857 /*
1858 * This was the reason why you shouldn't use the HWC in the Kernel:(
1859 * Obsoleted now by use of interrupts :-)
1860 */
1861
1862 #define VerticalRetraceWait(ba) \
1863 { \
1864 while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \
1865 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x08) ; \
1866 while ((vgar(ba, GREG_INPUT_STATUS1_R) & 0x08) == 0x00) ; \
1867 }
1868
1869
1870 int
1871 cv3d_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *info)
1872 {
1873 volatile void *ba, fb;
1874 int depth = gp->g_display.gd_planes;
1875
1876 ba = gp->g_regkva;
1877 fb = gp->g_fbkva;
1878
1879 if (info->set & GRFSPRSET_SHAPE) {
1880 /*
1881 * For an explanation of these weird actions here, see above
1882 * when reading the shape. We set the shape directly into
1883 * the video memory, there's no reason to keep 1k on the
1884 * kernel stack just as template
1885 */
1886 u_char *image, *mask;
1887 volatile u_short *hwp;
1888 u_char *imp, *mp;
1889 unsigned short row;
1890
1891 /* Cursor off */
1892 WCrt (ba, CRT_ID_HWGC_MODE, 0x00);
1893
1894 /*
1895 * The Trio64 crashes if the cursor data is written
1896 * while the cursor is displayed.
1897 * Sadly, turning the cursor off is not enough.
1898 * What we have to do is:
1899 * 1. Wait for vertical retrace, to make sure no-one
1900 * has moved the cursor in this sync period (because
1901 * another write then would have no effect, argh!).
1902 * 2. Move the cursor off-screen
1903 * 3. Another wait for v. retrace to make sure the cursor
1904 * is really off.
1905 * 4. Write the data, finally.
1906 * (thanks to Harald Koenig for this tip!)
1907 */
1908
1909 /*
1910 * Remark 06/06/96: Update in interrupt obsoletes this,
1911 * but the warning should stay there!
1912 */
1913
1914 VerticalRetraceWait(ba);
1915
1916 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7);
1917 WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, 0xff);
1918 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, 0xff);
1919 WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f);
1920 WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f);
1921 WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7);
1922
1923 if (info->size.y > 64)
1924 info->size.y = 64;
1925 if (info->size.x > 64)
1926 info->size.x = 64;
1927 if (info->size.x < 32)
1928 info->size.x = 32;
1929
1930 image = malloc(HWC_SIZE, M_TEMP, M_WAITOK);
1931 mask = image + HWC_SIZE/2;
1932
1933 copyin(info->image, image, info->size.y * info->size.x / 8);
1934 copyin(info->mask, mask, info->size.y * info->size.x / 8);
1935
1936 hwp = (u_short *)(fb +HWC_OFF);
1937
1938 /* This is necessary in order not to crash the board */
1939 VerticalRetraceWait(ba);
1940
1941 /*
1942 * setting it is slightly more difficult, because we can't
1943 * force the application to not pass a *smaller* than
1944 * supported bitmap
1945 */
1946
1947 for (row = 0, mp = mask, imp = image;
1948 row < info->size.y; row++) {
1949 u_short im1, im2, im3, im4, m1, m2, m3, m4;
1950
1951 m1 = ~(*(unsigned short *)mp);
1952 im1 = *(unsigned short *)imp & *(unsigned short *)mp;
1953 mp += 2;
1954 imp += 2;
1955
1956 m2 = ~(*(unsigned short *)mp);
1957 im2 = *(unsigned short *)imp & *(unsigned short *)mp;
1958 mp += 2;
1959 imp += 2;
1960
1961 if (info->size.x > 32) {
1962 m3 = ~(*(unsigned short *)mp);
1963 im3 = *(unsigned short *)imp & *(unsigned short *)mp;
1964 mp += 2;
1965 imp += 2;
1966 m4 = ~(*(unsigned short *)mp);
1967 im4 = *(unsigned short *)imp & *(unsigned short *)mp;
1968 mp += 2;
1969 imp += 2;
1970 } else {
1971 m3 = 0xffff;
1972 im3 = 0;
1973 m4 = 0xffff;
1974 im4 = 0;
1975 }
1976
1977 switch (depth) {
1978 case 8:
1979 *hwp++ = m1;
1980 *hwp++ = im1;
1981 *hwp++ = m2;
1982 *hwp++ = im2;
1983 *hwp++ = m3;
1984 *hwp++ = im3;
1985 *hwp++ = m4;
1986 *hwp++ = im4;
1987 break;
1988 case 15:
1989 case 16:
1990 *hwp++ = M2I(m1);
1991 *hwp++ = M2I(im1);
1992 *hwp++ = M2I(m2);
1993 *hwp++ = M2I(im2);
1994 *hwp++ = M2I(m3);
1995 *hwp++ = M2I(im3);
1996 *hwp++ = M2I(m4);
1997 *hwp++ = M2I(im4);
1998 break;
1999 case 24:
2000 case 32:
2001 *hwp++ = M2I(im1);
2002 *hwp++ = M2I(m1);
2003 *hwp++ = M2I(im2);
2004 *hwp++ = M2I(m2);
2005 *hwp++ = M2I(im3);
2006 *hwp++ = M2I(m3);
2007 *hwp++ = M2I(im4);
2008 *hwp++ = M2I(m4);
2009 break;
2010 }
2011 }
2012
2013 if (depth < 24) {
2014 for (; row < 64; row++) {
2015 *hwp++ = 0xffff;
2016 *hwp++ = 0x0000;
2017 *hwp++ = 0xffff;
2018 *hwp++ = 0x0000;
2019 *hwp++ = 0xffff;
2020 *hwp++ = 0x0000;
2021 *hwp++ = 0xffff;
2022 *hwp++ = 0x0000;
2023 }
2024 } else {
2025 for (; row < 64; row++) {
2026 *hwp++ = 0x0000;
2027 *hwp++ = 0xffff;
2028 *hwp++ = 0x0000;
2029 *hwp++ = 0xffff;
2030 *hwp++ = 0x0000;
2031 *hwp++ = 0xffff;
2032 *hwp++ = 0x0000;
2033 *hwp++ = 0xffff;
2034 }
2035 }
2036
2037 free(image, M_TEMP);
2038 /* cv3d_setup_hwc(gp); */
2039 cv3d_hotx = info->hot.x;
2040 cv3d_hoty = info->hot.y;
2041
2042 /* One must not write twice per vertical blank :-( */
2043 VerticalRetraceWait(ba);
2044 cv3d_setspritepos(gp, &info->pos);
2045 }
2046 if (info->set & GRFSPRSET_CMAP) {
2047 volatile void *hwc;
2048 int test;
2049
2050 /* reset colour stack */
2051 test = RCrt(ba, CRT_ID_HWGC_MODE);
2052 cpu_sync();
2053 switch (depth) {
2054 case 8:
2055 case 15:
2056 case 16:
2057 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
2058 hwc = ba + CRT_ADDRESS_W;
2059 *hwc = 0;
2060 break;
2061 case 32:
2062 case 24:
2063 WCrt (ba, CRT_ID_HWGC_FG_STACK, 0);
2064 hwc = ba + CRT_ADDRESS_W;
2065 *hwc = 0;
2066 *hwc = 0;
2067 break;
2068 }
2069
2070 test = RCrt(ba, CRT_ID_HWGC_MODE);
2071 cpu_sync();
2072 switch (depth) {
2073 case 8:
2074 WCrt (ba, CRT_ID_HWGC_BG_STACK, 1);
2075 hwc = ba + CRT_ADDRESS_W;
2076 *hwc = 1;
2077 break;
2078 case 15:
2079 case 16:
2080 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
2081 hwc = ba + CRT_ADDRESS_W;
2082 *hwc = 0xff;
2083 break;
2084 case 32:
2085 case 24:
2086 WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff);
2087 hwc = ba + CRT_ADDRESS_W;
2088 *hwc = 0xff;
2089 *hwc = 0xff;
2090 break;
2091 }
2092 }
2093
2094 if (info->set & GRFSPRSET_ENABLE) {
2095 if (info->enable) {
2096 cv3d_cursor_on = 1;
2097 cv3d_setup_hwc(gp);
2098 /* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */
2099 } else
2100 WCrt(ba, CRT_ID_HWGC_MODE, 0x00);
2101 }
2102 if (info->set & GRFSPRSET_POS)
2103 cv3d_setspritepos(gp, &info->pos);
2104 if (info->set & GRFSPRSET_HOT) {
2105
2106 cv3d_hotx = info->hot.x;
2107 cv3d_hoty = info->hot.y;
2108 cv3d_setspritepos (gp, &info->pos);
2109 }
2110 return(0);
2111 }
2112
2113
2114 int
2115 cv3d_getspritemax(struct grf_softc *gp, struct grf_position *pos)
2116 {
2117
2118 pos->x = 64;
2119 pos->y = 64;
2120 return(0);
2121 }
2122
2123 #endif /* CV3D_HARDWARE_CURSOR */
2124
2125 #if NWSDISPLAY > 0
2126
2127 static void
2128 cv3d_wscursor(void *c, int on, int row, int col)
2129 {
2130 struct rasops_info *ri;
2131 struct vcons_screen *scr;
2132 struct grf_softc *gp;
2133 volatile void *ba;
2134 int offs;
2135
2136 ri = c;
2137 scr = ri->ri_hw;
2138 gp = scr->scr_cookie;
2139 ba = gp->g_regkva;
2140
2141 if ((ri->ri_flg & RI_CURSOR) && !on) {
2142 /* cursor was visible, but we want to remove it */
2143 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
2144 ri->ri_flg &= ~RI_CURSOR;
2145 }
2146
2147 ri->ri_crow = row;
2148 ri->ri_ccol = col;
2149
2150 if (on) {
2151 /* move cursor to new location */
2152 if (!(ri->ri_flg & RI_CURSOR)) {
2153 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
2154 ri->ri_flg |= RI_CURSOR;
2155 }
2156 offs = gp->g_rowoffset[row] + col;
2157 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff);
2158 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, offs >> 8);
2159 }
2160 }
2161
2162 static void
2163 cv3d_wsputchar(void *cookie, int row, int col, u_int ch, long attr)
2164 {
2165 struct rasops_info *ri;
2166 struct vcons_screen *scr;
2167 struct grf_softc *gp;
2168 volatile unsigned char *cp;
2169
2170 ri = cookie;
2171 scr = ri->ri_hw;
2172 gp = scr->scr_cookie;
2173 cp = gp->g_fbkva;
2174 cp += (gp->g_rowoffset[row] + col) << 2;
2175 *cp++ = ch;
2176 *cp = attr;
2177 }
2178
2179 static void
2180 cv3d_wscopycols(void *c, int row, int srccol, int dstcol, int ncols)
2181 {
2182 struct rasops_info *ri;
2183 struct vcons_screen *scr;
2184 struct grf_softc *gp;
2185 volatile uint16_t *src, *dst;
2186
2187 KASSERT(ncols > 0);
2188 ri = c;
2189 scr = ri->ri_hw;
2190 gp = scr->scr_cookie;
2191 src = dst = gp->g_fbkva;
2192 src += (gp->g_rowoffset[row] + srccol) << 1;
2193 dst += (gp->g_rowoffset[row] + dstcol) << 1;
2194 if (src < dst) {
2195 /* need to copy backwards */
2196 src += (ncols - 1) << 1;
2197 dst += (ncols - 1) << 1;
2198 while (ncols--) {
2199 *dst = *src;
2200 src -= 2;
2201 dst -= 2;
2202 }
2203 } else
2204 while (ncols--) {
2205 *dst = *src;
2206 src += 2;
2207 dst += 2;
2208 }
2209 }
2210
2211 static void
2212 cv3d_wserasecols(void *c, int row, int startcol, int ncols, long fillattr)
2213 {
2214 struct rasops_info *ri;
2215 struct vcons_screen *scr;
2216 struct grf_softc *gp;
2217 volatile uint16_t *cp;
2218 uint16_t val;
2219
2220 ri = c;
2221 scr = ri->ri_hw;
2222 gp = scr->scr_cookie;
2223 cp = gp->g_fbkva;
2224 val = 0x2000 | fillattr;
2225 cp += (gp->g_rowoffset[row] + startcol) << 1;
2226 while (ncols--) {
2227 *cp = val;
2228 cp += 2;
2229 }
2230 }
2231
2232 static void
2233 cv3d_wscopyrows(void *c, int srcrow, int dstrow, int nrows)
2234 {
2235 struct rasops_info *ri;
2236 struct vcons_screen *scr;
2237 struct grf_softc *gp;
2238 volatile uint16_t *src, *dst;
2239 int n;
2240
2241 KASSERT(nrows > 0);
2242 ri = c;
2243 scr = ri->ri_hw;
2244 gp = scr->scr_cookie;
2245 src = dst = gp->g_fbkva;
2246 n = ri->ri_cols * nrows;
2247 if (srcrow < dstrow) {
2248 /* need to copy backwards */
2249 src += gp->g_rowoffset[srcrow + nrows] << 1;
2250 dst += gp->g_rowoffset[dstrow + nrows] << 1;
2251 while (n--) {
2252 src -= 2;
2253 dst -= 2;
2254 *dst = *src;
2255 }
2256 } else {
2257 src += gp->g_rowoffset[srcrow] << 1;
2258 dst += gp->g_rowoffset[dstrow] << 1;
2259 while (n--) {
2260 *dst = *src;
2261 src += 2;
2262 dst += 2;
2263 }
2264 }
2265 }
2266
2267 static void
2268 cv3d_wseraserows(void *c, int row, int nrows, long fillattr)
2269 {
2270 struct rasops_info *ri;
2271 struct vcons_screen *scr;
2272 struct grf_softc *gp;
2273 volatile uint16_t *cp;
2274 int n;
2275 uint16_t val;
2276
2277 ri = c;
2278 scr = ri->ri_hw;
2279 gp = scr->scr_cookie;
2280 cp = gp->g_fbkva;
2281 val = 0x2000 | fillattr;
2282 cp += gp->g_rowoffset[row] << 1;
2283 n = ri->ri_cols * nrows;
2284 while (n--) {
2285 *cp = val;
2286 cp += 2;
2287 }
2288 }
2289
2290 /* our font does not support unicode extensions */
2291 static int
2292 cv3d_wsmapchar(void *c, int ch, unsigned int *cp)
2293 {
2294
2295 if (ch > 0 && ch < 256) {
2296 *cp = ch;
2297 return 5;
2298 }
2299 *cp = ' ';
2300 return 0;
2301 }
2302
2303 static int
2304 cv3d_wsallocattr(void *c, int fg, int bg, int flg, long *attr)
2305 {
2306
2307 /* XXX color support? */
2308 *attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07;
2309 if (flg & WSATTR_UNDERLINE) *attr = 0x01;
2310 if (flg & WSATTR_HILIT) *attr |= 0x08;
2311 if (flg & WSATTR_BLINK) *attr |= 0x80;
2312 return 0;
2313 }
2314
2315 static int
2316 cv3d_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
2317 {
2318 struct vcons_data *vd;
2319 struct grf_softc *gp;
2320
2321 vd = v;
2322 gp = vd->cookie;
2323
2324 switch (cmd) {
2325 case WSDISPLAYIO_GETCMAP:
2326 /* Note: wsdisplay_cmap and grf_colormap have same format */
2327 if (gp->g_display.gd_planes == 8)
2328 return cv3d_getcmap(gp, (struct grf_colormap *)data);
2329 return EINVAL;
2330
2331 case WSDISPLAYIO_PUTCMAP:
2332 /* Note: wsdisplay_cmap and grf_colormap have same format */
2333 if (gp->g_display.gd_planes == 8)
2334 return cv3d_putcmap(gp, (struct grf_colormap *)data);
2335 return EINVAL;
2336
2337 case WSDISPLAYIO_GVIDEO:
2338 if (cv3d_isblank(gp))
2339 *(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
2340 else
2341 *(u_int *)data = WSDISPLAYIO_VIDEO_ON;
2342 return 0;
2343
2344 case WSDISPLAYIO_SVIDEO:
2345 return cv3d_blank(gp, *(u_int *)data == WSDISPLAYIO_VIDEO_ON);
2346
2347 case WSDISPLAYIO_SMODE:
2348 if ((*(int *)data) != gp->g_wsmode) {
2349 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
2350 /* load console text mode, redraw screen */
2351 (void)cv3d_load_mon(gp, &cv3dconsole_mode);
2352 if (vd->active != NULL)
2353 vcons_redraw_screen(vd->active);
2354 } else {
2355 /* switch to current graphics mode */
2356 if (!cv3d_load_mon(gp,
2357 (struct grfcv3dtext_mode *)monitor_current))
2358 return EINVAL;
2359 }
2360 gp->g_wsmode = *(int *)data;
2361 }
2362 return 0;
2363
2364 case WSDISPLAYIO_GET_FBINFO:
2365 return cv3d_get_fbinfo(gp, data);
2366 }
2367
2368 /* handle this command hw-independant in grf(4) */
2369 return grf_wsioctl(v, vs, cmd, data, flag, l);
2370 }
2371
2372 /*
2373 * Fill the wsdisplayio_fbinfo structure with information from the current
2374 * graphics mode. Even when text mode is active.
2375 */
2376 static int
2377 cv3d_get_fbinfo(struct grf_softc *gp, struct wsdisplayio_fbinfo *fbi)
2378 {
2379 struct grfvideo_mode *md;
2380 uint32_t rbits, gbits, bbits, abits;
2381
2382 md = monitor_current;
2383 abits = 0;
2384
2385 switch (md->depth) {
2386 case 8:
2387 fbi->fbi_bitsperpixel = 8;
2388 rbits = gbits = bbits = 6; /* keep gcc happy */
2389 break;
2390 case 15:
2391 fbi->fbi_bitsperpixel = 16;
2392 rbits = gbits = bbits = 5;
2393 break;
2394 case 16:
2395 fbi->fbi_bitsperpixel = 16;
2396 rbits = bbits = 5;
2397 gbits = 6;
2398 break;
2399 case 32:
2400 abits = 8;
2401 case 24:
2402 fbi->fbi_bitsperpixel = 32;
2403 rbits = gbits = bbits = 8;
2404 break;
2405 default:
2406 return EINVAL;
2407 }
2408
2409 fbi->fbi_stride = (fbi->fbi_bitsperpixel / 8) * md->disp_width;
2410 fbi->fbi_width = md->disp_width;
2411 fbi->fbi_height = md->disp_height;
2412
2413 if (md->depth > 8) {
2414 fbi->fbi_pixeltype = WSFB_RGB;
2415 fbi->fbi_subtype.fbi_rgbmasks.red_offset = bbits + gbits;
2416 fbi->fbi_subtype.fbi_rgbmasks.red_size = rbits;
2417 fbi->fbi_subtype.fbi_rgbmasks.green_offset = bbits;
2418 fbi->fbi_subtype.fbi_rgbmasks.green_size = gbits;
2419 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
2420 fbi->fbi_subtype.fbi_rgbmasks.blue_size = bbits;
2421 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset =
2422 bbits + gbits + rbits;
2423 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = abits;
2424 } else {
2425 fbi->fbi_pixeltype = WSFB_CI;
2426 fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << md->depth;
2427 }
2428
2429 fbi->fbi_flags = 0;
2430 fbi->fbi_fbsize = fbi->fbi_stride * fbi->fbi_height;
2431 fbi->fbi_fboffset = 0;
2432 return 0;
2433 }
2434 #endif /* NWSDISPLAY > 0 */
2435
2436 #endif /* NGRFCV3D */
2437