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