xref: /netbsd-src/sys/arch/amiga/dev/grf_cv.c (revision b6c8c37ff61c4264acd6dfb4f74f0eac3cfbf53f)
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