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