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