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